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);