diff --git a/src/main/java/ch/njol/skript/command/CommandUsage.java b/src/main/java/ch/njol/skript/command/CommandUsage.java new file mode 100644 index 00000000000..59b79765604 --- /dev/null +++ b/src/main/java/ch/njol/skript/command/CommandUsage.java @@ -0,0 +1,85 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * Copyright Peter Güttinger, SkriptLang team and contributors + */ +package ch.njol.skript.command; + +import ch.njol.skript.lang.VariableString; +import ch.njol.skript.util.Utils; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +/** + * Holds info about the usage of a command. + * TODO: replace with record when java 17 + */ +public class CommandUsage { + + /** + * A dynamic usage message that can contain expressions. + */ + private final VariableString usage; + + /** + * A fallback usage message that can be used in non-event environments, + * like when registering the Bukkit command. + */ + private final String defaultUsage; + + /** + * @param usage The dynamic usage message, can contain expressions. + * @param defaultUsage A fallback usage message for use in non-event environments. + */ + public CommandUsage(@Nullable VariableString usage, String defaultUsage) { + if (usage == null) { + usage = VariableString.newInstance(defaultUsage); + assert usage != null; + } + this.usage = usage; + this.defaultUsage = Utils.replaceChatStyles(defaultUsage); + } + + /** + * @return The usage message as a {@link VariableString}. + */ + public VariableString getRawUsage() { + return usage; + } + /** + * Get the usage message without an event to evaluate it. + * @return The evaluated usage message. + */ + public String getUsage() { + return getUsage(null); + } + + /** + * @param event The event used to evaluate the usage message. + * @return The evaluated usage message. + */ + public String getUsage(@Nullable Event event) { + if (event != null || usage.isSimple()) + return usage.toString(event); + return defaultUsage; + } + + @Override + public String toString() { + return getUsage(); + } + +} diff --git a/src/main/java/ch/njol/skript/command/ScriptCommand.java b/src/main/java/ch/njol/skript/command/ScriptCommand.java index 05d01680cc3..b82b204eb99 100644 --- a/src/main/java/ch/njol/skript/command/ScriptCommand.java +++ b/src/main/java/ch/njol/skript/command/ScriptCommand.java @@ -101,7 +101,7 @@ public class ScriptCommand implements TabExecutor { private final String cooldownBypass; @Nullable private final Expression cooldownStorage; - final String usage; + final CommandUsage usage; private final Trigger trigger; @@ -115,11 +115,13 @@ public class ScriptCommand implements TabExecutor { private Map lastUsageMap = new HashMap<>(); + // /** - * Creates a new SkriptCommand. + * Creates a new ScriptCommand. + * Prefer using the CommandUsage class for the usage parameter. * * @param name /name - * @param pattern + * @param pattern the Skript pattern used to parse the input into arguments. * @param arguments the list of Arguments this command takes * @param description description to display in /help * @param prefix the prefix of the command @@ -135,6 +137,33 @@ public ScriptCommand( String permission, @Nullable VariableString permissionMessage, @Nullable Timespan cooldown, @Nullable VariableString cooldownMessage, String cooldownBypass, @Nullable VariableString cooldownStorage, int executableBy, SectionNode node + ) { + this(script, name, pattern, arguments, description, prefix, new CommandUsage(null, usage), + aliases, permission, permissionMessage, cooldown, cooldownMessage, cooldownBypass, + cooldownStorage, executableBy, node); + } + // + + /** + * Creates a new ScriptCommand. + * + * @param name /name + * @param pattern the Skript pattern used to parse the input into arguments. + * @param arguments the list of Arguments this command takes + * @param description description to display in /help + * @param prefix the prefix of the command + * @param usage message to display if the command was used incorrectly + * @param aliases /alias1, /alias2, ... + * @param permission permission or null if none + * @param permissionMessage message to display if the player doesn't have the given permission + * @param node the node to parse and load into a Trigger + */ + public ScriptCommand( + Script script, String name, String pattern, List> arguments, + String description, @Nullable String prefix, CommandUsage usage, List aliases, + String permission, @Nullable VariableString permissionMessage, @Nullable Timespan cooldown, + @Nullable VariableString cooldownMessage, String cooldownBypass, + @Nullable VariableString cooldownStorage, int executableBy, SectionNode node ) { Validate.notNull(name, pattern, arguments, description, usage, aliases, node); this.name = name; @@ -180,7 +209,7 @@ public ScriptCommand( activeAliases = new ArrayList<>(aliases); this.description = Utils.replaceEnglishChatStyles(description); - this.usage = Utils.replaceEnglishChatStyles(usage); + this.usage = usage; this.executableBy = executableBy; @@ -205,7 +234,7 @@ private PluginCommand setupBukkitCommand() { // We can only set the message if it's simple (doesn't contains expressions) if (permissionMessage.isSimple()) bukkitCommand.setPermissionMessage(permissionMessage.toString(null)); - bukkitCommand.setUsage(usage); + bukkitCommand.setUsage(usage.getUsage()); bukkitCommand.setExecutor(this); return bukkitCommand; } catch (final Exception e) { @@ -300,7 +329,7 @@ boolean execute2(final ScriptCommandEvent event, final CommandSender sender, fin final LogEntry e = log.getError(); if (e != null) sender.sendMessage(ChatColor.DARK_RED + e.toString()); - sender.sendMessage(usage); + sender.sendMessage(usage.getUsage(event)); log.clear(); return false; } @@ -342,7 +371,7 @@ public boolean checkPermissions(CommandSender sender, Event event) { public void sendHelp(final CommandSender sender) { if (!description.isEmpty()) sender.sendMessage(description); - sender.sendMessage(ChatColor.GOLD + "Usage" + ChatColor.RESET + ": " + usage); + sender.sendMessage(ChatColor.GOLD + "Usage" + ChatColor.RESET + ": " + usage.getUsage()); } /** diff --git a/src/main/java/ch/njol/skript/structures/StructCommand.java b/src/main/java/ch/njol/skript/structures/StructCommand.java index cf2dc234276..12a0314b224 100644 --- a/src/main/java/ch/njol/skript/structures/StructCommand.java +++ b/src/main/java/ch/njol/skript/structures/StructCommand.java @@ -24,6 +24,7 @@ import ch.njol.skript.classes.ClassInfo; import ch.njol.skript.classes.Parser; import ch.njol.skript.command.Argument; +import ch.njol.skript.command.CommandUsage; import ch.njol.skript.command.Commands; import ch.njol.skript.command.ScriptCommand; import ch.njol.skript.command.ScriptCommandEvent; @@ -92,7 +93,7 @@ public class StructCommand extends Structure { Skript.registerStructure( StructCommand.class, EntryValidator.builder() - .addEntry("usage", null, true) + .addEntryData(new VariableStringEntryData("usage", null, true)) .addEntry("description", "", true) .addEntry("prefix", null, true) .addEntry("permission", "", true) @@ -261,10 +262,9 @@ public boolean load() { }); desc = Commands.unescape(desc).trim(); - String usage = entryContainer.getOptional("usage", String.class, false); - if (usage == null) { - usage = Commands.m_correct_usage + " " + desc; - } + VariableString usageMessage = entryContainer.getOptional("usage", VariableString.class, false); + String defaultUsageMessage = Commands.m_correct_usage + " " + desc; + CommandUsage usage = new CommandUsage(usageMessage, defaultUsageMessage); String description = entryContainer.get("description", String.class, true); String prefix = entryContainer.getOptional("prefix", String.class, false);