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.