From e5337b629828f8531868f2abbe6eeada9653eba8 Mon Sep 17 00:00:00 2001 From: RednedEpic Date: Sun, 4 Sep 2022 13:08:17 -0500 Subject: [PATCH] Reintroduce GeyserDefineCommandsEvent and cleanup a few things --- api/base/build.gradle.kts | 7 +- .../main/java/org/geysermc/api/Geyser.java | 4 +- .../org/geysermc/geyser/api/GeyserApi.java | 13 +- .../geysermc/geyser/api/command/Command.java | 39 ++++-- .../lifecycle/GeyserDefineCommandsEvent.java} | 29 ++--- .../event/lifecycle/GeyserShutdownEvent.java | 3 +- .../api/extension/ExtensionDescription.java | 20 ++- .../bungeecord/GeyserBungeePlugin.java | 14 +- .../platform/spigot/GeyserSpigotPlugin.java | 50 ++++++- .../command/GeyserSpigotCommandManager.java | 4 + .../spigot/src/main/resources/plugin.yml | 5 +- .../platform/sponge/GeyserSpongePlugin.java | 13 +- .../velocity/GeyserVelocityPlugin.java | 13 +- .../java/org/geysermc/geyser/GeyserImpl.java | 8 +- .../geyser/command/GeyserCommandManager.java | 122 ++++++++++++------ .../geyser/command/defaults/HelpCommand.java | 6 +- .../type/GeyserDefineCommandsEventImpl.java | 46 +++++++ ... => GeyserDefineCustomItemsEventImpl.java} | 4 +- .../extension/GeyserExtensionDescription.java | 9 +- .../command/GeyserExtensionCommand.java | 43 ++++++ .../loader/ProviderRegistryLoader.java | 5 +- .../populator/ItemRegistryPopulator.java | 5 +- 22 files changed, 355 insertions(+), 107 deletions(-) rename api/geyser/src/main/java/org/geysermc/geyser/api/{command/CommandManager.java => event/lifecycle/GeyserDefineCommandsEvent.java} (68%) create mode 100644 core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java rename core/src/main/java/org/geysermc/geyser/event/type/{DefineCustomItemsEvent.java => GeyserDefineCustomItemsEventImpl.java} (93%) create mode 100644 core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java diff --git a/api/base/build.gradle.kts b/api/base/build.gradle.kts index 03f08c6d2..a6fa608cc 100644 --- a/api/base/build.gradle.kts +++ b/api/base/build.gradle.kts @@ -1,4 +1,7 @@ dependencies { api("org.geysermc.cumulus", "cumulus", Versions.cumulusVersion) - api("org.geysermc.event", "events", Versions.eventsVersion) -} + api("org.geysermc.event", "events", Versions.eventsVersion) { + exclude(group = "com.google.guava", module = "guava") + exclude(group = "org.lanternpowered", module = "lmbda") + } +} \ No newline at end of file diff --git a/api/base/src/main/java/org/geysermc/api/Geyser.java b/api/base/src/main/java/org/geysermc/api/Geyser.java index 9f315faf4..d0bdf3b5e 100644 --- a/api/base/src/main/java/org/geysermc/api/Geyser.java +++ b/api/base/src/main/java/org/geysermc/api/Geyser.java @@ -69,7 +69,7 @@ public class Geyser { /** * Registers the given api type. The api cannot be - * registered if {@link #registered()} is true as + * registered if {@link #isRegistered()} is true as * an api has already been specified. * * @param api the api @@ -88,7 +88,7 @@ public class Geyser { * * @return if the api has been registered */ - public static boolean registered() { + public static boolean isRegistered() { return api != null; } } diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java b/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java index 82f0566fe..e73727104 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/GeyserApi.java @@ -29,7 +29,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.Geyser; import org.geysermc.api.GeyserApiBase; -import org.geysermc.geyser.api.command.CommandManager; import org.geysermc.geyser.api.connection.GeyserConnection; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.extension.ExtensionManager; @@ -66,15 +65,9 @@ public interface GeyserApi extends GeyserApiBase { * * @return the extension manager */ + @NonNull ExtensionManager extensionManager(); - /** - * Gets the {@link CommandManager}. - * - * @return the command manager - */ - CommandManager commandManager(); - /** * Provides an implementation for the specified API type. * @@ -92,6 +85,7 @@ public interface GeyserApi extends GeyserApiBase { * * @return the event bus */ + @NonNull EventBus eventBus(); /** @@ -100,6 +94,7 @@ public interface GeyserApi extends GeyserApiBase { * * @return the default remote server used within Geyser */ + @NonNull RemoteServer defaultRemoteServer(); /** @@ -108,6 +103,7 @@ public interface GeyserApi extends GeyserApiBase { * * @return the listener used for Bedrock client connectins */ + @NonNull BedrockListener bedrockListener(); /** @@ -115,6 +111,7 @@ public interface GeyserApi extends GeyserApiBase { * * @return the current geyser api instance */ + @NonNull static GeyserApi api() { return Geyser.api(GeyserApi.class); } diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java b/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java index 0ad296669..2f1f2b24d 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/command/Command.java @@ -27,6 +27,8 @@ package org.geysermc.geyser.api.command; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.api.GeyserApi; +import org.geysermc.geyser.api.connection.GeyserConnection; +import org.geysermc.geyser.api.extension.Extension; import java.util.Collections; import java.util.List; @@ -104,19 +106,39 @@ public interface Command { return false; } - static Command.Builder builder(Class sourceType) { - return GeyserApi.api().provider(Builder.class, sourceType); + /** + * Creates a new {@link Command.Builder} used to construct commands. + * + * @param extension the extension + * @param the source type + * @return a new command builder used to construct commands + */ + static Command.Builder builder(@NonNull Extension extension) { + return GeyserApi.api().provider(Builder.class, extension); } interface Builder { + /** + * Defines the source type to use for this command. + *

+ * Command source types can be anything that extend + * {@link CommandSource}, such as {@link GeyserConnection}. + * This will guarantee that the source used in the executor + * is an instance of this source. + * + * @param sourceType the source type + * @return the builder + */ + Builder source(@NonNull Class sourceType); + /** * Sets the command name. * * @param name the command name * @return the builder */ - Builder name(String name); + Builder name(@NonNull String name); /** * Sets the command description. @@ -124,7 +146,7 @@ public interface Command { * @param description the command description * @return the builder */ - Builder description(String description); + Builder description(@NonNull String description); /** * Sets the permission node. @@ -132,7 +154,7 @@ public interface Command { * @param permission the permission node * @return the builder */ - Builder permission(String permission); + Builder permission(@NonNull String permission); /** * Sets the aliases. @@ -140,7 +162,7 @@ public interface Command { * @param aliases the aliases * @return the builder */ - Builder aliases(List aliases); + Builder aliases(@NonNull List aliases); /** * Sets if this command is designed to be used only by server operators. @@ -164,7 +186,7 @@ public interface Command { * @param subCommands the subcommands * @return the builder */ - Builder subCommands(List subCommands); + Builder subCommands(@NonNull List subCommands); /** * Sets if this command is bedrock only. @@ -180,13 +202,14 @@ public interface Command { * @param executor the command executor * @return the builder */ - Builder executor(CommandExecutor executor); + Builder executor(@NonNull CommandExecutor executor); /** * Builds the command. * * @return the command */ + @NonNull Command build(); } } diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java b/api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java similarity index 68% rename from api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java rename to api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java index 9f29651ba..77d5efa65 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/command/CommandManager.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserDefineCommandsEvent.java @@ -23,36 +23,35 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.geyser.api.command; +package org.geysermc.geyser.api.event.lifecycle; import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.event.Event; +import org.geysermc.geyser.api.command.Command; import java.util.Map; /** - * Manages Bedrock commands within Geyser. + * Called when commands are defined within Geyser. + * + * This event allows you to register new commands using the {@link #register(Command)} + * method and retrieve the default commands defined. */ -public abstract class CommandManager { +public interface GeyserDefineCommandsEvent extends Event { /** - * Registers the given {@link Command}. + * Registers the given {@link Command} into the Geyser + * command manager. * * @param command the command to register */ - public abstract void register(@NonNull Command command); + void register(@NonNull Command command); /** - * Unregisters the given {@link Command}. + * Gets all the registered built-in {@link Command}s. * - * @param command the command to unregister - */ - public abstract void unregister(@NonNull Command command); - - /** - * Gets all the registered {@link Command}s. - * - * @return all the registered commands + * @return all the registered built-in commands */ @NonNull - public abstract Map commands(); + Map commands(); } diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserShutdownEvent.java b/api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserShutdownEvent.java index f2fab901d..a1c68d876 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserShutdownEvent.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/event/lifecycle/GeyserShutdownEvent.java @@ -27,12 +27,11 @@ package org.geysermc.geyser.api.event.lifecycle; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.event.Event; -import org.geysermc.geyser.api.command.CommandManager; import org.geysermc.geyser.api.event.EventBus; import org.geysermc.geyser.api.extension.ExtensionManager; /** * Called when Geyser is shutting down. */ -public record GeyserShutdownEvent(@NonNull ExtensionManager extensionManager, @NonNull CommandManager commandManager, @NonNull EventBus eventBus) implements Event { +public record GeyserShutdownEvent(@NonNull ExtensionManager extensionManager, @NonNull EventBus eventBus) implements Event { } diff --git a/api/geyser/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java b/api/geyser/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java index e77411144..8136bd761 100644 --- a/api/geyser/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java +++ b/api/geyser/src/main/java/org/geysermc/geyser/api/extension/ExtensionDescription.java @@ -30,12 +30,20 @@ import org.checkerframework.checker.nullness.qual.NonNull; import java.util.List; /** - * This is the Geyser extension description + * Represents the description of an {@link Extension}. */ public interface ExtensionDescription { /** - * Gets the extension's name + * Gets the extension's id. + * + * @return the extension's id + */ + @NonNull + String id(); + + /** + * Gets the extension's name. * * @return the extension's name */ @@ -43,7 +51,7 @@ public interface ExtensionDescription { String name(); /** - * Gets the extension's main class + * Gets the extension's main class. * * @return the extension's main class */ @@ -51,7 +59,7 @@ public interface ExtensionDescription { String main(); /** - * Gets the extension's api version + * Gets the extension's api version. * * @return the extension's api version */ @@ -59,7 +67,7 @@ public interface ExtensionDescription { String apiVersion(); /** - * Gets the extension's description + * Gets the extension's description. * * @return the extension's description */ @@ -67,7 +75,7 @@ public interface ExtensionDescription { String version(); /** - * Gets the extension's authors + * Gets the extension's authors. * * @return the extension's authors */ diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index c72503450..ed2c340db 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -32,6 +32,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -49,6 +51,7 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Map; import java.util.UUID; import java.util.logging.Level; @@ -149,8 +152,15 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { this.geyserBungeePingPassthrough = new GeyserBungeePingPassthrough(getProxy()); } - this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", geyser, geyserCommandManager.getCommands())); - this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyserext", geyser, geyserCommandManager.commands())); + this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor("geyser", this.geyser, this.geyserCommandManager.getCommands())); + for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { + Map commands = entry.getValue(); + if (commands.isEmpty()) { + continue; + } + + this.getProxy().getPluginManager().registerCommand(this, new GeyserBungeeCommandExecutor(entry.getKey().description().id(), this.geyser, commands)); + } } @Override diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index 4a371cfe8..e3b794578 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -32,9 +32,11 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import io.netty.buffer.ByteBuf; import me.lucko.commodore.CommodoreProvider; import org.bukkit.Bukkit; +import org.bukkit.command.CommandMap; import org.bukkit.command.PluginCommand; import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; +import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.geysermc.common.PlatformType; import org.geysermc.geyser.Constants; @@ -42,6 +44,7 @@ import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.adapters.spigot.SpigotAdapters; import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -62,6 +65,8 @@ import org.geysermc.geyser.util.FileUtils; import java.io.File; import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.net.SocketAddress; import java.nio.file.Path; import java.util.List; @@ -269,13 +274,32 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { PluginCommand geyserCommand = this.getCommand("geyser"); geyserCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands())); - PluginCommand geyserExtCommand = this.getCommand("geyserext"); - geyserExtCommand.setExecutor(new GeyserSpigotCommandExecutor(geyser, geyserCommandManager.getCommands())); + + CommandMap commandMap = GeyserSpigotCommandManager.getCommandMap(); + for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { + Map commands = entry.getValue(); + if (commands.isEmpty()) { + continue; + } + + // Thanks again, Bukkit + try { + Constructor constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + constructor.setAccessible(true); + + PluginCommand pluginCommand = constructor.newInstance(entry.getKey().description().id(), this); + pluginCommand.setExecutor(new GeyserSpigotCommandExecutor(this.geyser, commands)); + pluginCommand.setDescription("The main command for the " + entry.getKey().name() + " Geyser extension!"); + commandMap.register(entry.getKey().description().id(), "geyserext", pluginCommand); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException ex) { + this.geyserLogger.error("Failed to construct PluginCommand for extension " + entry.getKey().description().name(), ex); + } + } if (!INITIALIZED) { // Register permissions so they appear in, for example, LuckPerms' UI // Re-registering permissions throws an error - for (Map.Entry entry : geyserCommandManager.getCommands().entrySet()) { + for (Map.Entry entry : geyserCommandManager.commands().entrySet()) { Command command = entry.getValue(); if (command.aliases().contains(entry.getKey())) { // Don't register aliases @@ -286,6 +310,26 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { GeyserLocale.getLocaleStringLog(command.description()), command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE)); } + + // Register permissions for extension commands + for (Map.Entry> commandEntry : this.geyserCommandManager.extensionCommands().entrySet()) { + for (Map.Entry entry : commandEntry.getValue().entrySet()) { + Command command = entry.getValue(); + if (command.aliases().contains(entry.getKey())) { + // Don't register aliases + continue; + } + + if (command.permission().isBlank()) { + continue; + } + + Bukkit.getPluginManager().addPermission(new Permission(command.permission(), + GeyserLocale.getLocaleStringLog(command.description()), + command.isSuggestedOpOnly() ? PermissionDefault.OP : PermissionDefault.TRUE)); + } + } + Bukkit.getPluginManager().addPermission(new Permission(Constants.UPDATE_PERMISSION, "Whether update notifications can be seen", PermissionDefault.OP)); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java index 9fb19f0da..655d3be23 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/command/GeyserSpigotCommandManager.java @@ -65,4 +65,8 @@ public class GeyserSpigotCommandManager extends GeyserCommandManager { Command cmd = COMMAND_MAP.getCommand(command.replace("/", "")); return cmd != null ? cmd.getDescription() : ""; } + + public static CommandMap getCommandMap() { + return COMMAND_MAP; + } } diff --git a/bootstrap/spigot/src/main/resources/plugin.yml b/bootstrap/spigot/src/main/resources/plugin.yml index 0f6398b49..e28b8981d 100644 --- a/bootstrap/spigot/src/main/resources/plugin.yml +++ b/bootstrap/spigot/src/main/resources/plugin.yml @@ -8,7 +8,4 @@ api-version: 1.13 commands: geyser: description: The main command for Geyser. - usage: /geyser - geyserext: - description: The command any extensions can register to. - usage: /geyserext \ No newline at end of file + usage: /geyser \ No newline at end of file diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java index 312dfb087..d912d28d8 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java @@ -29,6 +29,8 @@ import com.google.inject.Inject; import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; @@ -50,6 +52,7 @@ import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.file.Path; +import java.util.Map; import java.util.UUID; @Plugin(id = "geyser", name = GeyserImpl.NAME + "-Sponge", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC") @@ -122,7 +125,15 @@ public class GeyserSpongePlugin implements GeyserBootstrap { this.geyserCommandManager = new GeyserSpongeCommandManager(Sponge.getCommandManager(), geyser); this.geyserCommandManager.init(); Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.getCommands()), "geyser"); - Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(geyser, geyserCommandManager.commands()), "geyserext"); + + for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { + Map commands = entry.getValue(); + if (commands.isEmpty()) { + continue; + } + + Sponge.getCommandManager().register(this, new GeyserSpongeCommandExecutor(this.geyser, commands), entry.getKey().description().id()); + } } @Override diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index e2f84a2a7..30d8deccd 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -39,6 +39,8 @@ import net.kyori.adventure.util.Codec; import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; @@ -58,6 +60,7 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Map; import java.util.UUID; @Plugin(id = "geyser", name = GeyserImpl.NAME + "-Velocity", version = GeyserImpl.VERSION, url = "https://geysermc.org", authors = "GeyserMC") @@ -159,7 +162,15 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.geyserCommandManager.init(); this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.getCommands())); - this.commandManager.register("geyserext", new GeyserVelocityCommandExecutor(geyser, geyserCommandManager.commands())); + for (Map.Entry> entry : this.geyserCommandManager.extensionCommands().entrySet()) { + Map commands = entry.getValue(); + if (commands.isEmpty()) { + continue; + } + + this.commandManager.register(entry.getKey().description().id(), new GeyserVelocityCommandExecutor(this.geyser, commands)); + } + if (geyserConfig.isLegacyPingPassthrough()) { this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(geyser); } else { diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index ed65ffbe9..24a5f5d2c 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -547,7 +547,7 @@ public class GeyserImpl implements GeyserApi { ResourcePack.PACKS.clear(); - this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.commandManager(), this.eventBus)); + this.eventBus.fire(new GeyserShutdownEvent(this.extensionManager, this.eventBus)); this.extensionManager.disableExtensions(); bootstrap.getGeyserLogger().info(GeyserLocale.getLocaleStringLog("geyser.core.shutdown.done")); @@ -572,11 +572,12 @@ public class GeyserImpl implements GeyserApi { } @Override + @NonNull public GeyserExtensionManager extensionManager() { return this.extensionManager; } - @Override + @NonNull public GeyserCommandManager commandManager() { return this.bootstrap.getGeyserCommandManager(); } @@ -587,15 +588,18 @@ public class GeyserImpl implements GeyserApi { } @Override + @NonNull public EventBus eventBus() { return this.eventBus; } + @NonNull public RemoteServer defaultRemoteServer() { return getConfig().getRemote(); } @Override + @NonNull public BedrockListener bedrockListener() { return getConfig().getBedrock(); } diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index cb3cf6eee..7c5bd6580 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -33,30 +33,46 @@ import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.command.CommandExecutor; -import org.geysermc.geyser.api.command.CommandManager; import org.geysermc.geyser.api.command.CommandSource; -import org.geysermc.geyser.command.defaults.*; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; +import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand; +import org.geysermc.geyser.command.defaults.AdvancementsCommand; +import org.geysermc.geyser.command.defaults.ConnectionTestCommand; +import org.geysermc.geyser.command.defaults.DumpCommand; +import org.geysermc.geyser.command.defaults.ExtensionsCommand; +import org.geysermc.geyser.command.defaults.HelpCommand; +import org.geysermc.geyser.command.defaults.ListCommand; +import org.geysermc.geyser.command.defaults.OffhandCommand; +import org.geysermc.geyser.command.defaults.ReloadCommand; +import org.geysermc.geyser.command.defaults.SettingsCommand; +import org.geysermc.geyser.command.defaults.StatisticsCommand; +import org.geysermc.geyser.command.defaults.StopCommand; +import org.geysermc.geyser.command.defaults.VersionCommand; +import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl; +import org.geysermc.geyser.extension.command.GeyserExtensionCommand; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @RequiredArgsConstructor -public abstract class GeyserCommandManager extends CommandManager { +public abstract class GeyserCommandManager { @Getter private final Map commands = new Object2ObjectOpenHashMap<>(12); - private final Map extensionCommands = new Object2ObjectOpenHashMap<>(0); + private final Map> extensionCommands = new Object2ObjectOpenHashMap<>(0); private final GeyserImpl geyser; public void init() { - registerBuiltInCommand(new HelpCommand(geyser, "help", "geyser.commands.help.desc", "geyser.command.help", "geyser", commands)); + registerBuiltInCommand(new HelpCommand(geyser, "help", "geyser.commands.help.desc", "geyser.command.help", "geyser", this.commands)); registerBuiltInCommand(new ListCommand(geyser, "list", "geyser.commands.list.desc", "geyser.command.list")); registerBuiltInCommand(new ReloadCommand(geyser, "reload", "geyser.commands.reload.desc", "geyser.command.reload")); registerBuiltInCommand(new OffhandCommand(geyser, "offhand", "geyser.commands.offhand.desc", "geyser.command.offhand")); @@ -67,11 +83,32 @@ public abstract class GeyserCommandManager extends CommandManager { registerBuiltInCommand(new AdvancementsCommand("advancements", "geyser.commands.advancements.desc", "geyser.command.advancements")); registerBuiltInCommand(new AdvancedTooltipsCommand("tooltips", "geyser.commands.advancedtooltips.desc", "geyser.command.tooltips")); registerBuiltInCommand(new ConnectionTestCommand(geyser, "connectiontest", "geyser.commands.connectiontest.desc", "geyser.command.connectiontest")); - if (GeyserImpl.getInstance().getPlatformType() == PlatformType.STANDALONE) { + if (this.geyser.getPlatformType() == PlatformType.STANDALONE) { registerBuiltInCommand(new StopCommand(geyser, "stop", "geyser.commands.stop.desc", "geyser.command.stop")); } - register(new HelpCommand(geyser, "help", "geyser.commands.exthelp.desc", "geyser.command.exthelp", "geyserext", extensionCommands)); + if (this.geyser.extensionManager().extensions().size() > 0) { + registerBuiltInCommand(new ExtensionsCommand(this.geyser, "extensions", "geyser.commands.extensions.desc", "geyser.command.extensions")); + } + + GeyserDefineCommandsEvent defineCommandsEvent = new GeyserDefineCommandsEventImpl(this.commands) { + + @Override + public void register(@NonNull Command command) { + if (!(command instanceof GeyserExtensionCommand extensionCommand)) { + throw new IllegalArgumentException("Expected GeyserExtensionCommand as part of command registration but got " + command + "! Did you use the Command builder properly?"); + } + + registerExtensionCommand(extensionCommand.extension(), extensionCommand); + } + }; + + this.geyser.eventBus().fire(defineCommandsEvent); + + // Register help commands for all extensions with commands + for (Map.Entry> entry : this.extensionCommands.entrySet()) { + registerExtensionCommand(entry.getKey(), new HelpCommand(this.geyser, "help", "geyser.commands.exthelp.desc", "geyser.command.exthelp", entry.getKey().description().id(), entry.getValue())); + } } /** @@ -81,9 +118,8 @@ public abstract class GeyserCommandManager extends CommandManager { register(command, this.commands); } - @Override - public void register(@NonNull Command command) { - register(command, this.extensionCommands); + public void registerExtensionCommand(@NonNull Extension extension, @NonNull Command command) { + register(command, this.extensionCommands.computeIfAbsent(extension, e -> new HashMap<>())); } private void register(Command command, Map commands) { @@ -99,32 +135,30 @@ public abstract class GeyserCommandManager extends CommandManager { } } - @Override - public void unregister(@NonNull Command command) { - this.extensionCommands.remove(command.name(), command); - - if (command.aliases().isEmpty()) { - return; - } - - for (String alias : command.aliases()) { - this.extensionCommands.remove(alias, command); - } + @NotNull + public Map commands() { + return Collections.unmodifiableMap(this.commands); } @NotNull - @Override - public Map commands() { + public Map> extensionCommands() { return Collections.unmodifiableMap(this.extensionCommands); } public boolean runCommand(GeyserCommandSource sender, String command) { - boolean extensionCommand = command.startsWith("geyserext "); - if (!command.startsWith("geyser ") && !extensionCommand) { + Extension extension = null; + for (Extension loopedExtension : this.extensionCommands.keySet()) { + if (command.startsWith(loopedExtension.description().id() + " ")) { + extension = loopedExtension; + break; + } + } + + if (!command.startsWith("geyser ") && extension == null) { return false; } - command = command.trim().replace(extensionCommand ? "geyserext " : "geyser ", ""); + command = command.trim().replace(extension != null ? extension.description().id() + " " : "geyser ", ""); String label; String[] args; @@ -137,9 +171,9 @@ public abstract class GeyserCommandManager extends CommandManager { args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine }; } - Command cmd = (extensionCommand ? this.extensionCommands : this.commands).get(label); + Command cmd = (extension != null ? this.extensionCommands.getOrDefault(extension, Collections.emptyMap()) : this.commands).get(label); if (cmd == null) { - geyser.getLogger().error(GeyserLocale.getLocaleStringLog("geyser.commands.invalid")); + sender.sendMessage(GeyserLocale.getLocaleStringLog("geyser.commands.invalid")); return false; } @@ -168,7 +202,8 @@ public abstract class GeyserCommandManager extends CommandManager { @RequiredArgsConstructor public static class CommandBuilder implements Command.Builder { - private final Class sourceType; + private final Extension extension; + private Class sourceType; private String name; private String description = ""; private String permission = ""; @@ -179,22 +214,28 @@ public abstract class GeyserCommandManager extends CommandManager { private boolean bedrockOnly; private CommandExecutor executor; - public CommandBuilder name(String name) { + @Override + public Command.Builder source(@NonNull Class sourceType) { + this.sourceType = sourceType; + return this; + } + + public CommandBuilder name(@NonNull String name) { this.name = name; return this; } - public CommandBuilder description(String description) { + public CommandBuilder description(@NonNull String description) { this.description = description; return this; } - public CommandBuilder permission(String permission) { + public CommandBuilder permission(@NonNull String permission) { this.permission = permission; return this; } - public CommandBuilder aliases(List aliases) { + public CommandBuilder aliases(@NonNull List aliases) { this.aliases = aliases; return this; } @@ -210,7 +251,7 @@ public abstract class GeyserCommandManager extends CommandManager { return this; } - public CommandBuilder subCommands(List subCommands) { + public CommandBuilder subCommands(@NonNull List subCommands) { this.subCommands = subCommands; return this; } @@ -220,22 +261,27 @@ public abstract class GeyserCommandManager extends CommandManager { return this; } - public CommandBuilder executor(CommandExecutor executor) { + public CommandBuilder executor(@NonNull CommandExecutor executor) { this.executor = executor; return this; } - public GeyserCommand build() { + @NonNull + public GeyserExtensionCommand build() { if (this.name == null || this.name.isBlank()) { throw new IllegalArgumentException("Command cannot be null or blank!"); } - return new GeyserCommand(this.name, this.description, this.permission) { + if (this.sourceType == null) { + throw new IllegalArgumentException("Source type was not defined for command " + this.name + " in extension " + this.extension.name()); + } + + return new GeyserExtensionCommand(this.extension, this.name, this.description, this.permission) { @SuppressWarnings("unchecked") @Override public void execute(@Nullable GeyserSession session, GeyserCommandSource sender, String[] args) { - Class sourceType = CommandBuilder.this.sourceType; + Class sourceType = CommandBuilder.this.sourceType; CommandExecutor executor = CommandBuilder.this.executor; if (sourceType.isInstance(session)) { executor.execute((T) session, this, args); diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java index 81f34b759..6e7ad2f04 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java @@ -66,19 +66,19 @@ public class HelpCommand extends GeyserCommand { String header = GeyserLocale.getPlayerLocaleString("geyser.commands.help.header", sender.locale(), page, maxPage); sender.sendMessage(header); - for (Map.Entry entry : commands.entrySet()) { + this.commands.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> { Command cmd = entry.getValue(); // Standalone hack-in since it doesn't have a concept of permissions if (geyser.getPlatformType() == PlatformType.STANDALONE || sender.hasPermission(cmd.permission())) { // Only list commands the player can actually run if (cmd.isBedrockOnly() && session == null) { - continue; + return; } sender.sendMessage(ChatColor.YELLOW + "/" + baseCommand + " " + entry.getKey() + ChatColor.WHITE + ": " + GeyserLocale.getPlayerLocaleString(cmd.description(), sender.locale())); } - } + }); } } diff --git a/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java new file mode 100644 index 000000000..e07a62d8a --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCommandsEventImpl.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.event.type; + +import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.geyser.api.command.Command; +import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; + +import java.util.Collections; +import java.util.Map; + +public abstract class GeyserDefineCommandsEventImpl implements GeyserDefineCommandsEvent { + private final Map commands; + + public GeyserDefineCommandsEventImpl(Map commands) { + this.commands = commands; + } + + @Override + public @NonNull Map commands() { + return Collections.unmodifiableMap(this.commands); + } +} diff --git a/core/src/main/java/org/geysermc/geyser/event/type/DefineCustomItemsEvent.java b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java similarity index 93% rename from core/src/main/java/org/geysermc/geyser/event/type/DefineCustomItemsEvent.java rename to core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java index 9011bfb3a..65fd7ea0d 100644 --- a/core/src/main/java/org/geysermc/geyser/event/type/DefineCustomItemsEvent.java +++ b/core/src/main/java/org/geysermc/geyser/event/type/GeyserDefineCustomItemsEventImpl.java @@ -36,11 +36,11 @@ import java.util.Collections; import java.util.List; import java.util.Map; -public abstract class DefineCustomItemsEvent implements GeyserDefineCustomItemsEvent { +public abstract class GeyserDefineCustomItemsEventImpl implements GeyserDefineCustomItemsEvent { private final Multimap customItems; private final List nonVanillaCustomItems; - public DefineCustomItemsEvent(Multimap customItems, List nonVanillaCustomItems) { + public GeyserDefineCustomItemsEventImpl(Multimap customItems, List nonVanillaCustomItems) { this.customItems = customItems; this.nonVanillaCustomItems = nonVanillaCustomItems; } diff --git a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java index eaf29a819..04f80e19d 100644 --- a/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java +++ b/core/src/main/java/org/geysermc/geyser/extension/GeyserExtensionDescription.java @@ -33,7 +33,7 @@ import org.yaml.snakeyaml.Yaml; import java.io.Reader; import java.util.*; -public record GeyserExtensionDescription(String name, String main, String apiVersion, String version, List authors) implements ExtensionDescription { +public record GeyserExtensionDescription(String id, String name, String main, String apiVersion, String version, List authors) implements ExtensionDescription { @SuppressWarnings("unchecked") public static GeyserExtensionDescription fromYaml(Reader reader) throws InvalidDescriptionException { DumperOptions dumperOptions = new DumperOptions(); @@ -42,6 +42,11 @@ public record GeyserExtensionDescription(String name, String main, String apiVer Yaml yaml = new Yaml(dumperOptions); Map yamlMap = yaml.loadAs(reader, LinkedHashMap.class); + String id = ((String) yamlMap.get("id")).replaceAll("[^A-Za-z0-9 _.-]", ""); + if (id.isBlank()) { + throw new InvalidDescriptionException("Invalid extension id, cannot be empty"); + } + String name = ((String) yamlMap.get("name")).replaceAll("[^A-Za-z0-9 _.-]", ""); if (name.isBlank()) { throw new InvalidDescriptionException("Invalid extension name, cannot be empty"); @@ -72,6 +77,6 @@ public record GeyserExtensionDescription(String name, String main, String apiVer } } - return new GeyserExtensionDescription(name, main, apiVersion, version, authors); + return new GeyserExtensionDescription(id, name, main, apiVersion, version, Collections.unmodifiableList(authors)); } } diff --git a/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java b/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java new file mode 100644 index 000000000..4a7830c90 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/extension/command/GeyserExtensionCommand.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019-2022 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.geyser.extension.command; + +import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.command.GeyserCommand; + +public abstract class GeyserExtensionCommand extends GeyserCommand { + private final Extension extension; + + public GeyserExtensionCommand(Extension extension, String name, String description, String permission) { + super(name, description, permission); + + this.extension = extension; + } + + public Extension extension() { + return this.extension; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java index 449f6574e..e7837688c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java +++ b/core/src/main/java/org/geysermc/geyser/registry/loader/ProviderRegistryLoader.java @@ -26,7 +26,7 @@ package org.geysermc.geyser.registry.loader; import org.geysermc.geyser.api.command.Command; -import org.geysermc.geyser.api.command.CommandSource; +import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; @@ -43,10 +43,9 @@ import java.util.Map; */ public class ProviderRegistryLoader implements RegistryLoader, ProviderSupplier>, Map, ProviderSupplier>> { - @SuppressWarnings("unchecked") @Override public Map, ProviderSupplier> load(Map, ProviderSupplier> providers) { - providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Class) args[0])); + providers.put(Command.Builder.class, args -> new GeyserCommandManager.CommandBuilder<>((Extension) args[0])); providers.put(CustomItemData.Builder.class, args -> new GeyserCustomItemData.CustomItemDataBuilder()); providers.put(CustomItemOptions.Builder.class, args -> new GeyserCustomItemOptions.CustomItemOptionsBuilder()); providers.put(NonVanillaCustomItemData.Builder.class, args -> new GeyserNonVanillaCustomItemData.NonVanillaCustomItemDataBuilder()); diff --git a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java index e6d1cb3e4..60a16245c 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java +++ b/core/src/main/java/org/geysermc/geyser/registry/populator/ItemRegistryPopulator.java @@ -48,11 +48,10 @@ import it.unimi.dsi.fastutil.objects.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; -import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomItemsEvent; import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData; -import org.geysermc.geyser.event.type.DefineCustomItemsEvent; +import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl; import org.geysermc.geyser.inventory.item.StoredItemMappings; import org.geysermc.geyser.item.GeyserCustomMappingData; import org.geysermc.geyser.item.mappings.MappingsConfigReader; @@ -109,7 +108,7 @@ public class ItemRegistryPopulator { }); nonVanillaCustomItems = new ObjectArrayList<>(); - GeyserImpl.getInstance().eventBus().fire(new DefineCustomItemsEvent(customItems, nonVanillaCustomItems) { + GeyserImpl.getInstance().eventBus().fire(new GeyserDefineCustomItemsEventImpl(customItems, nonVanillaCustomItems) { @Override public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) { if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) {