From 267ccf2298d31c2a5e00dd232f0c3aa04c9e93c2 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 15 Apr 2019 01:21:15 -0700 Subject: [PATCH] First attempt at integrating Piston as the only command system --- build.gradle | 2 + .../bukkit/BukkitCommandInspector.java | 41 ++-- .../bukkit/BukkitServerInterface.java | 36 ++-- .../worldedit/bukkit/WorldEditListener.java | 31 +-- worldedit-core/build.gradle | 11 +- .../worldedit/command/UtilityCommands.java | 23 ++- .../worldedit/command/WorldEditCommands.java | 2 +- .../worldedit/command/argument/Arguments.java | 31 +++ .../command/argument/EditSessionHolder.java | 87 +++++++++ .../command/composition/SelectionCommand.java | 2 +- .../composition/ShapedBrushCommand.java | 2 +- .../CommandPermissionsConditionGenerator.java | 6 +- .../command/util/MessageFutureCallback.java | 2 +- .../command/util/PermissionCondition.java | 49 +++++ .../extension/platform/Capability.java | 4 +- .../platform/CommandManagerCallable.java | 96 ---------- .../extension/platform/Platform.java | 7 +- ...ager.java => PlatformCommandMananger.java} | 177 +++++++++--------- .../extension/platform/PlatformManager.java | 8 +- .../command/CommandLoggingHandler.java | 113 +++++------ .../command/WorldEditExceptionConverter.java | 49 +++-- .../parametric/ExceptionConverter.java | 7 +- .../parametric/ExceptionConverterHelper.java | 7 +- .../formatting/component/CommandUsageBox.java | 4 +- .../sk89q/worldedit/forge/CommandWrapper.java | 22 ++- .../sk89q/worldedit/forge/ForgePlatform.java | 22 ++- .../worldedit/sponge/CommandAdapter.java | 24 ++- .../worldedit/sponge/SpongePlatform.java | 17 +- 28 files changed, 493 insertions(+), 389 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/Arguments.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EditSessionHolder.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PermissionCondition.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManagerCallable.java rename worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/{CommandManager.java => PlatformCommandMananger.java} (72%) diff --git a/build.gradle b/build.gradle index 8bdb1a122..41c04e0bd 100644 --- a/build.gradle +++ b/build.gradle @@ -101,6 +101,8 @@ subprojects { mavenCentral() maven { url "http://maven.sk89q.com/repo/" } maven { url "http://repo.maven.apache.org/maven2" } + // temporary, for Piston + mavenLocal() } if (JavaVersion.current().isJava8Compatible()) { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java index fa3f2917f..917d31981 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandInspector.java @@ -19,26 +19,29 @@ package com.sk89q.worldedit.bukkit; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Key; import com.sk89q.bukkit.util.CommandInspector; -import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.command.CommandMapping; -import com.sk89q.worldedit.util.command.Description; -import com.sk89q.worldedit.util.command.Dispatcher; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.NoInputCommandParameters; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Optional; + import static com.google.common.base.Preconditions.checkNotNull; class BukkitCommandInspector implements CommandInspector { private static final Logger logger = LoggerFactory.getLogger(BukkitCommandInspector.class); private final WorldEditPlugin plugin; - private final Dispatcher dispatcher; + private final CommandManager dispatcher; - BukkitCommandInspector(WorldEditPlugin plugin, Dispatcher dispatcher) { + BukkitCommandInspector(WorldEditPlugin plugin, CommandManager dispatcher) { checkNotNull(plugin); checkNotNull(dispatcher); this.plugin = plugin; @@ -47,9 +50,9 @@ class BukkitCommandInspector implements CommandInspector { @Override public String getShortText(Command command) { - CommandMapping mapping = dispatcher.get(command.getName()); - if (mapping != null) { - return mapping.getDescription().getDescription(); + Optional mapping = dispatcher.getCommand(command.getName()); + if (mapping.isPresent()) { + return mapping.get().getDescription(); } else { logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); return "Help text not available"; @@ -58,10 +61,9 @@ class BukkitCommandInspector implements CommandInspector { @Override public String getFullText(Command command) { - CommandMapping mapping = dispatcher.get(command.getName()); - if (mapping != null) { - Description description = mapping.getDescription(); - return "Usage: " + description.getUsage() + (description.getHelp() != null ? "\n" + description.getHelp() : ""); + Optional mapping = dispatcher.getCommand(command.getName()); + if (mapping.isPresent()) { + return mapping.get().getFullHelp(); } else { logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); return "Help text not available"; @@ -70,11 +72,14 @@ class BukkitCommandInspector implements CommandInspector { @Override public boolean testPermission(CommandSender sender, Command command) { - CommandMapping mapping = dispatcher.get(command.getName()); - if (mapping != null) { - CommandLocals locals = new CommandLocals(); - locals.put(Actor.class, plugin.wrapCommandSender(sender)); - return mapping.getCallable().testPermission(locals); + Optional mapping = dispatcher.getCommand(command.getName()); + if (mapping.isPresent()) { + CommandParameters parameters = NoInputCommandParameters.builder() + .injectedValues(ImmutableMap.of( + Key.get(Actor.class), plugin.wrapCommandSender(sender) + )) + .build(); + return mapping.get().getCondition().satisfied(parameters); } else { logger.warn("BukkitCommandInspector doesn't know how about the command '" + command + "'"); return false; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java index adfc64bc0..e24714821 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitServerInterface.java @@ -22,27 +22,28 @@ package com.sk89q.worldedit.bukkit; import com.sk89q.bukkit.util.CommandInfo; import com.sk89q.bukkit.util.CommandRegistration; import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; import com.sk89q.worldedit.util.command.CommandMapping; -import com.sk89q.worldedit.util.command.Description; -import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.world.registry.Registries; import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.entity.EntityType; +import org.enginehub.piston.CommandManager; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; import java.util.List; import java.util.Map; - -import javax.annotation.Nullable; +import java.util.stream.Collectors; +import java.util.stream.Stream; public class BukkitServerInterface implements MultiUserPlatform { public Server server; @@ -116,20 +117,25 @@ public class BukkitServerInterface implements MultiUserPlatform { } @Override - public void registerCommands(Dispatcher dispatcher) { - List toRegister = new ArrayList<>(); + public void registerCommands(CommandManager dispatcher) { BukkitCommandInspector inspector = new BukkitCommandInspector(plugin, dispatcher); - - for (CommandMapping command : dispatcher.getCommands()) { - Description description = command.getDescription(); - List permissions = description.getPermissions(); - String[] permissionsArray = new String[permissions.size()]; - permissions.toArray(permissionsArray); - toRegister.add(new CommandInfo(description.getUsage(), description.getDescription(), command.getAllAliases(), inspector, permissionsArray)); - } + dynamicCommands.register(dispatcher.getAllCommands() + .map(command -> { + String[] permissionsArray = command.getCondition() + .as(PermissionCondition.class) + .map(PermissionCondition::getPermissions) + .map(s -> s.toArray(new String[0])) + .orElseGet(() -> new String[0]); - dynamicCommands.register(toRegister); + String[] aliases = Stream.concat( + Stream.of(command.getName()), + command.getAliases().stream() + ).toArray(String[]::new); + return new CommandInfo(command.getUsage(), + command.getDescription(), aliases, + inspector, permissionsArray); + }).collect(Collectors.toList())); } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java index 05774b84c..9c124f83f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditListener.java @@ -21,13 +21,13 @@ package com.sk89q.worldedit.bukkit; -import com.sk89q.minecraft.util.commands.CommandLocals; +import com.google.common.collect.ImmutableMap; +import com.google.inject.Key; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.world.World; import org.bukkit.block.Block; import org.bukkit.event.Event.Result; @@ -40,9 +40,9 @@ import org.bukkit.event.player.PlayerCommandSendEvent; import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; - -import java.util.Set; -import java.util.stream.Collectors; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.NoInputCommandParameters; /** * Handles all events thrown in relation to a Player @@ -87,7 +87,7 @@ public class WorldEditListener implements Listener { if (split.length > 0) { split[0] = split[0].substring(1); - split = plugin.getWorldEdit().getPlatformManager().getCommandManager().commandDetection(split); + split = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().commandDetection(split); } final String newMessage = "/" + StringUtil.joinString(split, " "); @@ -108,13 +108,18 @@ public class WorldEditListener implements Listener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onPlayerCommand(PlayerCommandSendEvent event) { - CommandLocals locals = new CommandLocals(); - locals.put(Actor.class, plugin.wrapCommandSender(event.getPlayer())); - Set toRemove = plugin.getWorldEdit().getPlatformManager().getCommandManager().getDispatcher().getCommands().stream() - .filter(commandMapping -> !commandMapping.getCallable().testPermission(locals)) - .map(CommandMapping::getPrimaryAlias) - .collect(Collectors.toSet()); - event.getCommands().removeIf(toRemove::contains); + CommandParameters parameters = NoInputCommandParameters.builder() + .injectedValues(ImmutableMap.of( + Key.get(Actor.class), plugin.wrapCommandSender(event.getPlayer()) + )) + .build(); + CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().getCommandManager(); + event.getCommands().removeIf(name -> + // remove if in the manager and not satisfied + commandManager.getCommand(name) + .filter(command -> !command.getCondition().satisfied(parameters)) + .isPresent() + ); } /** diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index bfd0aac32..23f96a592 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -2,6 +2,7 @@ plugins { id("net.ltgt.apt") version "0.21" } +apply plugin: 'java-library' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'net.ltgt.apt-eclipse' @@ -13,11 +14,6 @@ configurations.all { Configuration it -> } } -repositories { - // temporary, for Piston - mavenLocal() -} - dependencies { compile 'de.schlichtherle:truezip:6.8.3' compile 'rhino:js:1.7R2' @@ -32,10 +28,11 @@ dependencies { compile 'org.slf4j:slf4j-api:1.7.26' def pistonVersion = '0.0.1-SNAPSHOT' + api "org.enginehub.piston:core:$pistonVersion" compileOnly "org.enginehub.piston.core-ap:annotations:$pistonVersion" - compile "org.enginehub.piston.core-ap:runtime:$pistonVersion" + implementation "org.enginehub.piston.core-ap:runtime:$pistonVersion" annotationProcessor "org.enginehub.piston.core-ap:processor:$pistonVersion" - compile "org.enginehub.piston:default-impl:$pistonVersion" + api "org.enginehub.piston:default-impl:$pistonVersion" //compile 'net.sf.trove4j:trove4j:3.0.3' testCompile 'org.mockito:mockito-core:1.9.0-rc1' } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 8768be6c8..415b77adf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -39,7 +39,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.extension.platform.CommandManager; +import com.sk89q.worldedit.extension.platform.PlatformCommandMananger; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.BlockPattern; @@ -67,6 +67,7 @@ import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; +import org.enginehub.piston.CommandManager; import java.util.ArrayList; import java.util.List; @@ -598,7 +599,10 @@ public class UtilityCommands { } public static void help(CommandContext args, WorldEdit we, Actor actor) { - CommandCallable callable = we.getPlatformManager().getCommandManager().getDispatcher(); + CommandManager manager = we.getPlatformManager().getPlatformCommandMananger().getCommandManager(); + + // TODO this will be implemented as a special utility in the manager + /* int page = 0; final int perPage = actor instanceof Player ? 8 : 20; // More pages for console @@ -626,15 +630,15 @@ public class UtilityCommands { for (int i = 0; i < effectiveLength; i++) { String command = args.getString(i); - if (callable instanceof Dispatcher) { + if (manager instanceof Dispatcher) { // Chop off the beginning / if we're are the root level if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') { command = command.substring(1); } - CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel); + CommandMapping mapping = detectCommand((Dispatcher) manager, command, isRootLevel); if (mapping != null) { - callable = mapping.getCallable(); + manager = mapping.getCallable(); } else { if (isRootLevel) { actor.printError(String.format("The command '%s' could not be found.", args.getString(i))); @@ -656,12 +660,12 @@ public class UtilityCommands { } // Create the message - if (callable instanceof Dispatcher) { - Dispatcher dispatcher = (Dispatcher) callable; + if (manager instanceof Dispatcher) { + Dispatcher dispatcher = (Dispatcher) manager; // Get a list of aliases List aliases = new ArrayList<>(dispatcher.getCommands()); - aliases.sort(new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN)); + aliases.sort(new PrimaryAliasComparator(PlatformCommandMananger.COMMAND_CLEAN_PATTERN)); // Calculate pagination int offset = perPage * page; @@ -698,9 +702,10 @@ public class UtilityCommands { actor.printRaw(ColorCodeBuilder.asColorCodes(box)); } else { - CommandUsageBox box = new CommandUsageBox(callable, Joiner.on(" ").join(visited)); + CommandUsageBox box = new CommandUsageBox(manager, Joiner.on(" ").join(visited)); actor.printRaw(ColorCodeBuilder.asColorCodes(box)); } + */ } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index 26c382beb..787859323 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -113,7 +113,7 @@ public class WorldEditCommands { actor.checkPermission("worldedit.report.pastebin"); ActorCallbackPaste.pastebin( we.getSupervisor(), actor, result, "WorldEdit report: %s.report", - WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter() + WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter() ); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/Arguments.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/Arguments.java new file mode 100644 index 000000000..1bf5fc4e9 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/Arguments.java @@ -0,0 +1,31 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.argument; + +import org.enginehub.piston.InjectedValueAccess; + +/** + * Key-interface for {@link InjectedValueAccess} for the String arguments. + */ +public interface Arguments { + + String get(); + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EditSessionHolder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EditSessionHolder.java new file mode 100644 index 000000000..b5113f545 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EditSessionHolder.java @@ -0,0 +1,87 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; + +import java.util.concurrent.locks.StampedLock; + +/** + * Lazily-created {@link EditSession}. + */ +public class EditSessionHolder { + + private final StampedLock lock = new StampedLock(); + private final WorldEdit worldEdit; + private final Player player; + + public EditSessionHolder(WorldEdit worldEdit, Player player) { + this.worldEdit = worldEdit; + this.player = player; + } + + private EditSession session; + + /** + * Get the session, but does not create it if it doesn't exist. + */ + public EditSession getSession() { + long stamp = lock.tryOptimisticRead(); + EditSession result = session; + if (!lock.validate(stamp)) { + stamp = lock.readLock(); + try { + result = session; + } finally { + lock.unlockRead(stamp); + } + } + return result; + } + + public EditSession getOrCreateSession() { + // use the already-generated result if possible + EditSession result = getSession(); + if (result != null) { + return result; + } + // otherwise, acquire write lock + long stamp = lock.writeLock(); + try { + // check session field again -- maybe another writer hit it in between + result = session; + if (result != null) { + return result; + } + // now we can do the actual creation + LocalSession localSession = worldEdit.getSessionManager().get(player); + EditSession editSession = localSession.createEditSession(player); + editSession.enableStandardMode(); + localSession.tellVersion(player); + return session = editSession; + } finally { + lock.unlockWrite(stamp); + } + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java index a8e89e364..dd51c64a2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java @@ -94,7 +94,7 @@ public class SelectionCommand extends SimpleCommand { return operation; } catch (IncompleteRegionException e) { - WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter().convert(e); + WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter().convert(e); return null; } } else { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ShapedBrushCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ShapedBrushCommand.java index 98daedde2..35fb758a3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ShapedBrushCommand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ShapedBrushCommand.java @@ -77,7 +77,7 @@ public class ShapedBrushCommand extends SimpleCommand { tool.setFill(null); tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission); } catch (MaxBrushRadiusException | InvalidToolBindException e) { - WorldEdit.getInstance().getPlatformManager().getCommandManager().getExceptionConverter().convert(e); + WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter().convert(e); } player.print("Set brush to " + factory); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissionsConditionGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissionsConditionGenerator.java index 84011e0ff..28041a1a1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissionsConditionGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissionsConditionGenerator.java @@ -34,15 +34,11 @@ import static com.google.common.base.Preconditions.checkNotNull; @NonnullByDefault public class CommandPermissionsConditionGenerator implements CommandConditionGenerator { - private static final Key ACTOR_KEY = Key.get(Actor.class); - @Override public Command.Condition generateCondition(Method commandMethod) { CommandPermissions annotation = commandMethod.getAnnotation(CommandPermissions.class); checkNotNull(annotation, "Annotation is missing from commandMethod"); Set permissions = ImmutableSet.copyOf(annotation.value()); - return p -> p.injectedValue(ACTOR_KEY) - .map(actor -> permissions.stream().anyMatch(actor::hasPermission)) - .orElse(false); + return new PermissionCondition(permissions); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageFutureCallback.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageFutureCallback.java index 3abb73545..58b25770d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageFutureCallback.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/MessageFutureCallback.java @@ -22,9 +22,9 @@ package com.sk89q.worldedit.command.util; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.util.concurrent.FutureCallback; -import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; +import org.enginehub.piston.exception.CommandException; import javax.annotation.Nullable; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PermissionCondition.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PermissionCondition.java new file mode 100644 index 000000000..2d7f7cd2e --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PermissionCondition.java @@ -0,0 +1,49 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.util; + +import com.google.inject.Key; +import com.sk89q.worldedit.extension.platform.Actor; +import org.enginehub.piston.Command; +import org.enginehub.piston.CommandParameters; + +import java.util.Set; + +public final class PermissionCondition implements Command.Condition { + + private static final Key ACTOR_KEY = Key.get(Actor.class); + + private final Set permissions; + + PermissionCondition(Set permissions) { + this.permissions = permissions; + } + + public Set getPermissions() { + return permissions; + } + + @Override + public boolean satisfied(CommandParameters parameters) { + return parameters.injectedValue(ACTOR_KEY) + .map(actor -> permissions.stream().anyMatch(actor::hasPermission)) + .orElse(false); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java index a753b0fd2..50aa913b4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Capability.java @@ -50,12 +50,12 @@ public enum Capability { USER_COMMANDS { @Override void initialize(PlatformManager platformManager, Platform platform) { - platformManager.getCommandManager().register(platform); + platformManager.getPlatformCommandMananger().register(platform); } @Override void unload(PlatformManager platformManager, Platform platform) { - platformManager.getCommandManager().unregister(); + platformManager.getPlatformCommandMananger().unregister(); } }, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManagerCallable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManagerCallable.java deleted file mode 100644 index fe22518ef..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManagerCallable.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * WorldEdit, a Minecraft world manipulation toolkit - * Copyright (C) sk89q - * Copyright (C) WorldEdit team and contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package com.sk89q.worldedit.extension.platform; - -import com.google.common.base.Splitter; -import com.google.inject.Key; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.Description; -import org.enginehub.piston.CommandManager; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -/** - * Hack to get {@link CommandManager} working under {@link CommandCallable}. - */ -public class CommandManagerCallable implements CommandCallable { - - private final WorldEdit worldEdit; - private final CommandManager manager; - private final Description description; - - public CommandManagerCallable(WorldEdit worldEdit, CommandManager manager, Description description) { - this.worldEdit = worldEdit; - this.manager = manager; - this.description = description; - } - - @Override - public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException { - manager.injectValue(Key.get(Actor.class), access -> Optional.of(locals.get(Actor.class))); - manager.injectValue(Key.get(Player.class), access -> { - Actor actor = locals.get(Actor.class); - return actor instanceof Player ? Optional.of(((Player) actor)) : Optional.empty(); - }); - manager.injectValue(Key.get(LocalSession.class), access -> - access.injectedValue(Key.get(Player.class)) - .map(worldEdit.getSessionManager()::get) - ); - manager.injectValue(Key.get(EditSession.class), access -> - access.injectedValue(Key.get(Player.class)) - .map(sender -> { - LocalSession session = worldEdit.getSessionManager().get(sender); - EditSession editSession = session.createEditSession(sender); - editSession.enableStandardMode(); - session.tellVersion(sender); - return editSession; - }) - ); - return manager.execute(Splitter.on(' ').splitToList(arguments)); - } - - private Player getPlayer(CommandLocals locals) { - Actor actor = locals.get(Actor.class); - return actor instanceof Player ? (Player) actor : null; - } - - @Override - public Description getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - - @Override - public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { - return Collections.emptyList(); - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java index 3b37a98b5..ace903fe0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Platform.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; +import org.enginehub.piston.CommandManager; import java.util.List; import java.util.Map; @@ -97,11 +98,11 @@ public interface Platform { @Nullable World matchWorld(World world); /** - * Register the commands contained within the given command dispatcher. + * Register the commands contained within the given command manager. * - * @param dispatcher the dispatcher + * @param commandManager the command manager */ - void registerCommands(Dispatcher dispatcher); + void registerCommands(CommandManager commandManager); /** * Register game hooks. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java similarity index 72% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index da697d182..e08c44eb5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -19,9 +19,8 @@ package com.sk89q.worldedit.extension.platform; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; -import com.sk89q.minecraft.util.commands.CommandException; +import com.google.inject.Key; import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandPermissionsException; import com.sk89q.minecraft.util.commands.WrappedCommandException; @@ -30,51 +29,25 @@ import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.BiomeCommands; -import com.sk89q.worldedit.command.BrushCommands; -import com.sk89q.worldedit.command.ChunkCommands; -import com.sk89q.worldedit.command.ClipboardCommands; -import com.sk89q.worldedit.command.GeneralCommands; -import com.sk89q.worldedit.command.GenerationCommands; -import com.sk89q.worldedit.command.HistoryCommands; -import com.sk89q.worldedit.command.NavigationCommands; -import com.sk89q.worldedit.command.RegionCommands; +import com.sk89q.worldedit.command.BiomeCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; -import com.sk89q.worldedit.command.ScriptingCommands; -import com.sk89q.worldedit.command.SelectionCommands; -import com.sk89q.worldedit.command.SnapshotCommands; -import com.sk89q.worldedit.command.SnapshotUtilCommands; -import com.sk89q.worldedit.command.SuperPickaxeCommands; -import com.sk89q.worldedit.command.ToolCommands; -import com.sk89q.worldedit.command.ToolUtilCommands; -import com.sk89q.worldedit.command.UtilityCommands; -import com.sk89q.worldedit.command.WorldEditCommands; -import com.sk89q.worldedit.command.argument.ReplaceParser; -import com.sk89q.worldedit.command.argument.TreeGeneratorParser; -import com.sk89q.worldedit.command.composition.ApplyCommand; -import com.sk89q.worldedit.command.composition.DeformCommand; -import com.sk89q.worldedit.command.composition.PaintCommand; -import com.sk89q.worldedit.command.composition.SelectionCommand; -import com.sk89q.worldedit.command.composition.ShapedBrushCommand; +import com.sk89q.worldedit.command.argument.Arguments; +import com.sk89q.worldedit.command.argument.EditSessionHolder; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.factory.Deform; -import com.sk89q.worldedit.function.factory.Deform.Mode; import com.sk89q.worldedit.internal.command.ActorAuthorizer; -import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.UserCommandCompleter; import com.sk89q.worldedit.internal.command.WorldEditBinding; import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; import com.sk89q.worldedit.session.request.Request; -import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.InvalidUsageException; -import com.sk89q.worldedit.util.command.SimpleDescription; -import com.sk89q.worldedit.util.command.composition.ProvidedValue; -import com.sk89q.worldedit.util.command.fluent.CommandGraph; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler; import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; @@ -84,35 +57,44 @@ import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; import com.sk89q.worldedit.util.logging.DynamicStreamHandler; import com.sk89q.worldedit.util.logging.LogFormat; import com.sk89q.worldedit.world.World; +import org.enginehub.piston.Command; +import org.enginehub.piston.CommandManager; import org.enginehub.piston.DefaultCommandManagerService; +import org.enginehub.piston.exception.CommandException; +import org.enginehub.piston.exception.CommandExecutionException; +import org.enginehub.piston.exception.ConditionFailedException; +import org.enginehub.piston.exception.UsageException; +import org.enginehub.piston.part.SubCommandPart; +import org.enginehub.piston.util.ValueProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; +import java.util.Optional; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.regex.Pattern; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt; /** * Handles the registration and invocation of commands. * *

This class is primarily for internal usage.

*/ -public final class CommandManager { +public final class PlatformCommandMananger { public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+"); - private static final Logger log = LoggerFactory.getLogger(CommandManager.class); + private static final Logger log = LoggerFactory.getLogger(PlatformCommandMananger.class); private static final java.util.logging.Logger commandLog = - java.util.logging.Logger.getLogger(CommandManager.class.getCanonicalName() + ".CommandLog"); + java.util.logging.Logger.getLogger(PlatformCommandMananger.class.getCanonicalName() + ".CommandLog"); private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$"); private final WorldEdit worldEdit; private final PlatformManager platformManager; - private final Dispatcher dispatcher; + private final CommandManager commandManager; private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); private final ExceptionConverter exceptionConverter; @@ -121,12 +103,14 @@ public final class CommandManager { * * @param worldEdit the WorldEdit instance */ - CommandManager(final WorldEdit worldEdit, PlatformManager platformManager) { + PlatformCommandMananger(final WorldEdit worldEdit, PlatformManager platformManager) { checkNotNull(worldEdit); checkNotNull(platformManager); this.worldEdit = worldEdit; this.platformManager = platformManager; this.exceptionConverter = new WorldEditExceptionConverter(worldEdit); + this.commandManager = DefaultCommandManagerService.getInstance() + .newCommandManager(); // Register this instance for command events worldEdit.getEventBus().register(this); @@ -140,12 +124,41 @@ public final class CommandManager { builder.setDefaultCompleter(new UserCommandCompleter(platformManager)); builder.addBinding(new WorldEditBinding(worldEdit)); builder.addInvokeListener(new LegacyCommandsHandler()); - builder.addInvokeListener(new CommandLoggingHandler(worldEdit, commandLog)); + CommandPermissionsConditionGenerator permsGenerator = + new CommandPermissionsConditionGenerator(); + + commandManager.register("schematic", cmd -> { + cmd.aliases(ImmutableList.of("schem", "/schematic", "/schem")); + cmd.description("Schematic commands for saving/loading areas"); + cmd.action(Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + SchematicCommandsRegistration.builder() + .commandManager(manager) + .containerInstance(new SchematicCommands(worldEdit)) + .commandPermissionsConditionGenerator( + permsGenerator + ).build(); + + cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() + .build()); + }); + + BiomeCommandsRegistration.builder() + .commandManager(commandManager) + .containerInstance(new BiomeCommands()) + .commandPermissionsConditionGenerator(permsGenerator) + .build(); + + // Unported commands are below. Delete once they're added to the main manager above. + /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new BiomeCommands()) .registerMethods(new ChunkCommands(worldEdit)) .registerMethods(new ClipboardCommands(worldEdit)) .registerMethods(new GeneralCommands(worldEdit)) @@ -164,7 +177,6 @@ public final class CommandManager { .describeAs("WorldEdit commands") .registerMethods(new WorldEditCommands(worldEdit)) .parent() - .register(schematicCommands(),"schematic", "schem", "/schematic", "/schem") .group("snapshot", "snap") .describeAs("Schematic commands for saving/loading areas") .registerMethods(new SnapshotCommands(worldEdit)) @@ -190,22 +202,7 @@ public final class CommandManager { .parent() .graph() .getDispatcher(); - } - - private CommandCallable schematicCommands() { - SimpleDescription desc = new SimpleDescription(); - desc.setDescription("Schematic commands for saving/loading areas"); - desc.setPermissions(ImmutableList.of()); - org.enginehub.piston.CommandManager manager = DefaultCommandManagerService.getInstance() - .newCommandManager(); - SchematicCommandsRegistration.builder() - .commandManager(manager) - .containerInstance(new SchematicCommands(worldEdit)) - .commandPermissionsConditionGenerator( - new CommandPermissionsConditionGenerator() - ).build(); - - return new CommandManagerCallable(worldEdit, manager, desc); + */ } public ExceptionConverter getExceptionConverter() { @@ -238,7 +235,7 @@ public final class CommandManager { dynamicHandler.setFormatter(new LogFormat(config.logFormat)); } - platform.registerCommands(dispatcher); + platform.registerCommands(commandManager); } void unregister() { @@ -258,10 +255,10 @@ public final class CommandManager { String searchCmd = split[0].toLowerCase(); // Try to detect the command - if (!dispatcher.contains(searchCmd)) { - if (worldEdit.getConfiguration().noDoubleSlash && dispatcher.contains("/" + searchCmd)) { + if (!commandManager.containsCommand(searchCmd)) { + if (worldEdit.getConfiguration().noDoubleSlash && commandManager.containsCommand("/" + searchCmd)) { split[0] = "/" + split[0]; - } else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && dispatcher.contains(searchCmd.substring(1))) { + } else if (searchCmd.length() >= 2 && searchCmd.charAt(0) == '/' && commandManager.containsCommand(searchCmd.substring(1))) { split[0] = split[0].substring(1); } } @@ -277,7 +274,7 @@ public final class CommandManager { String[] split = commandDetection(event.getArguments().split(" ")); // No command found! - if (!dispatcher.contains(split[0])) { + if (!commandManager.containsCommand(split[0])) { return; } @@ -291,9 +288,13 @@ public final class CommandManager { } LocalConfiguration config = worldEdit.getConfiguration(); - CommandLocals locals = new CommandLocals(); - locals.put(Actor.class, actor); - locals.put("arguments", event.getArguments()); + commandManager.injectValue(Key.get(Actor.class), ValueProvider.constant(actor)); + commandManager.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments)); + commandManager.injectValue(Key.get(EditSessionHolder.class), + context -> context.injectedValue(Key.get(Actor.class)) + .filter(Player.class::isInstance) + .map(Player.class::cast) + .map(p -> new EditSessionHolder(worldEdit, p))); long start = System.currentTimeMillis(); @@ -303,7 +304,7 @@ public final class CommandManager { // exceptions without writing a hook into every dispatcher, we need to unwrap these // exceptions and rethrow their converted form, if their is one. try { - dispatcher.call(Joiner.on(" ").join(split), locals, new String[0]); + commandManager.execute(ImmutableList.copyOf(split)); } catch (Throwable t) { // Use the exception converter to convert the exception if any of its causes // can be converted, otherwise throw the original exception @@ -315,21 +316,14 @@ public final class CommandManager { throw t; } - } catch (CommandPermissionsException e) { - actor.printError("You are not permitted to do that. Are you in the right mode?"); - } catch (InvalidUsageException e) { - if (e.isFullHelpSuggested()) { - actor.printRaw(ColorCodeBuilder.asColorCodes(new CommandUsageBox(e.getCommand(), e.getCommandUsed("/", ""), locals))); - String message = e.getMessage(); - if (message != null) { - actor.printError(message); - } - } else { - String message = e.getMessage(); - actor.printError(message != null ? message : "The command was not used properly (no more help available)."); - actor.printError("Usage: " + e.getSimpleUsageString("/")); + } catch (ConditionFailedException e) { + if (e.getCondition() instanceof PermissionCondition) { + actor.printError("You are not permitted to do that. Are you in the right mode?"); } - } catch (WrappedCommandException e) { + } catch (UsageException e) { + String message = e.getMessage(); + actor.printError(message != null ? message : "The command was not used properly (no more help available)."); + } catch (CommandExecutionException e) { Throwable t = e.getCause(); actor.printError("Please report this error: [See console]"); actor.printRaw(t.getClass().getName() + ": " + t.getMessage()); @@ -343,9 +337,11 @@ public final class CommandManager { log.error("An unknown error occurred", e); } } finally { - EditSession editSession = locals.get(EditSession.class); + Optional editSessionOpt = commandManager.injectedValue(Key.get(EditSessionHolder.class)) + .map(EditSessionHolder::getSession); - if (editSession != null) { + if (editSessionOpt.isPresent()) { + EditSession editSession = editSessionOpt.get(); session.remember(editSession); editSession.flushSession(); @@ -373,22 +369,21 @@ public final class CommandManager { @Subscribe public void handleCommandSuggestion(CommandSuggestionEvent event) { try { - CommandLocals locals = new CommandLocals(); - locals.put(Actor.class, event.getActor()); - locals.put("arguments", event.getArguments()); - event.setSuggestions(dispatcher.getSuggestions(event.getArguments(), locals)); + commandManager.injectValue(Key.get(Actor.class), ValueProvider.constant(event.getActor())); + commandManager.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments)); + // TODO suggestions } catch (CommandException e) { event.getActor().printError(e.getMessage()); } } /** - * Get the command dispatcher instance. + * Get the command manager instance. * - * @return the command dispatcher + * @return the command manager */ - public Dispatcher getDispatcher() { - return dispatcher; + public CommandManager getCommandManager() { + return commandManager; } public static java.util.logging.Logger getLogger() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 3b8347e7d..692c1558e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -68,7 +68,7 @@ public class PlatformManager { private static final Logger logger = LoggerFactory.getLogger(PlatformManager.class); private final WorldEdit worldEdit; - private final CommandManager commandManager; + private final PlatformCommandMananger platformCommandMananger; private final List platforms = new ArrayList<>(); private final Map preferences = new EnumMap<>(Capability.class); private @Nullable String firstSeenVersion; @@ -83,7 +83,7 @@ public class PlatformManager { public PlatformManager(WorldEdit worldEdit) { checkNotNull(worldEdit); this.worldEdit = worldEdit; - this.commandManager = new CommandManager(worldEdit, this); + this.platformCommandMananger = new PlatformCommandMananger(worldEdit, this); // Register this instance for events worldEdit.getEventBus().register(this); @@ -277,8 +277,8 @@ public class PlatformManager { * * @return the command manager */ - public CommandManager getCommandManager() { - return commandManager; + public PlatformCommandMananger getPlatformCommandMananger() { + return platformCommandMananger; } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandLoggingHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandLoggingHandler.java index 10ba092a3..f8fa06ff6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandLoggingHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandLoggingHandler.java @@ -19,8 +19,7 @@ package com.sk89q.worldedit.internal.command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; +import com.google.inject.Key; import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; @@ -28,22 +27,22 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.util.command.parametric.AbstractInvokeListener; -import com.sk89q.worldedit.util.command.parametric.InvokeHandler; -import com.sk89q.worldedit.util.command.parametric.ParameterData; -import com.sk89q.worldedit.util.command.parametric.ParameterException; +import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.gen.CommandCallListener; -import java.io.Closeable; import java.lang.reflect.Method; +import java.util.Optional; import java.util.logging.Handler; import java.util.logging.Logger; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static com.google.common.base.Preconditions.checkNotNull; /** * Logs called commands to a logger. */ -public class CommandLoggingHandler extends AbstractInvokeListener implements InvokeHandler, Closeable { +public class CommandLoggingHandler implements CommandCallListener, AutoCloseable { private final WorldEdit worldEdit; private final Logger logger; @@ -62,93 +61,77 @@ public class CommandLoggingHandler extends AbstractInvokeListener implements Inv } @Override - public void preProcess(Object object, Method method, ParameterData[] parameters, CommandContext context) throws CommandException, ParameterException { - } - - @Override - public void preInvoke(Object object, Method method, ParameterData[] parameters, Object[] args, CommandContext context) throws CommandException { + public void beforeCall(Method method, CommandParameters parameters) { Logging loggingAnnotation = method.getAnnotation(Logging.class); Logging.LogMode logMode; StringBuilder builder = new StringBuilder(); - + if (loggingAnnotation == null) { logMode = null; } else { logMode = loggingAnnotation.value(); } - Actor sender = context.getLocals().get(Actor.class); - Player player; + Optional playerOpt = parameters.injectedValue(Key.get(Actor.class)) + .filter(Player.class::isInstance) + .map(Player.class::cast); - if (sender == null) { + if (!playerOpt.isPresent()) { return; } - if (sender instanceof Player) { - player = (Player) sender; - } else { - return; - } + Player player = playerOpt.get(); - builder.append("WorldEdit: ").append(sender.getName()); - if (sender.isPlayer()) { - builder.append(" (in \"").append(player.getWorld().getName()).append("\")"); - } + builder.append("WorldEdit: ").append(player.getName()); + builder.append(" (in \"").append(player.getWorld().getName()).append("\")"); - builder.append(": ").append(context.getCommand()); - - if (context.argsLength() > 0) { - builder.append(" ").append(context.getJoinedStrings(0)); - } - - if (logMode != null && sender.isPlayer()) { + builder.append(": ").append(parameters.getMetadata().getCalledName()); + + builder.append(": ") + .append(Stream.concat( + Stream.of(parameters.getMetadata().getCalledName()), + parameters.getMetadata().getArguments().stream() + ).collect(Collectors.joining(" "))); + + if (logMode != null) { Vector3 position = player.getLocation().toVector(); LocalSession session = worldEdit.getSessionManager().get(player); - + switch (logMode) { - case PLACEMENT: - try { - position = session.getPlacementPosition(player).toVector3(); - } catch (IncompleteRegionException e) { + case PLACEMENT: + try { + position = session.getPlacementPosition(player).toVector3(); + } catch (IncompleteRegionException e) { + break; + } + /* FALL-THROUGH */ + + case POSITION: + builder.append(" - Position: ").append(position); break; - } - /* FALL-THROUGH */ - case POSITION: - builder.append(" - Position: ").append(position); - break; + case ALL: + builder.append(" - Position: ").append(position); + /* FALL-THROUGH */ - case ALL: - builder.append(" - Position: ").append(position); - /* FALL-THROUGH */ + case ORIENTATION_REGION: + builder.append(" - Orientation: ").append(player.getCardinalDirection().name()); + /* FALL-THROUGH */ - case ORIENTATION_REGION: - builder.append(" - Orientation: ").append(player.getCardinalDirection().name()); - /* FALL-THROUGH */ - - case REGION: - try { - builder.append(" - Region: ") + case REGION: + try { + builder.append(" - Region: ") .append(session.getSelection(player.getWorld())); - } catch (IncompleteRegionException e) { + } catch (IncompleteRegionException e) { + break; + } break; - } - break; } } logger.info(builder.toString()); } - @Override - public void postInvoke(Object object, Method method, ParameterData[] parameters, Object[] args, CommandContext context) throws CommandException { - } - - @Override - public InvokeHandler createInvokeHandler() { - return this; - } - @Override public void close() { for (Handler h : logger.getHandlers()) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java index 10294c0a2..2e9c6fa62 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.internal.command; import static com.google.common.base.Preconditions.checkNotNull; -import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.worldedit.DisallowedItemException; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.IncompleteRegionException; @@ -35,6 +34,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.InsufficientArgumentsException; import com.sk89q.worldedit.command.tool.InvalidToolBindException; +import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.util.command.parametric.ExceptionConverterHelper; @@ -42,6 +42,8 @@ import com.sk89q.worldedit.util.command.parametric.ExceptionMatch; import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException; import com.sk89q.worldedit.util.io.file.FilenameResolutionException; import com.sk89q.worldedit.util.io.file.InvalidFilenameException; +import org.enginehub.piston.exception.CommandException; +import org.enginehub.piston.exception.ConditionFailedException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -65,99 +67,106 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { if (matcher.matches()) { throw new CommandException("Number expected; string \"" + matcher.group(1) - + "\" given."); + + "\" given.", e, null); } else { - throw new CommandException("Number expected; string given."); + throw new CommandException("Number expected; string given.", e, null); } } @ExceptionMatch public void convert(IncompleteRegionException e) throws CommandException { - throw new CommandException("Make a region selection first."); + throw new CommandException("Make a region selection first.", e, null); } @ExceptionMatch public void convert(UnknownItemException e) throws CommandException { - throw new CommandException("Block name '" + e.getID() + "' was not recognized."); + throw new CommandException("Block name '" + e.getID() + "' was not recognized.", e, null); } @ExceptionMatch public void convert(InvalidItemException e) throws CommandException { - throw new CommandException(e.getMessage()); + throw new CommandException(e.getMessage(), e, null); } @ExceptionMatch public void convert(DisallowedItemException e) throws CommandException { throw new CommandException("Block '" + e.getID() - + "' not allowed (see WorldEdit configuration)."); + + "' not allowed (see WorldEdit configuration).", e, null); } @ExceptionMatch public void convert(MaxChangedBlocksException e) throws CommandException { throw new CommandException("Max blocks changed in an operation reached (" - + e.getBlockLimit() + ")."); + + e.getBlockLimit() + ").", e, null); } @ExceptionMatch public void convert(MaxBrushRadiusException e) throws CommandException { - throw new CommandException("Maximum brush radius (in configuration): " + worldEdit.getConfiguration().maxBrushRadius); + throw new CommandException("Maximum brush radius (in configuration): " + worldEdit.getConfiguration().maxBrushRadius, e, null); } @ExceptionMatch public void convert(MaxRadiusException e) throws CommandException { - throw new CommandException("Maximum radius (in configuration): " + worldEdit.getConfiguration().maxRadius); + throw new CommandException("Maximum radius (in configuration): " + worldEdit.getConfiguration().maxRadius, e, null); } @ExceptionMatch public void convert(UnknownDirectionException e) throws CommandException { - throw new CommandException("Unknown direction: " + e.getDirection()); + throw new CommandException("Unknown direction: " + e.getDirection(), e, null); } @ExceptionMatch public void convert(InsufficientArgumentsException e) throws CommandException { - throw new CommandException(e.getMessage()); + throw new CommandException(e.getMessage(), e, null); } @ExceptionMatch public void convert(RegionOperationException e) throws CommandException { - throw new CommandException(e.getMessage()); + throw new CommandException(e.getMessage(), e, null); } @ExceptionMatch public void convert(ExpressionException e) throws CommandException { - throw new CommandException(e.getMessage()); + throw new CommandException(e.getMessage(), e, null); } @ExceptionMatch public void convert(EmptyClipboardException e) throws CommandException { - throw new CommandException("Your clipboard is empty. Use //copy first."); + throw new CommandException("Your clipboard is empty. Use //copy first.", e, null); } @ExceptionMatch public void convert(InvalidFilenameException e) throws CommandException { throw new CommandException("Filename '" + e.getFilename() + "' invalid: " - + e.getMessage()); + + e.getMessage(), e, null); } @ExceptionMatch public void convert(FilenameResolutionException e) throws CommandException { throw new CommandException( - "File '" + e.getFilename() + "' resolution error: " + e.getMessage()); + "File '" + e.getFilename() + "' resolution error: " + e.getMessage(), e, null); } @ExceptionMatch public void convert(InvalidToolBindException e) throws CommandException { - throw new CommandException("Can't bind tool to " + e.getItemType().getName() + ": " + e.getMessage()); + throw new CommandException("Can't bind tool to " + e.getItemType().getName() + ": " + e.getMessage(), e, null); } @ExceptionMatch public void convert(FileSelectionAbortedException e) throws CommandException { - throw new CommandException("File selection aborted."); + throw new CommandException("File selection aborted.", e, null); } @ExceptionMatch public void convert(WorldEditException e) throws CommandException { - throw new CommandException(e.getMessage(), e); + throw new CommandException(e.getMessage(), e, null); + } + + @ExceptionMatch + public void convert(ConditionFailedException e) throws CommandException { + if (e.getCondition() instanceof PermissionCondition) { + throw new CommandException("You are not permitted to do that. Are you in the right mode?", e, null); + } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverter.java index 1eb9491ca..3ab0dda59 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverter.java @@ -19,8 +19,9 @@ package com.sk89q.worldedit.util.command.parametric; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.WrappedCommandException; + +import org.enginehub.piston.exception.CommandException; +import org.enginehub.piston.exception.CommandExecutionException; /** * Used to convert a recognized {@link Throwable} into an appropriate @@ -29,7 +30,7 @@ import com.sk89q.minecraft.util.commands.WrappedCommandException; *

Methods (when invoked by a {@link ParametricBuilder}-created command) may throw * relevant exceptions that are not caught by the command manager, but translate * into reasonable exceptions for an application. However, unknown exceptions are - * normally simply wrapped in a {@link WrappedCommandException} and bubbled up. Only + * normally simply wrapped in a {@link CommandExecutionException} and bubbled up. Only * normal {@link CommandException}s will be printed correctly, so a converter translates * one of these unknown exceptions into an appropriate {@link CommandException}.

* diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverterHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverterHelper.java index 5b2d9fd5d..f13557487 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverterHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverterHelper.java @@ -19,8 +19,9 @@ package com.sk89q.worldedit.util.command.parametric; -import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.WrappedCommandException; +import org.enginehub.piston.exception.CommandException; +import org.enginehub.piston.exception.CommandExecutionException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -75,9 +76,9 @@ public abstract class ExceptionConverterHelper implements ExceptionConverter { if (e.getCause() instanceof CommandException) { throw (CommandException) e.getCause(); } - throw new WrappedCommandException(e); + throw new CommandExecutionException(e, null); } catch (IllegalArgumentException | IllegalAccessException e) { - throw new WrappedCommandException(e); + throw new CommandExecutionException(e, null); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandUsageBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandUsageBox.java index 00a16c24e..c7c5cf40d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandUsageBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandUsageBox.java @@ -22,7 +22,7 @@ package com.sk89q.worldedit.util.formatting.component; import static com.google.common.base.Preconditions.checkNotNull; import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.extension.platform.CommandManager; +import com.sk89q.worldedit.extension.platform.PlatformCommandMananger; import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Description; @@ -72,7 +72,7 @@ public class CommandUsageBox extends StyledFragment { String prefix = !commandString.isEmpty() ? commandString + " " : ""; List list = new ArrayList<>(dispatcher.getCommands()); - list.sort(new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN)); + list.sort(new PrimaryAliasComparator(PlatformCommandMananger.COMMAND_CLEAN_PATTERN)); for (CommandMapping mapping : list) { if (locals == null || mapping.getCallable().testPermission(locals)) { diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java index daab12824..2f4c650b9 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/CommandWrapper.java @@ -19,15 +19,17 @@ package com.sk89q.worldedit.forge; +import com.google.common.collect.ImmutableList; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.tree.LiteralCommandNode; -import com.sk89q.worldedit.util.command.CommandMapping; +import com.sk89q.worldedit.command.util.PermissionCondition; import net.minecraft.command.CommandSource; import net.minecraft.entity.player.EntityPlayerMP; +import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Stream; import static net.minecraft.command.Commands.literal; @@ -35,11 +37,14 @@ public final class CommandWrapper { private CommandWrapper() { } - public static void register(CommandDispatcher dispatcher, CommandMapping command) { - for (String alias : command.getAllAliases()) { + public static void register(CommandDispatcher dispatcher, org.enginehub.piston.Command command) { + ImmutableList.Builder aliases = ImmutableList.builder(); + aliases.add(command.getName()).addAll(command.getAliases()); + for (String alias : aliases.build()) { LiteralArgumentBuilder base = literal(alias) .executes(FAKE_COMMAND); - if (command.getDescription().getPermissions().size() > 0) { + if (command.getCondition().as(PermissionCondition.class) + .filter(p -> p.getPermissions().size() > 0).isPresent()) { base.requires(requirementsFor(command)); } dispatcher.register(base); @@ -54,11 +59,14 @@ public final class CommandWrapper { return 1; }; - private static Predicate requirementsFor(CommandMapping mapping) { + private static Predicate requirementsFor(org.enginehub.piston.Command mapping) { return ctx -> { ForgePermissionsProvider permsProvider = ForgeWorldEdit.inst.getPermissionsProvider(); return ctx.getEntity() instanceof EntityPlayerMP && - mapping.getDescription().getPermissions().stream() + mapping.getCondition().as(PermissionCondition.class) + .map(PermissionCondition::getPermissions) + .map(Set::stream) + .orElseGet(Stream::empty) .allMatch(perm -> permsProvider.hasPermission( (EntityPlayerMP) ctx.getEntity(), perm )); diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java index 0530acc54..5989634bd 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlatform.java @@ -19,14 +19,13 @@ package com.sk89q.worldedit.forge; +import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.AbstractPlatform; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.MultiUserPlatform; import com.sk89q.worldedit.extension.platform.Preference; -import com.sk89q.worldedit.util.command.CommandMapping; -import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; import net.minecraft.command.Commands; @@ -36,13 +35,19 @@ import net.minecraft.server.management.PlayerList; import net.minecraft.util.ResourceLocation; import net.minecraft.world.WorldServer; import net.minecraftforge.fml.server.ServerLifecycleHooks; +import org.enginehub.piston.Command; +import org.enginehub.piston.CommandManager; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.EnumMap; import java.util.List; import java.util.Map; +import java.util.Set; + +import static java.util.stream.Collectors.toList; class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { @@ -117,16 +122,17 @@ class ForgePlatform extends AbstractPlatform implements MultiUserPlatform { } @Override - public void registerCommands(Dispatcher dispatcher) { + public void registerCommands(CommandManager manager) { if (server == null) return; Commands mcMan = server.getCommandManager(); - for (final CommandMapping command : dispatcher.getCommands()) { + for (Command command : manager.getAllCommands().collect(toList())) { CommandWrapper.register(mcMan.getDispatcher(), command); - if (command.getDescription().getPermissions().size() > 0) { - for (int i = 1; i < command.getDescription().getPermissions().size(); i++) { - ForgeWorldEdit.inst.getPermissionsProvider().registerPermission(command.getDescription().getPermissions().get(i)); - } + Set perms = command.getCondition().as(PermissionCondition.class) + .map(PermissionCondition::getPermissions) + .orElseGet(Collections::emptySet); + if (perms.size() > 0) { + perms.forEach(ForgeWorldEdit.inst.getPermissionsProvider()::registerPermission); } } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java index f94bd3b08..164f600d5 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/CommandAdapter.java @@ -19,23 +19,29 @@ package com.sk89q.worldedit.sponge; -import com.sk89q.worldedit.util.command.CommandMapping; +import com.sk89q.worldedit.command.util.PermissionCondition; +import org.enginehub.piston.Command; import org.spongepowered.api.command.CommandCallable; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.text.Text; +import java.util.Collections; import java.util.Optional; +import java.util.Set; public abstract class CommandAdapter implements CommandCallable { - private CommandMapping command; + private Command command; - protected CommandAdapter(CommandMapping command) { + protected CommandAdapter(Command command) { this.command = command; } @Override public boolean testPermission(CommandSource source) { - for (String perm : command.getDescription().getPermissions()) { + Set permissions = command.getCondition().as(PermissionCondition.class) + .map(PermissionCondition::getPermissions) + .orElseGet(Collections::emptySet); + for (String perm : permissions) { if (!source.hasPermission(perm)) { return false; } @@ -45,8 +51,8 @@ public abstract class CommandAdapter implements CommandCallable { @Override public Optional getShortDescription(CommandSource source) { - String description = command.getDescription().getDescription(); - if (description != null && !description.isEmpty()) { + String description = command.getDescription(); + if (!description.isEmpty()) { return Optional.of(Text.of(description)); } return Optional.empty(); @@ -54,8 +60,8 @@ public abstract class CommandAdapter implements CommandCallable { @Override public Optional getHelp(CommandSource source) { - String help = command.getDescription().getHelp(); - if (help != null && !help.isEmpty()) { + String help = command.getFullHelp(); + if (!help.isEmpty()) { return Optional.of(Text.of(help)); } return Optional.empty(); @@ -63,6 +69,6 @@ public abstract class CommandAdapter implements CommandCallable { @Override public Text getUsage(CommandSource source) { - return Text.of(command.getDescription().getUsage()); + return Text.of(command.getUsage()); } } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java index 774347645..29d2fad5a 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlatform.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.sponge; +import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.CommandEvent; @@ -33,6 +34,8 @@ import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.registry.Registries; +import org.enginehub.piston.Command; +import org.enginehub.piston.CommandManager; import org.spongepowered.api.Sponge; import org.spongepowered.api.command.CommandException; import org.spongepowered.api.command.CommandResult; @@ -50,6 +53,8 @@ import java.util.Optional; import javax.annotation.Nullable; +import static java.util.stream.Collectors.toList; + class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { private final SpongeWorldEdit mod; @@ -122,24 +127,26 @@ class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { } @Override - public void registerCommands(Dispatcher dispatcher) { - for (CommandMapping command : dispatcher.getCommands()) { + public void registerCommands(CommandManager manager) { + for (Command command : manager.getAllCommands().collect(toList())) { CommandAdapter adapter = new CommandAdapter(command) { @Override public CommandResult process(CommandSource source, String arguments) throws org.spongepowered.api.command.CommandException { - CommandEvent weEvent = new CommandEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getPrimaryAlias() + " " + arguments); + CommandEvent weEvent = new CommandEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getName() + " " + arguments); WorldEdit.getInstance().getEventBus().post(weEvent); return weEvent.isCancelled() ? CommandResult.success() : CommandResult.empty(); } @Override public List getSuggestions(CommandSource source, String arguments, @Nullable Location targetPosition) throws CommandException { - CommandSuggestionEvent weEvent = new CommandSuggestionEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getPrimaryAlias() + " " + arguments); + CommandSuggestionEvent weEvent = new CommandSuggestionEvent(SpongeWorldEdit.inst().wrapCommandSource(source), command.getName() + " " + arguments); WorldEdit.getInstance().getEventBus().post(weEvent); return weEvent.getSuggestions(); } }; - Sponge.getCommandManager().register(SpongeWorldEdit.inst(), adapter, command.getAllAliases()); + ImmutableList.Builder aliases = ImmutableList.builder(); + aliases.add(command.getName()).addAll(command.getAliases()); + Sponge.getCommandManager().register(SpongeWorldEdit.inst(), adapter, aliases.build()); } }