diff --git a/common/api/core/src/main/java/com/dfsek/terra/api/command/RegistryArgument.java b/common/api/core/src/main/java/com/dfsek/terra/api/command/RegistryArgument.java index 331413b48..cbf4047d8 100644 --- a/common/api/core/src/main/java/com/dfsek/terra/api/command/RegistryArgument.java +++ b/common/api/core/src/main/java/com/dfsek/terra/api/command/RegistryArgument.java @@ -46,12 +46,24 @@ public class RegistryArgument extends CommandArgument { return new Builder<>(name, registry); } + public static CommandArgument of(String name, Registry registry) { + return RegistryArgument.builder(name, registry).build(); + } + + public static CommandArgument optional(String name, Registry registry) { + return RegistryArgument.builder(name, registry).asOptional().build(); + } + + public static CommandArgument optional(String name, Registry registry, String defaultKey) { + return RegistryArgument.builder(name, registry).asOptionalWithDefault(defaultKey).build(); + } + public static final class Builder extends CommandArgument.Builder { private final Registry registry; @SuppressWarnings("unchecked") private Builder(@NonNull String name, Registry registry) { - super((TypeToken) registry.getType().getType(), name); + super((TypeToken) TypeToken.get(registry.getType().getType()), name); this.registry = registry; } diff --git a/common/api/core/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java b/common/api/core/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java new file mode 100644 index 000000000..91ed882db --- /dev/null +++ b/common/api/core/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java @@ -0,0 +1,19 @@ +package com.dfsek.terra.api.event.events.platform; + +import cloud.commandframework.CommandManager; + +import com.dfsek.terra.api.entity.CommandSender; +import com.dfsek.terra.api.event.events.Event; + + +public class CommandRegistrationEvent implements Event { + private final CommandManager commandManager; + + public CommandRegistrationEvent(CommandManager commandManager) { + this.commandManager = commandManager; + } + + public CommandManager getCommandManager() { + return commandManager; + } +} diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java index b6f36d591..5779c9b10 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -234,14 +234,6 @@ public abstract class AbstractPlatform implements Platform { logger.info("Terra addons successfully loaded."); - - try { - CommandUtil.registerAll(manager); - } catch(MalformedCommandException e) { - logger.error("Error registering commands", e); - } - - logger.info("Finished initialization."); } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java b/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java index 52f13ec06..28b5469ab 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/addon/InternalAddon.java @@ -28,6 +28,7 @@ import cloud.commandframework.arguments.standard.StringArgument; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; +import com.dfsek.terra.api.command.RegistryArgument; import com.dfsek.terra.api.entity.CommandSender; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; import com.dfsek.terra.api.event.functional.FunctionalEventHandler; @@ -43,7 +44,7 @@ public class InternalAddon implements BaseAddon { .then(event -> { CommandManager manager = event.getCommandManager(); manager.command( - manager.commandBuilder("addons", ArgumentDescription.of("Get information about installed Terra addons")) + manager.commandBuilder("addons", ArgumentDescription.of("List installed Terra addons")) .handler(context -> { StringBuilder addons = new StringBuilder("Installed addons:\n"); platform.getAddons() @@ -51,11 +52,29 @@ public class InternalAddon implements BaseAddon { .append("- ") .append(addon.getID()) .append('@') - .append(addon.getVersion()) + .append(addon.getVersion().getFormatted()) .append('\n')); context.getSender().sendMessage(addons.toString()); }) ); + manager.command(manager.commandBuilder("addons", ArgumentDescription.of("Get information about addons")) + .argument(RegistryArgument.of("addon", platform.getAddons())) + .handler(context -> { + BaseAddon addon = context.get("addon"); + StringBuilder addonInfo = new StringBuilder("Addon ").append(addon.getID()).append('\n'); + + addonInfo.append("Version: ").append(addon.getVersion().getFormatted()).append('\n'); + + addonInfo.append("Dependencies:\n"); + addon.getDependencies().forEach((id, versions) -> addonInfo + .append(" - ") + .append(id) + .append('@') + .append(versions.getFormatted()) + .append('\n')); + context.getSender().sendMessage(addonInfo.toString()); + }) + ); }); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index e136f306c..e5af7e4aa 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -63,7 +63,6 @@ public class TerraBukkitPlugin extends JavaPlugin { platform.getEventManager().callEvent(new PlatformInitializationEvent()); - PluginCommand cmd = Objects.requireNonNull(getCommand("terra")); try { PaperCommandManager commandManager = new PaperCommandManager<>(this, diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java deleted file mode 100644 index a110ce8c9..000000000 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/BukkitCommandAdapter.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra 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. - * - * Terra 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 Terra. If not, see . - */ - -package com.dfsek.terra.bukkit.command; - -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabCompleter; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; - -import com.dfsek.terra.api.command.CommandManager; -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.bukkit.world.BukkitAdapter; - - -public class BukkitCommandAdapter implements CommandExecutor, TabCompleter { - private static final Logger logger = LoggerFactory.getLogger(BukkitCommandAdapter.class); - - private final CommandManager manager; - - public BukkitCommandAdapter(CommandManager manager) { - this.manager = manager; - } - - @Override - public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - List argList = new ArrayList<>(Arrays.asList(args)); - if(argList.isEmpty()) { - sender.sendMessage("Command requires arguments."); - return true; - } - try { - manager.execute(argList.remove(0), BukkitAdapter.adapt(sender), argList); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return true; - } - - @Override - public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, - @NotNull String[] args) { - List argList = new ArrayList<>(Arrays.asList(args)); - - try { - return manager.tabComplete(argList.remove(0), BukkitAdapter.adapt(sender), argList).stream() - .filter(s -> s.toLowerCase(Locale.ROOT).startsWith(args[args.length - 1].toLowerCase(Locale.ROOT))).sorted( - String::compareTo).collect(Collectors.toList()); - } catch(CommandException e) { - logger.warn("Exception occurred during tab completion", e); - return Collections.emptyList(); - } - } -} diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java index 1a84db49a..97c925f75 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/FabricEntryPoint.java @@ -24,6 +24,8 @@ import com.dfsek.terra.api.entity.CommandSender; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; +import com.dfsek.terra.api.util.generic.Construct; + import net.fabricmc.api.ModInitializer; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.util.Identifier; diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java deleted file mode 100644 index bf47617da..000000000 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/mixin/CommandManagerMixin.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This file is part of Terra. - * - * Terra 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. - * - * Terra 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 Terra. If not, see . - */ - -package com.dfsek.terra.fabric.mixin; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import com.dfsek.terra.api.command.exception.CommandException; -import com.dfsek.terra.api.entity.CommandSender; -import com.dfsek.terra.api.entity.Entity; -import com.dfsek.terra.fabric.FabricEntryPoint; - -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; - - -@Mixin(CommandManager.class) -public abstract class CommandManagerMixin { - @Shadow - @Final - private CommandDispatcher dispatcher; - - @Inject(method = "", - at = @At(value = "INVOKE", - target = "Lcom/mojang/brigadier/CommandDispatcher;findAmbiguities(Lcom/mojang/brigadier/AmbiguityConsumer;)V", - remap = false)) - private void injectTerraCommands(CommandManager.RegistrationEnvironment environment, CallbackInfo ci) { - com.dfsek.terra.api.command.CommandManager manager = FabricEntryPoint.getPlatform().getManager(); - int max = manager.getMaxArgumentDepth(); - RequiredArgumentBuilder arg = argument("arg" + (max - 1), StringArgumentType.word()); - for(int i = 0; i < max; i++) { - RequiredArgumentBuilder next = argument("arg" + (max - i - 1), StringArgumentType.word()); - - arg = next.then(assemble(arg, manager)); - } - - dispatcher.register(literal("terra").executes(context -> 1).then(assemble(arg, manager))); - dispatcher.register(literal("te").executes(context -> 1).then(assemble(arg, manager))); - } - - private RequiredArgumentBuilder assemble(RequiredArgumentBuilder in, - com.dfsek.terra.api.command.CommandManager manager) { - return in.suggests((context, builder) -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrThrow(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.tabComplete(args.remove(0), sender, args).forEach(builder::suggest); - } catch(CommandException e) { - sender.sendMessage(e.getMessage()); - } - return builder.buildFuture(); - }).executes(context -> { - List args = parseCommand(context.getInput()); - CommandSender sender = (CommandSender) context.getSource(); - try { - sender = (Entity) context.getSource().getEntityOrThrow(); - } catch(CommandSyntaxException ignore) { - } - try { - manager.execute(args.remove(0), sender, args); - } catch(CommandException e) { - context.getSource().sendError(new LiteralText(e.getMessage())); - } - return 1; - }); - } - - private List parseCommand(String command) { - if(command.startsWith("/terra ")) command = command.substring("/terra ".length()); - else if(command.startsWith("/te ")) command = command.substring("/te ".length()); - List c = new ArrayList<>(Arrays.asList(command.split(" "))); - if(command.endsWith(" ")) c.add(""); - return c; - } -} diff --git a/platforms/fabric/src/main/resources/terra.mixins.json b/platforms/fabric/src/main/resources/terra.mixins.json index 33a19f06f..2abf1b65f 100644 --- a/platforms/fabric/src/main/resources/terra.mixins.json +++ b/platforms/fabric/src/main/resources/terra.mixins.json @@ -4,7 +4,6 @@ "package": "com.dfsek.terra.fabric.mixin", "compatibilityLevel": "JAVA_16", "mixins": [ - "CommandManagerMixin", "ConfiguredStructureFeaturesMixin", "ServerWorldMixin", "access.BiomeEffectsAccessor",