.withRequirement being called once you tab complete for arguments
ImNotStable opened this issue · comments
Description
I'd like CommandAPI to call the withRequirement lambda once you try to tab complete the first position ("test", "toggle", etc.)
I found out instead it calls the lambda several times once you join.
Expected code
private final CommandTree command = new CommandTree("request")
.then(new LiteralArgument("test")
.executesPlayer((sender, args) -> {
sender.sendMessage(Component.text(QualityEconomyAPI.hasRequest(sender.getUniqueId())));
}))
.then(new LiteralArgument("toggle")
.executesPlayer(this::toggleRequests))
.then(new MultiLiteralArgument("answer", "accept", "deny")
.withRequirement(sender -> {
if (sender instanceof Player) sender.sendMessage(Component.text("GOOD"));
else sender.sendMessage(Component.text("BAD"));
return (sender instanceof Player player) && QualityEconomyAPI.hasRequest(player.getUniqueId());
})
.then(new PlayerArgument("target")
.replaceSuggestions(ArgumentSuggestions.strings(info -> {
if (info.sender() instanceof Player player && requests.containsKey(player.getUniqueId()))
return requests.get(player.getUniqueId()).keySet().stream().map(Bukkit::getOfflinePlayer).map(OfflinePlayer::getName).toArray(String[]::new);
return new String[0];
}))
.executesPlayer(this::answerRequest)))
.then(new LiteralArgument("send")
.then(new PlayerArgument("target")
.replaceSuggestions(CommandUtils.getOnlinePlayerSuggestion())
.then(new DoubleArgument("amount", Number.getMinimumValue())
.executesPlayer(this::request))));
Extra details
No response
This sounds like it is working as intended. In vanilla, the client never asks the server which commands it can access. Instead, when the player joins, the server will figure out which commands they can access based on the requirements. This means that the server only needs to tell the client about the commands that they can access, so less information needs to be sent over the network.
If the requirements for your command change, you can trigger the server to resend commands to the player by calling Player#updateCommands
or CommandAPI#updateRequirements
. This is described in the documentation here: https://commandapi.jorel.dev/9.3.0/requirements.html#updating-requirements.
So how can I update the list of acceptable arguments when they tab complete the suggestions?
You probably want to call Player#updateCommands
or CommandAPI#updateRequirements
whenever the information being accessed by QualityEconomyAPI.hasRequest(player.getUniqueId())
(as seen in your code's call to withRequirement
) changes.
I don't know how your system is structured, but from a quick look at your repo (which might be out of date compared to your current code), I think you would need to expand on these lines:
requests.computeIfAbsent(requesteeUUID, uuid -> new HashMap<>()).put(requesterUUID, amount);
Bukkit.getScheduler().runTaskLater(QualityEconomy.getInstance(), () -> requests.get(requesteeUUID).remove(requesterUUID, amount), 1200);
To properly update the requestee
client on whether or not they are able to access the answer
, accept
, and deny
multiliteral, you can do something like this:
requests.computeIfAbsent(requesteeUUID, uuid -> new HashMap<>()).put(requesterUUID, amount);
CommandAPI.updateRequirements(requestee);
Bukkit.getScheduler().runTaskLater(QualityEconomy.getInstance(), () -> {
requests.get(requesteeUUID).remove(requesterUUID, amount);
CommandAPI.updateRequirements(requestee);
}, 1200);
Whenever a player gains or loses a request, the result returned by QualityEconomyAPI#hasRequest
in the call to withRequirement
might change, so you should call CommandAPI#updateRequriements
or Player#updateCommands
to reevaluate the requirements.
Thank you for the help!