diff --git a/eco-api/src/main/java/com/willfp/eco/core/Eco.java b/eco-api/src/main/java/com/willfp/eco/core/Eco.java index 2b9276c9..e5d43261 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/Eco.java +++ b/eco-api/src/main/java/com/willfp/eco/core/Eco.java @@ -498,6 +498,11 @@ public interface Eco { @Nullable Menu getOpenMenu(@NotNull Player player); + /** + * Sync commands. + */ + void syncCommands(); + /** * Get the instance of eco; the bridge between the api frontend * and the implementation backend. diff --git a/eco-api/src/main/java/com/willfp/eco/core/command/impl/DelegatedBukkitCommand.java b/eco-api/src/main/java/com/willfp/eco/core/command/impl/DelegatedBukkitCommand.java new file mode 100644 index 00000000..3c0a630f --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/command/impl/DelegatedBukkitCommand.java @@ -0,0 +1,44 @@ +package com.willfp.eco.core.command.impl; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Delegates a bukkit command to an eco command (for registrations). + */ +public final class DelegatedBukkitCommand extends Command implements TabCompleter { + /** + * The delegate command. + */ + private final PluginCommand delegate; + + /** + * Create a new delegated command. + * + * @param delegate The delegate. + */ + public DelegatedBukkitCommand(@NotNull final PluginCommand delegate) { + super(delegate.getName()); + + this.delegate = delegate; + } + + @Override + public boolean execute(@NotNull final CommandSender commandSender, + @NotNull final String label, + @NotNull final String[] args) { + return delegate.onCommand(commandSender, this, label, args); + } + + @Override + public List onTabComplete(@NotNull final CommandSender commandSender, + @NotNull final Command command, + @NotNull final String label, + @NotNull final String[] args) { + return delegate.onTabComplete(commandSender, command, label, args); + } +} diff --git a/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java b/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java index 43f818a4..528c0710 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java +++ b/eco-api/src/main/java/com/willfp/eco/core/command/impl/PluginCommand.java @@ -1,14 +1,17 @@ package com.willfp.eco.core.command.impl; +import com.willfp.eco.core.Eco; import com.willfp.eco.core.EcoPlugin; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; import org.bukkit.command.TabCompleter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.lang.reflect.Field; import java.util.List; /** @@ -43,9 +46,21 @@ public abstract class PluginCommand extends HandledCommand implements CommandExe */ public final void register() { org.bukkit.command.PluginCommand command = Bukkit.getPluginCommand(this.getName()); - assert command != null; - command.setExecutor(this); - command.setTabCompleter(this); + if (command != null) { + command.setExecutor(this); + command.setTabCompleter(this); + } else { + CommandMap commandMap = getCommandMap(); + + Command bukkit = commandMap.getCommand(this.getName()); + if (bukkit != null) { + bukkit.unregister(commandMap); + } + + commandMap.register(this.getName(), new DelegatedBukkitCommand(this)); + + Eco.get().syncCommands(); + } } /** @@ -93,4 +108,19 @@ public abstract class PluginCommand extends HandledCommand implements CommandExe return this.handleTabCompletion(sender, args); } + + /** + * Get the internal server CommandMap. + * + * @return The CommandMap. + */ + public static CommandMap getCommandMap() { + try { + Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + field.setAccessible(true); + return (CommandMap) field.get(Bukkit.getServer()); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new NullPointerException("Command map wasn't found!"); + } + } } diff --git a/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/SyncCommands.kt b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/SyncCommands.kt new file mode 100644 index 00000000..82ff7007 --- /dev/null +++ b/eco-core/core-nms/v1_17_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_17_R1/SyncCommands.kt @@ -0,0 +1,14 @@ +package com.willfp.eco.internal.spigot.proxy.v1_17_R1 + +import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_17_R1.CraftServer + +class SyncCommands : SyncCommandsProxy { + override fun syncCommands() { + (Bukkit.getServer() as CraftServer).syncCommands() + for (player in Bukkit.getOnlinePlayers()) { + player.updateCommands() + } + } +} diff --git a/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/SyncCommands.kt b/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/SyncCommands.kt new file mode 100644 index 00000000..cd770b92 --- /dev/null +++ b/eco-core/core-nms/v1_18_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R1/SyncCommands.kt @@ -0,0 +1,14 @@ +package com.willfp.eco.internal.spigot.proxy.v1_18_R1 + +import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_18_R1.CraftServer + +class SyncCommands : SyncCommandsProxy { + override fun syncCommands() { + (Bukkit.getServer() as CraftServer).syncCommands() + for (player in Bukkit.getOnlinePlayers()) { + player.updateCommands() + } + } +} diff --git a/eco-core/core-nms/v1_18_R2/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R2/SyncCommands.kt b/eco-core/core-nms/v1_18_R2/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R2/SyncCommands.kt new file mode 100644 index 00000000..8cedf493 --- /dev/null +++ b/eco-core/core-nms/v1_18_R2/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_18_R2/SyncCommands.kt @@ -0,0 +1,14 @@ +package com.willfp.eco.internal.spigot.proxy.v1_18_R2 + +import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_18_R2.CraftServer + +class SyncCommands : SyncCommandsProxy { + override fun syncCommands() { + (Bukkit.getServer() as CraftServer).syncCommands() + for (player in Bukkit.getOnlinePlayers()) { + player.updateCommands() + } + } +} diff --git a/eco-core/core-nms/v1_19_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_19_R1/SyncCommands.kt b/eco-core/core-nms/v1_19_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_19_R1/SyncCommands.kt new file mode 100644 index 00000000..e2eb1dae --- /dev/null +++ b/eco-core/core-nms/v1_19_R1/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/v1_19_R1/SyncCommands.kt @@ -0,0 +1,14 @@ +package com.willfp.eco.internal.spigot.proxy.v1_19_R1 + +import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.v1_19_R1.CraftServer + +class SyncCommands : SyncCommandsProxy { + override fun syncCommands() { + (Bukkit.getServer() as CraftServer).syncCommands() + for (player in Bukkit.getOnlinePlayers()) { + player.updateCommands() + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt index 05c80008..ea4465db 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoImpl.kt @@ -50,6 +50,7 @@ import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy import com.willfp.eco.internal.spigot.proxy.MiniMessageTranslatorProxy import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy import com.willfp.eco.internal.spigot.proxy.SkullProxy +import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy import com.willfp.eco.internal.spigot.proxy.TPSProxy import org.bukkit.Location import org.bukkit.NamespacedKey @@ -282,4 +283,7 @@ class EcoImpl : EcoSpigotPlugin(), Eco { override fun getOpenMenu(player: Player) = player.renderedInventory?.menu + + override fun syncCommands() = + this.getProxy(SyncCommandsProxy::class.java).syncCommands() } diff --git a/eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/SyncCommandsProxy.kt b/eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/SyncCommandsProxy.kt new file mode 100644 index 00000000..7f552c77 --- /dev/null +++ b/eco-core/core-proxy/src/main/kotlin/com/willfp/eco/internal/spigot/proxy/SyncCommandsProxy.kt @@ -0,0 +1,5 @@ +package com.willfp.eco.internal.spigot.proxy + +interface SyncCommandsProxy { + fun syncCommands() +}