From 0e9fee3b6044bd2bde3f5c5af04ff52bee636ff6 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 8 Sep 2019 17:42:57 -0700 Subject: [PATCH 1/6] Add /tool back, deprecate global tool commands --- .../sk89q/worldedit/command/ToolCommands.java | 75 ++++++++++++++++++- .../platform/PlatformCommandManager.java | 11 +-- .../internal/command/CommandUtil.java | 63 ++++++++++++++++ 3 files changed, 137 insertions(+), 12 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 5c8de085c..f3ef732b4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.command; +import com.google.common.collect.Collections2; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -38,16 +39,82 @@ import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; +import com.sk89q.worldedit.internal.command.CommandUtil; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.item.ItemType; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.CommandManagerService; +import org.enginehub.piston.CommandMetadata; +import org.enginehub.piston.CommandParameters; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.part.SubCommandPart; + +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ToolCommands { + + public static void register(CommandRegistrationHandler registration, + CommandManager commandManager, + CommandManagerService commandManagerService, + WorldEdit worldEdit) { + // Collect the tool commands + CommandManager collect = commandManagerService.newCommandManager(); + + registration.register( + collect, + ToolCommandsRegistration.builder(), + new ToolCommands(worldEdit) + ); + + // Register deprecated global commands + Set commands = collect.getAllCommands() + .collect(Collectors.toSet()); + for (org.enginehub.piston.Command command : commands) { + commandManager.register(CommandUtil.deprecate( + command, "Using global tool names is deprecated " + + "and will be removed in WorldEdit 8", ToolCommands::asNonGlobal + )); + } + + // Remove aliases with / in them, since it doesn't make sense for sub-commands. + Set nonGlobalCommands = commands.stream() + .map(command -> + command.toBuilder().aliases( + Collections2.filter(command.getAliases(), alias -> !alias.startsWith("/")) + ).build() + ) + .collect(Collectors.toSet()); + commandManager.register("tool", command -> { + command.addPart(SubCommandPart.builder( + TranslatableComponent.of("tool"), + TextComponent.of("The tool to bind") + ) + .withCommands(nonGlobalCommands) + .required() + .build()); + command.description(TextComponent.of("Binds a tool to the item in your hand")); + }); + } + + private static String asNonGlobal(org.enginehub.piston.Command oldCommand, + CommandParameters oldParameters) { + String name = Optional.ofNullable(oldParameters.getMetadata()) + .map(CommandMetadata::getCalledName) + .filter(n -> !n.startsWith("/")) + .orElseGet(oldCommand::getName); + return "/tool " + name; + } + private final WorldEdit we; public ToolCommands(WorldEdit we) { @@ -65,8 +132,8 @@ public class ToolCommands { } @Command( - name = "/selwand", - aliases = "selwand", + name = "selwand", + aliases = "/selwand", desc = "Selection wand tool" ) @CommandPermissions("worldedit.setwand") @@ -78,8 +145,8 @@ public class ToolCommands { } @Command( - name = "/navwand", - aliases = "navwand", + name = "navwand", + aliases = "/navwand", desc = "Navigation wand tool" ) @CommandPermissions("worldedit.setwand") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index 296dfd1c3..2913a277d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.extension.platform; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.TypeToken; @@ -64,7 +62,6 @@ import com.sk89q.worldedit.command.SnapshotUtilCommandsRegistration; import com.sk89q.worldedit.command.SuperPickaxeCommands; import com.sk89q.worldedit.command.SuperPickaxeCommandsRegistration; import com.sk89q.worldedit.command.ToolCommands; -import com.sk89q.worldedit.command.ToolCommandsRegistration; import com.sk89q.worldedit.command.ToolUtilCommands; import com.sk89q.worldedit.command.ToolUtilCommandsRegistration; import com.sk89q.worldedit.command.UtilityCommands; @@ -141,6 +138,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import static com.google.common.base.Preconditions.checkNotNull; + /** * Handles the registration and invocation of commands. * @@ -399,11 +398,7 @@ public final class PlatformCommandManager { SnapshotUtilCommandsRegistration.builder(), new SnapshotUtilCommands(worldEdit) ); - this.registration.register( - commandManager, - ToolCommandsRegistration.builder(), - new ToolCommands(worldEdit) - ); + ToolCommands.register(registration, commandManager, commandManagerService, worldEdit); this.registration.register( commandManager, ToolUtilCommandsRegistration.builder(), diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java index bdcd8e541..d1690fc24 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java @@ -21,11 +21,17 @@ package com.sk89q.worldedit.internal.command; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.PlatformCommandManager; import com.sk89q.worldedit.internal.util.Substring; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.formatting.text.format.TextDecoration; import org.enginehub.piston.Command; +import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.NoInputCommandParameters; import org.enginehub.piston.exception.CommandException; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; @@ -43,6 +49,63 @@ import static java.util.stream.Collectors.toList; public class CommandUtil { + private static Component makeDeprecatedFooter(Component newCommand) { + return TextComponent.builder("This command is deprecated. Use ", TextColor.GOLD) + .decoration(TextDecoration.ITALIC, true) + .append(newCommand) + .append(" instead.") + .build(); + } + + public interface NewCommandGenerator { + + String newCommand(Command oldCommand, CommandParameters oldParameters); + + } + + public static Command deprecate(Command command, String reason, + NewCommandGenerator newCommandGenerator) { + Component deprecatedWarning = makeDeprecatedFooter( + newCommandSuggestion(newCommandGenerator, + NoInputCommandParameters.builder().build(), + command) + ); + return command.toBuilder() + .action(parameters -> + deprecatedCommandWarning(parameters, command, reason, newCommandGenerator)) + .footer(command.getFooter() + .map(existingFooter -> existingFooter + .append(TextComponent.newline()).append(deprecatedWarning)) + .orElse(deprecatedWarning)) + .build(); + } + + private static int deprecatedCommandWarning( + CommandParameters parameters, + Command command, + String reason, + NewCommandGenerator generator + ) throws Exception { + parameters.injectedValue(Key.of(Actor.class)) + .ifPresent(actor -> { + Component suggestion = newCommandSuggestion(generator, parameters, command); + actor.print(TextComponent.of(reason + ". Please use ", TextColor.GOLD) + .append(suggestion) + .append(TextComponent.of(" instead.")) + ); + }); + return command.getAction().run(parameters); + } + + private static Component newCommandSuggestion(NewCommandGenerator generator, + CommandParameters parameters, + Command command) { + String suggestedCommand = generator.newCommand(command, parameters); + return TextComponent.of(suggestedCommand) + .decoration(TextDecoration.UNDERLINED, true) + .clickEvent(ClickEvent.suggestCommand(suggestedCommand)); + } + public static Map getSubCommands(Command currentCommand) { return currentCommand.getParts().stream() .filter(p -> p instanceof SubCommandPart) From ba26d788af7274a9abba5543226d5bcfd558ba2d Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 9 Sep 2019 18:13:57 -0700 Subject: [PATCH 2/6] Add `/brush none` and unbind aliases --- .../sk89q/worldedit/command/BrushCommands.java | 9 +++++++++ .../sk89q/worldedit/command/ToolCommands.java | 18 +++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 9b8e35dae..e15159af6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -82,6 +82,15 @@ public class BrushCommands { this.worldEdit = worldEdit; } + @Command( + name = "none", + aliases = "unbind", + desc = "Unbind a bound brush from your current item" + ) + void none(Player player, LocalSession session) throws WorldEditException { + ToolCommands.setToolNone(player, session, "Brush"); + } + @Command( name = "sphere", aliases = { "s" }, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index f3ef732b4..29c05676c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.command.tool.BlockReplacer; import com.sk89q.worldedit.command.tool.DistanceWand; import com.sk89q.worldedit.command.tool.FloatingTreeRemover; import com.sk89q.worldedit.command.tool.FloodFillTool; +import com.sk89q.worldedit.command.tool.InvalidToolBindException; import com.sk89q.worldedit.command.tool.LongRangeBuildTool; import com.sk89q.worldedit.command.tool.NavigationWand; import com.sk89q.worldedit.command.tool.QueryTool; @@ -80,6 +81,12 @@ public class ToolCommands { Set commands = collect.getAllCommands() .collect(Collectors.toSet()); for (org.enginehub.piston.Command command : commands) { + if (command.getAliases().contains("unbind")) { + // Don't register new /tool unbind alias + command = command.toBuilder().aliases( + Collections2.filter(command.getAliases(), alias -> !"unbind".equals(alias)) + ).build(); + } commandManager.register(CommandUtil.deprecate( command, "Using global tool names is deprecated " + "and will be removed in WorldEdit 8", ToolCommands::asNonGlobal @@ -115,6 +122,12 @@ public class ToolCommands { return "/tool " + name; } + static void setToolNone(Player player, LocalSession session, String type) + throws InvalidToolBindException { + session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null); + player.print(type + " unbound from your current item."); + } + private final WorldEdit we; public ToolCommands(WorldEdit we) { @@ -123,12 +136,11 @@ public class ToolCommands { @Command( name = "none", + aliases = "unbind", desc = "Unbind a bound tool from your current item" ) public void none(Player player, LocalSession session) throws WorldEditException { - - session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null); - player.print("Tool unbound from your current item."); + setToolNone(player, session, "Tool"); } @Command( From 6162a47002e26c72c37c9dc7ebe9d7030f722bd1 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sat, 21 Sep 2019 18:21:22 -0700 Subject: [PATCH 3/6] Force non-Locatable actors to use placeAtPos1 --- .../src/main/java/com/sk89q/worldedit/LocalSession.java | 8 ++++++++ .../java/com/sk89q/worldedit/session/SessionManager.java | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 0b85b6cd2..63e915ebe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -521,6 +521,14 @@ public class LocalSession { return selector.getPrimaryPosition(); } + public void setPlaceAtPos1(boolean placeAtPos1) { + this.placeAtPos1 = placeAtPos1; + } + + public boolean isPlaceAtPos1() { + return placeAtPos1; + } + /** * Toggle placement position. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java index ef346d429..4e45becca 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/SessionManager.java @@ -34,6 +34,7 @@ import com.sk89q.worldedit.command.tool.SelectionWand; import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; +import com.sk89q.worldedit.extension.platform.Locatable; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.storage.JsonFileSessionStore; import com.sk89q.worldedit.session.storage.SessionStore; @@ -199,6 +200,11 @@ public class SessionManager { && (owner.hasPermission("worldedit.inventory.unrestricted") || (config.useInventoryCreativeOverride && (!(owner instanceof Player) || ((Player) owner).getGameMode() == GameModes.CREATIVE))))); + // Force non-locatable actors to use placeAtPos1 + if (!(owner instanceof Locatable)) { + session.setPlaceAtPos1(true); + } + return session; } From bb8c150ed36004407f46541b27982333542638ca Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 22 Sep 2019 14:12:34 -0700 Subject: [PATCH 4/6] Update ForgeGradle + Gradle --- buildSrc/build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 101cff2aa..40fd86deb 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -32,5 +32,5 @@ dependencies { implementation("net.ltgt.apt-idea:net.ltgt.apt-idea.gradle.plugin:0.21") implementation("org.jfrog.buildinfo:build-info-extractor-gradle:4.9.7") implementation("gradle.plugin.org.spongepowered:spongegradle:0.9.0") - implementation("net.minecraftforge.gradle:ForgeGradle:3.0.141") + implementation("net.minecraftforge.gradle:ForgeGradle:3.0.143") } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 430dfabc5..ca9d62814 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 8e25e6c19..83f2acfdc 100755 --- a/gradlew +++ b/gradlew @@ -125,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` From fa25ad22cda96470fe9d8073e59c50a48cb7f81f Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 23 Sep 2019 11:46:24 -0700 Subject: [PATCH 6/6] Harden JsonFileSessionStore against nulls/Gson oddities --- .../session/storage/JsonFileSessionStore.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/storage/JsonFileSessionStore.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/storage/JsonFileSessionStore.java index ad8e422bf..aa2d579fd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/storage/JsonFileSessionStore.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/storage/JsonFileSessionStore.java @@ -88,7 +88,15 @@ public class JsonFileSessionStore implements SessionStore { try (Closer closer = Closer.create()) { FileReader fr = closer.register(new FileReader(file)); BufferedReader br = closer.register(new BufferedReader(fr)); - return gson.fromJson(br, LocalSession.class); + LocalSession session = gson.fromJson(br, LocalSession.class); + if (session == null) { + log.warn("Loaded a null session from {}, creating new session", file); + if (!file.delete()) { + log.warn("Failed to delete corrupted session {}", file); + } + session = new LocalSession(); + } + return session; } catch (JsonParseException e) { throw new IOException(e); } catch (FileNotFoundException e) { @@ -98,6 +106,7 @@ public class JsonFileSessionStore implements SessionStore { @Override public void save(UUID id, LocalSession session) throws IOException { + checkNotNull(session); File finalFile = getPath(id); File tempFile = new File(finalFile.getParentFile(), finalFile.getName() + ".tmp"); @@ -115,6 +124,10 @@ public class JsonFileSessionStore implements SessionStore { } } + if (tempFile.length() == 0) { + throw new IllegalStateException("Gson wrote zero bytes"); + } + if (!tempFile.renameTo(finalFile)) { log.warn("Failed to rename temporary session file to " + finalFile.getPath()); }