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

Add miscellaneous argument type 'World'

lokka30 opened this issue · comments

Description

Allows us to select world names, such as:

  • /kill @e[type=creeper] my_cool_world

..where my_cool_world is a world loaded on the server.

Can also be used as a list:

  • /kill @e[type=creeper] my_cool_world world world_nether world_the_end resource_world

Expected code

No response

Extra details

No response

Funnily enough, the World argument is used as an example in the documentation for making custom arguments:
https://commandapi.jorel.dev/8.5.1/customarguments.html?highlight=World,argumen#example---world-argument

// Function that returns our custom argument
public Argument<World> worldArgument(String nodeName) {
    
    // Construct our CustomArgument that takes in a String input and returns a World object
    return new CustomArgument<World, String>(new StringArgument(nodeName), info -> {
        // Parse the world from our input
        World world = Bukkit.getWorld(info.input());
    
        if(world == null) {
            throw new CustomArgumentException(new MessageBuilder("Unknown world: ").appendArgInput());
        } else {
            return world;
        }
    }).replaceSuggestions(ArgumentSuggestions.strings(info -> 
        // List of world names on the server
        Bukkit.getWorlds().stream().map(World::getName).toArray(String[]::new))
    );
}

In the meantime, that should work for your use, but I agree, an official WorldArgument might be a nice addition to the CommandAPI.

On the point of having a list of worlds, if you want to do that right now, you could create a ListArgument (see https://commandapi.jorel.dev/8.5.1/listarguments.html for how to do that).

Brilliant! Thanks so much @willkroboth. This ought to be the best documented library I have come across.

In case context is useful for the addition of this feature, I am writing a 'Kill' command for LevelledMobs, /lm kill <entity target> <world list>. Unfortunately Minecraft does not have a world name attribute which can be used in the selector for the entities, e.g., @e[world=world_the_end], only dimensions (minecraft:nether).

Unfortunately the current workaround doesn't seem to work on load: STARTUP plugins, nor on worlds which have been loaded after the plugin's commands were registered.
I have tried a workaround where I have replaced the suggestions with a list of worlds which are queried async, of course this hasn't resolved the issue since the list of allowed list values have not been modified.
For now, I will make it use a string list argument and parse worlds manually. 🙂

As mentioned in #365, the CommandAPI will only be accepting "custom argument implementations" that satisfy the following points:

  • The custom argument is an implementation of a Vanilla Minecraft argument type that is specified in Argument types.
  • The custom argument implementation heavily requires the use of Brigadier or NMS.

The World Argument requested in this issue can already be implemented without the use of Brigadier/NMS by using the CustomArgument class, using a base argument of a StringArgument for a single world, or a ListArgument for multiple worlds. In 8.6.0, this will be improved with the new TextArgument backed ListArgument (see #351) which would let you use such an argument anywhere in the query (instead of just at the end)


Making use of the synchronous argument suggestions should work regardless of load: STARTUP plugins and regardless of whether a world has been loaded after the plugin's commands have been registered (note the info -> in the example below):

.replaceSuggestions(ArgumentSuggestions.strings(info -> 
    // List of world names on the server
    Bukkit.getWorlds().stream().map(World::getName).toArray(String[]::new))
);

Using asynchronous world suggestions is not recommended as asynchronous queries should not be accessing the Bukkit API.

Thanks, no worries :)

After a quick chat with a member from the CommandAPI Discord server, I've discovered that the CommandAPI's implementation of Minecraft's DimensionArgument is terrible and doesn't do what it is supposed to!

Scheduling the implementation of a DimensionArgument for CommandAPI 8.6.0 which will do pretty much exactly what you would expect - it returns a Bukkit World object.

Implemented in release 8.6.0.