JorelAli / CommandAPI

A Bukkit/Spigot API for the command UI introduced in Minecraft 1.13

Home Page:https://commandapi.jorel.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CommandAPI's `NativeProxyCommandSender` cannot run vanilla commands

willkroboth opened this issue · comments

CommandAPI version

9.0.4-SNAPSHOT

Minecraft version

1.20.1

Are you shading the CommandAPI?

Yes

What I did

I registered this test command in onEnable:

new CommandAPICommand("test")
        .executesNative((sender, args) -> {
            Bukkit.dispatchCommand(sender, "say Hello");
        })
        .register();

Run the test command

What actually happened

This exception is thrown (running the command as console - similar exceptions happen for other CommandSender):

[Server thread/ERROR]: Unhandled exception executing '/test'
org.bukkit.command.CommandException: Unhandled exception executing 'say Hello' in org.bukkit.craftbukkit.v1_20_R1.command.VanillaCommandWrapper(say)
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:156) ~[spigot-api-1.20.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.craftbukkit.v1_20_R1.CraftServer.dispatchCommand(CraftServer.java:875) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at org.bukkit.Bukkit.dispatchCommand(Bukkit.java:884) ~[spigot-api-1.20.1-R0.1-SNAPSHOT.jar:?]
        at me.willkroboth.CommandAPITest.Main.lambda$onEnable$0(Main.java:24) ~[?:?]
        at me.willkroboth.CommandAPITest.commandapi.executors.NativeCommandExecutor.run(NativeCommandExecutor.java:49) ~[?:?]
        at me.willkroboth.CommandAPITest.commandapi.executors.NormalExecutor.executeWith(NormalExecutor.java:44) ~[?:?]
        at me.willkroboth.CommandAPITest.commandapi.CommandAPIExecutor.execute(CommandAPIExecutor.java:138) ~[?:?]
        at me.willkroboth.CommandAPITest.commandapi.CommandAPIExecutor.execute(CommandAPIExecutor.java:113) ~[?:?]
        at me.willkroboth.CommandAPITest.commandapi.CommandAPIExecutor.execute(CommandAPIExecutor.java:96) ~[?:?]
        at me.willkroboth.CommandAPITest.commandapi.CommandAPIHandler.lambda$generateCommand$0(CommandAPIHandler.java:258) ~[?:?]
        at com.mojang.brigadier.CommandDispatcher.execute(CommandDispatcher.java:265) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:?]
        at net.minecraft.commands.CommandDispatcher.performCommand(CommandDispatcher.java:314) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at net.minecraft.commands.CommandDispatcher.performPrefixedCommand(CommandDispatcher.java:293) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at org.bukkit.craftbukkit.v1_20_R1.command.VanillaCommandWrapper.execute(VanillaCommandWrapper.java:45) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.20.1-R0.1-SNAPSHOT.jar:?]
        at org.bukkit.craftbukkit.v1_20_R1.CraftServer.dispatchCommand(CraftServer.java:875) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at org.bukkit.craftbukkit.v1_20_R1.CraftServer.dispatchServerCommand(CraftServer.java:860) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at net.minecraft.server.dedicated.DedicatedServer.bf(DedicatedServer.java:413) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at net.minecraft.server.dedicated.DedicatedServer.b(DedicatedServer.java:389) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at net.minecraft.server.MinecraftServer.a(MinecraftServer.java:1198) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:1015) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at net.minecraft.server.MinecraftServer.lambda$0(MinecraftServer.java:304) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: java.lang.ClassCastException: class me.willkroboth.CommandAPITest.commandapi.wrappers.NativeProxyCommandSender cannot be cast to class org.bukkit.craftbukkit.v1_20_R1.command.ProxiedNativeCommandSender (me.willkroboth.CommandAPITest.commandapi.wrappers.NativeProxyCommandSender is in unnamed module of loader org.bukkit.plugin.java.PluginClassLoader @5b499bce; org.bukkit.craftbukkit.v1_20_R1.command.ProxiedNativeCommandSender is in unnamed module of loader java.net.URLClassLoader @2e5d6d97)
        at org.bukkit.craftbukkit.v1_20_R1.command.VanillaCommandWrapper.getListener(VanillaCommandWrapper.java:83) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at org.bukkit.craftbukkit.v1_20_R1.command.VanillaCommandWrapper.execute(VanillaCommandWrapper.java:44) ~[spigot-1.20.1-R0.1-SNAPSHOT.jar:3838-Spigot-3374045-a2fafdd]
        at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-api-1.20.1-R0.1-SNAPSHOT.jar:?]
        ... 22 more
[Server thread/INFO]: An unexpected error occurred trying to execute that command

What should have happened

The Vanilla say command should have been executed without an exception.

Server logs and CommandAPI config

No response

Other

The exception is thrown by VanillaCommandWrapper#getListener:

public static CommandListenerWrapper getListener(CommandSender sender) {
    if (sender instanceof Player) {
        return ((CraftPlayer) sender).getHandle().createCommandSourceStack();
    }
    if (sender instanceof BlockCommandSender) {
        return ((CraftBlockCommandSender) sender).getWrapper();
    }
    if (sender instanceof CommandMinecart) {
        return ((EntityMinecartCommandBlock) ((CraftMinecartCommand) sender).getHandle()).getCommandBlock().createCommandSourceStack();
    }
    if (sender instanceof RemoteConsoleCommandSender) {
        return ((DedicatedServer) MinecraftServer.getServer()).rconConsoleSource.createCommandSourceStack();
    }
    if (sender instanceof ConsoleCommandSender) {
        return ((CraftServer) sender.getServer()).getServer().createCommandSourceStack();
    }
    if (sender instanceof ProxiedCommandSender) {
        return ((ProxiedNativeCommandSender) sender).getHandle();
    }

    throw new IllegalArgumentException("Cannot make " + sender + " a vanilla command listener");
}

Specifically, the exception is thrown when an instance of the CommandAPI's NativeProxyCommandSender is passed into this method. The test command here replicates this by using executesNative to get a NativeProxyCommandSender, and runs the Vanilla say command, which is handled by the VanillaCommandWrapper.

Since NativeProxyCommandSender extends ProxiedCommandSender, it passes into the last if-statement. That code assumes the sender is an org.bukkit.craftbukkit.v1_20_R1.command.ProxiedNativeCommandSender and casts it as such. This cast fails, and the ClassCastException is thrown.

This is not a Spigot bug. As SPIGOT-7023 states specifically for CommandSender, classes in the Bukkit API are generally not designed to be implemented, and any bugs resulting from doing so will be disregarded. This bug happens because the CommandAPI tried to implement the org.bukkit.command.ProxiedCommandSender class, which is not supported.

While Bukkit does not support this situation, it can be worked around. If the CommandAPI's NativeProxyCommandSender extended ProxiedNativeCommandSender, then VanillaCommandWrapper would work as expected. Unfortunately, ProxiedNativeCommandSender is a version-specific CraftBukkit class, so making this work is not trivial. However, it should be possible to make this work, and personally, I have successfully implemented something similar before.