ScriptCraft

ScriptCraft

14.6k Downloads

Can't register new commands!

spacefluff432 opened this issue ยท 4 comments

commented

Annoyingly, the bukkit developers decided to make org.bukkit.command.Command a protected class. See "Constructor Summary" at the following URL: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/command/Command.html

It would be nice if we could register commands from within the game, like so:

// generate a new commandMap
var commandMap = new org.bukkit.command.SimpleCommandMap(server);

// generate a new command (currently impossible)
var command = new org.bukkit.command.Command('command');

// register the command to our commandMap
commandMap.register('plugin', command);

// add listener for command execution
command.on('execute', function (player, args) {
    return 'Your username is ' + player.name + ' and you typed ' + args;
});

// tab-completer
command.on('tab', function (player, args) => {
    if (args.join(' ') === 'secret completions are') {
        return [
            "I'm a tab completion!",
            "And I'm a tab completion!",
            "Oh, and I'm a tab completion!"
        ]
    }
});

The resulting commands registered would be:
/command
/plugin:command

commented

The alternative is to build the jar with a custom class that can create new commands, like AbstractCommand by Goblom: https://github.com/Goblom/Bukkit-Libraries/blob/master/src/main/java/command/AbstractCommand.java

commented

In the past 2 years, I've tried countless times to crack this issue, and I've finally done it. The following code must be ran at plugin load time to work properly.

const Command = Java.extend(org.bukkit.command.Command);

const commandMap = server.getClass().getDeclaredField('commandMap');
commandMap.setAccessible(true);
const registry = commandMap.get(server);

registry.register(
   'prefix',
   new Command('test', {
      execute: (...args) => {
         console.log(...args);
         console.log('hello world');
         return true;
      },
      tabComplete: (...args) => {
         console.log(...args);
         return [ 'tab 1', 'tab 2', 'tab 3' ];
      }
   })
);

This script will add the commands /test and /prefix:test to the server.

commented

Don't "new" an abstract class. Get an instance of one of the concrete classes that already derives from that base. If they are inadequate, just inherit from one of them and add your own customizations, or derive a new class from Command and copy in details as required. For your purposes, look for examples for instantiating from class PluginCommand -- that's the one you want. This thread should be helpful.
https://bukkit.org/threads/tutorial-registering-commands-at-runtime.158461/

If you receive an object of type Command, that's just means the object must be from a class that derives from Command, and it is guaranteed to support the abstract class members. But it won't be an instance of 'Command'. When you receive an object of type Command, decide what it is and then cast it so that you can work with it properly. Again, in your case you should be receiving a PluginCommand to your event handler.

I'm getting the feeling that I am misunderstanding your intent. Do you want to create a command outside of initialization, like a dynamic command that changes depending on what you're doing?

commented

The desired effect of this code is to have custom commands executable and tab-completable, meaning when somebody types them in, they can be tab-completed and executed based on input.

That code produces the desired effect. That's what my intent is