diff --git a/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandHelpers.java b/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandHelpers.java new file mode 100644 index 000000000..85c8fb0cb --- /dev/null +++ b/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandHelpers.java @@ -0,0 +1,106 @@ +package vg.civcraft.mc.civmodcore.commands; + +import co.aikar.commands.CommandCompletions; +import co.aikar.commands.CommandContexts; +import co.aikar.commands.InvalidCommandArgument; +import java.util.Arrays; +import java.util.List; +import org.bukkit.Material; +import org.bukkit.command.ConsoleCommandSender; +import org.jetbrains.annotations.NotNull; +import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils; + +/** + * This is a separate helper class that allows plugins to use ACF without needing to commit to {@link CommandManager} + * to get all the additional features it provides. It also allows some degree of optimisation since not all plugins + * need their own item-material completions (like CivChat2). + */ +public final class CommandHelpers { + /** + * ACF has an automatic help generator, but it's currently considered an unstable API. + * Read more. + * + *
+ * // Somewhere in your plugin enable process
+ * CommandHelpers.enableCommandHelp(this.commandManager);
+ *
+ * // Example Command
+ * @CommandAlias("example")
+ * public class ExampleCommand extends BaseCommand {
+ * @Default
+ * public void showHelp(final @NotNull Player sender) {
+ * throw new ShowCommandHelp(); // Sends a help page to the player
+ * }
+ * }
+ *
+ */
+ @SuppressWarnings("deprecation")
+ public static void enableCommandHelp(
+ final @NotNull co.aikar.commands.CommandManager, ?, ?, ?, ?, ?> manager
+ ) {
+ manager.enableUnstableAPI("help");
+ }
+
+ // ============================================================
+ // Completions
+ // ============================================================
+
+ /**
+ * ACF already has the "@nothing" completion, but that seems less intuitive than "@none", so this adds "@none".
+ */
+ public static void registerNoneCompletion(
+ final @NotNull CommandCompletions> completions
+ ) {
+ completions.registerStaticCompletion(
+ "none",
+ List.of()
+ );
+ }
+
+ /**
+ * Completion for all Bukkit materials.
+ */
+ public static void registerMaterialsCompletion(
+ final @NotNull CommandCompletions> completions
+ ) {
+ completions.registerStaticCompletion(
+ "materials",
+ Arrays.stream(Material.values())
+ .map(Enum::name)
+ .toList()
+ );
+ }
+
+ /**
+ * Completion for all Bukkit materials that are items, excluding Air.
+ */
+ public static void registerItemMaterialsCompletion(
+ final @NotNull CommandCompletions> completions
+ ) {
+ completions.registerStaticCompletion(
+ "itemMaterials",
+ Arrays.stream(Material.values())
+ .filter(ItemUtils::isValidItemMaterial)
+ .map(Enum::name)
+ .toList()
+ );
+ }
+
+ // ============================================================
+ // Contexts
+ // ============================================================
+
+ /**
+ * Registers a context that requires the command-sender to be the console.
+ */
+ public static void registerConsoleSenderContext(
+ final @NotNull CommandContexts> contexts
+ ) {
+ contexts.registerIssuerAwareContext(ConsoleCommandSender.class, (context) -> {
+ if (context.getIssuer().getIssuer() instanceof final ConsoleCommandSender console) {
+ return console;
+ }
+ throw new InvalidCommandArgument("Command can only be called from console!", false);
+ });
+ }
+}
diff --git a/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandManager.java b/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandManager.java
index 9ddec6910..603b920cf 100644
--- a/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandManager.java
+++ b/plugins/civmodcore-paper/src/main/java/vg/civcraft/mc/civmodcore/commands/CommandManager.java
@@ -8,36 +8,34 @@ import co.aikar.commands.CommandCompletions;
import co.aikar.commands.CommandCompletions.CommandCompletionHandler;
import co.aikar.commands.CommandContexts;
import com.google.common.base.Strings;
-
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.logging.Level;
import javax.annotation.Nonnull;
-
import org.apache.commons.lang3.reflect.FieldUtils;
import org.bukkit.Bukkit;
-import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.plugin.Plugin;
-import vg.civcraft.mc.civmodcore.inventory.items.ItemUtils;
import vg.civcraft.mc.civmodcore.utilities.CivLogger;
/**
* Command registration class wrapper around {@link BukkitCommandManager}.
*/
public class CommandManager extends BukkitCommandManager {
-
- // allMaterials and itemMaterials won't change over a run, so autocomplete lists can be prebuilt globally.
- private final static List