-
Notifications
You must be signed in to change notification settings - Fork 29
Context Providers
Sometimes a command needs more context than just the arguments the player passed. And sometimes this results in a lot of needlessly copy-pasted code. For example, you might need to get the item the player is holding. You would need to retrieve this, ensure it's not null, and send the player a message if it is. Command manager saves you from having to do that.
Similarly to ArgType
, you can create a ContextProvider
which will provide that context and send an error message if it's not available. Let's assume you need to get the team the player is on, and you have a Team
class already made:
ContextProvider<Team> teamProvider = new ContextProvider<>("team",
ChatColor.RED + "You are not on a team!",
Team::getTeam);
The first argument there is the name of the context provider. The second is the error message that will be shown to players if the ContextProvider
returns null, and the third is a Function<Player, T>
with T
being the type being provided. Note that it takes a Player
, meaning commands that use context providers may only be run by players. Now that you've created a ContextProvider
, you have to register it with the CommandParser
, just like ArgType
:
new CommandParser(this.getResource("command.rdcml"))
.setContextProviders(teamProvider)
.parse().register("prefix", this);
And once you've done that, you're ready to specify it in your command file:
tchat string...:message {
help Sends a message to your team
user player
context team
hook tchat
}
After specifying it in the command file, you can take it as an argument in your command hook:
@CommandHook("tchat")
public void teamChat(Player sender, String message, Team team) {
team.broadcast(sender.getName() + ": " + message);
}
You must always take all context arguments after all command arguments. You can use multiple context arguments in a single command by simply separating them with a space, then taking them in the same order you listed them in your command hook method. If Team.getTeam(sender)
returns null, then the command hook method will not be called, and the player will be shown the ContextProvider
's error message instead.
Sometimes, though, you just want to make sure that a condition is true before the command can be run. An example is that you might want to ensure a player is within a certain area when running the command, or has a certain item in their inventory. However, you don't actually need to do anything with this data after ensuring its presence. If you wanted to ensure that the player is on a team, but don't need to do anything with the Team
object, you can use the assert
tag instead of context
in your command file:
commandname {
hook hookname
assert team
}
Now, the command manager will ensure that the Team
context provider doesn't return null before executing your method hook. If it is null, the player will be shown the error message in the context provider. Since you're asserting this condition rather than requesting it as context, you don't need to take it as an argument in your command hook method.
A helpful method for creating ContextProvider
s which are mainly intended for assertion is ContextProvider.assertProvider
. It takes a name and a Predicate<Player>
, and spits out a ContextProvider<Player, Boolean>
which will return true if the condition passes, and null otherwise. If you wanted to ensure a player is above Y=100 when running your command, you could create a ContextProvider
like this:
ContextProvider.assertProvider("altitude", p -> p.getLocation().getY() > 100);
The last way that context providers can be used is to supply default values for optional arguments. By default, there is one context provider included called self
, which will reference the player who ran the command. This is only useful for this case:
give player:target?(context self) int:amount?(1) {
help Gives you the coolest item
hook give
}
Here, the target will be assumed to be the command sender if it is not passed. If this command is run from console and the target
argument is not supplied, console will be shown an error stating that it must be provided, since context providers can only be used for players.