From 1966e5a8a24f0f14927fe5cd3a2eadfd58df7fee Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 14 Mar 2019 02:10:37 -0700 Subject: [PATCH 01/57] Initial Piston conversion test. Non-functional. --- gradle/wrapper/gradle-wrapper.properties | 3 +- settings.gradle | 4 +- worldedit-core/build.gradle | 73 +++++++++-------- .../worldedit/command/SchematicCommands.java | 80 +++++++++---------- .../command/util/AsyncCommandHelper.java | 7 +- .../util/paste/ActorCallbackPaste.java | 3 +- 6 files changed, 91 insertions(+), 79 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a95009c3b..a9534e761 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Thu Mar 14 00:19:48 PDT 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip diff --git a/settings.gradle b/settings.gradle index 576283ecc..6b725d8d1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,5 @@ rootProject.name = 'worldedit' -include 'worldedit-core', 'worldedit-bukkit', 'worldedit-forge', 'worldedit-sponge' \ No newline at end of file +include 'worldedit-core', 'worldedit-bukkit', 'worldedit-forge', 'worldedit-sponge' + +includeBuild("../Piston") diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index f91186083..3047ad577 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -1,32 +1,41 @@ -apply plugin: 'eclipse' -apply plugin: 'idea' - -dependencies { - compile 'de.schlichtherle:truezip:6.8.3' - compile 'rhino:js:1.7R2' - compile 'org.yaml:snakeyaml:1.9' - compile 'com.google.guava:guava:21.0' - compile 'com.sk89q:jchronic:0.2.4a' - compile 'com.google.code.findbugs:jsr305:1.3.9' - compile 'com.thoughtworks.paranamer:paranamer:2.6' - compile 'com.google.code.gson:gson:2.8.0' - compile 'com.sk89q.lib:jlibnoise:1.0.0' - compile 'com.googlecode.json-simple:json-simple:1.1.1' - compile 'org.slf4j:slf4j-api:1.7.26' - //compile 'net.sf.trove4j:trove4j:3.0.3' - testCompile 'org.mockito:mockito-core:1.9.0-rc1' -} - -sourceSets { - main { - java { - srcDir 'src/main/java' - srcDir 'src/legacy/java' - } - resources { - srcDir 'src/main/resources' - } - } -} - -build.dependsOn(shadowJar) +plugins { + id("net.ltgt.apt") version "0.21" +} + +apply plugin: 'eclipse' +apply plugin: 'idea' +apply plugin: 'net.ltgt.apt-eclipse' +apply plugin: 'net.ltgt.apt-idea' + +dependencies { + compile 'de.schlichtherle:truezip:6.8.3' + compile 'rhino:js:1.7R2' + compile 'org.yaml:snakeyaml:1.9' + compile 'com.google.guava:guava:21.0' + compile 'com.sk89q:jchronic:0.2.4a' + compile 'com.google.code.findbugs:jsr305:1.3.9' + compile 'com.thoughtworks.paranamer:paranamer:2.6' + compile 'com.google.code.gson:gson:2.8.0' + compile 'com.sk89q.lib:jlibnoise:1.0.0' + compile 'com.googlecode.json-simple:json-simple:1.1.1' + compile 'org.slf4j:slf4j-api:1.7.26' + compileOnly 'org.enginehub.piston:core-ap-annotations:0.0.1-SNAPSHOT' + annotationProcessor 'org.enginehub.piston:core-ap-processor:0.0.1-SNAPSHOT' + compile 'org.enginehub.piston:default-impl:0.0.1-SNAPSHOT' + //compile 'net.sf.trove4j:trove4j:3.0.3' + testCompile 'org.mockito:mockito-core:1.9.0-rc1' +} + +sourceSets { + main { + java { + srcDir 'src/main/java' + srcDir 'src/legacy/java' + } + resources { + srcDir 'src/main/resources' + } + } +} + +build.dependsOn(shadowJar) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index ab8ff950b..d685318f8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.command; import com.google.common.collect.Multimap; import com.google.common.io.Files; -import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandPermissions; @@ -41,10 +40,13 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.session.ClipboardHolder; -import com.sk89q.worldedit.util.command.binding.Switch; -import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.file.FilenameException; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.ArgFlag; +import org.enginehub.piston.annotation.param.Switch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,6 +66,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Commands that work with schematic files. */ +@CommandContainer public class SchematicCommands { /** @@ -84,13 +87,13 @@ public class SchematicCommands { } @Command( - aliases = { "load" }, - usage = "[] ", - desc = "Load a schematic into your clipboard", - min = 1, max = 2 + name = "load", + desc = "Load a schematic into your clipboard" ) - @CommandPermissions({ "worldedit.clipboard.load", "worldedit.schematic.load" }) - public void load(Player player, LocalSession session, @Optional("sponge") String formatName, String filename) throws FilenameException { + @CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"}) + public void load(Player player, LocalSession session, + @Arg(desc = "File name.") String filename, + @Arg(desc = "Format name.", def = "sponge") String formatName) throws FilenameException { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -127,16 +130,15 @@ public class SchematicCommands { } @Command( - aliases = { "save" }, - flags = "f", - usage = "[] ", - desc = "Save a schematic into your clipboard", - help = "-f is required to overwrite an existing file", - min = 1, max = 2 + name = "save", + desc = "Save a schematic into your clipboard" ) - @CommandPermissions({ "worldedit.clipboard.save", "worldedit.schematic.save" }) - public void save(Player player, LocalSession session, @Optional("sponge") String formatName, - String filename, @Switch('f') boolean allowOverwrite) throws CommandException, WorldEditException { + @CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"}) + public void save(Player player, LocalSession session, + @Arg(desc = "File name.") String filename, + @Arg(desc = "Format name.", def = "sponge") String formatName, + @Switch(name = 'f', desc = "Overwrite an existing file.") boolean allowOverwrite + ) throws CommandException, WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -198,15 +200,13 @@ public class SchematicCommands { } @Command( - aliases = { "delete", "d" }, - usage = "", - desc = "Delete a saved schematic", - help = "Delete a schematic from the schematic list", - min = 1, - max = 1 + name = "delete", + aliases = {"d"}, + desc = "Delete a saved schematic" ) @CommandPermissions("worldedit.schematic.delete") - public void delete(Actor actor, String filename) throws WorldEditException { + public void delete(Actor actor, + @Arg(desc = "File name.") String filename) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -232,12 +232,12 @@ public class SchematicCommands { } @Command( - aliases = {"formats", "listformats", "f"}, - desc = "List available formats", - max = 0 + name = "formats", + aliases = {"listformats", "f"}, + desc = "List available formats" ) @CommandPermissions("worldedit.schematic.formats") - public void formats(Actor actor) throws WorldEditException { + public void formats(Actor actor) { actor.print("Available clipboard formats (Name: Lookup names)"); StringBuilder builder; boolean first = true; @@ -257,18 +257,14 @@ public class SchematicCommands { } @Command( - aliases = {"list", "all", "ls"}, - desc = "List saved schematics", - max = 1, - flags = "dnp", - help = "List all schematics in the schematics directory\n" + - " -d sorts by date, oldest first\n" + - " -n sorts by date, newest first\n" + - " -p prints the requested page\n" + - "Note: Format is not thoroughly verified until loading." + name = "list", + aliases = {"all", "ls"}, + desc = "List saved schematics", + descFooter = "Note: Format is not fully verified until loading." ) @CommandPermissions("worldedit.schematic.list") - public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page) throws WorldEditException { + public void list(Actor actor, CommandContext args, + @ArgFlag(name = 'p', desc = "Page to view.", def = "1") int page) { File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir); List fileList = allFiles(dir); @@ -315,7 +311,7 @@ public class SchematicCommands { actor.print("Available schematics (Filename: Format) [" + page + "/" + pageCount + "]:"); StringBuilder build = new StringBuilder(); int limit = Math.min(offset + SCHEMATICS_PER_PAGE, schematics.size()); - for (int i = offset; i < limit;) { + for (int i = offset; i < limit; ) { build.append(schematics.get(i)); if (++i != limit) { build.append("\n"); @@ -351,10 +347,10 @@ public class SchematicCommands { //ClipboardFormat format = ClipboardFormats.findByFile(file); Multimap exts = ClipboardFormats.getFileExtensionMap(); ClipboardFormat format = exts.get(Files.getFileExtension(file.getName())) - .stream().findFirst().orElse(null); + .stream().findFirst().orElse(null); boolean inRoot = file.getParentFile().getName().equals(prefix); build.append(inRoot ? file.getName() : file.getPath().split(Pattern.quote(prefix + File.separator))[1]) - .append(": ").append(format == null ? "Unknown" : format.getName() + "*"); + .append(": ").append(format == null ? "Unknown" : format.getName() + "*"); result.add(build.toString()); } return result; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java index f3b707435..7557b0834 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java @@ -30,6 +30,7 @@ import com.sk89q.worldedit.util.task.Supervisor; import com.sk89q.worldedit.world.World; import javax.annotation.Nullable; +import java.util.concurrent.ForkJoinPool; public class AsyncCommandHelper { @@ -85,7 +86,8 @@ public class AsyncCommandHelper { .exceptionConverter(exceptionConverter) .onSuccess(format(success)) .onFailure(format(failure)) - .build()); + .build(), + ForkJoinPool.commonPool()); return this; } @@ -96,7 +98,8 @@ public class AsyncCommandHelper { new MessageFutureCallback.Builder(sender) .exceptionConverter(exceptionConverter) .onFailure(format(failure)) - .build()); + .build(), + ForkJoinPool.commonPool()); return this; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java index bcacbfd8f..4c86e6866 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java @@ -30,6 +30,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.URL; +import java.util.concurrent.ForkJoinPool; public class ActorCallbackPaste { @@ -65,7 +66,7 @@ public class ActorCallbackPaste { LOGGER.warn("Failed to submit pastebin", throwable); sender.printError("Failed to submit to a pastebin. Please see console for the error."); } - }); + }, ForkJoinPool.commonPool()); } } From 8ab6585815474986c0b93f5144f5041861dfd92c Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 4 Apr 2019 16:16:04 -0700 Subject: [PATCH 02/57] Patch new cmds system into old system --- config/checkstyle/import-control.xml | 2 + worldedit-bukkit/build.gradle | 6 ++ worldedit-core/build.gradle | 9 +- .../worldedit/command/SchematicCommands.java | 22 +++-- .../command/util/CommandPermissions.java | 39 ++++++++ .../CommandPermissionsConditionGenerator.java | 49 ++++++++++ .../extension/platform/CommandManager.java | 32 +++++-- .../platform/CommandManagerCallable.java | 90 +++++++++++++++++++ worldedit-forge/build.gradle | 6 ++ 9 files changed, 238 insertions(+), 17 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissions.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissionsConditionGenerator.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManagerCallable.java diff --git a/config/checkstyle/import-control.xml b/config/checkstyle/import-control.xml index 28ccad1e4..5bcfffeb3 100644 --- a/config/checkstyle/import-control.xml +++ b/config/checkstyle/import-control.xml @@ -16,6 +16,8 @@ + + diff --git a/worldedit-bukkit/build.gradle b/worldedit-bukkit/build.gradle index 335b96c0a..3c5832e9b 100644 --- a/worldedit-bukkit/build.gradle +++ b/worldedit-bukkit/build.gradle @@ -8,6 +8,12 @@ repositories { maven { url 'https://papermc.io/repo/repository/maven-public/' } } +configurations.all { Configuration it -> + it.resolutionStrategy { ResolutionStrategy rs -> + rs.force("com.google.guava:guava:21.0") + } +} + dependencies { compile project(':worldedit-core') compile 'com.sk89q:dummypermscompat:1.10' diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index 3047ad577..5f6cce5a6 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -7,6 +7,12 @@ apply plugin: 'idea' apply plugin: 'net.ltgt.apt-eclipse' apply plugin: 'net.ltgt.apt-idea' +configurations.all { Configuration it -> + it.resolutionStrategy { ResolutionStrategy rs -> + rs.force("com.google.guava:guava:21.0") + } +} + dependencies { compile 'de.schlichtherle:truezip:6.8.3' compile 'rhino:js:1.7R2' @@ -20,7 +26,8 @@ dependencies { compile 'com.googlecode.json-simple:json-simple:1.1.1' compile 'org.slf4j:slf4j-api:1.7.26' compileOnly 'org.enginehub.piston:core-ap-annotations:0.0.1-SNAPSHOT' - annotationProcessor 'org.enginehub.piston:core-ap-processor:0.0.1-SNAPSHOT' + compile 'org.enginehub.piston:core-ap-runtime:0.0.1-SNAPSHOT' + annotationProcessor 'org.enginehub.piston:core-ap-processor:0.0.1-SNAPSHOT' compile 'org.enginehub.piston:default-impl:0.0.1-SNAPSHOT' //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/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index d685318f8..2bdd77bf0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -21,13 +21,11 @@ package com.sk89q.worldedit.command; import com.google.common.collect.Multimap; import com.google.common.io.Files; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -49,6 +47,7 @@ import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.Switch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.enginehub.piston.exception.StopExecutionException; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -138,7 +137,7 @@ public class SchematicCommands { @Arg(desc = "File name.") String filename, @Arg(desc = "Format name.", def = "sponge") String formatName, @Switch(name = 'f', desc = "Overwrite an existing file.") boolean allowOverwrite - ) throws CommandException, WorldEditException { + ) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -154,7 +153,7 @@ public class SchematicCommands { boolean overwrite = f.exists(); if (overwrite) { if (!player.hasPermission("worldedit.schematic.delete")) { - throw new CommandException("That schematic already exists!"); + throw new StopExecutionException("That schematic already exists!"); } if (!allowOverwrite) { player.printError("That schematic already exists. Use the -f flag to overwrite it."); @@ -181,7 +180,7 @@ public class SchematicCommands { File parent = f.getParentFile(); if (parent != null && !parent.exists()) { if (!parent.mkdirs()) { - throw new CommandException("Could not create folder for schematics!"); + throw new StopExecutionException("Could not create folder for schematics!"); } } @@ -263,8 +262,13 @@ public class SchematicCommands { descFooter = "Note: Format is not fully verified until loading." ) @CommandPermissions("worldedit.schematic.list") - public void list(Actor actor, CommandContext args, - @ArgFlag(name = 'p', desc = "Page to view.", def = "1") int page) { + public void list(Actor actor, + @ArgFlag(name = 'p', desc = "Page to view.", def = "1") int page, + @Switch(name = 'd', desc = "Sort by date, oldest first") boolean oldFirst, + @Switch(name = 'n', desc = "Sort by date, newest first") boolean newFirst) { + if (oldFirst && newFirst) { + throw new StopExecutionException("Cannot sort by oldest and newest."); + } File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir); List fileList = allFiles(dir); @@ -286,7 +290,7 @@ public class SchematicCommands { return; } - final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0; + final int sortType = oldFirst ? -1 : newFirst ? 1 : 0; // cleanup file list Arrays.sort(files, (f1, f2) -> { // http://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissions.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissions.java new file mode 100644 index 000000000..feefb9aba --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissions.java @@ -0,0 +1,39 @@ +/* + * 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 org.enginehub.piston.annotation.CommandCondition; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@CommandCondition(CommandPermissionsConditionGenerator.class) +public @interface CommandPermissions { + + /** + * A list of permissions. Only one permission has to be met + * for the command to be permitted. + * + * @return a list of permissions strings + */ + String[] value(); + +} 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 new file mode 100644 index 000000000..d00d286d6 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CommandPermissionsConditionGenerator.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.common.collect.ImmutableSet; +import com.google.inject.Key; +import com.sk89q.worldedit.extension.platform.Actor; +import org.enginehub.piston.Command; +import org.enginehub.piston.gen.CommandConditionGenerator; +import org.enginehub.piston.util.NonnullByDefault; + +import java.lang.reflect.Method; +import java.util.Set; + +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 -> { + Actor actor = p.injectedValue(ACTOR_KEY); + return permissions.stream().anyMatch(actor::hasPermission); + }; + } +} 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/CommandManager.java index a0be07b65..9a2a9da78 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/CommandManager.java @@ -19,10 +19,8 @@ package com.sk89q.worldedit.extension.platform; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.util.command.composition.LegacyCommandAdapter.adapt; - import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandPermissionsException; @@ -41,6 +39,7 @@ import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.NavigationCommands; import com.sk89q.worldedit.command.RegionCommands; 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; @@ -57,6 +56,7 @@ 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.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; @@ -69,8 +69,10 @@ 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; @@ -82,6 +84,7 @@ 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.DefaultCommandManagerService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,6 +94,9 @@ import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.regex.Pattern; +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. * @@ -158,10 +164,7 @@ public final class CommandManager { .describeAs("WorldEdit commands") .registerMethods(new WorldEditCommands(worldEdit)) .parent() - .group("schematic", "schem", "/schematic", "/schem") - .describeAs("Schematic commands for saving/loading areas") - .registerMethods(new SchematicCommands(worldEdit)) - .parent() + .register(schematicCommands(),"schematic", "schem", "/schematic", "/schem") .group("snapshot", "snap") .describeAs("Schematic commands for saving/loading areas") .registerMethods(new SnapshotCommands(worldEdit)) @@ -189,6 +192,21 @@ public final class CommandManager { .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(); + new SchematicCommandsRegistration( + manager, + new SchematicCommands(worldEdit), + new CommandPermissionsConditionGenerator() + ); + + return new CommandManagerCallable(worldEdit, manager, desc); + } + public ExceptionConverter getExceptionConverter() { return exceptionConverter; } 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 new file mode 100644 index 000000000..bb6079713 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManagerCallable.java @@ -0,0 +1,90 @@ +/* + * 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; + +/** + * 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), () -> locals.get(Actor.class)); + manager.injectValue(Key.get(Player.class), () -> getPlayer(locals)); + manager.injectValue(Key.get(LocalSession.class), () -> { + Player sender = getPlayer(locals); + return worldEdit.getSessionManager().get(sender); + }); + manager.injectValue(Key.get(EditSession.class), () -> { + Player sender = getPlayer(locals); + 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-forge/build.gradle b/worldedit-forge/build.gradle index 8fe3fb9af..62b38c8e8 100644 --- a/worldedit-forge/build.gradle +++ b/worldedit-forge/build.gradle @@ -16,6 +16,12 @@ apply plugin: 'net.minecraftforge.gradle' def minecraftVersion = "1.13.2" def forgeVersion = "25.0.76" +configurations.all { Configuration it -> + it.resolutionStrategy { ResolutionStrategy rs -> + rs.force("com.google.guava:guava:21.0") + } +} + dependencies { compile project(':worldedit-core') compile 'org.apache.logging.log4j:log4j-slf4j-impl:2.11.2' From f8c4f23658a18b356087ae8a973fa04de83dbd64 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 14 Apr 2019 01:30:40 -0700 Subject: [PATCH 03/57] Partial work on biome commands, need logging replacement --- .../worldedit/command/BiomeCommands.java | 74 ++++++++----------- .../CommandPermissionsConditionGenerator.java | 7 +- .../extension/platform/CommandManager.java | 13 ++-- .../platform/CommandManagerCallable.java | 32 ++++---- 4 files changed, 60 insertions(+), 66 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index f3d9e9694..a1df6dcb5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -19,17 +19,11 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.function.FlatRegionFunction; @@ -46,11 +40,14 @@ import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.registry.BiomeRegistry; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; import java.util.Collection; import java.util.HashSet; @@ -59,33 +56,27 @@ import java.util.Set; /** * Implements biome-related commands such as "/biomelist". */ +@CommandContainer public class BiomeCommands { - private final WorldEdit worldEdit; - /** * Create a new instance. - * - * @param worldEdit reference to WorldEdit */ - public BiomeCommands(WorldEdit worldEdit) { - checkNotNull(worldEdit); - this.worldEdit = worldEdit; + public BiomeCommands() { } @Command( - aliases = { "biomelist", "biomels" }, - usage = "[page]", - desc = "Gets all biomes available.", - max = 1 + name = "biomelist", + aliases = { "biomels" }, + desc = "Gets all biomes available." ) @CommandPermissions("worldedit.biome.list") - public void biomeList(Player player, CommandContext args) throws WorldEditException { - int page; + public void biomeList(Player player, + @Arg(desc = "Page number.", def = "0") int page) throws WorldEditException { int offset; int count = 0; - if (args.argsLength() == 0 || (page = args.getInteger(0)) < 2) { + if (page < 2) { page = 1; offset = 0; } else { @@ -115,24 +106,24 @@ public class BiomeCommands { } @Command( - aliases = { "biomeinfo" }, - flags = "pt", + name = "biomeinfo", desc = "Get the biome of the targeted block.", - help = - "Get the biome of the block.\n" + - "By default use all the blocks contained in your selection.\n" + - "-t use the block you are looking at.\n" + - "-p use the block you are currently in", - max = 0 + descFooter = "By default, uses all blocks in your selection." ) @CommandPermissions("worldedit.biome.info") - public void biomeInfo(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void biomeInfo(Player player, LocalSession session, + @Switch( + name = 't', desc="Use the block you are looking at." + ) boolean useLineOfSight, + @Switch( + name = 'p', desc="Use the block you are currently in." + ) boolean usePosition) throws WorldEditException { BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); Set biomes = new HashSet<>(); String qualifier; - if (args.hasFlag('t')) { + if (useLineOfSight) { Location blockPosition = player.getBlockTrace(300); if (blockPosition == null) { player.printError("No block in sight!"); @@ -143,7 +134,7 @@ public class BiomeCommands { biomes.add(biome); qualifier = "at line of sight point"; - } else if (args.hasFlag('p')) { + } else if (usePosition) { BiomeType biome = player.getWorld().getBiome(player.getLocation().toVector().toBlockPoint().toBlockVector2()); biomes.add(biome); @@ -177,18 +168,15 @@ public class BiomeCommands { } @Command( - aliases = { "/setbiome" }, - usage = "", - flags = "p", - desc = "Sets the biome of the player's current block or region.", - help = - "Set the biome of the region.\n" + - "By default use all the blocks contained in your selection.\n" + - "-p use the block you are currently in" + name = "/setbiome", + desc = "Sets the biome of the player's current block or region.", + descFooter = "By default, uses all the blocks in your selection" ) - @Logging(REGION) +// @Logging(REGION) @CommandPermissions("worldedit.biome.set") - public void setBiome(Player player, LocalSession session, EditSession editSession, BiomeType target, @Switch('p') boolean atPosition) throws WorldEditException { + public void setBiome(Player player, LocalSession session, EditSession editSession, + BiomeType target, + @Switch(name = 'p', desc = "Use your current position") boolean atPosition) throws WorldEditException { World world = player.getWorld(); Region region; Mask mask = editSession.getMask(); 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 d00d286d6..84011e0ff 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 @@ -41,9 +41,8 @@ public class CommandPermissionsConditionGenerator implements CommandConditionGen CommandPermissions annotation = commandMethod.getAnnotation(CommandPermissions.class); checkNotNull(annotation, "Annotation is missing from commandMethod"); Set permissions = ImmutableSet.copyOf(annotation.value()); - return p -> { - Actor actor = p.injectedValue(ACTOR_KEY); - return permissions.stream().anyMatch(actor::hasPermission); - }; + return p -> p.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/CommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index 9a2a9da78..da697d182 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/CommandManager.java @@ -145,7 +145,7 @@ public final class CommandManager { dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new BiomeCommands(worldEdit)) + .registerMethods(new BiomeCommands()) .registerMethods(new ChunkCommands(worldEdit)) .registerMethods(new ClipboardCommands(worldEdit)) .registerMethods(new GeneralCommands(worldEdit)) @@ -198,11 +198,12 @@ public final class CommandManager { desc.setPermissions(ImmutableList.of()); org.enginehub.piston.CommandManager manager = DefaultCommandManagerService.getInstance() .newCommandManager(); - new SchematicCommandsRegistration( - manager, - new SchematicCommands(worldEdit), - new CommandPermissionsConditionGenerator() - ); + SchematicCommandsRegistration.builder() + .commandManager(manager) + .containerInstance(new SchematicCommands(worldEdit)) + .commandPermissionsConditionGenerator( + new CommandPermissionsConditionGenerator() + ).build(); return new CommandManagerCallable(worldEdit, manager, desc); } 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 index bb6079713..fe22518ef 100644 --- 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 @@ -33,6 +33,7 @@ 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}. @@ -51,20 +52,25 @@ public class CommandManagerCallable implements CommandCallable { @Override public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException { - manager.injectValue(Key.get(Actor.class), () -> locals.get(Actor.class)); - manager.injectValue(Key.get(Player.class), () -> getPlayer(locals)); - manager.injectValue(Key.get(LocalSession.class), () -> { - Player sender = getPlayer(locals); - return worldEdit.getSessionManager().get(sender); - }); - manager.injectValue(Key.get(EditSession.class), () -> { - Player sender = getPlayer(locals); - LocalSession session = worldEdit.getSessionManager().get(sender); - EditSession editSession = session.createEditSession(sender); - editSession.enableStandardMode(); - session.tellVersion(sender); - return editSession; + 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)); } From da35b3c1741d996f39431c0b6add1ad099c136dc Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 14 Apr 2019 01:53:04 -0700 Subject: [PATCH 04/57] Switch to using local maven for Piston --- settings.gradle | 2 -- worldedit-core/build.gradle | 15 +++++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/settings.gradle b/settings.gradle index 6b725d8d1..84bd77d7d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,3 @@ rootProject.name = 'worldedit' include 'worldedit-core', 'worldedit-bukkit', 'worldedit-forge', 'worldedit-sponge' - -includeBuild("../Piston") diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index 5f6cce5a6..bfd0aac32 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -13,6 +13,11 @@ configurations.all { Configuration it -> } } +repositories { + // temporary, for Piston + mavenLocal() +} + dependencies { compile 'de.schlichtherle:truezip:6.8.3' compile 'rhino:js:1.7R2' @@ -25,10 +30,12 @@ dependencies { compile 'com.sk89q.lib:jlibnoise:1.0.0' compile 'com.googlecode.json-simple:json-simple:1.1.1' compile 'org.slf4j:slf4j-api:1.7.26' - compileOnly 'org.enginehub.piston:core-ap-annotations:0.0.1-SNAPSHOT' - compile 'org.enginehub.piston:core-ap-runtime:0.0.1-SNAPSHOT' - annotationProcessor 'org.enginehub.piston:core-ap-processor:0.0.1-SNAPSHOT' - compile 'org.enginehub.piston:default-impl:0.0.1-SNAPSHOT' + + def pistonVersion = '0.0.1-SNAPSHOT' + compileOnly "org.enginehub.piston.core-ap:annotations:$pistonVersion" + compile "org.enginehub.piston.core-ap:runtime:$pistonVersion" + annotationProcessor "org.enginehub.piston.core-ap:processor:$pistonVersion" + compile "org.enginehub.piston:default-impl:$pistonVersion" //compile 'net.sf.trove4j:trove4j:3.0.3' testCompile 'org.mockito:mockito-core:1.9.0-rc1' } From 267ccf2298d31c2a5e00dd232f0c3aa04c9e93c2 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 15 Apr 2019 01:21:15 -0700 Subject: [PATCH 05/57] 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()); } } From 2b10128720972d7d5d1842629f4c8758368e4588 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 15 Apr 2019 01:25:19 -0700 Subject: [PATCH 06/57] Restore Logging for setbiome --- .../main/java/com/sk89q/worldedit/command/BiomeCommands.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index a1df6dcb5..5830474a2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.command; +import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -53,6 +54,8 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; +import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; + /** * Implements biome-related commands such as "/biomelist". */ @@ -172,7 +175,7 @@ public class BiomeCommands { desc = "Sets the biome of the player's current block or region.", descFooter = "By default, uses all the blocks in your selection" ) -// @Logging(REGION) + @Logging(REGION) @CommandPermissions("worldedit.biome.set") public void setBiome(Player player, LocalSession session, EditSession editSession, BiomeType target, From e4d809143220acdb6d9112853e72012fa129381d Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 15 Apr 2019 02:01:25 -0700 Subject: [PATCH 07/57] Convert part of the brush commands --- .../worldedit/command/BrushCommands.java | 171 +++++++++--------- .../command/util/CreatureButcher.java | 2 +- .../platform/PlatformCommandMananger.java | 25 ++- 3 files changed, 112 insertions(+), 86 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 26fcf4d92..41da9f0f3 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 @@ -19,11 +19,6 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -37,6 +32,7 @@ import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush; import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush; import com.sk89q.worldedit.command.tool.brush.SmoothBrush; import com.sk89q.worldedit.command.tool.brush.SphereBrush; +import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -48,13 +44,18 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.util.HandSide; -import com.sk89q.worldedit.util.command.binding.Switch; -import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.world.block.BlockTypes; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; + +import static com.google.common.base.Preconditions.checkNotNull; /** * Commands to set brush shape. */ +@CommandContainer public class BrushCommands { private final WorldEdit worldEdit; @@ -70,19 +71,16 @@ public class BrushCommands { } @Command( - aliases = { "sphere", "s" }, - usage = " [radius]", - flags = "h", - desc = "Choose the sphere brush", - help = - "Chooses the sphere brush.\n" + - "The -h flag creates hollow spheres instead.", - min = 1, - max = 2 + name = "sphere", + aliases = { "s" }, + desc = "Choose the sphere brush" ) @CommandPermissions("worldedit.brush.sphere") public void sphereBrush(Player player, LocalSession session, Pattern fill, - @Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException { + @Arg(desc = "The radius of the sphere", def = "2") + double radius, + @Switch(name = 'h', desc = "Create hollow spheres instead") + boolean hollow) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); @@ -99,19 +97,18 @@ public class BrushCommands { } @Command( - aliases = { "cylinder", "cyl", "c" }, - usage = " [radius] [height]", - flags = "h", - desc = "Choose the cylinder brush", - help = - "Chooses the cylinder brush.\n" + - "The -h flag creates hollow cylinders instead.", - min = 1, - max = 3 + name = "cylinder", + aliases = { "cyl", "c" }, + desc = "Choose the cylinder brush" ) @CommandPermissions("worldedit.brush.cylinder") public void cylinderBrush(Player player, LocalSession session, Pattern fill, - @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException { + @Arg(desc = "The radius of the cylinder", def = "2") + double radius, + @Arg(desc = "The height of the cylinder", def = "1") + int height, + @Switch(name = 'h', desc = "Create hollow cylinders instead") + boolean hollow) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(height); @@ -129,19 +126,16 @@ public class BrushCommands { } @Command( - aliases = { "clipboard", "copy" }, - usage = "", - flags = "ap", - desc = "Choose the clipboard brush", - help = - "Chooses the clipboard brush.\n" + - "The -a flag makes it not paste air.\n" + - "Without the -p flag, the paste will appear centered at the target location. " + - "With the flag, then the paste will appear relative to where you had " + - "stood relative to the copied area when you copied it." + name = "clipboard", + aliases = { "copy" }, + desc = "Choose the clipboard brush" ) @CommandPermissions("worldedit.brush.clipboard") - public void clipboardBrush(Player player, LocalSession session, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin) throws WorldEditException { + public void clipboardBrush(Player player, LocalSession session, + @Switch(name = 'a', desc = "Don't paste air from the clipboard") + boolean ignoreAir, + @Switch(name = 'p', desc = "Paste using clipboard origin, instead of being centered at the target location") + boolean usingOrigin) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); @@ -158,18 +152,18 @@ public class BrushCommands { } @Command( - aliases = { "smooth" }, - usage = "[size] [iterations] [filter]", + name = "smooth", desc = "Choose the terrain softener brush", - help = - "Chooses the terrain softener brush. Optionally, specify a mask of blocks to be used for the heightmap.\n" + - "For example, '/brush smooth 2 4 grass_block,dirt,stone'.", - min = 0, - max = 3 + descFooter = "Example: '/brush smooth 2 4 grass_block,dirt,stone'" ) @CommandPermissions("worldedit.brush.smooth") public void smoothBrush(Player player, LocalSession session, - @Optional("2") double radius, @Optional("4") int iterations, @Optional Mask mask) throws WorldEditException { + @Arg(desc = "The radius to sample for softening", def = "2") + double radius, + @Arg(desc = "The number of iterations to perform", def = "4") + int iterations, + @Arg(desc = "The mask of blocks to use for the heightmap", def = "") + Mask mask) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); @@ -180,14 +174,14 @@ public class BrushCommands { } @Command( - aliases = { "ex", "extinguish" }, - usage = "[radius]", - desc = "Shortcut fire extinguisher brush", - min = 0, - max = 1 + name = "extinguish", + aliases = { "ex" }, + desc = "Shortcut fire extinguisher brush" ) @CommandPermissions("worldedit.brush.ex") - public void extinguishBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { + public void extinguishBrush(Player player, LocalSession session, + @Arg(desc = "The radius to extinguish", def = "5") + double radius) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); @@ -201,19 +195,16 @@ public class BrushCommands { } @Command( - aliases = { "gravity", "grav" }, - usage = "[radius]", - flags = "h", - desc = "Gravity brush", - help = - "This brush simulates the affect of gravity.\n" + - "The -h flag makes it affect blocks starting at the world's max y, " + - "instead of the clicked block's y + radius.", - min = 0, - max = 1 + name = "gravity", + aliases = { "grav" }, + desc = "Gravity brush, simulates the effect of gravity" ) @CommandPermissions("worldedit.brush.gravity") - public void gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException { + public void gravityBrush(Player player, LocalSession session, + @Arg(desc = "The radius to apply gravity in", def = "5") + double radius, + @Switch(name = 'h', desc = "Affect blocks starting at max Y, rather than the target location Y + radius") + boolean fromMaxY) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); @@ -225,29 +216,34 @@ public class BrushCommands { } @Command( - aliases = { "butcher", "kill" }, - usage = "[radius]", - flags = "plangbtfr", - desc = "Butcher brush", - help = "Kills nearby mobs within the specified radius.\n" + - "Flags:\n" + - " -p also kills pets.\n" + - " -n also kills NPCs.\n" + - " -g also kills Golems.\n" + - " -a also kills animals.\n" + - " -b also kills ambient mobs.\n" + - " -t also kills mobs with name tags.\n" + - " -f compounds all previous flags.\n" + - " -r also destroys armor stands.\n" + - " -l currently does nothing.", - min = 0, - max = 1 + name = "butcher", + aliases = { "kill" }, + desc = "Butcher brush, kills mobs within a radius" ) @CommandPermissions("worldedit.brush.butcher") - public void butcherBrush(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void butcherBrush(Player player, LocalSession session, + @Arg(desc = "Radius to kill mobs in", def = "5") + double radius, + @Switch(name = 'p', desc = "Also kill pets") + boolean killPets, + @Switch(name = 'n', desc = "Also kill NPCs") + boolean killNpcs, + @Switch(name = 'g', desc = "Also kill golems") + boolean killGolems, + @Switch(name = 'a', desc = "Also kill animals") + boolean killAnimals, + @Switch(name = 'b', desc = "Also kill ambient mobs") + boolean killAmbient, + @Switch(name = 't', desc = "Also kill mobs with name tags") + boolean killWithName, + @Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)") + boolean killFriendly, + @Switch(name = 'r', desc = "Also destroy armor stands") + boolean killArmorStands, + @Switch(name = 'l', desc = "Kill via lightning. Currently non-functioning.") + boolean killWithLightning) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); - double radius = args.argsLength() > 0 ? args.getDouble(0) : 5; double maxRadius = config.maxBrushRadius; // hmmmm not horribly worried about this because -1 is still rather efficient, // the problem arises when butcherMaxRadius is some really high number but not infinite @@ -261,7 +257,16 @@ public class BrushCommands { } CreatureButcher flags = new CreatureButcher(player); - flags.fromCommand(args); + flags.or(CreatureButcher.Flags.FRIENDLY , killFriendly); // No permission check here. Flags will instead be filtered by the subsequent calls. + flags.or(CreatureButcher.Flags.PETS , killPets, "worldedit.butcher.pets"); + flags.or(CreatureButcher.Flags.NPCS , killNpcs, "worldedit.butcher.npcs"); + flags.or(CreatureButcher.Flags.GOLEMS , killGolems, "worldedit.butcher.golems"); + flags.or(CreatureButcher.Flags.ANIMALS , killAnimals, "worldedit.butcher.animals"); + flags.or(CreatureButcher.Flags.AMBIENT , killAmbient, "worldedit.butcher.ambient"); + flags.or(CreatureButcher.Flags.TAGGED , killWithName, "worldedit.butcher.tagged"); + flags.or(CreatureButcher.Flags.ARMOR_STAND , killArmorStands, "worldedit.butcher.armorstands"); + + flags.or(CreatureButcher.Flags.WITH_LIGHTNING, killWithLightning, "worldedit.butcher.lightning"); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); tool.setSize(radius); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java index 94c7d5ad2..940d6a99c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java @@ -29,7 +29,7 @@ import com.sk89q.worldedit.function.EntityFunction; */ public class CreatureButcher { - final class Flags { + public final class Flags { @SuppressWarnings("PointlessBitwiseExpression") public static final int PETS = 1 << 0; public static final int NPCS = 1 << 1; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index e08c44eb5..5851efe9c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -30,6 +30,8 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BiomeCommandsRegistration; +import com.sk89q.worldedit.command.BrushCommands; +import com.sk89q.worldedit.command.BrushCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; @@ -145,7 +147,27 @@ public final class PlatformCommandMananger { cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") .withCommands(manager.getAllCommands().collect(Collectors.toList())) .required() - .build()); + .build()); + }); + + commandManager.register("brush", cmd -> { + cmd.aliases(ImmutableList.of("br")); + cmd.description("Brushing commands"); + cmd.action(Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + BrushCommandsRegistration.builder() + .commandManager(manager) + .containerInstance(new BrushCommands(worldEdit)) + .commandPermissionsConditionGenerator( + permsGenerator + ).build(); + + cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() + .build()); }); BiomeCommandsRegistration.builder() @@ -183,7 +205,6 @@ public final class PlatformCommandMananger { .parent() .group("brush", "br") .describeAs("Brushing commands") - .registerMethods(new BrushCommands(worldEdit)) .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") .register(adapt(new ShapedBrushCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within region"), "worldedit.brush.set")), "set") .register(adapt(new ShapedBrushCommand(new PaintCommand(), "worldedit.brush.paint")), "paint") From e127bb89e56b670bc6629dca30807420256ed36d Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 15 Apr 2019 02:03:05 -0700 Subject: [PATCH 08/57] Align annotation formatting with brush command methods --- .../worldedit/command/BiomeCommands.java | 16 +++++------ .../worldedit/command/SchematicCommands.java | 27 ++++++++++++------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 5830474a2..81d208885 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -75,7 +75,8 @@ public class BiomeCommands { ) @CommandPermissions("worldedit.biome.list") public void biomeList(Player player, - @Arg(desc = "Page number.", def = "0") int page) throws WorldEditException { + @Arg(desc = "Page number.", def = "0") + int page) throws WorldEditException { int offset; int count = 0; @@ -115,12 +116,10 @@ public class BiomeCommands { ) @CommandPermissions("worldedit.biome.info") public void biomeInfo(Player player, LocalSession session, - @Switch( - name = 't', desc="Use the block you are looking at." - ) boolean useLineOfSight, - @Switch( - name = 'p', desc="Use the block you are currently in." - ) boolean usePosition) throws WorldEditException { + @Switch(name = 't', desc="Use the block you are looking at.") + boolean useLineOfSight, + @Switch(name = 'p', desc="Use the block you are currently in.") + boolean usePosition) throws WorldEditException { BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); Set biomes = new HashSet<>(); @@ -179,7 +178,8 @@ public class BiomeCommands { @CommandPermissions("worldedit.biome.set") public void setBiome(Player player, LocalSession session, EditSession editSession, BiomeType target, - @Switch(name = 'p', desc = "Use your current position") boolean atPosition) throws WorldEditException { + @Switch(name = 'p', desc = "Use your current position") + boolean atPosition) throws WorldEditException { World world = player.getWorld(); Region region; Mask mask = editSession.getMask(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 2bdd77bf0..ffa28d8ec 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -91,8 +91,10 @@ public class SchematicCommands { ) @CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load"}) public void load(Player player, LocalSession session, - @Arg(desc = "File name.") String filename, - @Arg(desc = "Format name.", def = "sponge") String formatName) throws FilenameException { + @Arg(desc = "File name.") + String filename, + @Arg(desc = "Format name.", def = "sponge") + String formatName) throws FilenameException { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -134,9 +136,12 @@ public class SchematicCommands { ) @CommandPermissions({"worldedit.clipboard.save", "worldedit.schematic.save"}) public void save(Player player, LocalSession session, - @Arg(desc = "File name.") String filename, - @Arg(desc = "Format name.", def = "sponge") String formatName, - @Switch(name = 'f', desc = "Overwrite an existing file.") boolean allowOverwrite + @Arg(desc = "File name.") + String filename, + @Arg(desc = "Format name.", def = "sponge") + String formatName, + @Switch(name = 'f', desc = "Overwrite an existing file.") + boolean allowOverwrite ) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); @@ -205,7 +210,8 @@ public class SchematicCommands { ) @CommandPermissions("worldedit.schematic.delete") public void delete(Actor actor, - @Arg(desc = "File name.") String filename) throws WorldEditException { + @Arg(desc = "File name.") + String filename) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); @@ -263,9 +269,12 @@ public class SchematicCommands { ) @CommandPermissions("worldedit.schematic.list") public void list(Actor actor, - @ArgFlag(name = 'p', desc = "Page to view.", def = "1") int page, - @Switch(name = 'd', desc = "Sort by date, oldest first") boolean oldFirst, - @Switch(name = 'n', desc = "Sort by date, newest first") boolean newFirst) { + @ArgFlag(name = 'p', desc = "Page to view.", def = "1") + int page, + @Switch(name = 'd', desc = "Sort by date, oldest first") + boolean oldFirst, + @Switch(name = 'n', desc = "Sort by date, newest first") + boolean newFirst) { if (oldFirst && newFirst) { throw new StopExecutionException("Cannot sort by oldest and newest."); } From f33140b327c0137bc6e3a3073eca1df1e5e8a2bf Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 16 Apr 2019 23:02:23 -0700 Subject: [PATCH 09/57] Port ChunkCommands, fix up injection, simplify registration --- .../worldedit/command/BiomeCommands.java | 7 +- .../worldedit/command/BrushCommands.java | 3 +- .../worldedit/command/ChunkCommands.java | 35 ++--- .../worldedit/command/ClipboardCommands.java | 6 +- .../worldedit/command/GenerationCommands.java | 8 +- .../worldedit/command/NavigationCommands.java | 4 +- .../worldedit/command/RegionCommands.java | 9 +- .../worldedit/command/SchematicCommands.java | 3 +- .../worldedit/command/ScriptingCommands.java | 4 +- .../worldedit/command/SelectionCommands.java | 6 +- .../command/SnapshotUtilCommands.java | 4 +- .../worldedit/command/UtilityCommands.java | 14 +- .../worldedit/command/argument/Arguments.java | 3 +- .../CommandPermissionsConditionGenerator.java | 7 +- .../command/util}/Logging.java | 2 +- .../platform/PlatformCommandMananger.java | 122 ++++++++++++------ .../command/CommandLoggingHandler.java | 2 +- 17 files changed, 135 insertions(+), 104 deletions(-) rename worldedit-core/src/main/java/com/sk89q/{minecraft/util/commands => worldedit/command/util}/Logging.java (93%) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 81d208885..0bf6878dd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -19,12 +19,13 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.function.FlatRegionFunction; @@ -54,12 +55,12 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; /** * Implements biome-related commands such as "/biomelist". */ -@CommandContainer +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class BiomeCommands { /** 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 41da9f0f3..e310f136a 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 @@ -33,6 +33,7 @@ import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush; import com.sk89q.worldedit.command.tool.brush.SmoothBrush; import com.sk89q.worldedit.command.tool.brush.SphereBrush; import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.Clipboard; @@ -55,7 +56,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Commands to set brush shape. */ -@CommandContainer +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class BrushCommands { private final WorldEdit worldEdit; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java index 30d99269d..8f9dc6ceb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java @@ -20,22 +20,23 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.storage.LegacyChunkStore; import com.sk89q.worldedit.world.storage.McRegionChunkStore; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; import java.io.FileOutputStream; import java.io.IOException; @@ -45,21 +46,19 @@ import java.util.Set; /** * Commands for working with chunks. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ChunkCommands { private final WorldEdit worldEdit; - + public ChunkCommands(WorldEdit worldEdit) { checkNotNull(worldEdit); this.worldEdit = worldEdit; } @Command( - aliases = { "chunkinfo" }, - usage = "", - desc = "Get information about the chunk that you are inside", - min = 0, - max = 0 + name = "chunkinfo", + desc = "Get information about the chunk that you are inside" ) @CommandPermissions("worldedit.chunkinfo") public void chunkInfo(Player player) throws WorldEditException { @@ -79,11 +78,8 @@ public class ChunkCommands { } @Command( - aliases = { "listchunks" }, - usage = "", - desc = "List chunks that your selection includes", - min = 0, - max = 0 + name = "listchunks", + desc = "List chunks that your selection includes" ) @CommandPermissions("worldedit.listchunks") public void listChunks(Player player, LocalSession session) throws WorldEditException { @@ -95,11 +91,8 @@ public class ChunkCommands { } @Command( - aliases = { "delchunks" }, - usage = "", - desc = "Delete chunks that your selection includes", - min = 0, - max = 0 + name = "delchunks", + desc = "Delete chunks that your selection includes" ) @CommandPermissions("worldedit.delchunks") @Logging(REGION) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 0f61f0d2a..9d0dfe984 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -20,16 +20,16 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 971fb58d8..f4578bdcd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -20,17 +20,17 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; +import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.annotation.Selection; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index 2d64d472b..b2fb9c4cb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -20,15 +20,15 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.command.parametric.Optional; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index d788063d5..093d84f0e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -20,24 +20,23 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.ORIENTATION_REGION; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ORIENTATION_REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; import static com.sk89q.worldedit.regions.Regions.asFlatRegion; import static com.sk89q.worldedit.regions.Regions.maximumBlockY; import static com.sk89q.worldedit.regions.Regions.minimumBlockY; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.generator.FloraGenerator; -import com.sk89q.worldedit.function.generator.ForestGenerator; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.NoiseFilter2D; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index ffa28d8ec..5fd4c6d98 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -65,7 +66,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Commands that work with schematic files. */ -@CommandContainer +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SchematicCommands { /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java index 2b7d9a61f..d09c76c39 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java @@ -20,15 +20,15 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import java.io.File; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 24e92070b..c79ec4fec 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -19,19 +19,19 @@ package com.sk89q.worldedit.command; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index 51c5695e5..b8d6c7f3f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -22,12 +22,12 @@ package com.sk89q.worldedit.command; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.DataException; @@ -40,7 +40,7 @@ import com.sk89q.worldedit.world.storage.MissingWorldException; import java.io.File; import java.io.IOException; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; public class SnapshotUtilCommands { 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 415b77adf..4d69452b2 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 @@ -19,14 +19,12 @@ package com.sk89q.worldedit.command; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; -import com.google.common.base.Joiner; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -34,12 +32,12 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.command.util.EntityRemover; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Entity; 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.PlatformCommandMananger; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.BlockPattern; @@ -53,17 +51,9 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.SessionOwner; -import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Dispatcher; -import com.sk89q.worldedit.util.command.PrimaryAliasComparator; import com.sk89q.worldedit.util.command.binding.Text; -import com.sk89q.worldedit.util.formatting.ColorCodeBuilder; -import com.sk89q.worldedit.util.formatting.Style; -import com.sk89q.worldedit.util.formatting.StyledFragment; -import com.sk89q.worldedit.util.formatting.component.Code; -import com.sk89q.worldedit.util.formatting.component.CommandListBox; -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; 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 index 1bf5fc4e9..a1b444cbe 100644 --- 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 @@ -19,7 +19,8 @@ package com.sk89q.worldedit.command.argument; -import org.enginehub.piston.InjectedValueAccess; + +import org.enginehub.piston.inject.InjectedValueAccess; /** * Key-interface for {@link InjectedValueAccess} for the String arguments. 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 28041a1a1..b126198a6 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 @@ -20,10 +20,9 @@ package com.sk89q.worldedit.command.util; import com.google.common.collect.ImmutableSet; -import com.google.inject.Key; -import com.sk89q.worldedit.extension.platform.Actor; import org.enginehub.piston.Command; import org.enginehub.piston.gen.CommandConditionGenerator; +import org.enginehub.piston.gen.CommandRegistration; import org.enginehub.piston.util.NonnullByDefault; import java.lang.reflect.Method; @@ -34,6 +33,10 @@ import static com.google.common.base.Preconditions.checkNotNull; @NonnullByDefault public class CommandPermissionsConditionGenerator implements CommandConditionGenerator { + public interface Registration { + Registration commandPermissionsConditionGenerator(CommandPermissionsConditionGenerator generator); + } + @Override public Command.Condition generateCondition(Method commandMethod) { CommandPermissions annotation = commandMethod.getAnnotation(CommandPermissions.class); diff --git a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/Logging.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/Logging.java similarity index 93% rename from worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/Logging.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/command/util/Logging.java index d8d87dcc0..e678cfde3 100644 --- a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/Logging.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/Logging.java @@ -20,7 +20,7 @@ //$Id$ -package com.sk89q.minecraft.util.commands; +package com.sk89q.worldedit.command.util; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 5851efe9c..08c39fb49 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -21,9 +21,6 @@ package com.sk89q.worldedit.extension.platform; import com.google.common.collect.ImmutableList; 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; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -32,6 +29,8 @@ import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BiomeCommandsRegistration; import com.sk89q.worldedit.command.BrushCommands; import com.sk89q.worldedit.command.BrushCommandsRegistration; +import com.sk89q.worldedit.command.ChunkCommands; +import com.sk89q.worldedit.command.ChunkCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; @@ -44,18 +43,16 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extent.Extent; 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.SessionOwner; import com.sk89q.worldedit.session.request.Request; -import com.sk89q.worldedit.util.command.Dispatcher; -import com.sk89q.worldedit.util.command.InvalidUsageException; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler; import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.util.eventbus.Subscribe; -import com.sk89q.worldedit.util.formatting.ColorCodeBuilder; -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; @@ -66,6 +63,12 @@ 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.gen.CommandCallListener; +import org.enginehub.piston.gen.CommandRegistration; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.InjectedValueStore; +import org.enginehub.piston.inject.MapBackedValueStore; +import org.enginehub.piston.inject.MemoizingValueAccess; import org.enginehub.piston.part.SubCommandPart; import org.enginehub.piston.util.ValueProvider; import org.slf4j.Logger; @@ -73,6 +76,8 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; +import java.util.Collections; +import java.util.List; import java.util.Optional; import java.util.logging.FileHandler; import java.util.logging.Level; @@ -93,12 +98,14 @@ public final class PlatformCommandMananger { private static final java.util.logging.Logger commandLog = java.util.logging.Logger.getLogger(PlatformCommandMananger.class.getCanonicalName() + ".CommandLog"); private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$"); + private static final CommandPermissionsConditionGenerator PERM_GEN = new CommandPermissionsConditionGenerator(); private final WorldEdit worldEdit; private final PlatformManager platformManager; private final CommandManager commandManager; private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); private final ExceptionConverter exceptionConverter; + private final List callListeners; /** * Create a new instance. @@ -113,7 +120,27 @@ public final class PlatformCommandMananger { this.exceptionConverter = new WorldEditExceptionConverter(worldEdit); this.commandManager = DefaultCommandManagerService.getInstance() .newCommandManager(); + this.callListeners = Collections.singletonList( + new CommandLoggingHandler(worldEdit, commandLog) + ); + // setup separate from main constructor + // ensures that everything is definitely assigned + initialize(); + } + private void register(CommandManager manager, CommandRegistration registration, CI instance) { + registration.containerInstance(instance) + .commandManager(manager) + .listeners(callListeners); + if (registration instanceof CommandPermissionsConditionGenerator.Registration) { + ((CommandPermissionsConditionGenerator.Registration) registration).commandPermissionsConditionGenerator( + PERM_GEN + ); + } + registration.build(); + } + + private void initialize() { // Register this instance for command events worldEdit.getEventBus().register(this); @@ -127,9 +154,6 @@ public final class PlatformCommandMananger { builder.addBinding(new WorldEditBinding(worldEdit)); builder.addInvokeListener(new LegacyCommandsHandler()); - CommandPermissionsConditionGenerator permsGenerator = - new CommandPermissionsConditionGenerator(); - commandManager.register("schematic", cmd -> { cmd.aliases(ImmutableList.of("schem", "/schematic", "/schem")); cmd.description("Schematic commands for saving/loading areas"); @@ -137,19 +161,17 @@ public final class PlatformCommandMananger { CommandManager manager = DefaultCommandManagerService.getInstance() .newCommandManager(); - SchematicCommandsRegistration.builder() - .commandManager(manager) - .containerInstance(new SchematicCommands(worldEdit)) - .commandPermissionsConditionGenerator( - permsGenerator - ).build(); + register( + manager, + SchematicCommandsRegistration.builder(), + new SchematicCommands(worldEdit) + ); cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") .withCommands(manager.getAllCommands().collect(Collectors.toList())) .required() .build()); }); - commandManager.register("brush", cmd -> { cmd.aliases(ImmutableList.of("br")); cmd.description("Brushing commands"); @@ -157,31 +179,33 @@ public final class PlatformCommandMananger { CommandManager manager = DefaultCommandManagerService.getInstance() .newCommandManager(); - BrushCommandsRegistration.builder() - .commandManager(manager) - .containerInstance(new BrushCommands(worldEdit)) - .commandPermissionsConditionGenerator( - permsGenerator - ).build(); + register( + manager, + BrushCommandsRegistration.builder(), + new BrushCommands(worldEdit) + ); 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(); + register( + commandManager, + BiomeCommandsRegistration.builder(), + new BiomeCommands() + ); + register( + commandManager, + ChunkCommandsRegistration.builder(), + new ChunkCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new ChunkCommands(worldEdit)) .registerMethods(new ClipboardCommands(worldEdit)) .registerMethods(new GeneralCommands(worldEdit)) .registerMethods(new GenerationCommands(worldEdit)) @@ -309,13 +333,31 @@ public final class PlatformCommandMananger { } LocalConfiguration config = worldEdit.getConfiguration(); - 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))); + InjectedValueStore store = MapBackedValueStore.create(); + store.injectValue(Key.get(Actor.class), ValueProvider.constant(actor)); + if (actor instanceof Player) { + store.injectValue(Key.get(Player.class), ValueProvider.constant((Player) actor)); + } + store.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments)); + store.injectValue(Key.get(LocalSession.class), + context -> { + LocalSession localSession = worldEdit.getSessionManager().get(actor); + localSession.tellVersion(actor); + return Optional.of(localSession); + }); + store.injectValue(Key.get(EditSession.class), + context -> { + LocalSession localSession = context.injectedValue(Key.get(LocalSession.class)) + .orElseThrow(() -> new IllegalStateException("No LocalSession")); + return context.injectedValue(Key.get(Player.class)) + .map(player -> { + EditSession editSession = localSession.createEditSession(player); + editSession.enableStandardMode(); + return editSession; + }); + }); + + MemoizingValueAccess context = MemoizingValueAccess.wrap(store); long start = System.currentTimeMillis(); @@ -325,7 +367,7 @@ public final class PlatformCommandMananger { // exceptions without writing a hook into every dispatcher, we need to unwrap these // exceptions and rethrow their converted form, if their is one. try { - commandManager.execute(ImmutableList.copyOf(split)); + commandManager.execute(context, 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 @@ -358,8 +400,8 @@ public final class PlatformCommandMananger { log.error("An unknown error occurred", e); } } finally { - Optional editSessionOpt = commandManager.injectedValue(Key.get(EditSessionHolder.class)) - .map(EditSessionHolder::getSession); + Optional editSessionOpt = + context.injectedValueIfMemoized(Key.get(EditSession.class)); if (editSessionOpt.isPresent()) { EditSession editSession = editSessionOpt.get(); 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 f8fa06ff6..8cd2cdb5f 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 @@ -20,7 +20,7 @@ package com.sk89q.worldedit.internal.command; import com.google.inject.Key; -import com.sk89q.minecraft.util.commands.Logging; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; From 37c993be168ad41592458f0b70515533bdb4813a Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 18 Apr 2019 12:34:57 -0700 Subject: [PATCH 10/57] Port ClipboardCommands, update to new Key --- .../bukkit/BukkitCommandInspector.java | 4 +- .../worldedit/bukkit/WorldEditListener.java | 4 +- .../worldedit/command/ClipboardCommands.java | 145 ++++++++---------- .../command/util/PermissionCondition.java | 4 +- .../platform/PlatformCommandMananger.java | 33 ++-- .../internal/annotation/Selection.java | 4 +- .../command/CommandLoggingHandler.java | 6 +- 7 files changed, 93 insertions(+), 107 deletions(-) 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 917d31981..d889903be 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 @@ -20,7 +20,6 @@ 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.worldedit.extension.platform.Actor; import org.bukkit.command.Command; @@ -28,6 +27,7 @@ import org.bukkit.command.CommandSender; import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandParameters; import org.enginehub.piston.NoInputCommandParameters; +import org.enginehub.piston.inject.Key; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,7 +76,7 @@ class BukkitCommandInspector implements CommandInspector { if (mapping.isPresent()) { CommandParameters parameters = NoInputCommandParameters.builder() .injectedValues(ImmutableMap.of( - Key.get(Actor.class), plugin.wrapCommandSender(sender) + Key.of(Actor.class), plugin.wrapCommandSender(sender) )) .build(); return mapping.get().getCondition().satisfied(parameters); 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 9c124f83f..9d335bb24 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 @@ -22,7 +22,6 @@ package com.sk89q.worldedit.bukkit; 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; @@ -43,6 +42,7 @@ import org.bukkit.inventory.EquipmentSlot; import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandParameters; import org.enginehub.piston.NoInputCommandParameters; +import org.enginehub.piston.inject.Key; /** * Handles all events thrown in relation to a Player @@ -110,7 +110,7 @@ public class WorldEditListener implements Listener { public void onPlayerCommand(PlayerCommandSendEvent event) { CommandParameters parameters = NoInputCommandParameters.builder() .injectedValues(ImmutableMap.of( - Key.get(Actor.class), plugin.wrapCommandSender(event.getPlayer()) + Key.of(Actor.class), plugin.wrapCommandSender(event.getPlayer()) )) .build(); CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().getCommandManager(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 9d0dfe984..db5c5fa63 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -19,16 +19,11 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; -import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -48,42 +43,38 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.session.ClipboardHolder; -import com.sk89q.worldedit.util.command.binding.Switch; -import com.sk89q.worldedit.util.command.parametric.Optional; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.ArgFlag; +import org.enginehub.piston.annotation.param.Switch; + +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; /** * Clipboard commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ClipboardCommands { - private final WorldEdit worldEdit; - /** * Create a new instance. - * - * @param worldEdit reference to WorldEdit */ - public ClipboardCommands(WorldEdit worldEdit) { - checkNotNull(worldEdit); - this.worldEdit = worldEdit; + public ClipboardCommands() { } @Command( - aliases = { "/copy" }, - flags = "em", - desc = "Copy the selection to the clipboard", - help = "Copy the selection to the clipboard\n" + - "Flags:\n" + - " -e will also copy entities\n" + - " -m sets a source mask so that excluded blocks become air", - min = 0, - max = 0 + name = "/copy", + desc = "Copy the selection to the clipboard" ) @CommandPermissions("worldedit.clipboard.copy") public void copy(Player player, LocalSession session, EditSession editSession, - @Selection Region region, @Switch('e') boolean copyEntities, - @Switch('m') Mask mask) throws WorldEditException { - + @Selection Region region, + @Switch(name = 'e', desc = "Also copy entities") + boolean copyEntities, + @ArgFlag(name = 'm', desc = "Set the exclude mask, matching blocks become air", def = "") + Mask mask) throws WorldEditException { BlockArrayClipboard clipboard = new BlockArrayClipboard(region); clipboard.setOrigin(session.getPlacementPosition(player)); ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint()); @@ -98,22 +89,20 @@ public class ClipboardCommands { } @Command( - aliases = { "/cut" }, - flags = "em", - usage = "[leave-id]", + name = "/cut", desc = "Cut the selection to the clipboard", - help = "Copy the selection to the clipboard\n" + - "Flags:\n" + - " -e will also cut entities\n" + - " -m sets a source mask so that excluded blocks become air\n" + - "WARNING: Cutting and pasting entities cannot yet be undone!", - max = 1 + descFooter = "WARNING: Cutting and pasting entities cannot be undone!" ) @CommandPermissions("worldedit.clipboard.cut") @Logging(REGION) public void cut(Player player, LocalSession session, EditSession editSession, - @Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean copyEntities, - @Switch('m') Mask mask) throws WorldEditException { + @Selection Region region, + @Arg(desc = "Pattern to leave in place of the selection", def = "air") + Pattern leavePattern, + @Switch(name = 'e', desc = "Also cut entities") + boolean copyEntities, + @ArgFlag(name = 'm', desc = "Set the exclude mask, matching blocks become air", def = "") + Mask mask) throws WorldEditException { BlockArrayClipboard clipboard = new BlockArrayClipboard(region); clipboard.setOrigin(session.getPlacementPosition(player)); @@ -131,24 +120,18 @@ public class ClipboardCommands { } @Command( - aliases = { "/paste" }, - usage = "", - flags = "sao", - desc = "Paste the clipboard's contents", - help = - "Pastes the clipboard's contents.\n" + - "Flags:\n" + - " -a skips air blocks\n" + - " -o pastes at the original position\n" + - " -s selects the region after pasting", - min = 0, - max = 0 + name = "/paste", + desc = "Paste the clipboard's contents" ) @CommandPermissions("worldedit.clipboard.paste") @Logging(PLACEMENT) public void paste(Player player, LocalSession session, EditSession editSession, - @Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin, - @Switch('s') boolean selectPasted) throws WorldEditException { + @Switch(name = 'a', desc = "Skip air blocks") + boolean ignoreAirBlocks, + @Switch(name = 'o', desc = "Paste at the original position") + boolean atOrigin, + @Switch(name = 's', desc = "Select the region after pasting") + boolean selectPasted) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); @@ -156,10 +139,10 @@ public class ClipboardCommands { BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player); Operation operation = holder - .createPaste(editSession) - .to(to) - .ignoreAirBlocks(ignoreAirBlocks) - .build(); + .createPaste(editSession) + .to(to) + .ignoreAirBlocks(ignoreAirBlocks) + .build(); Operations.completeLegacy(operation); if (selectPasted) { @@ -176,42 +159,43 @@ public class ClipboardCommands { } @Command( - aliases = { "/rotate" }, - usage = " [] []", + name = "/rotate", desc = "Rotate the contents of the clipboard", - help = "Non-destructively rotate the contents of the clipboard.\n" + - "Angles are provided in degrees and a positive angle will result in a clockwise rotation. " + - "Multiple rotations can be stacked. Interpolation is not performed so angles should be a multiple of 90 degrees.\n" + descFooter = "Non-destructively rotate the contents of the clipboard.\n" + + "Angles are provided in degrees and a positive angle will result in a clockwise rotation. " + + "Multiple rotations can be stacked. Interpolation is not performed so angles should be a multiple of 90 degrees.\n" ) @CommandPermissions("worldedit.clipboard.rotate") - public void rotate(Player player, LocalSession session, Double yRotate, @Optional Double xRotate, @Optional Double zRotate) throws WorldEditException { - if ((yRotate != null && Math.abs(yRotate % 90) > 0.001) || - xRotate != null && Math.abs(xRotate % 90) > 0.001 || - zRotate != null && Math.abs(zRotate % 90) > 0.001) { + public void rotate(Player player, LocalSession session, + @Arg(desc = "Amount to rotate on the y-axis") + double yRotate, + @Arg(desc = "Amount to rotate on the x-axis", def = "0") + double xRotate, + @Arg(desc = "Amount to rotate on the z-axis", def = "0") + double zRotate) throws WorldEditException { + if (Math.abs(yRotate % 90) > 0.001 || + Math.abs(xRotate % 90) > 0.001 || + Math.abs(zRotate % 90) > 0.001) { player.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended."); } ClipboardHolder holder = session.getClipboard(); AffineTransform transform = new AffineTransform(); - transform = transform.rotateY(-(yRotate != null ? yRotate : 0)); - transform = transform.rotateX(-(xRotate != null ? xRotate : 0)); - transform = transform.rotateZ(-(zRotate != null ? zRotate : 0)); + transform = transform.rotateY(-yRotate); + transform = transform.rotateX(-xRotate); + transform = transform.rotateZ(-zRotate); holder.setTransform(holder.getTransform().combine(transform)); player.print("The clipboard copy has been rotated."); } @Command( - aliases = { "/flip" }, - usage = "[]", - desc = "Flip the contents of the clipboard", - help = - "Flips the contents of the clipboard across the point from which the copy was made.\n", - min = 0, - max = 1 + name = "/flip", + desc = "Flip the contents of the clipboard across the origin" ) @CommandPermissions("worldedit.clipboard.flip") public void flip(Player player, LocalSession session, - @Optional(Direction.AIM) @Direction BlockVector3 direction) throws WorldEditException { + @Arg(desc = "The direction to flip, defaults to look direction.", def = Direction.AIM) + @Direction BlockVector3 direction) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); AffineTransform transform = new AffineTransform(); transform = transform.scale(direction.abs().multiply(-2).add(1, 1, 1).toVector3()); @@ -220,11 +204,8 @@ public class ClipboardCommands { } @Command( - aliases = { "clearclipboard" }, - usage = "", - desc = "Clear your clipboard", - min = 0, - max = 0 + name = "clearclipboard", + desc = "Clear your clipboard" ) @CommandPermissions("worldedit.clipboard.clear") public void clearClipboard(Player player, LocalSession session) throws WorldEditException { 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 index 2d7f7cd2e..4b33675f9 100644 --- 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 @@ -19,16 +19,16 @@ 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 org.enginehub.piston.inject.Key; import java.util.Set; public final class PermissionCondition implements Command.Condition { - private static final Key ACTOR_KEY = Key.get(Actor.class); + private static final Key ACTOR_KEY = Key.of(Actor.class); private final Set permissions; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 08c39fb49..aefcb4323 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.extension.platform; import com.google.common.collect.ImmutableList; -import com.google.inject.Key; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; @@ -31,10 +30,11 @@ import com.sk89q.worldedit.command.BrushCommands; import com.sk89q.worldedit.command.BrushCommandsRegistration; import com.sk89q.worldedit.command.ChunkCommands; import com.sk89q.worldedit.command.ChunkCommandsRegistration; +import com.sk89q.worldedit.command.ClipboardCommands; +import com.sk89q.worldedit.command.ClipboardCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; 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; @@ -47,7 +47,6 @@ 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.SessionOwner; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler; @@ -65,8 +64,8 @@ import org.enginehub.piston.exception.ConditionFailedException; import org.enginehub.piston.exception.UsageException; import org.enginehub.piston.gen.CommandCallListener; import org.enginehub.piston.gen.CommandRegistration; -import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.InjectedValueStore; +import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.MapBackedValueStore; import org.enginehub.piston.inject.MemoizingValueAccess; import org.enginehub.piston.part.SubCommandPart; @@ -200,13 +199,17 @@ public final class PlatformCommandMananger { ChunkCommandsRegistration.builder(), new ChunkCommands(worldEdit) ); + register( + commandManager, + ClipboardCommandsRegistration.builder(), + new ClipboardCommands() + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new ClipboardCommands(worldEdit)) .registerMethods(new GeneralCommands(worldEdit)) .registerMethods(new GenerationCommands(worldEdit)) .registerMethods(new HistoryCommands(worldEdit)) @@ -334,22 +337,22 @@ public final class PlatformCommandMananger { LocalConfiguration config = worldEdit.getConfiguration(); InjectedValueStore store = MapBackedValueStore.create(); - store.injectValue(Key.get(Actor.class), ValueProvider.constant(actor)); + store.injectValue(Key.of(Actor.class), ValueProvider.constant(actor)); if (actor instanceof Player) { - store.injectValue(Key.get(Player.class), ValueProvider.constant((Player) actor)); + store.injectValue(Key.of(Player.class), ValueProvider.constant((Player) actor)); } - store.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments)); - store.injectValue(Key.get(LocalSession.class), + store.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments)); + store.injectValue(Key.of(LocalSession.class), context -> { LocalSession localSession = worldEdit.getSessionManager().get(actor); localSession.tellVersion(actor); return Optional.of(localSession); }); - store.injectValue(Key.get(EditSession.class), + store.injectValue(Key.of(EditSession.class), context -> { - LocalSession localSession = context.injectedValue(Key.get(LocalSession.class)) + LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) .orElseThrow(() -> new IllegalStateException("No LocalSession")); - return context.injectedValue(Key.get(Player.class)) + return context.injectedValue(Key.of(Player.class)) .map(player -> { EditSession editSession = localSession.createEditSession(player); editSession.enableStandardMode(); @@ -401,7 +404,7 @@ public final class PlatformCommandMananger { } } finally { Optional editSessionOpt = - context.injectedValueIfMemoized(Key.get(EditSession.class)); + context.injectedValueIfMemoized(Key.of(EditSession.class)); if (editSessionOpt.isPresent()) { EditSession editSession = editSessionOpt.get(); @@ -432,8 +435,8 @@ public final class PlatformCommandMananger { @Subscribe public void handleCommandSuggestion(CommandSuggestionEvent event) { try { - commandManager.injectValue(Key.get(Actor.class), ValueProvider.constant(event.getActor())); - commandManager.injectValue(Key.get(Arguments.class), ValueProvider.constant(event::getArguments)); + commandManager.injectValue(Key.of(Actor.class), ValueProvider.constant(event.getActor())); + commandManager.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments)); // TODO suggestions } catch (CommandException e) { event.getActor().printError(e.getMessage()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Selection.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Selection.java index 9647c360f..1886f43f7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Selection.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Selection.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.internal.annotation; +import org.enginehub.piston.inject.InjectAnnotation; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -29,6 +31,6 @@ import java.lang.annotation.Target; */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) +@InjectAnnotation public @interface Selection { - } 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 8cd2cdb5f..f97123292 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,16 +19,16 @@ package com.sk89q.worldedit.internal.command; -import com.google.inject.Key; -import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.math.Vector3; import org.enginehub.piston.CommandParameters; import org.enginehub.piston.gen.CommandCallListener; +import org.enginehub.piston.inject.Key; import java.lang.reflect.Method; import java.util.Optional; @@ -72,7 +72,7 @@ public class CommandLoggingHandler implements CommandCallListener, AutoCloseable logMode = loggingAnnotation.value(); } - Optional playerOpt = parameters.injectedValue(Key.get(Actor.class)) + Optional playerOpt = parameters.injectedValue(Key.of(Actor.class)) .filter(Player.class::isInstance) .map(Player.class::cast); From ac03de89cc9b8be20fbf63b541360422f62ff462 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 18 Apr 2019 19:11:57 -0700 Subject: [PATCH 11/57] Work on adding converters for some arguments --- config/checkstyle/import-control.xml | 2 +- .../bukkit/BukkitCommandInspector.java | 10 +- .../worldedit/bukkit/WorldEditListener.java | 17 ++- worldedit-core/build.gradle | 3 + .../command/argument/DirectionConverter.java | 109 ++++++++++++++++++ .../command/argument/MaskConverter.java | 58 ++++++++++ .../command/argument/package-info.java | 21 ++++ .../platform/PlatformCommandMananger.java | 57 +++++++-- .../internal/annotation/Direction.java | 8 +- 9 files changed, 260 insertions(+), 25 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java diff --git a/config/checkstyle/import-control.xml b/config/checkstyle/import-control.xml index 5bcfffeb3..36ccf3d0b 100644 --- a/config/checkstyle/import-control.xml +++ b/config/checkstyle/import-control.xml @@ -17,7 +17,6 @@ - @@ -40,6 +39,7 @@ + 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 d889903be..8944cb586 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 @@ -27,7 +27,10 @@ import org.bukkit.command.CommandSender; import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandParameters; import org.enginehub.piston.NoInputCommandParameters; +import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; +import org.enginehub.piston.inject.MapBackedValueStore; +import org.enginehub.piston.inject.MemoizingValueAccess; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,10 +77,11 @@ class BukkitCommandInspector implements CommandInspector { public boolean testPermission(CommandSender sender, Command command) { Optional mapping = dispatcher.getCommand(command.getName()); if (mapping.isPresent()) { + InjectedValueStore store = MapBackedValueStore.create(); + store.injectValue(Key.of(Actor.class), context -> + Optional.of(plugin.wrapCommandSender(sender))); CommandParameters parameters = NoInputCommandParameters.builder() - .injectedValues(ImmutableMap.of( - Key.of(Actor.class), plugin.wrapCommandSender(sender) - )) + .injectedValues(MemoizingValueAccess.wrap(store)) .build(); return mapping.get().getCondition().satisfied(parameters); } else { 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 9d335bb24..699263d50 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,7 +21,6 @@ package com.sk89q.worldedit.bukkit; -import com.google.common.collect.ImmutableMap; import com.sk89q.util.StringUtil; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; @@ -42,7 +41,12 @@ import org.bukkit.inventory.EquipmentSlot; import org.enginehub.piston.CommandManager; import org.enginehub.piston.CommandParameters; import org.enginehub.piston.NoInputCommandParameters; +import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; +import org.enginehub.piston.inject.MapBackedValueStore; +import org.enginehub.piston.inject.MemoizingValueAccess; + +import java.util.Optional; /** * Handles all events thrown in relation to a Player @@ -108,17 +112,18 @@ public class WorldEditListener implements Listener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onPlayerCommand(PlayerCommandSendEvent event) { + InjectedValueStore store = MapBackedValueStore.create(); + store.injectValue(Key.of(Actor.class), context -> + Optional.of(plugin.wrapCommandSender(event.getPlayer()))); CommandParameters parameters = NoInputCommandParameters.builder() - .injectedValues(ImmutableMap.of( - Key.of(Actor.class), plugin.wrapCommandSender(event.getPlayer()) - )) + .injectedValues(MemoizingValueAccess.wrap(store)) .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() + .filter(command -> !command.getCondition().satisfied(parameters)) + .isPresent() ); } diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index 23f96a592..efbf0aed3 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -33,6 +33,9 @@ dependencies { implementation "org.enginehub.piston.core-ap:runtime:$pistonVersion" annotationProcessor "org.enginehub.piston.core-ap:processor:$pistonVersion" api "org.enginehub.piston:default-impl:$pistonVersion" + def avVersion = "1.6.5" + compileOnly "com.google.auto.value:auto-value-annotations:$avVersion" + annotationProcessor "com.google.auto.value:auto-value:$avVersion" //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/argument/DirectionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java new file mode 100644 index 000000000..f454191da --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java @@ -0,0 +1,109 @@ +/* + * 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.google.auto.value.AutoAnnotation; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.sk89q.worldedit.UnknownDirectionException; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.internal.annotation.Direction; +import com.sk89q.worldedit.math.BlockVector3; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.List; + +import static java.util.stream.Collectors.toList; + +public class DirectionConverter implements ArgumentConverter { + + @AutoAnnotation + private static Direction direction(boolean includeDiagonals) { + return new AutoAnnotation_DirectionConverter_direction(includeDiagonals); + } + + public static void register(WorldEdit worldEdit, CommandManager commandManager) { + commandManager.registerConverter( + Key.of(BlockVector3.class, direction(false)), + new DirectionConverter(worldEdit, false) + ); + commandManager.registerConverter( + Key.of(BlockVector3.class, direction(true)), + new DirectionConverter(worldEdit, true) + ); + } + + private static final ImmutableSet NON_DIAGONALS = ImmutableSet.of( + "north", "south", "east", "west", "up", "down" + ); + private static final ImmutableSet RELATIVE = ImmutableSet.of( + "me", "forward", "back", "left", "right" + ); + private static final ImmutableSet DIAGONALS = ImmutableSet.of( + "northeast", "northwest", "southeast", "southwest" + ); + + private final WorldEdit worldEdit; + private final boolean includeDiagonals; + private final ImmutableList suggestions; + + private DirectionConverter(WorldEdit worldEdit, boolean includeDiagonals) { + this.worldEdit = worldEdit; + this.includeDiagonals = includeDiagonals; + suggestions = ImmutableList.builder() + .addAll(NON_DIAGONALS) + .addAll(RELATIVE) + .addAll(includeDiagonals ? DIAGONALS : ImmutableList.of()) + .build(); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + Player player = context.injectedValue(Key.of(Player.class)) + .orElseThrow(() -> new IllegalStateException("No player available")); + try { + return SuccessfulConversion.fromSingle(includeDiagonals + ? worldEdit.getDiagonalDirection(player, argument) + : worldEdit.getDirection(player, argument)); + } catch (UnknownDirectionException e) { + return FailedConversion.from(e); + } + } + + @Override + public String describeAcceptableArguments() { + return "`me` to use facing direction, or any " + + (includeDiagonals ? "direction" : "non-diagonal direction"); + } + + @Override + public List getSuggestions(String input) { + return suggestions.stream() + .filter(s -> s.startsWith(input)) + .collect(toList()); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java new file mode 100644 index 000000000..cabe53ec5 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java @@ -0,0 +1,58 @@ +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.NoMatchException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.world.World; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +public class MaskConverter implements ArgumentConverter { + + public static void register(WorldEdit worldEdit, CommandManager commandManager) { + commandManager.registerConverter(Key.of(Mask.class), new MaskConverter(worldEdit)); + } + + private final WorldEdit worldEdit; + + private MaskConverter(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + Actor actor = context.injectedValue(Key.of(Actor.class)) + .orElseThrow(() -> new IllegalStateException("No actor")); + ParserContext parserContext = new ParserContext(); + parserContext.setActor(actor); + if (actor instanceof Entity) { + Extent extent = ((Entity) actor).getExtent(); + if (extent instanceof World) { + parserContext.setWorld((World) extent); + } + } + parserContext.setSession(worldEdit.getSessionManager().get(actor)); + try { + return SuccessfulConversion.fromSingle( + worldEdit.getMaskFactory().parseFromInput(argument, parserContext) + ); + } catch (InputParseException e) { + return FailedConversion.from(e); + } + } + + @Override + public String describeAcceptableArguments() { + return "any mask"; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java new file mode 100644 index 000000000..e1d68643b --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/package-info.java @@ -0,0 +1,21 @@ +/* + * 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 . + */ + +@org.enginehub.piston.util.NonnullByDefault +package com.sk89q.worldedit.command.argument; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index aefcb4323..7bbab6a16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -21,6 +21,7 @@ package com.sk89q.worldedit.extension.platform; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -35,6 +36,8 @@ import com.sk89q.worldedit.command.ClipboardCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; +import com.sk89q.worldedit.command.argument.DirectionConverter; +import com.sk89q.worldedit.command.argument.MaskConverter; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Entity; @@ -42,11 +45,13 @@ 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.internal.annotation.Selection; 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.regions.Region; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler; @@ -103,7 +108,7 @@ public final class PlatformCommandMananger { private final PlatformManager platformManager; private final CommandManager commandManager; private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); - private final ExceptionConverter exceptionConverter; + private final WorldEditExceptionConverter exceptionConverter; private final List callListeners; /** @@ -153,6 +158,45 @@ public final class PlatformCommandMananger { builder.addBinding(new WorldEditBinding(worldEdit)); builder.addInvokeListener(new LegacyCommandsHandler()); + registerAlwaysInjectedValues(); + registerArgumentConverters(); + registerAllCommands(); + } + + private void registerArgumentConverters() { + DirectionConverter.register(worldEdit, commandManager); + MaskConverter.register(worldEdit, commandManager); + } + + private void registerAlwaysInjectedValues() { + commandManager.injectValue(Key.of(Region.class, Selection.class), + context -> { + LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) + .orElseThrow(() -> new IllegalStateException("No LocalSession")); + return context.injectedValue(Key.of(Player.class)) + .map(player -> { + try { + return localSession.getSelection(player.getWorld()); + } catch (IncompleteRegionException e) { + exceptionConverter.convert(e); + throw new AssertionError("Should have thrown a new exception."); + } + }); + }); + commandManager.injectValue(Key.of(EditSession.class), + context -> { + LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) + .orElseThrow(() -> new IllegalStateException("No LocalSession")); + return context.injectedValue(Key.of(Player.class)) + .map(player -> { + EditSession editSession = localSession.createEditSession(player); + editSession.enableStandardMode(); + return editSession; + }); + }); + } + + private void registerAllCommands() { commandManager.register("schematic", cmd -> { cmd.aliases(ImmutableList.of("schem", "/schematic", "/schem")); cmd.description("Schematic commands for saving/loading areas"); @@ -348,17 +392,6 @@ public final class PlatformCommandMananger { localSession.tellVersion(actor); return Optional.of(localSession); }); - store.injectValue(Key.of(EditSession.class), - context -> { - LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) - .orElseThrow(() -> new IllegalStateException("No LocalSession")); - return context.injectedValue(Key.of(Player.class)) - .map(player -> { - EditSession editSession = localSession.createEditSession(player); - editSession.enableStandardMode(); - return editSession; - }); - }); MemoizingValueAccess context = MemoizingValueAccess.wrap(store); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Direction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Direction.java index dbc7d3b29..bd2b55b4f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Direction.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Direction.java @@ -19,7 +19,8 @@ package com.sk89q.worldedit.internal.annotation; -import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.math.BlockVector3; +import org.enginehub.piston.inject.InjectAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -27,12 +28,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Annotates a {@link Vector3} parameter to inject a direction. + * Annotates a {@link BlockVector3} parameter to inject a direction. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) +@InjectAnnotation public @interface Direction { - + String AIM = "me"; boolean includeDiagonals() default false; From 48fcfeed3573a81dd783d3664550d644b5e564f2 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 18 Apr 2019 19:12:09 -0700 Subject: [PATCH 12/57] Fix licenses --- .../command/argument/MaskConverter.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java index cabe53ec5..f53c5a180 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java @@ -1,3 +1,22 @@ +/* + * 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.WorldEdit; From f481f7d26da5f7f0c34bda85d0ec9b7ece3d343e Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 18 Apr 2019 19:59:53 -0700 Subject: [PATCH 13/57] Handle lack of global injected value store --- .../platform/PlatformCommandMananger.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 7bbab6a16..df71157f7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -73,6 +73,7 @@ import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.MapBackedValueStore; import org.enginehub.piston.inject.MemoizingValueAccess; +import org.enginehub.piston.inject.MergedValueAccess; import org.enginehub.piston.part.SubCommandPart; import org.enginehub.piston.util.ValueProvider; import org.slf4j.Logger; @@ -107,6 +108,7 @@ public final class PlatformCommandMananger { private final WorldEdit worldEdit; private final PlatformManager platformManager; private final CommandManager commandManager; + private final InjectedValueStore globalInjectedValues; private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); private final WorldEditExceptionConverter exceptionConverter; private final List callListeners; @@ -124,6 +126,7 @@ public final class PlatformCommandMananger { this.exceptionConverter = new WorldEditExceptionConverter(worldEdit); this.commandManager = DefaultCommandManagerService.getInstance() .newCommandManager(); + this.globalInjectedValues = MapBackedValueStore.create(); this.callListeners = Collections.singletonList( new CommandLoggingHandler(worldEdit, commandLog) ); @@ -169,7 +172,7 @@ public final class PlatformCommandMananger { } private void registerAlwaysInjectedValues() { - commandManager.injectValue(Key.of(Region.class, Selection.class), + globalInjectedValues.injectValue(Key.of(Region.class, Selection.class), context -> { LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) .orElseThrow(() -> new IllegalStateException("No LocalSession")); @@ -183,7 +186,7 @@ public final class PlatformCommandMananger { } }); }); - commandManager.injectValue(Key.of(EditSession.class), + globalInjectedValues.injectValue(Key.of(EditSession.class), context -> { LocalSession localSession = context.injectedValue(Key.of(LocalSession.class)) .orElseThrow(() -> new IllegalStateException("No LocalSession")); @@ -393,7 +396,9 @@ public final class PlatformCommandMananger { return Optional.of(localSession); }); - MemoizingValueAccess context = MemoizingValueAccess.wrap(store); + MemoizingValueAccess context = MemoizingValueAccess.wrap( + MergedValueAccess.of(store, globalInjectedValues) + ); long start = System.currentTimeMillis(); @@ -437,7 +442,7 @@ public final class PlatformCommandMananger { } } finally { Optional editSessionOpt = - context.injectedValueIfMemoized(Key.of(EditSession.class)); + context.snapshotMemory().injectedValue(Key.of(EditSession.class)); if (editSessionOpt.isPresent()) { EditSession editSession = editSessionOpt.get(); @@ -468,8 +473,8 @@ public final class PlatformCommandMananger { @Subscribe public void handleCommandSuggestion(CommandSuggestionEvent event) { try { - commandManager.injectValue(Key.of(Actor.class), ValueProvider.constant(event.getActor())); - commandManager.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments)); + globalInjectedValues.injectValue(Key.of(Actor.class), ValueProvider.constant(event.getActor())); + globalInjectedValues.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments)); // TODO suggestions } catch (CommandException e) { event.getActor().printError(e.getMessage()); From 51be16ad81b5af8754d0256c3e776c3b98196a68 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 21 Apr 2019 13:10:20 -0700 Subject: [PATCH 14/57] Port GeneralCommands --- .../worldedit/command/GeneralCommands.java | 127 ++++++++---------- .../platform/PlatformCommandMananger.java | 8 +- 2 files changed, 63 insertions(+), 72 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index b05adf155..a5a0a9796 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -19,28 +19,31 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.collect.Sets; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.DisallowedUsageException; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; + +import static com.google.common.base.Preconditions.checkNotNull; /** * General WorldEdit commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class GeneralCommands { private final WorldEdit worldEdit; @@ -56,19 +59,18 @@ public class GeneralCommands { } @Command( - aliases = { "/limit" }, - usage = "[limit]", - desc = "Modify block change limit", - min = 0, - max = 1 + name = "/limit", + desc = "Modify block change limit" ) @CommandPermissions("worldedit.limit") - public void limit(Player player, LocalSession session, CommandContext args) throws WorldEditException { - + public void limit(Player player, LocalSession session, + @Arg(desc = "The limit to set", def = "") + Integer limit) throws WorldEditException { + LocalConfiguration config = worldEdit.getConfiguration(); boolean mayDisable = player.hasPermission("worldedit.limit.unrestricted"); - int limit = args.argsLength() == 0 ? config.defaultChangeLimit : Math.max(-1, args.getInteger(0)); + limit = limit == null ? config.defaultChangeLimit : Math.max(-1, limit); if (!mayDisable && config.maxChangeLimit > -1) { if (limit > config.maxChangeLimit) { player.printError("Your maximum allowable limit is " + config.maxChangeLimit + "."); @@ -86,19 +88,18 @@ public class GeneralCommands { } @Command( - aliases = { "/timeout" }, - usage = "[time]", - desc = "Modify evaluation timeout time.", - min = 0, - max = 1 + name = "/timeout", + desc = "Modify evaluation timeout time." ) @CommandPermissions("worldedit.timeout") - public void timeout(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void timeout(Player player, LocalSession session, + @Arg(desc = "The timeout time to set", def = "") + Integer limit) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); boolean mayDisable = player.hasPermission("worldedit.timeout.unrestricted"); - int limit = args.argsLength() == 0 ? config.calculationTimeout : Math.max(-1, args.getInteger(0)); + limit = limit == null ? config.calculationTimeout : Math.max(-1, limit); if (!mayDisable && config.maxCalculationTimeout > -1) { if (limit > config.maxCalculationTimeout) { player.printError("Your maximum allowable timeout is " + config.maxCalculationTimeout + " ms."); @@ -116,16 +117,14 @@ public class GeneralCommands { } @Command( - aliases = { "/fast" }, - usage = "[on|off]", - desc = "Toggle fast mode", - min = 0, - max = 1 + name = "/fast", + desc = "Toggle fast mode" ) @CommandPermissions("worldedit.fast") - public void fast(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void fast(Player player, LocalSession session, + @Arg(name = "on|off", desc = "The new fast mode state", def = "toggle") + String newState) throws WorldEditException { - String newState = args.getString(0, null); if (session.hasFastMode()) { if ("on".equals(newState)) { player.printError("Fast mode already enabled."); @@ -146,15 +145,13 @@ public class GeneralCommands { } @Command( - aliases = { "/reorder" }, - usage = "[multi|fast|none]", - desc = "Sets the reorder mode of WorldEdit", - min = 0, - max = 1 + name = "/reorder", + desc = "Sets the reorder mode of WorldEdit" ) @CommandPermissions("worldedit.reorder") - public void reorderMode(Player player, LocalSession session, CommandContext args) throws WorldEditException { - String newState = args.getString(0, null); + public void reorderMode(Player player, LocalSession session, + @Arg(name = "multi|fast|none", desc = "The reorder mode", def = "") + String newState) throws WorldEditException { if (newState == null) { player.print("The reorder mode is " + session.getReorderMode().getDisplayName()); } else { @@ -171,19 +168,16 @@ public class GeneralCommands { } @Command( - aliases = { "/drawsel" }, - usage = "[on|off]", - desc = "Toggle drawing the current selection", - min = 0, - max = 1 + name = "/drawsel", + desc = "Toggle drawing the current selection" ) @CommandPermissions("worldedit.drawsel") - public void drawSelection(Player player, LocalSession session, CommandContext args) throws WorldEditException { - + public void drawSelection(Player player, LocalSession session, + @Arg(name = "on|off", desc = "The new fast mode state", def = "toggle") + String newState) throws WorldEditException { if (!WorldEdit.getInstance().getConfiguration().serverSideCUI) { throw new DisallowedUsageException("This functionality is disabled in the configuration!"); } - String newState = args.getString(0, null); if (session.shouldUseServerCUI()) { if ("on".equals(newState)) { player.printError("Server CUI already enabled."); @@ -206,14 +200,14 @@ public class GeneralCommands { } @Command( - aliases = { "/gmask", "gmask" }, - usage = "[mask]", - desc = "Set the global mask", - min = 0, - max = -1 + name = "gmask", + aliases = {"/gmask"}, + desc = "Set the global mask" ) @CommandPermissions("worldedit.global-mask") - public void gmask(Player player, LocalSession session, @Optional Mask mask) throws WorldEditException { + public void gmask(Player player, LocalSession session, + @Arg(desc = "The mask to set", def = "") + Mask mask) throws WorldEditException { if (mask == null) { session.setMask((Mask) null); player.print("Global mask disabled."); @@ -224,11 +218,9 @@ public class GeneralCommands { } @Command( - aliases = { "/toggleplace", "toggleplace" }, - usage = "", - desc = "Switch between your position and pos1 for placement", - min = 0, - max = 0 + name = "toggleplace", + aliases = {"/toggleplace"}, + desc = "Switch between your position and pos1 for placement" ) public void togglePlace(Player player, LocalSession session) throws WorldEditException { @@ -240,24 +232,17 @@ public class GeneralCommands { } @Command( - aliases = { "/searchitem", "/l", "/search", "searchitem" }, - usage = "", - flags = "bi", - desc = "Search for an item", - help = - "Searches for an item.\n" + - "Flags:\n" + - " -b only search for blocks\n" + - " -i only search for items", - min = 1, - max = 1 + name = "searchitem", + aliases = {"/searchitem", "/l", "/search"}, + desc = "Search for an item" ) - public void searchItem(Actor actor, CommandContext args) throws WorldEditException { - - String query = args.getString(0).trim().toLowerCase(); - boolean blocksOnly = args.hasFlag('b'); - boolean itemsOnly = args.hasFlag('i'); - + public void searchItem(Actor actor, + @Arg(desc = "Item query") + String query, + @Switch(name = 'b', desc = "Only search for blocks") + boolean blocksOnly, + @Switch(name = 'i', desc = "Only search for items") + boolean itemsOnly) throws WorldEditException { ItemType type = ItemTypes.get(query); if (type != null) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index df71157f7..8df64ab03 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -33,6 +33,8 @@ import com.sk89q.worldedit.command.ChunkCommands; import com.sk89q.worldedit.command.ChunkCommandsRegistration; import com.sk89q.worldedit.command.ClipboardCommands; import com.sk89q.worldedit.command.ClipboardCommandsRegistration; +import com.sk89q.worldedit.command.GeneralCommands; +import com.sk89q.worldedit.command.GeneralCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; @@ -251,13 +253,17 @@ public final class PlatformCommandMananger { ClipboardCommandsRegistration.builder(), new ClipboardCommands() ); + register( + commandManager, + GeneralCommandsRegistration.builder(), + new GeneralCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new GeneralCommands(worldEdit)) .registerMethods(new GenerationCommands(worldEdit)) .registerMethods(new HistoryCommands(worldEdit)) .registerMethods(new NavigationCommands(worldEdit)) From 31486cd47389d700cf81ca403c50e5549a3ed017 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 10:11:54 -0700 Subject: [PATCH 15/57] Port generation commands --- .../worldedit/command/GenerationCommands.java | 298 +++++++++--------- .../CommaSeparatedValuesConverter.java | 68 ++++ ...tternParser.java => PatternConverter.java} | 45 +-- .../command/argument/ReplaceParser.java | 8 +- .../extension/platform/Annotations.java | 16 + .../platform/PlatformCommandMananger.java | 20 +- .../worldedit/internal/annotation/Radii.java | 40 +++ 7 files changed, 321 insertions(+), 174 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java rename worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/{PatternParser.java => PatternConverter.java} (60%) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Radii.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index f4578bdcd..962243c9f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -19,35 +19,39 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; -import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; -import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.annotation.Radii; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.TreeGenerator.TreeType; -import com.sk89q.worldedit.util.command.binding.Range; -import com.sk89q.worldedit.util.command.binding.Switch; -import com.sk89q.worldedit.util.command.binding.Text; -import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.world.biome.BiomeType; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; + +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; +import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; /** * Commands for the generation of shapes and other objects. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class GenerationCommands { private final WorldEdit worldEdit; @@ -63,54 +67,52 @@ public class GenerationCommands { } @Command( - aliases = { "/hcyl" }, - usage = " [,] [height]", - desc = "Generates a hollow cylinder.", - help = - "Generates a hollow cylinder.\n" + - "By specifying 2 radii, separated by a comma,\n" + - "you can generate elliptical cylinders.\n" + - "The 1st radius is north/south, the 2nd radius is east/west.", - min = 2, - max = 3 + name = "/hcyl", + desc = "Generates a hollow cylinder." ) @CommandPermissions("worldedit.generation.cylinder") @Logging(PLACEMENT) - public void hcyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height) throws WorldEditException { - cyl(player, session, editSession, pattern, radiusString, height, true); + public int hcyl(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The pattern of blocks to generate") + Pattern pattern, + @Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W") + @Radii(2) + List radii, + @Arg(desc = "The height of the cylinder", def = "1") + int height) throws WorldEditException { + return cyl(player, session, editSession, pattern, radii, height, true); } @Command( - aliases = { "/cyl" }, - usage = " [,] [height]", - flags = "h", - desc = "Generates a cylinder.", - help = - "Generates a cylinder.\n" + - "By specifying 2 radii, separated by a comma,\n" + - "you can generate elliptical cylinders.\n" + - "The 1st radius is north/south, the 2nd radius is east/west.", - min = 2, - max = 3 + name = "/cyl", + desc = "Generates a cylinder." ) @CommandPermissions("worldedit.generation.cylinder") @Logging(PLACEMENT) - public void cyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException { - String[] radii = radiusString.split(","); + public int cyl(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The pattern of blocks to generate") + Pattern pattern, + @Arg(desc = "The radii of the cylinder. 1st is N/S, 2nd is E/W") + @Radii(2) + List radii, + @Arg(desc = "The height of the cylinder", def = "1") + int height, + @Switch(name = 'h', desc = "Make a hollow cylinder") + boolean hollow) throws WorldEditException { final double radiusX, radiusZ; - switch (radii.length) { + switch (radii.size()) { case 1: - radiusX = radiusZ = Math.max(1, Double.parseDouble(radii[0])); + radiusX = radiusZ = Math.max(1, radii.get(0)); break; case 2: - radiusX = Math.max(1, Double.parseDouble(radii[0])); - radiusZ = Math.max(1, Double.parseDouble(radii[1])); + radiusX = Math.max(1, radii.get(0)); + radiusZ = Math.max(1, radii.get(1)); break; default: player.printError("You must either specify 1 or 2 radius values."); - return; + return 0; } worldEdit.checkMaxRadius(radiusX); @@ -120,58 +122,57 @@ public class GenerationCommands { BlockVector3 pos = session.getPlacementPosition(player); int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow); player.print(affected + " block(s) have been created."); + return affected; } @Command( - aliases = { "/hsphere" }, - usage = " [,,] [raised?]", - desc = "Generates a hollow sphere.", - help = - "Generates a hollow sphere.\n" + - "By specifying 3 radii, separated by commas,\n" + - "you can generate an ellipsoid. The order of the ellipsoid radii\n" + - "is north/south, up/down, east/west.", - min = 2, - max = 3 + name = "/hsphere", + desc = "Generates a hollow sphere." ) @CommandPermissions("worldedit.generation.sphere") @Logging(PLACEMENT) - public void hsphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised) throws WorldEditException { - sphere(player, session, editSession, pattern, radiusString, raised, true); + public int hsphere(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The pattern of blocks to generate") + Pattern pattern, + @Arg(desc = "The radii of the sphere. Order is N/S, U/D, E/W") + @Radii(3) + List radii, + @Switch(name = 'r', desc = "Raise the bottom of the sphere to the placement position") + boolean raised) throws WorldEditException { + return sphere(player, session, editSession, pattern, radii, raised, true); } @Command( - aliases = { "/sphere" }, - usage = " [,,] [raised?]", - flags = "h", - desc = "Generates a filled sphere.", - help = - "Generates a filled sphere.\n" + - "By specifying 3 radii, separated by commas,\n" + - "you can generate an ellipsoid. The order of the ellipsoid radii\n" + - "is north/south, up/down, east/west.", - min = 2, - max = 3 + name = "/sphere", + desc = "Generates a filled sphere." ) @CommandPermissions("worldedit.generation.sphere") @Logging(PLACEMENT) - public void sphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised, @Switch('h') boolean hollow) throws WorldEditException { - String[] radii = radiusString.split(","); + public int sphere(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The pattern of blocks to generate") + Pattern pattern, + @Arg(desc = "The radii of the sphere. Order is N/S, U/D, E/W") + @Radii(3) + List radii, + @Switch(name = 'r', desc = "Raise the bottom of the sphere to the placement position") + boolean raised, + @Switch(name = 'h', desc = "Make a hollow sphere") + boolean hollow) throws WorldEditException { final double radiusX, radiusY, radiusZ; - switch (radii.length) { + switch (radii.size()) { case 1: - radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radii[0])); + radiusX = radiusY = radiusZ = Math.max(1, radii.get(0)); break; case 3: - radiusX = Math.max(1, Double.parseDouble(radii[0])); - radiusY = Math.max(1, Double.parseDouble(radii[1])); - radiusZ = Math.max(1, Double.parseDouble(radii[2])); + radiusX = Math.max(1, radii.get(0)); + radiusY = Math.max(1, radii.get(1)); + radiusZ = Math.max(1, radii.get(2)); break; default: player.printError("You must either specify 1 or 3 radius values."); - return; + return 0; } worldEdit.checkMaxRadius(radiusX); @@ -186,98 +187,102 @@ public class GenerationCommands { int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow); player.findFreePosition(); player.print(affected + " block(s) have been created."); + return affected; } @Command( - aliases = { "forestgen" }, - usage = "[size] [type] [density]", - desc = "Generate a forest", - min = 0, - max = 3 + name = "forestgen", + desc = "Generate a forest" ) @CommandPermissions("worldedit.generation.forest") @Logging(POSITION) - public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size, - @Optional("tree") TreeType type, @Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException { + public int forestGen(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The size of the forest, in blocks", def = "10") + int size, + @Arg(desc = "The type of forest", def = "tree") + TreeType type, + @Arg(desc = "The density of the forest, between 0 and 100", def = "5") + double density) throws WorldEditException { + if (density < 0 || density > 100) { + throw new IllegalArgumentException("Density must be between 0 and 100"); + } density = density / 100; int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type); player.print(affected + " trees created."); + return affected; } @Command( - aliases = { "pumpkins" }, - usage = "[size]", - desc = "Generate pumpkin patches", - min = 0, - max = 1 + name = "pumpkins", + desc = "Generate pumpkin patches" ) @CommandPermissions("worldedit.generation.pumpkins") @Logging(POSITION) - public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException { - int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem); + public int pumpkins(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The size of the patch", def = "10") + int size) throws WorldEditException { + int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), size); player.print(affected + " pumpkin patches created."); + return affected; } @Command( - aliases = { "/hpyramid" }, - usage = " ", - desc = "Generate a hollow pyramid", - min = 2, - max = 2 + name = "/hpyramid", + desc = "Generate a hollow pyramid" ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) - public void hollowPyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size) throws WorldEditException { - pyramid(player, session, editSession, pattern, size, true); + public int hollowPyramid(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern, + @Arg(desc = "The size of the pyramid") + int size) throws WorldEditException { + return pyramid(player, session, editSession, pattern, size, true); } @Command( - aliases = { "/pyramid" }, - usage = " ", - flags = "h", - desc = "Generate a filled pyramid", - min = 2, - max = 2 + name = "/pyramid", + desc = "Generate a filled pyramid" ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) - public void pyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size, @Switch('h') boolean hollow) throws WorldEditException { + public int pyramid(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern, + @Arg(desc = "The size of the pyramid") + int size, + @Switch(name = 'h', desc = "Make a hollow pyramid") + boolean hollow) throws WorldEditException { BlockVector3 pos = session.getPlacementPosition(player); worldEdit.checkMaxRadius(size); int affected = editSession.makePyramid(pos, pattern, size, !hollow); player.findFreePosition(); player.print(affected + " block(s) have been created."); + return affected; } @Command( - aliases = { "/generate", "/gen", "/g" }, - usage = " ", + name = "/generate", + aliases = { "/gen", "/g" }, desc = "Generates a shape according to a formula.", - help = - "Generates a shape according to a formula that is expected to\n" + - "return positive numbers (true) if the point is inside the shape\n" + - "Optionally set type/data to the desired block.\n" + - "Flags:\n" + - " -h to generate a hollow shape\n" + - " -r to use raw minecraft coordinates\n" + - " -o is like -r, except offset from placement.\n" + - " -c is like -r, except offset selection center.\n" + - "If neither -r nor -o is given, the selection is mapped to -1..1\n" + - "See also tinyurl.com/wesyntax.", - flags = "hroc", - min = 2, - max = -1 + descFooter = "See also https://tinyurl.com/wesyntax." ) @CommandPermissions("worldedit.generation.shape") @Logging(ALL) - public void generate(Player player, LocalSession session, EditSession editSession, - @Selection Region region, - Pattern pattern, - @Text String expression, - @Switch('h') boolean hollow, - @Switch('r') boolean useRawCoords, - @Switch('o') boolean offset, - @Switch('c') boolean offsetCenter) throws WorldEditException { + public int generate(Player player, LocalSession session, EditSession editSession, + @Selection Region region, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern, + @Arg(desc = "Expression to test block placement locations and set block type") + String expression, + @Switch(name = 'h', desc = "Generate a hollow shape") + boolean hollow, + @Switch(name = 'r', desc = "Use the game's coordinate origin") + boolean useRawCoords, + @Switch(name = 'o', desc = "Use the placement's coordinate origin") + boolean offset, + @Switch(name = 'c', desc = "Use the selection's center as origin") + boolean offsetCenter) throws WorldEditException { final Vector3 zero; Vector3 unit; @@ -310,40 +315,35 @@ public class GenerationCommands { final int affected = editSession.makeShape(region, zero, unit, pattern, expression, hollow, session.getTimeout()); player.findFreePosition(); player.print(affected + " block(s) have been created."); + return affected; } catch (ExpressionException e) { player.printError(e.getMessage()); + return 0; } } @Command( - aliases = { "/generatebiome", "/genbiome", "/gb" }, - usage = " ", + name = "/generatebiome", + aliases = { "/genbiome", "/gb" }, desc = "Sets biome according to a formula.", - help = - "Generates a shape according to a formula that is expected to\n" + - "return positive numbers (true) if the point is inside the shape\n" + - "Sets the biome of blocks in that shape.\n" + - "Flags:\n" + - " -h to generate a hollow shape\n" + - " -r to use raw minecraft coordinates\n" + - " -o is like -r, except offset from placement.\n" + - " -c is like -r, except offset selection center.\n" + - "If neither -r nor -o is given, the selection is mapped to -1..1\n" + - "See also tinyurl.com/wesyntax.", - flags = "hroc", - min = 2, - max = -1 + descFooter = "See also https://tinyurl.com/wesyntax." ) @CommandPermissions("worldedit.generation.shape.biome") @Logging(ALL) - public void generateBiome(Player player, LocalSession session, EditSession editSession, - @Selection Region region, - BiomeType target, - @Text String expression, - @Switch('h') boolean hollow, - @Switch('r') boolean useRawCoords, - @Switch('o') boolean offset, - @Switch('c') boolean offsetCenter) throws WorldEditException { + public int generateBiome(Player player, LocalSession session, EditSession editSession, + @Selection Region region, + @Arg(desc = "The biome type to set") + BiomeType target, + @Arg(desc = "Expression to test block placement locations and set biome type") + String expression, + @Switch(name = 'h', desc = "Generate a hollow shape") + boolean hollow, + @Switch(name = 'r', desc = "Use the game's coordinate origin") + boolean useRawCoords, + @Switch(name = 'o', desc = "Use the placement's coordinate origin") + boolean offset, + @Switch(name = 'c', desc = "Use the selection's center as origin") + boolean offsetCenter) throws WorldEditException { final Vector3 zero; Vector3 unit; @@ -375,8 +375,10 @@ public class GenerationCommands { final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow, session.getTimeout()); player.findFreePosition(); player.print("" + affected + " columns affected."); + return affected; } catch (ExpressionException e) { player.printError(e.getMessage()); + return 0; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java new file mode 100644 index 000000000..f4b2cafa5 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java @@ -0,0 +1,68 @@ +package com.sk89q.worldedit.command.argument; + +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; + +import java.util.List; + +import static com.google.common.base.Preconditions.checkArgument; + +public class CommaSeparatedValuesConverter implements ArgumentConverter { + + public static CommaSeparatedValuesConverter wrap(ArgumentConverter delegate) { + return wrapAndLimit(delegate, -1); + } + + public static CommaSeparatedValuesConverter wrapAndLimit(ArgumentConverter delegate, int maximum) { + return new CommaSeparatedValuesConverter<>(delegate, maximum); + } + + private static final Splitter COMMA = Splitter.on(','); + + private final ArgumentConverter delegate; + private final int maximum; + + private CommaSeparatedValuesConverter(ArgumentConverter delegate, int maximum) { + checkArgument(maximum == -1 || maximum > 1, + "Maximum must be bigger than 1, or exactly -1"); + this.delegate = delegate; + this.maximum = maximum; + } + + @Override + public String describeAcceptableArguments() { + StringBuilder result = new StringBuilder(); + if (maximum > -1) { + result.append("up to ").append(maximum).append(' '); + } + result.append("comma separated values of ") + .append(delegate.describeAcceptableArguments()); + result.setCharAt(0, Character.toUpperCase(result.charAt(0))); + return result.toString(); + } + + @Override + public List getSuggestions(String input) { + String lastInput = Iterables.getLast(COMMA.split(input)); + return delegate.getSuggestions(lastInput); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + ImmutableList.Builder result = ImmutableList.builder(); + for (String input : COMMA.split(argument)) { + ConversionResult temp = delegate.convert(input, context); + if (!temp.isSuccessful()) { + return temp; + } + result.addAll(temp.get()); + } + return SuccessfulConversion.from(result.build()); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternConverter.java similarity index 60% rename from worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternConverter.java index e8d209e4c..3155c17f5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternConverter.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.command.argument; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Entity; @@ -29,23 +27,30 @@ import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; import com.sk89q.worldedit.world.World; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; -public class PatternParser extends SimpleCommand { +public class PatternConverter implements ArgumentConverter { - private final StringParser stringParser; + public static void register(WorldEdit worldEdit, CommandManager commandManager) { + commandManager.registerConverter(Key.of(Pattern.class), new PatternConverter(worldEdit)); + } - public PatternParser(String name) { - stringParser = addParameter(new StringParser(name, "The pattern")); + private final WorldEdit worldEdit; + + private PatternConverter(WorldEdit worldEdit) { + this.worldEdit = worldEdit; } @Override - public Pattern call(CommandArgs args, CommandLocals locals) throws CommandException { - String patternString = stringParser.call(args, locals); - - Actor actor = locals.get(Actor.class); + public ConversionResult convert(String argument, InjectedValueAccess context) { + Actor actor = context.injectedValue(Key.of(Actor.class)) + .orElseThrow(() -> new IllegalStateException("No actor")); LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); ParserContext parserContext = new ParserContext(); @@ -59,20 +64,16 @@ public class PatternParser extends SimpleCommand { parserContext.setSession(session); try { - return WorldEdit.getInstance().getPatternFactory().parseFromInput(patternString, parserContext); + return SuccessfulConversion.fromSingle( + worldEdit.getPatternFactory().parseFromInput(argument, parserContext) + ); } catch (InputParseException e) { - throw new CommandException(e.getMessage(), e); + throw new IllegalArgumentException(e); } } @Override - public String getDescription() { - return "Choose a pattern"; + public String describeAcceptableArguments() { + return "any pattern"; } - - @Override - public boolean testPermission0(CommandLocals locals) { - return true; - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java index 4d98103c3..eebfb4a16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java @@ -35,12 +35,14 @@ import com.sk89q.worldedit.util.command.composition.SimpleCommand; public class ReplaceParser extends SimpleCommand> { - private final PatternParser fillArg = addParameter(new PatternParser("fillPattern")); + // TODO rewrite for new system +// private final PatternParser fillArg = addParameter(new PatternParser("fillPattern")); @Override public Contextual call(CommandArgs args, CommandLocals locals) throws CommandException { - Pattern fill = fillArg.call(args, locals); - return new ReplaceFactory(fill); +// Pattern fill = fillArg.call(args, locals); +// return new ReplaceFactory(fill); + return null; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java new file mode 100644 index 000000000..08ad84d6c --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java @@ -0,0 +1,16 @@ +package com.sk89q.worldedit.extension.platform; + +import com.google.auto.value.AutoAnnotation; +import com.sk89q.worldedit.internal.annotation.Radii; + +/** + * Holder for generated annotation classes. + */ +class Annotations { + + @AutoAnnotation + static Radii radii(int value) { + return new AutoAnnotation_Annotations_radii(value); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 8df64ab03..d40c2e39e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.extension.platform; import com.google.common.collect.ImmutableList; +import com.google.common.reflect.TypeToken; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalConfiguration; @@ -35,11 +36,15 @@ import com.sk89q.worldedit.command.ClipboardCommands; import com.sk89q.worldedit.command.ClipboardCommandsRegistration; import com.sk89q.worldedit.command.GeneralCommands; import com.sk89q.worldedit.command.GeneralCommandsRegistration; +import com.sk89q.worldedit.command.GenerationCommands; +import com.sk89q.worldedit.command.GenerationCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; +import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; import com.sk89q.worldedit.command.argument.MaskConverter; +import com.sk89q.worldedit.command.argument.PatternConverter; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Entity; @@ -65,6 +70,7 @@ 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.converter.ArgumentConverters; import org.enginehub.piston.exception.CommandException; import org.enginehub.piston.exception.CommandExecutionException; import org.enginehub.piston.exception.ConditionFailedException; @@ -171,6 +177,14 @@ public final class PlatformCommandMananger { private void registerArgumentConverters() { DirectionConverter.register(worldEdit, commandManager); MaskConverter.register(worldEdit, commandManager); + PatternConverter.register(worldEdit, commandManager); + for (int count = 2; count <= 3; count++) { + commandManager.registerConverter(Key.of(double.class, Annotations.radii(count)), + CommaSeparatedValuesConverter.wrapAndLimit(ArgumentConverters.get( + TypeToken.of(double.class) + ), count) + ); + } } private void registerAlwaysInjectedValues() { @@ -258,13 +272,17 @@ public final class PlatformCommandMananger { GeneralCommandsRegistration.builder(), new GeneralCommands(worldEdit) ); + register( + commandManager, + GenerationCommandsRegistration.builder(), + new GenerationCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new GenerationCommands(worldEdit)) .registerMethods(new HistoryCommands(worldEdit)) .registerMethods(new NavigationCommands(worldEdit)) .registerMethods(new RegionCommands(worldEdit)) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Radii.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Radii.java new file mode 100644 index 000000000..82423fba9 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Radii.java @@ -0,0 +1,40 @@ +/* + * 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.internal.annotation; + +import org.enginehub.piston.inject.InjectAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a {@code double} parameter to inject multiple radii values. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@InjectAnnotation +public @interface Radii { + /** + * Number of radii values to inject at maximum. May inject less. + */ + int value(); +} From 20da6227d474562796d184c0fd410b573c54f8f0 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 15:35:05 -0700 Subject: [PATCH 16/57] Port history commands --- .../worldedit/command/HistoryCommands.java | 82 ++++++++++--------- .../platform/PlatformCommandMananger.java | 7 ++ 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index b960dfbe4..b9a247132 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -19,20 +19,23 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; + +import static com.google.common.base.Preconditions.checkNotNull; /** * Commands to undo, redo, and clear history. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.class) public class HistoryCommands { private final WorldEdit worldEdit; @@ -48,28 +51,29 @@ public class HistoryCommands { } @Command( - aliases = { "/undo", "undo" }, - usage = "[times] [player]", - desc = "Undoes the last action", - min = 0, - max = 2 + name = "undo", + aliases = { "/undo" }, + desc = "Undoes the last action (from history)" ) @CommandPermissions("worldedit.history.undo") - public void undo(Player player, LocalSession session, CommandContext args) throws WorldEditException { - int times = Math.max(1, args.getInteger(0, 1)); + public void undo(Player player, LocalSession session, + @Arg(desc = "Number of undoes to perform", def = "1") + int times, + @Arg(name = "player", desc = "Undo this player's operations", def = "") + String playerName) throws WorldEditException { + times = Math.max(1, times); for (int i = 0; i < times; ++i) { - EditSession undone; - if (args.argsLength() < 2) { - undone = session.undo(session.getBlockBag(player), player); - } else { + LocalSession undoSession = session; + if (playerName != null) { player.checkPermission("worldedit.history.undo.other"); - LocalSession sess = worldEdit.getSessionManager().findByName(args.getString(1)); + LocalSession sess = worldEdit.getSessionManager().findByName(playerName); if (sess == null) { - player.printError("Unable to find session for " + args.getString(1)); + player.printError("Unable to find session for " + playerName); break; } - undone = sess.undo(session.getBlockBag(player), player); + undoSession = session; } + EditSession undone = undoSession.undo(undoSession.getBlockBag(player), player); if (undone != null) { player.print("Undo successful."); worldEdit.flushBlockBag(player, undone); @@ -81,45 +85,43 @@ public class HistoryCommands { } @Command( - aliases = { "/redo", "redo" }, - usage = "[times] [player]", - desc = "Redoes the last action (from history)", - min = 0, - max = 2 + name = "redo", + aliases = { "redo" }, + desc = "Redoes the last action (from history)" ) @CommandPermissions("worldedit.history.redo") - public void redo(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - int times = Math.max(1, args.getInteger(0, 1)); - + public void redo(Player player, LocalSession session, + @Arg(desc = "Number of redoes to perform", def = "1") + int times, + @Arg(name = "player", desc = "Redo this player's operations", def = "") + String playerName) throws WorldEditException { + times = Math.max(1, times); for (int i = 0; i < times; ++i) { - EditSession redone; - if (args.argsLength() < 2) { - redone = session.redo(session.getBlockBag(player), player); - } else { + LocalSession redoSession = session; + if (playerName != null) { player.checkPermission("worldedit.history.redo.other"); - LocalSession sess = worldEdit.getSessionManager().findByName(args.getString(1)); + LocalSession sess = worldEdit.getSessionManager().findByName(playerName); if (sess == null) { - player.printError("Unable to find session for " + args.getString(1)); + player.printError("Unable to find session for " + playerName); break; } - redone = sess.redo(session.getBlockBag(player), player); + redoSession = session; } + EditSession redone = redoSession.redo(redoSession.getBlockBag(player), player); if (redone != null) { player.print("Redo successful."); worldEdit.flushBlockBag(player, redone); } else { player.printError("Nothing left to redo."); + break; } } } @Command( - aliases = { "/clearhistory", "clearhistory" }, - usage = "", - desc = "Clear your history", - min = 0, - max = 0 + name = "clearhistory", + aliases = { "/clearhistory" }, + desc = "Clear your history" ) @CommandPermissions("worldedit.history.clear") public void clearHistory(Player player, LocalSession session) throws WorldEditException { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index d40c2e39e..8f0e0a8d7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -38,6 +38,8 @@ import com.sk89q.worldedit.command.GeneralCommands; import com.sk89q.worldedit.command.GeneralCommandsRegistration; import com.sk89q.worldedit.command.GenerationCommands; import com.sk89q.worldedit.command.GenerationCommandsRegistration; +import com.sk89q.worldedit.command.HistoryCommands; +import com.sk89q.worldedit.command.HistoryCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; @@ -277,6 +279,11 @@ public final class PlatformCommandMananger { GenerationCommandsRegistration.builder(), new GenerationCommands(worldEdit) ); + register( + commandManager, + HistoryCommandsRegistration.builder(), + new HistoryCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* From 6d4982f23aa1c2ef774deae950b6b7df1df7eb7e Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 15:44:33 -0700 Subject: [PATCH 17/57] Fix checkstyle/license/gen code --- .../worldedit/command/HistoryCommands.java | 8 +++---- .../CommaSeparatedValuesConverter.java | 19 ++++++++++++++++ .../CommandPermissionsConditionGenerator.java | 2 +- .../extension/platform/Annotations.java | 22 +++++++++++++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index b9a247132..c5bb07699 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -35,7 +35,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Commands to undo, redo, and clear history. */ -@CommandContainer(superTypes = CommandPermissionsConditionGenerator.class) +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class HistoryCommands { private final WorldEdit worldEdit; @@ -58,9 +58,9 @@ public class HistoryCommands { @CommandPermissions("worldedit.history.undo") public void undo(Player player, LocalSession session, @Arg(desc = "Number of undoes to perform", def = "1") - int times, + int times, @Arg(name = "player", desc = "Undo this player's operations", def = "") - String playerName) throws WorldEditException { + String playerName) throws WorldEditException { times = Math.max(1, times); for (int i = 0; i < times; ++i) { LocalSession undoSession = session; @@ -86,7 +86,7 @@ public class HistoryCommands { @Command( name = "redo", - aliases = { "redo" }, + aliases = { "/redo" }, desc = "Redoes the last action (from history)" ) @CommandPermissions("worldedit.history.redo") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java index f4b2cafa5..d2947a44a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java @@ -1,3 +1,22 @@ +/* + * 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.google.common.base.Splitter; 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 b126198a6..f0de910e8 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 @@ -31,7 +31,7 @@ import java.util.Set; import static com.google.common.base.Preconditions.checkNotNull; @NonnullByDefault -public class CommandPermissionsConditionGenerator implements CommandConditionGenerator { +public final class CommandPermissionsConditionGenerator implements CommandConditionGenerator { public interface Registration { Registration commandPermissionsConditionGenerator(CommandPermissionsConditionGenerator generator); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java index 08ad84d6c..f1f1319e9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Annotations.java @@ -1,3 +1,22 @@ +/* + * 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.auto.value.AutoAnnotation; @@ -13,4 +32,7 @@ class Annotations { return new AutoAnnotation_Annotations_radii(value); } + private Annotations() { + } + } From f2283e8ad019a342eef8e8863a15a9d2b9842d55 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 16:14:21 -0700 Subject: [PATCH 18/57] Port navigation commands --- .../worldedit/command/NavigationCommands.java | 126 +++++++++--------- .../platform/PlatformCommandMananger.java | 9 +- 2 files changed, 67 insertions(+), 68 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index b2fb9c4cb..0b70e0bd7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -19,23 +19,26 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.command.parametric.Optional; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; /** * Commands for moving the player around. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class NavigationCommands { private final WorldEdit worldEdit; @@ -51,80 +54,78 @@ public class NavigationCommands { } @Command( - aliases = { "unstuck", "!" }, - usage = "", - desc = "Escape from being stuck inside a block", - min = 0, - max = 0 + name = "unstuck", + aliases = { "!" }, + desc = "Escape from being stuck inside a block" ) @CommandPermissions("worldedit.navigation.unstuck") public void unstuck(Player player) throws WorldEditException { - player.print("There you go!"); player.findFreePosition(); + player.print("There you go!"); } @Command( - aliases = { "ascend", "asc" }, - usage = "[# of levels]", - desc = "Go up a floor", - min = 0, - max = 1 + name = "ascend", + aliases = { "asc" }, + desc = "Go up a floor" ) @CommandPermissions("worldedit.navigation.ascend") - public void ascend(Player player, @Optional("1") int levelsToAscend) throws WorldEditException { + public void ascend(Player player, + @Arg(desc = "# of levels to ascend", def = "1") + int levels) throws WorldEditException { int ascentLevels = 0; while (player.ascendLevel()) { ++ascentLevels; - if (levelsToAscend == ascentLevels) { + if (levels == ascentLevels) { break; } } if (ascentLevels == 0) { player.printError("No free spot above you found."); } else { - player.print((ascentLevels != 1) ? "Ascended " + Integer.toString(ascentLevels) + " levels." : "Ascended a level."); + player.print((ascentLevels != 1) ? "Ascended " + ascentLevels + " levels." : "Ascended a level."); } } @Command( - aliases = { "descend", "desc" }, - usage = "[# of floors]", - desc = "Go down a floor", - min = 0, - max = 1 + name = "descend", + aliases = { "desc" }, + desc = "Go down a floor" ) @CommandPermissions("worldedit.navigation.descend") - public void descend(Player player, @Optional("1") int levelsToDescend) throws WorldEditException { + public void descend(Player player, + @Arg(desc = "# of levels to descend", def = "1") + int levels) throws WorldEditException { int descentLevels = 0; while (player.descendLevel()) { ++descentLevels; - if (levelsToDescend == descentLevels) { + if (levels == descentLevels) { break; } } if (descentLevels == 0) { player.printError("No free spot below you found."); } else { - player.print((descentLevels != 1) ? "Descended " + Integer.toString(descentLevels) + " levels." : "Descended a level."); + player.print((descentLevels != 1) ? "Descended " + descentLevels + " levels." : "Descended a level."); } } @Command( - aliases = { "ceil" }, - usage = "[clearance]", - desc = "Go to the celing", - flags = "fg", - min = 0, - max = 1 + name = "ceil", + desc = "Go to the ceiling" ) @CommandPermissions("worldedit.navigation.ceiling") @Logging(POSITION) - public void ceiling(Player player, CommandContext args) throws WorldEditException { + public void ceiling(Player player, + @Arg(desc = "# of blocks to leave above you", def = "0") + int clearance, + @Switch(name = 'f', desc = "Force using flight to keep you still") + boolean forceFlight, + @Switch(name = 'g', desc = "Force using glass to keep you still") + boolean forceGlass) throws WorldEditException { + clearance = Math.max(0, clearance); - final int clearance = args.argsLength() > 0 ? - Math.max(0, args.getInteger(0)) : 0; - - final boolean alwaysGlass = getAlwaysGlass(args); + boolean alwaysGlass = getAlwaysGlass(forceFlight, forceGlass); if (player.ascendToCeiling(clearance, alwaysGlass)) { player.print("Whoosh!"); } else { @@ -133,11 +134,8 @@ public class NavigationCommands { } @Command( - aliases = { "thru" }, - usage = "", - desc = "Passthrough walls", - min = 0, - max = 0 + name = "thru", + desc = "Pass through walls" ) @CommandPermissions("worldedit.navigation.thru.command") public void thru(Player player) throws WorldEditException { @@ -149,11 +147,9 @@ public class NavigationCommands { } @Command( - aliases = { "jumpto", "j" }, - usage = "", - desc = "Teleport to a location", - min = 0, - max = 0 + name = "jumpto", + aliases = { "j" }, + desc = "Teleport to a location" ) @CommandPermissions("worldedit.navigation.jumpto.command") public void jumpTo(Player player) throws WorldEditException { @@ -168,19 +164,19 @@ public class NavigationCommands { } @Command( - aliases = { "up" }, - usage = "", - desc = "Go upwards some distance", - flags = "fg", - min = 1, - max = 1 + name = "up", + desc = "Go upwards some distance" ) @CommandPermissions("worldedit.navigation.up") @Logging(POSITION) - public void up(Player player, CommandContext args) throws WorldEditException { - final int distance = args.getInteger(0); - - final boolean alwaysGlass = getAlwaysGlass(args); + public void up(Player player, + @Arg(desc = "Distance to go upwards") + int distance, + @Switch(name = 'f', desc = "Force using flight to keep you still") + boolean forceFlight, + @Switch(name = 'g', desc = "Force using glass to keep you still") + boolean forceGlass) throws WorldEditException { + boolean alwaysGlass = getAlwaysGlass(forceFlight, forceGlass); if (player.ascendUpwards(distance, alwaysGlass)) { player.print("Whoosh!"); } else { @@ -190,16 +186,14 @@ public class NavigationCommands { /** * Helper function for /up and /ceil. - * - * @param args The {@link CommandContext} to extract the flags from. + * + * @param forceFlight if flight should be used, rather than the default config option + * @param forceGlass if glass should always be placed, rather than the default config option * @return true, if glass should always be put under the player */ - private boolean getAlwaysGlass(CommandContext args) { + private boolean getAlwaysGlass(boolean forceFlight, boolean forceGlass) { final LocalConfiguration config = worldEdit.getConfiguration(); - final boolean forceFlight = args.hasFlag('f'); - final boolean forceGlass = args.hasFlag('g'); - return forceGlass || (config.navigationUseGlass && !forceFlight); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 8f0e0a8d7..59013d552 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -40,6 +40,8 @@ import com.sk89q.worldedit.command.GenerationCommands; import com.sk89q.worldedit.command.GenerationCommandsRegistration; import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.HistoryCommandsRegistration; +import com.sk89q.worldedit.command.NavigationCommands; +import com.sk89q.worldedit.command.NavigationCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; @@ -284,14 +286,17 @@ public final class PlatformCommandMananger { HistoryCommandsRegistration.builder(), new HistoryCommands(worldEdit) ); + register( + commandManager, + NavigationCommandsRegistration.builder(), + new NavigationCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new HistoryCommands(worldEdit)) - .registerMethods(new NavigationCommands(worldEdit)) .registerMethods(new RegionCommands(worldEdit)) .registerMethods(new ScriptingCommands(worldEdit)) .registerMethods(new SelectionCommands(worldEdit)) From f81ffdde0c45e0684659efd960a3aab2a9428646 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 18:46:46 -0700 Subject: [PATCH 19/57] Port region commands --- .../worldedit/command/RegionCommands.java | 367 +++++++++--------- .../platform/PlatformCommandMananger.java | 8 +- .../command/WorldEditExceptionConverter.java | 6 +- 3 files changed, 183 insertions(+), 198 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 093d84f0e..6c5bcbfc2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -19,20 +19,11 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; -import static com.sk89q.worldedit.command.util.Logging.LogMode.ORIENTATION_REGION; -import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; -import static com.sk89q.worldedit.regions.Regions.asFlatRegion; -import static com.sk89q.worldedit.regions.Regions.maximumBlockY; -import static com.sk89q.worldedit.regions.Regions.minimumBlockY; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.GroundFunction; @@ -57,56 +48,54 @@ import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.util.TreeGenerator.TreeType; -import com.sk89q.worldedit.util.command.binding.Range; -import com.sk89q.worldedit.util.command.binding.Switch; -import com.sk89q.worldedit.util.command.binding.Text; -import com.sk89q.worldedit.util.command.parametric.Optional; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; import java.util.ArrayList; import java.util.List; +import static com.google.common.base.Preconditions.checkArgument; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ORIENTATION_REGION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +import static com.sk89q.worldedit.regions.Regions.asFlatRegion; +import static com.sk89q.worldedit.regions.Regions.maximumBlockY; +import static com.sk89q.worldedit.regions.Regions.minimumBlockY; + /** * Commands that operate on regions. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class RegionCommands { - private final WorldEdit worldEdit; - /** * Create a new instance. - * - * @param worldEdit reference to WorldEdit */ - public RegionCommands(WorldEdit worldEdit) { - checkNotNull(worldEdit); - this.worldEdit = worldEdit; + public RegionCommands() { } @Command( - aliases = { "/line" }, - usage = " [thickness]", - desc = "Draws a line segment between cuboid selection corners", - help = - "Draws a line segment between cuboid selection corners.\n" + - "Can only be used with cuboid selections.\n" + - "Flags:\n" + - " -h generates only a shell", - flags = "h", - min = 1, - max = 2 + name = "/line", + desc = "Draws a line segment between cuboid selection corners", + descFooter = "Can only be used with a cuboid selection" ) @CommandPermissions("worldedit.region.line") @Logging(REGION) - public void line(Player player, EditSession editSession, - @Selection Region region, - Pattern pattern, - @Optional("0") @Range(min = 0) int thickness, - @Switch('h') boolean shell) throws WorldEditException { - + public int line(Player player, EditSession editSession, + @Selection Region region, + @Arg(desc = "The pattern of blocks to place") + Pattern pattern, + @Arg(desc = "The thickness of the line", def = "0") + int thickness, + @Switch(name = 'h', desc = "Generate only a shell") + boolean shell) throws WorldEditException { if (!(region instanceof CuboidRegion)) { player.printError("//line only works with cuboid selections"); - return; + return 0; } + checkArgument(thickness >= 0, "Thickness must be >= 0"); CuboidRegion cuboidregion = (CuboidRegion) region; BlockVector3 pos1 = cuboidregion.getPos1(); @@ -114,32 +103,29 @@ public class RegionCommands { int blocksChanged = editSession.drawLine(pattern, pos1, pos2, thickness, !shell); player.print(blocksChanged + " block(s) have been changed."); + return blocksChanged; } @Command( - aliases = { "/curve" }, - usage = " [thickness]", - desc = "Draws a spline through selected points", - help = - "Draws a spline through selected points.\n" + - "Can only be used with convex polyhedral selections.\n" + - "Flags:\n" + - " -h generates only a shell", - flags = "h", - min = 1, - max = 2 + name = "/curve", + desc = "Draws a spline through selected points", + descFooter = "Can only be used with a convex polyhedral selection" ) @CommandPermissions("worldedit.region.curve") @Logging(REGION) - public void curve(Player player, EditSession editSession, - @Selection Region region, - Pattern pattern, - @Optional("0") @Range(min = 0) int thickness, - @Switch('h') boolean shell) throws WorldEditException { + public int curve(Player player, EditSession editSession, + @Selection Region region, + @Arg(desc = "The pattern of blocks to place") + Pattern pattern, + @Arg(desc = "The thickness of the curve", def = "0") + int thickness, + @Switch(name = 'h', desc = "Generate only a shell") + boolean shell) throws WorldEditException { if (!(region instanceof ConvexPolyhedralRegion)) { player.printError("//curve only works with convex polyhedral selections"); - return; + return 0; } + checkArgument(thickness >= 0, "Thickness must be >= 0"); ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region; List vectors = new ArrayList<>(cpregion.getVertices()); @@ -147,139 +133,140 @@ public class RegionCommands { int blocksChanged = editSession.drawSpline(pattern, vectors, 0, 0, 0, 10, thickness, !shell); player.print(blocksChanged + " block(s) have been changed."); + return blocksChanged; } @Command( - aliases = { "/replace", "/re", "/rep" }, - usage = "[from-block] ", - desc = "Replace all blocks in the selection with another", - flags = "f", - min = 1, - max = 2 + name = "/replace", + aliases = { "/re", "/rep" }, + desc = "Replace all blocks in the selection with another" ) @CommandPermissions("worldedit.region.replace") @Logging(REGION) - public void replace(Player player, EditSession editSession, @Selection Region region, @Optional Mask from, Pattern to) throws WorldEditException { + public int replace(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The mask representing blocks to replace", def = "") + Mask from, + @Arg(desc = "The pattern of blocks to replace with") + Pattern to) throws WorldEditException { if (from == null) { from = new ExistingBlockMask(editSession); } int affected = editSession.replaceBlocks(region, from, to); player.print(affected + " block(s) have been replaced."); + return affected; } @Command( - aliases = { "/overlay" }, - usage = "", - desc = "Set a block on top of blocks in the region", - min = 1, - max = 1 + name = "/overlay", + desc = "Set a block on top of blocks in the region" ) @CommandPermissions("worldedit.region.overlay") @Logging(REGION) - public void overlay(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { + public int overlay(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The pattern of blocks to overlay") + Pattern pattern) throws WorldEditException { int affected = editSession.overlayCuboidBlocks(region, pattern); player.print(affected + " block(s) have been overlaid."); + return affected; } @Command( - aliases = { "/center", "/middle" }, - usage = "", - desc = "Set the center block(s)", - min = 1, - max = 1 + name = "/center", + aliases = { "/middle" }, + desc = "Set the center block(s)" ) @Logging(REGION) @CommandPermissions("worldedit.region.center") - public void center(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { + public int center(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern) throws WorldEditException { int affected = editSession.center(region, pattern); - player.print("Center set ("+ affected + " blocks changed)"); + player.print("Center set (" + affected + " block(s) changed)"); + return affected; } @Command( - aliases = { "/naturalize" }, - usage = "", - desc = "3 layers of dirt on top then rock below", - min = 0, - max = 0 + name = "/naturalize", + desc = "3 layers of dirt on top then rock below" ) @CommandPermissions("worldedit.region.naturalize") @Logging(REGION) - public void naturalize(Player player, EditSession editSession, @Selection Region region) throws WorldEditException { + public int naturalize(Player player, EditSession editSession, @Selection Region region) throws WorldEditException { int affected = editSession.naturalizeCuboidBlocks(region); player.print(affected + " block(s) have been made to look more natural."); + return affected; } @Command( - aliases = { "/walls" }, - usage = "", - desc = "Build the four sides of the selection", - min = 1, - max = 1 + name = "/walls", + desc = "Build the four sides of the selection" ) @CommandPermissions("worldedit.region.walls") @Logging(REGION) - public void walls(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { + public int walls(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern) throws WorldEditException { int affected = editSession.makeWalls(region, pattern); player.print(affected + " block(s) have been changed."); + return affected; } @Command( - aliases = { "/faces", "/outline" }, - usage = "", - desc = "Build the walls, ceiling, and floor of a selection", - min = 1, - max = 1 + name = "/faces", + aliases = { "/outline" }, + desc = "Build the walls, ceiling, and floor of a selection" ) @CommandPermissions("worldedit.region.faces") @Logging(REGION) - public void faces(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { + public int faces(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern) throws WorldEditException { int affected = editSession.makeCuboidFaces(region, pattern); player.print(affected + " block(s) have been changed."); + return affected; } @Command( - aliases = { "/smooth" }, - usage = "[iterations] [filter]", + name = "/smooth", desc = "Smooth the elevation in the selection", - help = - "Smooths the elevation in the selection.\n" + - "Optionally, restricts the height map to a set of blocks specified with mask syntax.\n" + - "For example, '//smooth 1 grass_block,dirt,stone' would only smooth natural surface terrain.", - min = 0, - max = 2 + descFooter = "Example: '//smooth 1 grass_block,dirt,stone' would only smooth natural surface terrain." ) @CommandPermissions("worldedit.region.smooth") @Logging(REGION) - public void smooth(Player player, EditSession editSession, @Selection Region region, @Optional("1") int iterations, @Optional Mask mask) throws WorldEditException { + public int smooth(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "# of iterations to perform", def = "1") + int iterations, + @Arg(desc = "The mask of blocks to use as the height map", def = "") + Mask mask) throws WorldEditException { HeightMap heightMap = new HeightMap(editSession, region, mask); HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0)); int affected = heightMap.applyFilter(filter, iterations); player.print("Terrain's height map smoothed. " + affected + " block(s) changed."); - + return affected; } @Command( - aliases = { "/move" }, - usage = "[count] [direction] [leave-id]", - flags = "sa", - desc = "Move the contents of the selection", - help = - "Moves the contents of the selection.\n" + - "The -s flag shifts the selection to the target location.\n" + - "The -a flag skips air blocks.\n" + - "Optionally fills the old location with .", - min = 0, - max = 3 + name = "/move", + desc = "Move the contents of the selection" ) @CommandPermissions("worldedit.region.move") @Logging(ORIENTATION_REGION) - public void move(Player player, EditSession editSession, LocalSession session, - @Selection Region region, - @Optional("1") @Range(min = 1) int count, - @Optional(Direction.AIM) @Direction(includeDiagonals = true) BlockVector3 direction, - @Optional("air") Pattern replace, - @Switch('s') boolean moveSelection, - @Switch('a') boolean ignoreAirBlocks) throws WorldEditException { + public int move(Player player, EditSession editSession, LocalSession session, + @Selection Region region, + @Arg(desc = "# of blocks to move", def = "1") + int count, + @Arg(desc = "The direction to move", def = Direction.AIM) + @Direction(includeDiagonals = true) + BlockVector3 direction, + @Arg(desc = "The pattern of blocks to leave", def = "air") + Pattern replace, + @Switch(name = 's', desc = "Shift the selection to the target location") + boolean moveSelection, + @Switch(name = 'a', desc = "Ignore air blocks") + boolean ignoreAirBlocks) throws WorldEditException { + if (count < 1) { + throw new IllegalArgumentException("Count must be >= 1"); + } int affected = editSession.moveRegion(region, direction, count, !ignoreAirBlocks, replace); @@ -294,30 +281,27 @@ public class RegionCommands { } } - player.print(affected + " blocks moved."); + player.print(affected + " block(s) moved."); + return affected; } @Command( - aliases = { "/stack" }, - usage = "[count] [direction]", - flags = "sa", - desc = "Repeat the contents of the selection", - help = - "Repeats the contents of the selection.\n" + - "Flags:\n" + - " -s shifts the selection to the last stacked copy\n" + - " -a skips air blocks", - min = 0, - max = 2 + name = "/stack", + desc = "Repeat the contents of the selection" ) @CommandPermissions("worldedit.region.stack") @Logging(ORIENTATION_REGION) - public void stack(Player player, EditSession editSession, LocalSession session, - @Selection Region region, - @Optional("1") @Range(min = 1) int count, - @Optional(Direction.AIM) @Direction(includeDiagonals = true) BlockVector3 direction, - @Switch('s') boolean moveSelection, - @Switch('a') boolean ignoreAirBlocks) throws WorldEditException { + public int stack(Player player, EditSession editSession, LocalSession session, + @Selection Region region, + @Arg(desc = "# of copies to stack", def = "1") + int count, + @Arg(desc = "The direction to stack", def = Direction.AIM) + @Direction(includeDiagonals = true) + BlockVector3 direction, + @Switch(name = 's', desc = "Shift the selection to the last stacked copy") + boolean moveSelection, + @Switch(name = 'a', desc = "Ignore air blocks") + boolean ignoreAirBlocks) throws WorldEditException { int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks); if (moveSelection) { @@ -334,26 +318,22 @@ public class RegionCommands { } } - player.print(affected + " blocks changed. Undo with //undo"); + player.print(affected + " block(s) changed. Undo with //undo"); + return affected; } @Command( - aliases = { "/regen" }, - usage = "", + name = "/regen", desc = "Regenerates the contents of the selection", - help = - "Regenerates the contents of the current selection.\n" + - "This command might affect things outside the selection,\n" + - "if they are within the same chunk.", - min = 0, - max = 0 + descFooter = "This command might affect things outside the selection,\n" + + "if they are within the same chunk." ) @CommandPermissions("worldedit.regen") @Logging(REGION) public void regenerateChunk(Player player, LocalSession session, EditSession editSession, @Selection Region region) throws WorldEditException { Mask mask = session.getMask(); try { - session.setMask((Mask) null); + session.setMask(null); player.getWorld().regenerate(region, editSession); } finally { session.setMask(mask); @@ -362,25 +342,22 @@ public class RegionCommands { } @Command( - aliases = { "/deform" }, - usage = "", - desc = "Deforms a selected region with an expression", - help = - "Deforms a selected region with an expression\n" + - "The expression is executed for each block and is expected\n" + - "to modify the variables x, y and z to point to a new block\n" + - "to fetch. See also tinyurl.com/wesyntax.", - flags = "ro", - min = 1, - max = -1 + name = "/deform", + desc = "Deforms a selected region with an expression", + descFooter = "The expression is executed for each block and is expected\n" + + "to modify the variables x, y and z to point to a new block\n" + + "to fetch. See also tinyurl.com/wesyntax." ) @CommandPermissions("worldedit.region.deform") @Logging(ALL) - public void deform(Player player, LocalSession session, EditSession editSession, - @Selection Region region, - @Text String expression, - @Switch('r') boolean useRawCoords, - @Switch('o') boolean offset) throws WorldEditException { + public int deform(Player player, LocalSession session, EditSession editSession, + @Selection Region region, + @Arg(desc = "The expression to use") + String expression, + @Switch(name = 'r', desc = "Use the game's coordinate origin") + boolean useRawCoords, + @Switch(name = 'o', desc = "Use the selection's center as origin") + boolean offset) throws WorldEditException { final Vector3 zero; Vector3 unit; @@ -406,58 +383,60 @@ public class RegionCommands { final int affected = editSession.deformRegion(region, zero, unit, expression, session.getTimeout()); player.findFreePosition(); player.print(affected + " block(s) have been deformed."); + return affected; } catch (ExpressionException e) { player.printError(e.getMessage()); + return 0; } } @Command( - aliases = { "/hollow" }, - usage = "[[ ]]", + name = "/hollow", desc = "Hollows out the object contained in this selection", - help = - "Hollows out the object contained in this selection.\n" + - "Optionally fills the hollowed out part with the given block.\n" + - "Thickness is measured in manhattan distance.", - min = 0, - max = 2 + descFooter = "Thickness is measured in manhattan distance." ) @CommandPermissions("worldedit.region.hollow") @Logging(REGION) - public void hollow(Player player, EditSession editSession, - @Selection Region region, - @Optional("0") @Range(min = 0) int thickness, - @Optional("air") Pattern pattern) throws WorldEditException { + public int hollow(Player player, EditSession editSession, + @Selection Region region, + @Arg(desc = "Thickness of the shell to leave", def = "0") + int thickness, + @Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air") + Pattern pattern) throws WorldEditException { + checkArgument(thickness >= 0, "Thickness must be >= 0"); int affected = editSession.hollowOutRegion(region, thickness, pattern); player.print(affected + " block(s) have been changed."); + return affected; } @Command( - aliases = { "/forest" }, - usage = "[type] [density]", - desc = "Make a forest within the region", - min = 0, - max = 2 + name = "/forest", + desc = "Make a forest within the region" ) @CommandPermissions("worldedit.region.forest") @Logging(REGION) - public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type, - @Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException { + public int forest(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The type of tree to place", def = "tree") + TreeType type, + @Arg(desc = "The density of the forest", def = "5") + double density) throws WorldEditException { + checkArgument(0 <= density && density <= 100, "Density must be in [0, 100]"); int affected = editSession.makeForest(region, density / 100, type); player.print(affected + " trees created."); + return affected; } @Command( - aliases = { "/flora" }, - usage = "[density]", - desc = "Make flora within the region", - min = 0, - max = 1 + name = "/flora", + desc = "Make flora within the region" ) @CommandPermissions("worldedit.region.flora") @Logging(REGION) - public void flora(Player player, EditSession editSession, @Selection Region region, @Optional("10") @Range(min = 0, max = 100) double density) throws WorldEditException { + public int flora(Player player, EditSession editSession, @Selection Region region, + @Arg(desc = "The density of the forest", def = "5") + double density) throws WorldEditException { + checkArgument(0 <= density && density <= 100, "Density must be in [0, 100]"); density = density / 100; FloraGenerator generator = new FloraGenerator(editSession); GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator); @@ -465,7 +444,9 @@ public class RegionCommands { visitor.setMask(new NoiseFilter2D(new RandomNoise(), density)); Operations.completeLegacy(visitor); - player.print(ground.getAffected() + " flora created."); + int affected = ground.getAffected(); + player.print(affected + " flora created."); + return affected; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 59013d552..7dd59b9f2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -42,6 +42,8 @@ import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.HistoryCommandsRegistration; import com.sk89q.worldedit.command.NavigationCommands; import com.sk89q.worldedit.command.NavigationCommandsRegistration; +import com.sk89q.worldedit.command.RegionCommands; +import com.sk89q.worldedit.command.RegionCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; @@ -291,13 +293,17 @@ public final class PlatformCommandMananger { NavigationCommandsRegistration.builder(), new NavigationCommands(worldEdit) ); + register( + commandManager, + RegionCommandsRegistration.builder(), + new RegionCommands() + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new RegionCommands(worldEdit)) .registerMethods(new ScriptingCommands(worldEdit)) .registerMethods(new SelectionCommands(worldEdit)) .registerMethods(new SnapshotUtilCommands(worldEdit)) 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 2e9c6fa62..b75d1c5b3 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 @@ -163,10 +163,8 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { } @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); - } + public void convert(IllegalArgumentException e) throws CommandException { + throw new CommandException(e.getMessage(), e, null); } } From c95fc06b828fb6be09e501542e1dfe63b624d937 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 19:32:27 -0700 Subject: [PATCH 20/57] Port scripting commands --- .../worldedit/command/ScriptingCommands.java | 61 ++++++++++--------- .../platform/PlatformCommandMananger.java | 8 ++- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java index d09c76c39..e60a3db51 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ScriptingCommands.java @@ -19,23 +19,28 @@ package com.sk89q.worldedit.command; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; import java.io.File; +import java.util.List; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; /** * Commands related to scripting. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ScriptingCommands { private final WorldEdit worldEdit; @@ -51,43 +56,40 @@ public class ScriptingCommands { } @Command( - aliases = { "cs" }, - usage = " [args...]", - desc = "Execute a CraftScript", - min = 1, - max = -1 + name = "cs", + desc = "Execute a CraftScript" ) @CommandPermissions("worldedit.scripting.execute") @Logging(ALL) - public void execute(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - String[] scriptArgs = args.getSlice(1); - String name = args.getString(0); - - if (!player.hasPermission("worldedit.scripting.execute." + name)) { + public void execute(Player player, LocalSession session, + @Arg(desc = "Filename of the CraftScript to load") + String filename, + @Arg(desc = "Arguments to the CraftScript", def = "", variable = true) + List args) throws WorldEditException { + if (!player.hasPermission("worldedit.scripting.execute." + filename)) { player.printError("You don't have permission to use that script."); return; } - session.setLastScript(name); + session.setLastScript(filename); File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir); - File f = worldEdit.getSafeOpenFile(player, dir, name, "js", "js"); + File f = worldEdit.getSafeOpenFile(player, dir, filename, "js", "js"); - worldEdit.runScript(player, f, scriptArgs); + worldEdit.runScript(player, f, Stream.concat(Stream.of(filename), args.stream()) + .toArray(String[]::new)); } @Command( - aliases = { ".s" }, - usage = "[args...]", - desc = "Execute last CraftScript", - min = 0, - max = -1 + name = ".s", + desc = "Execute last CraftScript" ) @CommandPermissions("worldedit.scripting.execute") @Logging(ALL) - public void executeLast(Player player, LocalSession session, CommandContext args) throws WorldEditException { - + public void executeLast(Player player, LocalSession session, + @Arg(desc = "Arguments to the CraftScript", def = "", variable = true) + List args) throws WorldEditException { + String lastScript = session.getLastScript(); if (!player.hasPermission("worldedit.scripting.execute." + lastScript)) { @@ -100,11 +102,10 @@ public class ScriptingCommands { return; } - String[] scriptArgs = args.getSlice(0); - File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir); File f = worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js"); - worldEdit.runScript(player, f, scriptArgs); + worldEdit.runScript(player, f, Stream.concat(Stream.of(lastScript), args.stream()) + .toArray(String[]::new)); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 7dd59b9f2..a0a94591d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -46,6 +46,8 @@ import com.sk89q.worldedit.command.RegionCommands; import com.sk89q.worldedit.command.RegionCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; +import com.sk89q.worldedit.command.ScriptingCommands; +import com.sk89q.worldedit.command.ScriptingCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; @@ -298,13 +300,17 @@ public final class PlatformCommandMananger { RegionCommandsRegistration.builder(), new RegionCommands() ); + register( + commandManager, + ScriptingCommandsRegistration.builder(), + new ScriptingCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new ScriptingCommands(worldEdit)) .registerMethods(new SelectionCommands(worldEdit)) .registerMethods(new SnapshotUtilCommands(worldEdit)) .registerMethods(new ToolUtilCommands(worldEdit)) From e07e0d10b0a7d3f7219c5407051fad522b09e82b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 22:58:30 -0700 Subject: [PATCH 21/57] Port selection commands --- .../worldedit/command/SelectionCommands.java | 562 +++++++----------- .../CommaSeparatedValuesConverter.java | 3 +- .../command/argument/DirectionConverter.java | 25 +- .../command/argument/EnumConverter.java | 52 ++ .../command/argument/ExpandAmount.java | 32 + .../argument/ExpandAmountConverter.java | 48 ++ .../command/argument/SelectorChoice.java | 14 + .../command/argument/VectorConverter.java | 109 ++++ .../platform/PlatformCommandMananger.java | 14 +- .../internal/annotation/MultiDirection.java | 37 ++ 10 files changed, 540 insertions(+), 356 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/MultiDirection.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index c79ec4fec..e705930a6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -19,18 +19,15 @@ package com.sk89q.worldedit.command; -import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; -import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; +import com.sk89q.worldedit.command.argument.ExpandAmount; +import com.sk89q.worldedit.command.argument.SelectorChoice; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.ParserContext; @@ -39,6 +36,8 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.block.BlockDistributionCounter; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.visitor.RegionVisitor; +import com.sk89q.worldedit.internal.annotation.Direction; +import com.sk89q.worldedit.internal.annotation.MultiDirection; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -64,44 +63,43 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.storage.ChunkStore; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; -import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.stream.Stream; + +import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; /** * Selection commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SelectionCommands { private final WorldEdit we; - + public SelectionCommands(WorldEdit we) { this.we = we; } @Command( - aliases = { "/pos1" }, - usage = "[coordinates]", - desc = "Set position 1", - min = 0, - max = 1 + name = "/pos1", + desc = "Set position 1" ) @Logging(POSITION) @CommandPermissions("worldedit.selection.pos") - public void pos1(Player player, LocalSession session, CommandContext args) throws WorldEditException { - + public void pos1(Player player, LocalSession session, + @Arg(desc = "Coordinates to set position 1 to", def = "") + BlockVector3 coordinates) throws WorldEditException { Location pos; - - if (args.argsLength() == 1) { - if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) { - String[] coords = args.getString(0).split(","); - pos = new Location(player.getWorld(), Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2])); - } else { - player.printError("Invalid coordinates " + args.getString(0)); - return; - } + if (coordinates != null) { + pos = new Location(player.getWorld(), coordinates.toVector3()); } else { pos = player.getBlockIn(); } @@ -116,27 +114,17 @@ public class SelectionCommands { } @Command( - aliases = { "/pos2" }, - usage = "[coordinates]", - desc = "Set position 2", - min = 0, - max = 1 + name = "/pos2", + desc = "Set position 2" ) @Logging(POSITION) @CommandPermissions("worldedit.selection.pos") - public void pos2(Player player, LocalSession session, CommandContext args) throws WorldEditException { - + public void pos2(Player player, LocalSession session, + @Arg(desc = "Coordinates to set position 2 to", def = "") + BlockVector3 coordinates) throws WorldEditException { Location pos; - if (args.argsLength() == 1) { - if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) { - String[] coords = args.getString(0).split(","); - pos = new Location(player.getWorld(), Integer.parseInt(coords[0]), - Integer.parseInt(coords[1]), - Integer.parseInt(coords[2])); - } else { - player.printError("Invalid coordinates " + args.getString(0)); - return; - } + if (coordinates != null) { + pos = new Location(player.getWorld(), coordinates.toVector3()); } else { pos = player.getBlockIn(); } @@ -151,11 +139,8 @@ public class SelectionCommands { } @Command( - aliases = { "/hpos1" }, - usage = "", - desc = "Set position 1 to targeted block", - min = 0, - max = 0 + name = "/hpos1", + desc = "Set position 1 to targeted block" ) @CommandPermissions("worldedit.selection.hpos") public void hpos1(Player player, LocalSession session) throws WorldEditException { @@ -176,11 +161,8 @@ public class SelectionCommands { } @Command( - aliases = { "/hpos2" }, - usage = "", - desc = "Set position 2 to targeted block", - min = 0, - max = 0 + name = "/hpos2", + desc = "Set position 2 to targeted block" ) @CommandPermissions("worldedit.selection.hpos") public void hpos2(Player player, LocalSession session) throws WorldEditException { @@ -201,28 +183,22 @@ public class SelectionCommands { } @Command( - aliases = { "/chunk" }, - usage = "[x,z coordinates]", - flags = "sc", - desc = "Set the selection to your current chunk.", - help = - "Set the selection to the chunk you are currently in.\n" + - "With the -s flag, your current selection is expanded\n" + - "to encompass all chunks that are part of it.\n\n" + - "Specifying coordinates will use those instead of your\n"+ - "current position. Use -c to specify chunk coordinates,\n" + - "otherwise full coordinates will be implied.\n" + - "(for example, the coordinates 5,5 are the same as -c 0,0)", - min = 0, - max = 1 + name = "/chunk", + desc = "Set the selection to your current chunk." ) @Logging(POSITION) @CommandPermissions("worldedit.selection.chunk") - public void chunk(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void chunk(Player player, LocalSession session, + @Arg(desc = "The chunk to select", def = "") + BlockVector2 coordinates, + @Switch(name = 's', desc = "Expand your selection to encompass all chunks that are part of it") + boolean expandSelection, + @Switch(name = 'c', desc = "Use chunk coordinates instead of block coordinates") + boolean useChunkCoordinates) throws WorldEditException { final BlockVector3 min; final BlockVector3 max; final World world = player.getWorld(); - if (args.hasFlag('s')) { + if (expandSelection) { Region region = session.getSelection(world); final BlockVector2 min2D = ChunkStore.toChunk(region.getMinimumPoint()); @@ -236,16 +212,11 @@ public class SelectionCommands { + max2D.getBlockX() + ", " + max2D.getBlockZ() + ")"); } else { final BlockVector2 min2D; - if (args.argsLength() == 1) { + if (coordinates != null) { // coords specified - String[] coords = args.getString(0).split(","); - if (coords.length != 2) { - throw new InsufficientArgumentsException("Invalid coordinates specified."); - } - int x = Integer.parseInt(coords[0]); - int z = Integer.parseInt(coords[1]); - BlockVector2 pos = BlockVector2.at(x, z); - min2D = (args.hasFlag('c')) ? pos : ChunkStore.toChunk(pos.toBlockVector3()); + min2D = useChunkCoordinates + ? coordinates + : ChunkStore.toChunk(coordinates.toBlockVector3()); } else { // use player loc min2D = ChunkStore.toChunk(player.getBlockIn().toVector().toBlockPoint()); @@ -273,29 +244,21 @@ public class SelectionCommands { } @Command( - aliases = { "/wand" }, - usage = "", - desc = "Get the wand object", - min = 0, - max = 0 + name = "/wand", + desc = "Get the wand object" ) @CommandPermissions("worldedit.wand") public void wand(Player player) throws WorldEditException { - player.giveItem(new BaseItemStack(ItemTypes.get(we.getConfiguration().wandItem), 1)); player.print("Left click: select pos #1; Right click: select pos #2"); } @Command( - aliases = { "toggleeditwand" }, - usage = "", - desc = "Toggle functionality of the edit wand", - min = 0, - max = 0 + name = "toggleeditwand", + desc = "Toggle functionality of the edit wand" ) @CommandPermissions("worldedit.wand.toggle") - public void toggleWand(Player player, LocalSession session, CommandContext args) throws WorldEditException { - + public void toggleWand(Player player, LocalSession session) throws WorldEditException { session.setToolControl(!session.isToolControlEnabled()); if (session.isToolControlEnabled()) { @@ -306,20 +269,23 @@ public class SelectionCommands { } @Command( - aliases = { "/expand" }, - usage = " [reverse-amount] ", - desc = "Expand the selection area", - min = 1, - max = 3 + name = "/expand", + desc = "Expand the selection area" ) @Logging(REGION) @CommandPermissions("worldedit.selection.expand") - public void expand(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void expand(Player player, LocalSession session, + @Arg(desc = "Amount to expand the selection by, can be `vert` to expand to the whole vertical column") + ExpandAmount amount, + @Arg(desc = "Amount to expand the selection by in the other direction", def = "0") + int reverseAmount, + @Arg(desc = "Direction to expand", def = Direction.AIM) + @MultiDirection + List direction) throws WorldEditException { // Special syntax (//expand vert) to expand the selection between // sky and bedrock. - if (args.getString(0).equalsIgnoreCase("vert") - || args.getString(0).equalsIgnoreCase("vertical")) { + if (amount.isVert()) { Region region = session.getSelection(player.getWorld()); try { int oldSize = region.getArea(); @@ -338,134 +304,56 @@ public class SelectionCommands { return; } - List dirs = new ArrayList<>(); - int change = args.getInteger(0); - int reverseChange = 0; - - switch (args.argsLength()) { - case 2: - // Either a reverse amount or a direction - try { - reverseChange = args.getInteger(1); - dirs.add(we.getDirection(player, "me")); - } catch (NumberFormatException e) { - if (args.getString(1).contains(",")) { - String[] split = args.getString(1).split(","); - for (String s : split) { - dirs.add(we.getDirection(player, s.toLowerCase())); - } - } else { - dirs.add(we.getDirection(player, args.getString(1).toLowerCase())); - } - } - break; - - case 3: - // Both reverse amount and direction - reverseChange = args.getInteger(1); - if (args.getString(2).contains(",")) { - String[] split = args.getString(2).split(","); - for (String s : split) { - dirs.add(we.getDirection(player, s.toLowerCase())); - } - } else { - dirs.add(we.getDirection(player, args.getString(2).toLowerCase())); - } - break; - - default: - dirs.add(we.getDirection(player, "me")); - break; - - } - Region region = session.getSelection(player.getWorld()); int oldSize = region.getArea(); - if (reverseChange == 0) { - for (BlockVector3 dir : dirs) { - region.expand(dir.multiply(change)); + if (reverseAmount == 0) { + for (BlockVector3 dir : direction) { + region.expand(dir.multiply(amount.getAmount())); } } else { - for (BlockVector3 dir : dirs) { - region.expand(dir.multiply(change), dir.multiply(-reverseChange)); + for (BlockVector3 dir : direction) { + region.expand(dir.multiply(amount.getAmount()), dir.multiply(-reverseAmount)); } } session.getRegionSelector(player.getWorld()).learnChanges(); int newSize = region.getArea(); - + session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session); - player.print("Region expanded " + (newSize - oldSize) + " blocks."); + player.print("Region expanded " + (newSize - oldSize) + " block(s)."); } @Command( - aliases = { "/contract" }, - usage = " [reverse-amount] [direction]", - desc = "Contract the selection area", - min = 1, - max = 3 + name = "/contract", + desc = "Contract the selection area" ) @Logging(REGION) @CommandPermissions("worldedit.selection.contract") - public void contract(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - List dirs = new ArrayList<>(); - int change = args.getInteger(0); - int reverseChange = 0; - - switch (args.argsLength()) { - case 2: - // Either a reverse amount or a direction - try { - reverseChange = args.getInteger(1); - dirs.add(we.getDirection(player, "me")); - } catch (NumberFormatException e) { - if (args.getString(1).contains(",")) { - String[] split = args.getString(1).split(","); - for (String s : split) { - dirs.add(we.getDirection(player, s.toLowerCase())); - } - } else { - dirs.add(we.getDirection(player, args.getString(1).toLowerCase())); - } - } - break; - - case 3: - // Both reverse amount and direction - reverseChange = args.getInteger(1); - if (args.getString(2).contains(",")) { - String[] split = args.getString(2).split(","); - for (String s : split) { - dirs.add(we.getDirection(player, s.toLowerCase())); - } - } else { - dirs.add(we.getDirection(player, args.getString(2).toLowerCase())); - } - break; - - default: - dirs.add(we.getDirection(player, "me")); - break; - } - + public void contract(Player player, LocalSession session, + @Arg(desc = "Amount to contract the selection by") + int amount, + @Arg(desc = "Amount to contract the selection by in the other direction", def = "0") + int reverseAmount, + @Arg(desc = "Direction to contract", def = Direction.AIM) + @MultiDirection + List direction) throws WorldEditException { try { Region region = session.getSelection(player.getWorld()); int oldSize = region.getArea(); - if (reverseChange == 0) { - for (BlockVector3 dir : dirs) { - region.contract(dir.multiply(change)); + if (reverseAmount == 0) { + for (BlockVector3 dir : direction) { + region.contract(dir.multiply(amount)); } } else { - for (BlockVector3 dir : dirs) { - region.contract(dir.multiply(change), dir.multiply(-reverseChange)); + for (BlockVector3 dir : direction) { + region.contract(dir.multiply(amount), dir.multiply(-reverseAmount)); } } session.getRegionSelector(player.getWorld()).learnChanges(); int newSize = region.getArea(); - + session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session); @@ -476,35 +364,22 @@ public class SelectionCommands { } @Command( - aliases = { "/shift" }, - usage = " [direction]", - desc = "Shift the selection area", - min = 1, - max = 2 + name = "/shift", + desc = "Shift the selection area" ) @Logging(REGION) @CommandPermissions("worldedit.selection.shift") - public void shift(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - List dirs = new ArrayList<>(); - int change = args.getInteger(0); - if (args.argsLength() == 2) { - if (args.getString(1).contains(",")) { - for (String s : args.getString(1).split(",")) { - dirs.add(we.getDirection(player, s.toLowerCase())); - } - } else { - dirs.add(we.getDirection(player, args.getString(1).toLowerCase())); - } - } else { - dirs.add(we.getDirection(player, "me")); - } - + public void shift(Player player, LocalSession session, + @Arg(desc = "Amount to shift the selection by") + int amount, + @Arg(desc = "Direction to contract", def = Direction.AIM) + @MultiDirection + List direction) throws WorldEditException { try { Region region = session.getSelection(player.getWorld()); - for (BlockVector3 dir : dirs) { - region.shift(dir.multiply(change)); + for (BlockVector3 dir : direction) { + region.shift(dir.multiply(amount)); } session.getRegionSelector(player.getWorld()).learnChanges(); @@ -518,81 +393,72 @@ public class SelectionCommands { } @Command( - aliases = { "/outset" }, - usage = "", - desc = "Outset the selection area", - help = - "Expands the selection by the given amount in all directions.\n" + - "Flags:\n" + - " -h only expand horizontally\n" + - " -v only expand vertically\n", - flags = "hv", - min = 1, - max = 1 + name = "/outset", + desc = "Outset the selection area" ) @Logging(REGION) @CommandPermissions("worldedit.selection.outset") - public void outset(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void outset(Player player, LocalSession session, + @Arg(desc = "Amount to expand the selection by in all directions") + int amount, + @Switch(name = 'h', desc = "Only expand horizontally") + boolean onlyHorizontal, + @Switch(name = 'v', desc = "Only expand vertically") + boolean onlyVertical) throws WorldEditException { Region region = session.getSelection(player.getWorld()); - region.expand(getChangesForEachDir(args)); + region.expand(getChangesForEachDir(amount, onlyHorizontal, onlyVertical)); session.getRegionSelector(player.getWorld()).learnChanges(); session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session); player.print("Region outset."); } @Command( - aliases = { "/inset" }, - usage = "", - desc = "Inset the selection area", - help = - "Contracts the selection by the given amount in all directions.\n" + - "Flags:\n" + - " -h only contract horizontally\n" + - " -v only contract vertically\n", - flags = "hv", - min = 1, - max = 1 + name = "/inset", + desc = "Inset the selection area" ) @Logging(REGION) @CommandPermissions("worldedit.selection.inset") - public void inset(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void inset(Player player, LocalSession session, + @Arg(desc = "Amount to contract the selection by in all directions") + int amount, + @Switch(name = 'h', desc = "Only contract horizontally") + boolean onlyHorizontal, + @Switch(name = 'v', desc = "Only contract vertically") + boolean onlyVertical) throws WorldEditException { Region region = session.getSelection(player.getWorld()); - region.contract(getChangesForEachDir(args)); + region.contract(getChangesForEachDir(amount, onlyHorizontal, onlyVertical)); session.getRegionSelector(player.getWorld()).learnChanges(); session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session); player.print("Region inset."); } - private BlockVector3[] getChangesForEachDir(CommandContext args) { - List changes = new ArrayList<>(6); - int change = args.getInteger(0); + private BlockVector3[] getChangesForEachDir(int amount, boolean onlyHorizontal, boolean onlyVertical) { + Stream.Builder changes = Stream.builder(); - if (!args.hasFlag('h')) { - changes.add((BlockVector3.UNIT_Y).multiply(change)); - changes.add((BlockVector3.UNIT_MINUS_Y).multiply(change)); + if (!onlyHorizontal) { + changes.add(BlockVector3.UNIT_Y); + changes.add(BlockVector3.UNIT_MINUS_Y); } - if (!args.hasFlag('v')) { - changes.add((BlockVector3.UNIT_X).multiply(change)); - changes.add((BlockVector3.UNIT_MINUS_X).multiply(change)); - changes.add((BlockVector3.UNIT_Z).multiply(change)); - changes.add((BlockVector3.UNIT_MINUS_Z).multiply(change)); + if (!onlyVertical) { + changes.add(BlockVector3.UNIT_X); + changes.add(BlockVector3.UNIT_MINUS_X); + changes.add(BlockVector3.UNIT_Z); + changes.add(BlockVector3.UNIT_MINUS_Z); } - return changes.toArray(new BlockVector3[0]); + return changes.build().map(v -> v.multiply(amount)).toArray(BlockVector3[]::new); } @Command( - aliases = { "/size" }, - flags = "c", - usage = "", - desc = "Get information about the selection", - min = 0, - max = 0 + name = "/size", + desc = "Get information about the selection" ) @CommandPermissions("worldedit.selection.size") - public void size(Player player, LocalSession session, CommandContext args) throws WorldEditException { - if (args.hasFlag('c')) { + public void size(Player player, LocalSession session, + @Switch(name = 'c', desc = "Get clipboard info instead") + boolean clipboardInfo) throws WorldEditException { + if (clipboardInfo) { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); Region region = clipboard.getRegion(); @@ -602,7 +468,7 @@ public class SelectionCommands { player.print("Cuboid dimensions (max - min): " + size); player.print("Offset: " + origin); player.print("Cuboid distance: " + size.distance(BlockVector3.ONE)); - player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ())); + player.print("# of blocks: " + (size.getX() * size.getY() * size.getZ())); return; } @@ -626,48 +492,41 @@ public class SelectionCommands { @Command( - aliases = { "/count" }, - usage = "", - flags = "f", - desc = "Counts the number of a certain type of block", - min = 1, - max = 1 + name = "/count", + desc = "Counts the number of a certain type of block" ) @CommandPermissions("worldedit.analysis.count") - public void count(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - + public void count(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The block type(s) to count") + String blocks, + @Switch(name = 'f', desc = "Fuzzy, match states using a wildcard") + boolean fuzzy) throws WorldEditException { ParserContext context = new ParserContext(); context.setActor(player); context.setExtent(player.getExtent()); context.setWorld(player.getWorld()); context.setSession(session); context.setRestricted(false); - context.setPreferringWildcard(args.hasFlag('f')); + context.setPreferringWildcard(fuzzy); - Set searchBlocks = we.getBlockFactory().parseFromListInput(args.getString(0), context); + Set searchBlocks = we.getBlockFactory().parseFromListInput(blocks, context); int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks); player.print("Counted: " + count); } @Command( - aliases = { "/distr" }, - usage = "", - desc = "Get the distribution of blocks in the selection", - help = - "Gets the distribution of blocks in the selection.\n" + - "The -c flag gets the distribution of your clipboard.\n" + - "The -d flag separates blocks by state", - flags = "cd", - min = 0, - max = 0 + name = "/distr", + desc = "Get the distribution of blocks in the selection" ) @CommandPermissions("worldedit.analysis.distr") - public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException { - - boolean separateStates = args.hasFlag('d'); + public void distr(Player player, LocalSession session, EditSession editSession, + @Switch(name = 'c', desc = "Get the distribution of the clipboard instead") + boolean clipboardDistr, + @Switch(name = 'd', desc = "Separate blocks by state") + boolean separateStates) throws WorldEditException { List> distribution; - if (args.hasFlag('c')) { + if (clipboardDistr) { Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing BlockDistributionCounter count = new BlockDistributionCounter(clipboard, separateStates); RegionVisitor visitor = new RegionVisitor(clipboard.getRegion(), count); @@ -707,73 +566,86 @@ public class SelectionCommands { } @Command( - aliases = { "/sel", ";", "/desel", "/deselect" }, - flags = "d", - usage = "[cuboid|extend|poly|ellipsoid|sphere|cyl|convex]", - desc = "Choose a region selector", - min = 0, - max = 1 + name = "/sel", + aliases = { ";", "/desel", "/deselect" }, + desc = "Choose a region selector" ) - public void select(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void select(Player player, LocalSession session, + @Arg(desc = "Selector to switch to", def = "") + SelectorChoice selector, + @Switch(name = 'd', desc = "Set default selector") + boolean setDefaultSelector) throws WorldEditException { final World world = player.getWorld(); - if (args.argsLength() == 0) { + if (selector == null) { session.getRegionSelector(world).clear(); session.dispatchCUISelection(player); player.print("Selection cleared."); return; } - final String typeName = args.getString(0); final RegionSelector oldSelector = session.getRegionSelector(world); - final RegionSelector selector; - if (typeName.equalsIgnoreCase("cuboid")) { - selector = new CuboidRegionSelector(oldSelector); - player.print("Cuboid: left click for point 1, right click for point 2"); - } else if (typeName.equalsIgnoreCase("extend")) { - selector = new ExtendingCuboidRegionSelector(oldSelector); - player.print("Cuboid: left click for a starting point, right click to extend"); - } else if (typeName.equalsIgnoreCase("poly")) { - selector = new Polygonal2DRegionSelector(oldSelector); - player.print("2D polygon selector: Left/right click to add a point."); - Optional limit = ActorSelectorLimits.forActor(player).getPolygonVertexLimit(); - limit.ifPresent(integer -> player.print(integer + " points maximum.")); - } else if (typeName.equalsIgnoreCase("ellipsoid")) { - selector = new EllipsoidRegionSelector(oldSelector); - player.print("Ellipsoid selector: left click=center, right click to extend"); - } else if (typeName.equalsIgnoreCase("sphere")) { - selector = new SphereRegionSelector(oldSelector); - player.print("Sphere selector: left click=center, right click to set radius"); - } else if (typeName.equalsIgnoreCase("cyl")) { - selector = new CylinderRegionSelector(oldSelector); - player.print("Cylindrical selector: Left click=center, right click to extend."); - } else if (typeName.equalsIgnoreCase("convex") || typeName.equalsIgnoreCase("hull") || typeName.equalsIgnoreCase("polyhedron")) { - selector = new ConvexPolyhedralRegionSelector(oldSelector); - player.print("Convex polyhedral selector: Left click=First vertex, right click to add more."); - Optional limit = ActorSelectorLimits.forActor(player).getPolyhedronVertexLimit(); - limit.ifPresent(integer -> player.print(integer + " points maximum.")); - } else { - CommandListBox box = new CommandListBox("Selection modes"); - StyledFragment contents = box.getContents(); - StyledFragment tip = contents.createFragment(Style.RED); - tip.append("Select one of the modes below:").newLine(); + final RegionSelector newSelector; + switch (selector) { + case CUBOID: + newSelector = new CuboidRegionSelector(oldSelector); + player.print("Cuboid: left click for point 1, right click for point 2"); + break; + case EXTEND: + newSelector = new ExtendingCuboidRegionSelector(oldSelector); + player.print("Cuboid: left click for a starting point, right click to extend"); + break; + case POLY: { + newSelector = new Polygonal2DRegionSelector(oldSelector); + player.print("2D polygon selector: Left/right click to add a point."); + Optional limit = ActorSelectorLimits.forActor(player).getPolygonVertexLimit(); + limit.ifPresent(integer -> player.print(integer + " points maximum.")); + break; + } + case ELLIPSOID: + newSelector = new EllipsoidRegionSelector(oldSelector); + player.print("Ellipsoid selector: left click=center, right click to extend"); + break; + case SPHERE: + newSelector = new SphereRegionSelector(oldSelector); + player.print("Sphere selector: left click=center, right click to set radius"); + break; + case CYL: + newSelector = new CylinderRegionSelector(oldSelector); + player.print("Cylindrical selector: Left click=center, right click to extend."); + break; + case CONVEX: + case HULL: + case POLYHEDRON: { + newSelector = new ConvexPolyhedralRegionSelector(oldSelector); + player.print("Convex polyhedral selector: Left click=First vertex, right click to add more."); + Optional limit = ActorSelectorLimits.forActor(player).getPolyhedronVertexLimit(); + limit.ifPresent(integer -> player.print(integer + " points maximum.")); + break; + } + case UNKNOWN: + default: + CommandListBox box = new CommandListBox("Selection modes"); + StyledFragment contents = box.getContents(); + StyledFragment tip = contents.createFragment(Style.RED); + tip.append("Select one of the modes below:").newLine(); - box.appendCommand("cuboid", "Select two corners of a cuboid"); - box.appendCommand("extend", "Fast cuboid selection mode"); - box.appendCommand("poly", "Select a 2D polygon with height"); - box.appendCommand("ellipsoid", "Select an ellipsoid"); - box.appendCommand("sphere", "Select a sphere"); - box.appendCommand("cyl", "Select a cylinder"); - box.appendCommand("convex", "Select a convex polyhedral"); + box.appendCommand("cuboid", "Select two corners of a cuboid"); + box.appendCommand("extend", "Fast cuboid selection mode"); + box.appendCommand("poly", "Select a 2D polygon with height"); + box.appendCommand("ellipsoid", "Select an ellipsoid"); + box.appendCommand("sphere", "Select a sphere"); + box.appendCommand("cyl", "Select a cylinder"); + box.appendCommand("convex", "Select a convex polyhedral"); - player.printRaw(ColorCodeBuilder.asColorCodes(box)); - return; + player.printRaw(ColorCodeBuilder.asColorCodes(box)); + return; } - if (args.hasFlag('d')) { + if (setDefaultSelector) { RegionSelectorType found = null; for (RegionSelectorType type : RegionSelectorType.values()) { - if (type.getSelectorClass() == selector.getClass()) { + if (type.getSelectorClass() == newSelector.getClass()) { found = type; break; } @@ -787,7 +659,7 @@ public class SelectionCommands { } } - session.setRegionSelector(world, selector); + session.setRegionSelector(world, newSelector); session.dispatchCUISelection(player); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java index d2947a44a..70db3963f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java @@ -59,9 +59,8 @@ public class CommaSeparatedValuesConverter implements ArgumentConverter { if (maximum > -1) { result.append("up to ").append(maximum).append(' '); } - result.append("comma separated values of ") + result.append("comma separated values of: ") .append(delegate.describeAcceptableArguments()); - result.setCharAt(0, Character.toUpperCase(result.charAt(0))); return result.toString(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java index f454191da..092b7bf5d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.UnknownDirectionException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.internal.annotation.Direction; +import com.sk89q.worldedit.internal.annotation.MultiDirection; import com.sk89q.worldedit.math.BlockVector3; import org.enginehub.piston.CommandManager; import org.enginehub.piston.converter.ArgumentConverter; @@ -46,15 +47,23 @@ public class DirectionConverter implements ArgumentConverter { return new AutoAnnotation_DirectionConverter_direction(includeDiagonals); } + @AutoAnnotation + private static MultiDirection multiDirection(boolean includeDiagonals) { + return new AutoAnnotation_DirectionConverter_multiDirection(includeDiagonals); + } + public static void register(WorldEdit worldEdit, CommandManager commandManager) { - commandManager.registerConverter( - Key.of(BlockVector3.class, direction(false)), - new DirectionConverter(worldEdit, false) - ); - commandManager.registerConverter( - Key.of(BlockVector3.class, direction(true)), - new DirectionConverter(worldEdit, true) - ); + for (boolean includeDiagonals : new boolean[] { false, true }) { + DirectionConverter directionConverter = new DirectionConverter(worldEdit, includeDiagonals); + commandManager.registerConverter( + Key.of(BlockVector3.class, direction(includeDiagonals)), + directionConverter + ); + commandManager.registerConverter( + Key.of(BlockVector3.class, multiDirection(includeDiagonals)), + CommaSeparatedValuesConverter.wrap(directionConverter) + ); + } } private static final ImmutableSet NON_DIAGONALS = ImmutableSet.of( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java new file mode 100644 index 000000000..353a46a77 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java @@ -0,0 +1,52 @@ +package com.sk89q.worldedit.command.argument; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedMap; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import javax.annotation.Nullable; +import java.util.EnumSet; + +public class EnumConverter> implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(SelectorChoice.class), + new EnumConverter<>(SelectorChoice.class, SelectorChoice.UNKNOWN)); + } + + private final ImmutableMap map; + @Nullable + private final E unknownValue; + + private EnumConverter(Class enumClass, @Nullable E unknownValue) { + ImmutableSortedMap.Builder map = ImmutableSortedMap.orderedBy(String.CASE_INSENSITIVE_ORDER); + EnumSet validValues = EnumSet.allOf(enumClass); + if (unknownValue != null) { + validValues.remove(unknownValue); + } + for (E e : validValues) { + map.put(e.name(), e); + } + this.map = map.build(); + this.unknownValue = unknownValue; + } + + @Override + public String describeAcceptableArguments() { + return String.join("|", map.keySet()); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + E result = map.getOrDefault(argument, unknownValue); + return result == null + ? FailedConversion.from(new IllegalArgumentException("Not a valid choice: " + argument)) + : SuccessfulConversion.fromSingle(result); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java new file mode 100644 index 000000000..d567c3d19 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java @@ -0,0 +1,32 @@ +package com.sk89q.worldedit.command.argument; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class ExpandAmount { + + public static ExpandAmount vert() { + return new ExpandAmount(null); + } + + public static ExpandAmount from(int amount) { + return new ExpandAmount(amount); + } + + @Nullable + private final Integer amount; + + private ExpandAmount(@Nullable Integer amount) { + this.amount = amount; + } + + public boolean isVert() { + return amount == null; + } + + public int getAmount() { + return checkNotNull(amount, "This amount is vertical, i.e. undefined"); + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java new file mode 100644 index 000000000..4c6e64c77 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java @@ -0,0 +1,48 @@ +package com.sk89q.worldedit.command.argument; + +import com.google.common.reflect.TypeToken; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ArgumentConverters; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ExpandAmountConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(ExpandAmount.class), new ExpandAmountConverter()); + } + + private final ArgumentConverter integerConverter = + ArgumentConverters.get(TypeToken.of(int.class)); + + private ExpandAmountConverter() { + } + + @Override + public String describeAcceptableArguments() { + return "`vert` or " + integerConverter.describeAcceptableArguments(); + } + + @Override + public List getSuggestions(String input) { + return Stream.concat(Stream.of("vert"), integerConverter.getSuggestions(input).stream()) + .filter(x -> x.startsWith(input)) + .collect(Collectors.toList()); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + if (argument.equalsIgnoreCase("vert") + || argument.equalsIgnoreCase("vertical")) { + return SuccessfulConversion.fromSingle(ExpandAmount.vert()); + } + return integerConverter.convert(argument, context).mapSingle(ExpandAmount::from); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java new file mode 100644 index 000000000..8aa63e6e0 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java @@ -0,0 +1,14 @@ +package com.sk89q.worldedit.command.argument; + +public enum SelectorChoice { + CUBOID, + EXTEND, + POLY, + ELLIPSOID, + SPHERE, + CYL, + CONVEX, + HULL, + POLYHEDRON, + UNKNOWN +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java new file mode 100644 index 000000000..fda47dd0f --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java @@ -0,0 +1,109 @@ +/* + * 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.google.common.collect.ImmutableList; +import com.google.common.reflect.TypeToken; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.Vector2; +import com.sk89q.worldedit.math.Vector3; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ArgumentConverters; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SimpleArgumentConverter; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.List; +import java.util.function.Function; + +public class VectorConverter implements ArgumentConverter { + public static void register(CommandManager commandManager) { + CommaSeparatedValuesConverter intConverter = CommaSeparatedValuesConverter.wrap(ArgumentConverters.get(TypeToken.of(int.class))); + CommaSeparatedValuesConverter doubleConverter = CommaSeparatedValuesConverter.wrap(ArgumentConverters.get(TypeToken.of(double.class))); + commandManager.registerConverter(Key.of(BlockVector2.class), + new VectorConverter<>( + intConverter, + 2, + cmps -> BlockVector2.at(cmps.get(0), cmps.get(1)), + "block vector with x and z" + )); + commandManager.registerConverter(Key.of(Vector2.class), + new VectorConverter<>( + doubleConverter, + 3, + cmps -> Vector2.at(cmps.get(0), cmps.get(1)), + "vector with x and z" + )); + commandManager.registerConverter(Key.of(BlockVector3.class), + new VectorConverter<>( + intConverter, + 2, + cmps -> BlockVector3.at(cmps.get(0), cmps.get(1), cmps.get(2)), + "block vector with x, y, and z" + )); + commandManager.registerConverter(Key.of(Vector3.class), + new VectorConverter<>( + doubleConverter, + 3, + cmps -> Vector3.at(cmps.get(0), cmps.get(1), cmps.get(2)), + "vector with x, y, and z" + )); + } + + private final ArgumentConverter componentConverter; + private final int componentCount; + private final Function, T> vectorConstructor; + private final String acceptableArguments; + + + private VectorConverter(ArgumentConverter componentConverter, + int componentCount, + Function, T> vectorConstructor, + String acceptableArguments) { + this.componentConverter = componentConverter; + this.componentCount = componentCount; + this.vectorConstructor = vectorConstructor; + this.acceptableArguments = acceptableArguments; + } + + @Override + public String describeAcceptableArguments() { + return "any " + acceptableArguments; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + ConversionResult components = componentConverter.convert(argument, context); + if (!components.isSuccessful()) { + return components.failureAsAny(); + } + if (components.get().size() != componentCount) { + return FailedConversion.from(new IllegalArgumentException( + "Must have exactly " + componentCount + " vector components")); + } + T vector = vectorConstructor.apply(ImmutableList.copyOf(components.get())); + return SuccessfulConversion.fromSingle(vector); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index a0a94591d..037617ab3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -48,11 +48,16 @@ import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.SchematicCommandsRegistration; import com.sk89q.worldedit.command.ScriptingCommands; import com.sk89q.worldedit.command.ScriptingCommandsRegistration; +import com.sk89q.worldedit.command.SelectionCommands; +import com.sk89q.worldedit.command.SelectionCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; +import com.sk89q.worldedit.command.argument.EnumConverter; +import com.sk89q.worldedit.command.argument.ExpandAmountConverter; import com.sk89q.worldedit.command.argument.MaskConverter; import com.sk89q.worldedit.command.argument.PatternConverter; +import com.sk89q.worldedit.command.argument.VectorConverter; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Entity; @@ -193,6 +198,9 @@ public final class PlatformCommandMananger { ), count) ); } + VectorConverter.register(commandManager); + EnumConverter.register(commandManager); + ExpandAmountConverter.register(commandManager); } private void registerAlwaysInjectedValues() { @@ -305,13 +313,17 @@ public final class PlatformCommandMananger { ScriptingCommandsRegistration.builder(), new ScriptingCommands(worldEdit) ); + register( + commandManager, + SelectionCommandsRegistration.builder(), + new SelectionCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new SelectionCommands(worldEdit)) .registerMethods(new SnapshotUtilCommands(worldEdit)) .registerMethods(new ToolUtilCommands(worldEdit)) .registerMethods(new ToolCommands(worldEdit)) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/MultiDirection.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/MultiDirection.java new file mode 100644 index 000000000..efd1ba701 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/MultiDirection.java @@ -0,0 +1,37 @@ +/* + * 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.internal.annotation; + +import org.enginehub.piston.inject.InjectAnnotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotates a {@code List} parameter to inject multiple direction. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@InjectAnnotation +public @interface MultiDirection { + boolean includeDiagonals() default false; +} From ea3605204c424ae896b68748f2dd531eaa30dd25 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 22:59:11 -0700 Subject: [PATCH 22/57] Fix licenses --- .../command/argument/EnumConverter.java | 19 +++++++++++++++++++ .../command/argument/ExpandAmount.java | 19 +++++++++++++++++++ .../argument/ExpandAmountConverter.java | 19 +++++++++++++++++++ .../command/argument/SelectorChoice.java | 19 +++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java index 353a46a77..a5fab7da3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java @@ -1,3 +1,22 @@ +/* + * 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.google.common.collect.ImmutableMap; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java index d567c3d19..062a330c9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmount.java @@ -1,3 +1,22 @@ +/* + * 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 javax.annotation.Nullable; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java index 4c6e64c77..02ef20447 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java @@ -1,3 +1,22 @@ +/* + * 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.google.common.reflect.TypeToken; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java index 8aa63e6e0..c17c71601 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/SelectorChoice.java @@ -1,3 +1,22 @@ +/* + * 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; public enum SelectorChoice { From 2ea30dc70efb01065b80290bc199263ddce1494b Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 23 Apr 2019 23:47:22 -0700 Subject: [PATCH 23/57] Port snapshot commands, update some time stuff to new time --- .../com/sk89q/worldedit/LocalSession.java | 12 +- .../worldedit/command/SnapshotCommands.java | 139 +++++++----------- .../command/SnapshotUtilCommands.java | 27 ++-- .../worldedit/command/WorldEditCommands.java | 23 +-- .../argument/ZonedDateTimeConverter.java | 40 +++++ .../platform/PlatformCommandMananger.java | 33 ++++- .../worldedit/world/snapshot/Snapshot.java | 8 +- .../world/snapshot/SnapshotRepository.java | 15 +- 8 files changed, 172 insertions(+), 125 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java 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 bf15a504a..b0c1ebd45 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -52,6 +52,7 @@ import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.snapshot.Snapshot; import javax.annotation.Nullable; +import java.time.ZoneId; import java.util.Calendar; import java.util.HashMap; import java.util.LinkedList; @@ -91,7 +92,7 @@ public class LocalSession { private transient int cuiVersion = -1; private transient boolean fastMode = false; private transient Mask mask; - private transient TimeZone timezone = TimeZone.getDefault(); + private transient ZoneId timezone = ZoneId.systemDefault(); private transient BlockVector3 cuiTemporaryBlock; private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE; @@ -169,7 +170,7 @@ public class LocalSession { * * @return the timezone */ - public TimeZone getTimeZone() { + public ZoneId getTimeZone() { return timezone; } @@ -178,7 +179,7 @@ public class LocalSession { * * @param timezone the user's timezone */ - public void setTimezone(TimeZone timezone) { + public void setTimezone(ZoneId timezone) { checkNotNull(timezone); this.timezone = timezone; } @@ -849,9 +850,10 @@ public class LocalSession { public Calendar detectDate(String input) { checkNotNull(input); - Time.setTimeZone(getTimeZone()); + TimeZone tz = TimeZone.getTimeZone(getTimeZone()); + Time.setTimeZone(tz); Options opt = new com.sk89q.jchronic.Options(); - opt.setNow(Calendar.getInstance(getTimeZone())); + opt.setNow(Calendar.getInstance(tz)); Span date = Chronic.parse(input, opt); if (date == null) { return null; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java index 1c4987734..643b064b1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotCommands.java @@ -21,32 +21,34 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException; import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.storage.MissingWorldException; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; import java.io.File; import java.io.IOException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; /** * Snapshot commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SnapshotCommands { - private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); - + private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); + private final WorldEdit we; public SnapshotCommands(WorldEdit we) { @@ -54,14 +56,13 @@ public class SnapshotCommands { } @Command( - aliases = { "list" }, - usage = "[num]", - desc = "List snapshots", - min = 0, - max = 1 + name = "list", + desc = "List snapshots" ) @CommandPermissions("worldedit.snapshots.list") - public void list(Player player, CommandContext args) throws WorldEditException { + public void list(Player player, + @Arg(desc = "# of snapshots to list", def = "5") + int num) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -75,7 +76,7 @@ public class SnapshotCommands { if (!snapshots.isEmpty()) { - int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5; + num = Math.min(40, Math.max(5, num)); player.print("Snapshots for world: '" + player.getWorld().getName() + "'"); for (byte i = 0; i < Math.min(num, snapshots.size()); i++) { @@ -104,14 +105,13 @@ public class SnapshotCommands { } @Command( - aliases = { "use" }, - usage = "", - desc = "Choose a snapshot to use", - min = 1, - max = 1 + name = "use", + desc = "Choose a snapshot to use" ) @CommandPermissions("worldedit.snapshots.restore") - public void use(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void use(Player player, LocalSession session, + @Arg(desc = "Snapeshot to use") + String name) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -120,8 +120,6 @@ public class SnapshotCommands { return; } - String name = args.getString(0); - // Want the latest snapshot? if (name.equalsIgnoreCase("latest")) { try { @@ -147,14 +145,13 @@ public class SnapshotCommands { } @Command( - aliases = { "sel" }, - usage = "", - desc = "Choose the snapshot based on the list id", - min = 1, - max = 1 + name = "sel", + desc = "Choose the snapshot based on the list id" ) @CommandPermissions("worldedit.snapshots.restore") - public void sel(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void sel(Player player, LocalSession session, + @Arg(desc = "The list ID to select") + int index) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); if (config.snapshotRepo == null) { @@ -162,14 +159,6 @@ public class SnapshotCommands { return; } - int index = -1; - try { - index = Integer.parseInt(args.getString(0)); - } catch (NumberFormatException e) { - player.printError("Invalid index, " + args.getString(0) + " is not a valid integer."); - return; - } - if (index < 1) { player.printError("Invalid index, must be equal or higher then 1."); return; @@ -194,14 +183,13 @@ public class SnapshotCommands { } @Command( - aliases = { "before" }, - usage = "", - desc = "Choose the nearest snapshot before a date", - min = 1, - max = -1 + name = "before", + desc = "Choose the nearest snapshot before a date" ) @CommandPermissions("worldedit.snapshots.restore") - public void before(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void before(Player player, LocalSession session, + @Arg(desc = "The soonest date that may be used") + ZonedDateTime date) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -210,37 +198,29 @@ public class SnapshotCommands { return; } - Calendar date = session.detectDate(args.getJoinedStrings(0)); + try { + Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName()); - if (date == null) { - player.printError("Could not detect the date inputted."); - } else { - try { - Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName()); - - if (snapshot == null) { - dateFormat.setTimeZone(session.getTimeZone()); - player.printError("Couldn't find a snapshot before " - + dateFormat.format(date.getTime()) + "."); - } else { - session.setSnapshot(snapshot); - player.print("Snapshot set to: " + snapshot.getName()); - } - } catch (MissingWorldException ex) { - player.printError("No snapshots were found for this world."); + if (snapshot == null) { + player.printError("Couldn't find a snapshot before " + + dateFormat.withZone(session.getTimeZone()).format(date) + "."); + } else { + session.setSnapshot(snapshot); + player.print("Snapshot set to: " + snapshot.getName()); } + } catch (MissingWorldException ex) { + player.printError("No snapshots were found for this world."); } } @Command( - aliases = { "after" }, - usage = "", - desc = "Choose the nearest snapshot after a date", - min = 1, - max = -1 + name = "after", + desc = "Choose the nearest snapshot after a date" ) @CommandPermissions("worldedit.snapshots.restore") - public void after(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void after(Player player, LocalSession session, + @Arg(desc = "The soonest date that may be used") + ZonedDateTime date) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -249,24 +229,17 @@ public class SnapshotCommands { return; } - Calendar date = session.detectDate(args.getJoinedStrings(0)); - - if (date == null) { - player.printError("Could not detect the date inputted."); - } else { - try { - Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); - if (snapshot == null) { - dateFormat.setTimeZone(session.getTimeZone()); - player.printError("Couldn't find a snapshot after " - + dateFormat.format(date.getTime()) + "."); - } else { - session.setSnapshot(snapshot); - player.print("Snapshot set to: " + snapshot.getName()); - } - } catch (MissingWorldException ex) { - player.printError("No snapshots were found for this world."); + try { + Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); + if (snapshot == null) { + player.printError("Couldn't find a snapshot after " + + dateFormat.withZone(session.getTimeZone()).format(date) + "."); + } else { + session.setSnapshot(snapshot); + player.print("Snapshot set to: " + snapshot.getName()); } + } catch (MissingWorldException ex) { + player.printError("No snapshots were found for this world."); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index b8d6c7f3f..14a90e2fe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -19,14 +19,13 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.regions.Region; @@ -36,12 +35,16 @@ import com.sk89q.worldedit.world.snapshot.Snapshot; import com.sk89q.worldedit.world.snapshot.SnapshotRestore; import com.sk89q.worldedit.world.storage.ChunkStore; import com.sk89q.worldedit.world.storage.MissingWorldException; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; import java.io.File; import java.io.IOException; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SnapshotUtilCommands { private final WorldEdit we; @@ -51,15 +54,15 @@ public class SnapshotUtilCommands { } @Command( - aliases = { "restore", "/restore" }, - usage = "[snapshot]", - desc = "Restore the selection from a snapshot", - min = 0, - max = 1 + name = "restore", + aliases = { "/restore" }, + desc = "Restore the selection from a snapshot" ) @Logging(REGION) @CommandPermissions("worldedit.snapshots.restore") - public void restore(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { + public void restore(Player player, LocalSession session, EditSession editSession, + @Arg(name = "snapshot", desc = "The snapshot to restore", def = "") + String snapshotName) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -71,9 +74,9 @@ public class SnapshotUtilCommands { Region region = session.getSelection(player.getWorld()); Snapshot snapshot; - if (args.argsLength() > 0) { + if (snapshotName != null) { try { - snapshot = config.snapshotRepo.getSnapshot(args.getString(0)); + snapshot = config.snapshotRepo.getSnapshot(snapshotName); } catch (InvalidSnapshotException e) { player.printError("That snapshot does not exist or is not available."); return; @@ -110,7 +113,7 @@ public class SnapshotUtilCommands { } } - ChunkStore chunkStore = null; + ChunkStore chunkStore; // Load chunk store try { 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 787859323..5378d5819 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 @@ -40,16 +40,17 @@ import com.sk89q.worldedit.util.report.SystemInfoReport; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.TimeZone; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.TextStyle; +import java.util.Locale; public class WorldEditCommands { - private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); - + private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); + private final WorldEdit we; - + public WorldEditCommands(WorldEdit we) { this.we = we; } @@ -138,11 +139,13 @@ public class WorldEditCommands { max = 1 ) public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException { - TimeZone tz = TimeZone.getTimeZone(args.getString(0)); + ZoneId tz = ZoneId.of(args.getString(0)); session.setTimezone(tz); - player.print("Timezone set for this session to: " + tz.getDisplayName()); + player.print("Timezone set for this session to: " + tz.getDisplayName( + TextStyle.FULL, Locale.ENGLISH + )); player.print("The current time in that timezone is: " - + dateFormat.format(Calendar.getInstance(tz).getTime())); + + dateFormat.format(ZonedDateTime.now(tz))); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java new file mode 100644 index 000000000..5d96c28ab --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java @@ -0,0 +1,40 @@ +package com.sk89q.worldedit.command.argument; + +import com.sk89q.worldedit.LocalSession; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Calendar; + +public class ZonedDateTimeConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(ZonedDateTime.class), new ZonedDateTimeConverter()); + } + + private ZonedDateTimeConverter() { + } + + @Override + public String describeAcceptableArguments() { + return "any date"; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + LocalSession session = context.injectedValue(Key.of(LocalSession.class)) + .orElseThrow(() -> new IllegalStateException("Need a local session")); + Calendar date = session.detectDate(argument); + if (date == null) { + return FailedConversion.from(new IllegalArgumentException("Not a date: " + argument)); + } + return SuccessfulConversion.fromSingle(date.toInstant().atZone(ZoneOffset.UTC)); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 037617ab3..795d8cddb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -50,6 +50,10 @@ import com.sk89q.worldedit.command.ScriptingCommands; import com.sk89q.worldedit.command.ScriptingCommandsRegistration; import com.sk89q.worldedit.command.SelectionCommands; import com.sk89q.worldedit.command.SelectionCommandsRegistration; +import com.sk89q.worldedit.command.SnapshotCommands; +import com.sk89q.worldedit.command.SnapshotCommandsRegistration; +import com.sk89q.worldedit.command.SnapshotUtilCommands; +import com.sk89q.worldedit.command.SnapshotUtilCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; @@ -58,6 +62,7 @@ import com.sk89q.worldedit.command.argument.ExpandAmountConverter; import com.sk89q.worldedit.command.argument.MaskConverter; import com.sk89q.worldedit.command.argument.PatternConverter; import com.sk89q.worldedit.command.argument.VectorConverter; +import com.sk89q.worldedit.command.argument.ZonedDateTimeConverter; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Entity; @@ -201,6 +206,7 @@ public final class PlatformCommandMananger { VectorConverter.register(commandManager); EnumConverter.register(commandManager); ExpandAmountConverter.register(commandManager); + ZonedDateTimeConverter.register(commandManager); } private void registerAlwaysInjectedValues() { @@ -250,6 +256,24 @@ public final class PlatformCommandMananger { .required() .build()); }); + commandManager.register("snapshot", cmd -> { + cmd.aliases(ImmutableList.of("snapshot", "snap")); + cmd.description("Snapshot commands for saving/loading snapshots"); + cmd.action(Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + register( + manager, + SnapshotCommandsRegistration.builder(), + new SnapshotCommands(worldEdit) + ); + + cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() + .build()); + }); commandManager.register("brush", cmd -> { cmd.aliases(ImmutableList.of("br")); cmd.description("Brushing commands"); @@ -318,6 +342,11 @@ public final class PlatformCommandMananger { SelectionCommandsRegistration.builder(), new SelectionCommands(worldEdit) ); + register( + commandManager, + SnapshotUtilCommandsRegistration.builder(), + new SnapshotUtilCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* @@ -333,10 +362,6 @@ public final class PlatformCommandMananger { .describeAs("WorldEdit commands") .registerMethods(new WorldEditCommands(worldEdit)) .parent() - .group("snapshot", "snap") - .describeAs("Schematic commands for saving/loading areas") - .registerMethods(new SnapshotCommands(worldEdit)) - .parent() .group("brush", "br") .describeAs("Brushing commands") .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java index 0af2b6e18..e05ba9e60 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/Snapshot.java @@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.Calendar; +import java.time.ZonedDateTime; import java.util.zip.ZipFile; /** @@ -46,7 +46,7 @@ public class Snapshot implements Comparable { protected File file; protected String name; - protected Calendar date; + protected ZonedDateTime date; /** * Construct a snapshot restoration operation. @@ -185,7 +185,7 @@ public class Snapshot implements Comparable { * * @return date for the snapshot */ - public Calendar getDate() { + public ZonedDateTime getDate() { return date; } @@ -194,7 +194,7 @@ public class Snapshot implements Comparable { * * @param date the date of the snapshot */ - public void setDate(Calendar date) { + public void setDate(ZonedDateTime date) { this.date = date; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java index 72650a408..1838c2747 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/snapshot/SnapshotRepository.java @@ -23,15 +23,16 @@ package com.sk89q.worldedit.world.snapshot; import com.sk89q.worldedit.world.storage.MissingWorldException; +import javax.annotation.Nullable; import java.io.File; import java.io.FilenameFilter; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.List; -import javax.annotation.Nullable; - /** * A repository contains zero or more snapshots. */ @@ -115,12 +116,12 @@ public class SnapshotRepository { * @return a snapshot or null */ @Nullable - public Snapshot getSnapshotAfter(Calendar date, String world) throws MissingWorldException { + public Snapshot getSnapshotAfter(ZonedDateTime date, String world) throws MissingWorldException { List snapshots = getSnapshots(true, world); Snapshot last = null; for (Snapshot snapshot : snapshots) { - if (snapshot.getDate() != null && snapshot.getDate().before(date)) { + if (snapshot.getDate() != null && snapshot.getDate().compareTo(date) < 0) { return last; } @@ -137,12 +138,12 @@ public class SnapshotRepository { * @return a snapshot or null */ @Nullable - public Snapshot getSnapshotBefore(Calendar date, String world) throws MissingWorldException { + public Snapshot getSnapshotBefore(ZonedDateTime date, String world) throws MissingWorldException { List snapshots = getSnapshots(false, world); Snapshot last = null; for (Snapshot snapshot : snapshots) { - if (snapshot.getDate().after(date)) { + if (snapshot.getDate().compareTo(date) > 0) { return last; } @@ -161,7 +162,7 @@ public class SnapshotRepository { for (SnapshotDateParser parser : dateParsers) { Calendar date = parser.detectDate(snapshot.getFile()); if (date != null) { - snapshot.setDate(date); + snapshot.setDate(date.toInstant().atZone(ZoneOffset.UTC)); return; } } From e447ac55dbd369b5bfb4412f5199aad660a8cac7 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Wed, 24 Apr 2019 00:00:56 -0700 Subject: [PATCH 24/57] Port super pickaxe commands --- .../command/SuperPickaxeCommands.java | 42 +++++++++---------- .../argument/ZonedDateTimeConverter.java | 19 +++++++++ .../platform/PlatformCommandMananger.java | 27 +++++++++--- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java index a3e21db8a..754473a9a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SuperPickaxeCommands.java @@ -19,9 +19,6 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -29,8 +26,14 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.tool.AreaPickaxe; import com.sk89q.worldedit.command.tool.RecursivePickaxe; import com.sk89q.worldedit.command.tool.SinglePickaxe; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.entity.Player; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SuperPickaxeCommands { private final WorldEdit we; @@ -39,32 +42,26 @@ public class SuperPickaxeCommands { } @Command( - aliases = { "single" }, - usage = "", - desc = "Enable the single block super pickaxe mode", - min = 0, - max = 0 + name = "single", + desc = "Enable the single block super pickaxe mode" ) @CommandPermissions("worldedit.superpickaxe") public void single(Player player, LocalSession session) throws WorldEditException { - session.setSuperPickaxe(new SinglePickaxe()); session.enableSuperPickAxe(); player.print("Mode changed. Left click with a pickaxe. // to disable."); } @Command( - aliases = { "area" }, - usage = "", - desc = "Enable the area super pickaxe pickaxe mode", - min = 1, - max = 1 + name = "area", + desc = "Enable the area super pickaxe pickaxe mode" ) @CommandPermissions("worldedit.superpickaxe.area") - public void area(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void area(Player player, LocalSession session, + @Arg(desc = "The range of the area pickaxe") + int range) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); - int range = args.getInteger(0); if (range > config.maxSuperPickaxeSize) { player.printError("Maximum range: " + config.maxSuperPickaxeSize); @@ -77,17 +74,16 @@ public class SuperPickaxeCommands { } @Command( - aliases = { "recur", "recursive" }, - usage = "", - desc = "Enable the recursive super pickaxe pickaxe mode", - min = 1, - max = 1 + name = "recursive", + aliases = { "recur" }, + desc = "Enable the recursive super pickaxe pickaxe mode" ) @CommandPermissions("worldedit.superpickaxe.recursive") - public void recursive(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void recursive(Player player, LocalSession session, + @Arg(desc = "The range of the recursive pickaxe") + double range) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); - double range = args.getDouble(0); if (range > config.maxSuperPickaxeSize) { player.printError("Maximum range: " + config.maxSuperPickaxeSize); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java index 5d96c28ab..4efd97555 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ZonedDateTimeConverter.java @@ -1,3 +1,22 @@ +/* + * 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.LocalSession; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 795d8cddb..b6c2b6c89 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -54,6 +54,8 @@ import com.sk89q.worldedit.command.SnapshotCommands; import com.sk89q.worldedit.command.SnapshotCommandsRegistration; import com.sk89q.worldedit.command.SnapshotUtilCommands; import com.sk89q.worldedit.command.SnapshotUtilCommandsRegistration; +import com.sk89q.worldedit.command.SuperPickaxeCommands; +import com.sk89q.worldedit.command.SuperPickaxeCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; @@ -257,7 +259,7 @@ public final class PlatformCommandMananger { .build()); }); commandManager.register("snapshot", cmd -> { - cmd.aliases(ImmutableList.of("snapshot", "snap")); + cmd.aliases(ImmutableList.of("snap")); cmd.description("Snapshot commands for saving/loading snapshots"); cmd.action(Command.Action.NULL_ACTION); @@ -274,6 +276,24 @@ public final class PlatformCommandMananger { .required() .build()); }); + commandManager.register("superpickaxe", cmd -> { + cmd.aliases(ImmutableList.of("pickaxe", "sp")); + cmd.description("Super-pickaxe commands"); + cmd.action(Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + register( + manager, + SuperPickaxeCommandsRegistration.builder(), + new SuperPickaxeCommands(worldEdit) + ); + + cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() + .build()); + }); commandManager.register("brush", cmd -> { cmd.aliases(ImmutableList.of("br")); cmd.description("Brushing commands"); @@ -353,7 +373,6 @@ public final class PlatformCommandMananger { dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new SnapshotUtilCommands(worldEdit)) .registerMethods(new ToolUtilCommands(worldEdit)) .registerMethods(new ToolCommands(worldEdit)) .registerMethods(new UtilityCommands(worldEdit)) @@ -372,10 +391,6 @@ public final class PlatformCommandMananger { .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise") .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower") .parent() - .group("superpickaxe", "pickaxe", "sp") - .describeAs("Super-pickaxe commands") - .registerMethods(new SuperPickaxeCommands(worldEdit)) - .parent() .group("tool") .describeAs("Bind functions to held items") .registerMethods(new ToolCommands(worldEdit)) From 8c2b725f42abe1d54c89bf1b88b4e13f58c3b03c Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 12:49:03 -0700 Subject: [PATCH 25/57] Port toll / tool util commands, add more enums --- .../java/com/sk89q/worldedit/EditSession.java | 9 -- .../worldedit/command/GeneralCommands.java | 55 ++++----- .../sk89q/worldedit/command/ToolCommands.java | 104 +++++++----------- .../worldedit/command/ToolUtilCommands.java | 98 ++++++++--------- .../command/argument/BooleanConverter.java | 65 +++++++++++ .../command/argument/EnumConverter.java | 51 ++++++++- .../platform/PlatformCommandMananger.java | 18 ++- .../sk89q/worldedit/util/TreeGenerator.java | 9 +- 8 files changed, 238 insertions(+), 171 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index bf26a0a1f..a831c10b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -175,15 +175,6 @@ public class EditSession implements Extent, AutoCloseable { public String getDisplayName() { return this.displayName; } - - public static Optional getFromDisplayName(String name) { - for (ReorderMode mode : values()) { - if (mode.getDisplayName().equalsIgnoreCase(name)) { - return Optional.of(mode); - } - } - return Optional.empty(); - } } @SuppressWarnings("ProtectedField") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index a5a0a9796..220b30de2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -122,23 +122,18 @@ public class GeneralCommands { ) @CommandPermissions("worldedit.fast") public void fast(Player player, LocalSession session, - @Arg(name = "on|off", desc = "The new fast mode state", def = "toggle") - String newState) throws WorldEditException { - - if (session.hasFastMode()) { - if ("on".equals(newState)) { - player.printError("Fast mode already enabled."); - return; - } + @Arg(desc = "The new fast mode state", def = "") + Boolean fastMode) throws WorldEditException { + boolean hasFastMode = session.hasFastMode(); + if (fastMode != null && fastMode == hasFastMode) { + player.printError("Fast mode already " + (fastMode ? "enabled" : "disabled") + "."); + return; + } + if (hasFastMode) { session.setFastMode(false); player.print("Fast mode disabled."); } else { - if ("off".equals(newState)) { - player.printError("Fast mode already disabled."); - return; - } - session.setFastMode(true); player.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes."); } @@ -150,18 +145,11 @@ public class GeneralCommands { ) @CommandPermissions("worldedit.reorder") public void reorderMode(Player player, LocalSession session, - @Arg(name = "multi|fast|none", desc = "The reorder mode", def = "") - String newState) throws WorldEditException { - if (newState == null) { + @Arg(desc = "The reorder mode", def = "") + EditSession.ReorderMode reorderMode) throws WorldEditException { + if (reorderMode == null) { player.print("The reorder mode is " + session.getReorderMode().getDisplayName()); } else { - java.util.Optional reorderModeOptional = EditSession.ReorderMode.getFromDisplayName(newState); - if (!reorderModeOptional.isPresent()) { - player.printError("Unknown reorder mode!"); - return; - } - - EditSession.ReorderMode reorderMode = reorderModeOptional.get(); session.setReorderMode(reorderMode); player.print("The reorder mode is now " + session.getReorderMode().getDisplayName()); } @@ -173,26 +161,21 @@ public class GeneralCommands { ) @CommandPermissions("worldedit.drawsel") public void drawSelection(Player player, LocalSession session, - @Arg(name = "on|off", desc = "The new fast mode state", def = "toggle") - String newState) throws WorldEditException { + @Arg(desc = "The new draw selection state", def = "toggle") + Boolean drawSelection) throws WorldEditException { if (!WorldEdit.getInstance().getConfiguration().serverSideCUI) { throw new DisallowedUsageException("This functionality is disabled in the configuration!"); } - if (session.shouldUseServerCUI()) { - if ("on".equals(newState)) { - player.printError("Server CUI already enabled."); - return; - } - + boolean useServerCui = session.shouldUseServerCUI(); + if (drawSelection != null && drawSelection == useServerCui) { + player.printError("Server CUI already " + (useServerCui ? "enabled" : "disabled") + "."); + return; + } + if (useServerCui) { session.setUseServerCUI(false); session.updateServerCUI(player); player.print("Server CUI disabled."); } else { - if ("off".equals(newState)) { - player.printError("Server CUI already disabled."); - return; - } - session.setUseServerCUI(true); session.updateServerCUI(player); player.print("Server CUI enabled. This only supports cuboid regions, with a maximum size of 32x32x32."); 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 c61c2fc92..2af2b8750 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,9 +19,6 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -35,12 +32,18 @@ import com.sk89q.worldedit.command.tool.FloodFillTool; import com.sk89q.worldedit.command.tool.LongRangeBuildTool; import com.sk89q.worldedit.command.tool.QueryTool; import com.sk89q.worldedit.command.tool.TreePlanter; +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.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.TreeGenerator; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ToolCommands { private final WorldEdit we; @@ -49,11 +52,8 @@ public class ToolCommands { } @Command( - aliases = { "none" }, - usage = "", - desc = "Unbind a bound tool from your current item", - min = 0, - max = 0 + name = "none", + desc = "Unbind a bound tool from your current item" ) public void none(Player player, LocalSession session) throws WorldEditException { @@ -62,11 +62,8 @@ public class ToolCommands { } @Command( - aliases = { "info" }, - usage = "", - desc = "Block information tool", - min = 0, - max = 0 + name = "info", + desc = "Block information tool" ) @CommandPermissions("worldedit.tool.info") public void info(Player player, LocalSession session) throws WorldEditException { @@ -78,49 +75,34 @@ public class ToolCommands { } @Command( - aliases = { "tree" }, - usage = "[type]", - desc = "Tree generator tool", - min = 0, - max = 1 + name = "tree", + desc = "Tree generator tool" ) @CommandPermissions("worldedit.tool.tree") - public void tree(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - TreeGenerator.TreeType type = args.argsLength() > 0 - ? TreeGenerator.lookup(args.getString(0)) - : TreeGenerator.TreeType.TREE; - - if (type == null) { - player.printError("Tree type '" + args.getString(0) + "' is unknown."); - return; - } - + public void tree(Player player, LocalSession session, + @Arg(desc = "Type of tree to generate", def = "tree") + TreeGenerator.TreeType type) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); session.setTool(itemStack.getType(), new TreePlanter(type)); player.print("Tree tool bound to " + itemStack.getType().getName() + "."); } @Command( - aliases = { "repl" }, - usage = "", - desc = "Block replacer tool", - min = 1, - max = 1 + name = "repl", + desc = "Block replacer tool" ) @CommandPermissions("worldedit.tool.replacer") - public void repl(Player player, LocalSession session, Pattern pattern) throws WorldEditException { + public void repl(Player player, LocalSession session, + @Arg(desc = "The pattern of blocks to place") + Pattern pattern) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); session.setTool(itemStack.getType(), new BlockReplacer(pattern)); player.print("Block replacer tool bound to " + itemStack.getType().getName() + "."); } @Command( - aliases = { "cycler" }, - usage = "", - desc = "Block data cycler tool", - min = 0, - max = 0 + name = "cycler", + desc = "Block data cycler tool" ) @CommandPermissions("worldedit.tool.data-cycler") public void cycler(Player player, LocalSession session) throws WorldEditException { @@ -131,14 +113,16 @@ public class ToolCommands { } @Command( - aliases = { "floodfill", "flood" }, - usage = " ", - desc = "Flood fill tool", - min = 2, - max = 2 + name = "floodfill", + aliases = { "flood" }, + desc = "Flood fill tool" ) @CommandPermissions("worldedit.tool.flood-fill") - public void floodFill(Player player, LocalSession session, Pattern pattern, int range) throws WorldEditException { + public void floodFill(Player player, LocalSession session, + @Arg(desc = "The pattern to flood fill") + Pattern pattern, + @Arg(desc = "The range to perform the fill") + int range) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -153,11 +137,8 @@ public class ToolCommands { } @Command( - aliases = { "deltree" }, - usage = "", - desc = "Floating tree remover tool", - min = 0, - max = 0 + name = "deltree", + desc = "Floating tree remover tool" ) @CommandPermissions("worldedit.tool.deltree") public void deltree(Player player, LocalSession session) throws WorldEditException { @@ -169,11 +150,8 @@ public class ToolCommands { } @Command( - aliases = { "farwand" }, - usage = "", - desc = "Wand at a distance tool", - min = 0, - max = 0 + name = "farwand", + desc = "Wand at a distance tool" ) @CommandPermissions("worldedit.tool.farwand") public void farwand(Player player, LocalSession session) throws WorldEditException { @@ -184,14 +162,16 @@ public class ToolCommands { } @Command( - aliases = { "lrbuild", "/lrbuild" }, - usage = " ", - desc = "Long-range building tool", - min = 2, - max = 2 + name = "lrbuild", + aliases = { "/lrbuild" }, + desc = "Long-range building tool" ) @CommandPermissions("worldedit.tool.lrbuild") - public void longrangebuildtool(Player player, LocalSession session, Pattern secondary, Pattern primary) throws WorldEditException { + public void longrangebuildtool(Player player, LocalSession session, + @Arg(desc = "Block to set on left-click") + Pattern primary, + @Arg(desc = "Block to set on right-click") + Pattern secondary) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); session.setTool(itemStack.getType(), new LongRangeBuildTool(primary, secondary)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java index df1637880..6f53cc1bf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java @@ -19,21 +19,23 @@ package com.sk89q.worldedit.command; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +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.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.HandSide; -import com.sk89q.worldedit.util.command.parametric.Optional; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; /** * Tool commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class ToolUtilCommands { private final WorldEdit we; @@ -42,44 +44,37 @@ public class ToolUtilCommands { } @Command( - aliases = { "/", "," }, - usage = "[on|off]", - desc = "Toggle the super pickaxe function", - min = 0, - max = 1 + name = "/", + aliases = { "," }, + desc = "Toggle the super pickaxe function" ) @CommandPermissions("worldedit.superpickaxe") - public void togglePickaxe(Player player, LocalSession session, CommandContext args) throws WorldEditException { - - String newState = args.getString(0, null); - if (session.hasSuperPickAxe()) { - if ("on".equals(newState)) { - player.printError("Super pick axe already enabled."); - return; - } - + public void togglePickaxe(Player player, LocalSession session, + @Arg(desc = "The new super pickaxe state", def = "") + Boolean superPickaxe) throws WorldEditException { + boolean hasSuperPickAxe = session.hasSuperPickAxe(); + if (superPickaxe != null && superPickaxe == hasSuperPickAxe) { + player.printError("Super pickaxe already " + (superPickaxe ? "enabled" : "disabled") + "."); + return; + } + if (hasSuperPickAxe) { session.disableSuperPickAxe(); - player.print("Super pick axe disabled."); + player.print("Super pickaxe disabled."); } else { - if ("off".equals(newState)) { - player.printError("Super pick axe already disabled."); - return; - } session.enableSuperPickAxe(); - player.print("Super pick axe enabled."); + player.print("Super pickaxe enabled."); } } @Command( - aliases = { "mask" }, - usage = "[mask]", - desc = "Set the brush mask", - min = 0, - max = -1 + name = "mask", + desc = "Set the brush mask" ) @CommandPermissions("worldedit.brush.options.mask") - public void mask(Player player, LocalSession session, @Optional Mask mask) throws WorldEditException { + public void mask(Player player, LocalSession session, + @Arg(desc = "The mask to set", def = "") + Mask mask) throws WorldEditException { if (mask == null) { session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setMask(null); player.print("Brush mask disabled."); @@ -90,46 +85,41 @@ public class ToolUtilCommands { } @Command( - aliases = { "mat", "material" }, - usage = "[pattern]", - desc = "Set the brush material", - min = 1, - max = 1 + name = "material", + aliases = { "material" }, + desc = "Set the brush material" ) @CommandPermissions("worldedit.brush.options.material") - public void material(Player player, LocalSession session, Pattern pattern) throws WorldEditException { + public void material(Player player, LocalSession session, + @Arg(desc = "The pattern of blocks to use") + Pattern pattern) throws WorldEditException { session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setFill(pattern); player.print("Brush material set."); } @Command( - aliases = { "range" }, - usage = "[pattern]", - desc = "Set the brush range", - min = 1, - max = 1 - ) + name = "range", + desc = "Set the brush range" + ) @CommandPermissions("worldedit.brush.options.range") - public void range(Player player, LocalSession session, CommandContext args) throws WorldEditException { - int range = args.getInteger(0); + public void range(Player player, LocalSession session, + @Arg(desc = "The range of the brush") + int range) throws WorldEditException { session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setRange(range); player.print("Brush range set."); } @Command( - aliases = { "size" }, - usage = "[pattern]", - desc = "Set the brush size", - min = 1, - max = 1 + name = "size", + desc = "Set the brush size" ) @CommandPermissions("worldedit.brush.options.size") - public void size(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void size(Player player, LocalSession session, + @Arg(desc = "The size of the brush") + int size) throws WorldEditException { + we.checkMaxBrushRadius(size); - int radius = args.getInteger(0); - we.checkMaxBrushRadius(radius); - - session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setSize(radius); + session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setSize(size); player.print("Brush size set."); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java new file mode 100644 index 000000000..fccc6a932 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java @@ -0,0 +1,65 @@ +/* + * 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.google.common.collect.ImmutableSortedSet; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +public class BooleanConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(Boolean.class), new BooleanConverter()); + } + + private static final ImmutableSortedSet TRUE = ImmutableSortedSet + .orderedBy(String.CASE_INSENSITIVE_ORDER) + .add("on", "t", "true", "y", "yes") + .build(); + + private static final ImmutableSortedSet FALSE = ImmutableSortedSet + .orderedBy(String.CASE_INSENSITIVE_ORDER) + .add("off", "f", "false", "n", "no") + .build(); + + private BooleanConverter() { + } + + @Override + public String describeAcceptableArguments() { + return "on|off|true|false"; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + if (TRUE.contains(argument)) { + return SuccessfulConversion.fromSingle(true); + } + if (FALSE.contains(argument)) { + return SuccessfulConversion.fromSingle(false); + } + return FailedConversion.from(new IllegalArgumentException("Not a strictly boolean value: " + argument)); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java index a5fab7da3..cb91c31a6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java @@ -20,7 +20,10 @@ package com.sk89q.worldedit.command.argument; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.util.TreeGenerator; import org.enginehub.piston.CommandManager; import org.enginehub.piston.converter.ArgumentConverter; import org.enginehub.piston.converter.ConversionResult; @@ -31,34 +34,74 @@ import org.enginehub.piston.inject.Key; import javax.annotation.Nullable; import java.util.EnumSet; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.stream.Collectors.joining; public class EnumConverter> implements ArgumentConverter { public static void register(CommandManager commandManager) { commandManager.registerConverter(Key.of(SelectorChoice.class), - new EnumConverter<>(SelectorChoice.class, SelectorChoice.UNKNOWN)); + basic(SelectorChoice.class, SelectorChoice.UNKNOWN)); + commandManager.registerConverter(Key.of(TreeGenerator.TreeType.class), + full(TreeGenerator.TreeType.class, + t -> ImmutableSet.copyOf(t.lookupKeys), + null)); + commandManager.registerConverter(Key.of(EditSession.ReorderMode.class), + full(EditSession.ReorderMode.class, + r -> ImmutableSet.of(r.getDisplayName()), + null)); } + private static > EnumConverter basic(Class enumClass) { + return full(enumClass, e -> ImmutableSet.of(e.name()), null); + } + + private static > EnumConverter basic(Class enumClass, E unknownValue) { + return full(enumClass, e -> ImmutableSet.of(e.name()), unknownValue); + } + + private static > EnumConverter full(Class enumClass, + Function> lookupKeys, + @Nullable E unknownValue) { + return new EnumConverter<>(enumClass, lookupKeys, unknownValue); + } + + private final String choices; private final ImmutableMap map; @Nullable private final E unknownValue; - private EnumConverter(Class enumClass, @Nullable E unknownValue) { + private EnumConverter(Class enumClass, + Function> lookupKeys, + @Nullable E unknownValue) { ImmutableSortedMap.Builder map = ImmutableSortedMap.orderedBy(String.CASE_INSENSITIVE_ORDER); + Stream.Builder> choices = Stream.builder(); EnumSet validValues = EnumSet.allOf(enumClass); if (unknownValue != null) { validValues.remove(unknownValue); } for (E e : validValues) { - map.put(e.name(), e); + Set keys = lookupKeys.apply(e); + checkState(keys.size() > 0, "No lookup keys for enum value %s", e); + choices.add(keys); + for (String key : keys) { + map.put(key, e); + } } + this.choices = choices.build() + .map(choice -> choice.stream().collect(joining("|", "[", "]"))) + .collect(joining("|")); this.map = map.build(); this.unknownValue = unknownValue; } @Override public String describeAcceptableArguments() { - return String.join("|", map.keySet()); + return choices; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index b6c2b6c89..016500666 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -56,7 +56,12 @@ import com.sk89q.worldedit.command.SnapshotUtilCommands; 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.argument.Arguments; +import com.sk89q.worldedit.command.argument.BooleanConverter; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; import com.sk89q.worldedit.command.argument.EnumConverter; @@ -209,6 +214,7 @@ public final class PlatformCommandMananger { EnumConverter.register(commandManager); ExpandAmountConverter.register(commandManager); ZonedDateTimeConverter.register(commandManager); + BooleanConverter.register(commandManager); } private void registerAlwaysInjectedValues() { @@ -367,14 +373,22 @@ public final class PlatformCommandMananger { SnapshotUtilCommandsRegistration.builder(), new SnapshotUtilCommands(worldEdit) ); + register( + commandManager, + ToolCommandsRegistration.builder(), + new ToolCommands(worldEdit) + ); + register( + commandManager, + ToolUtilCommandsRegistration.builder(), + new ToolUtilCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new ToolUtilCommands(worldEdit)) - .registerMethods(new ToolCommands(worldEdit)) .registerMethods(new UtilityCommands(worldEdit)) .register(adapt(new SelectionCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within selection"), "worldedit.region.set")), "/set") .group("worldedit", "we") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java index 60e5f12f3..1bd79f2ff 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.util; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; @@ -113,22 +114,22 @@ public class TreeGenerator { private static final Set primaryAliases = Sets.newHashSet(); private final String name; - private final String[] lookupKeys; + public final ImmutableList lookupKeys; static { for (TreeType type : EnumSet.allOf(TreeType.class)) { for (String key : type.lookupKeys) { lookup.put(key, type); } - if (type.lookupKeys.length > 0) { - primaryAliases.add(type.lookupKeys[0]); + if (type.lookupKeys.size() > 0) { + primaryAliases.add(type.lookupKeys.get(0)); } } } TreeType(String name, String... lookupKeys) { this.name = name; - this.lookupKeys = lookupKeys; + this.lookupKeys = ImmutableList.copyOf(lookupKeys); } public static Set getAliases() { From c05e1ed0cc7f16ac9fad486fb34cd226eb8cd830 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 13:30:16 -0700 Subject: [PATCH 26/57] Fix a few bugs in tool commands --- .../java/com/sk89q/worldedit/command/ToolUtilCommands.java | 2 +- .../src/main/java/com/sk89q/worldedit/util/TreeGenerator.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java index 6f53cc1bf..e053eccb8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java @@ -86,7 +86,7 @@ public class ToolUtilCommands { @Command( name = "material", - aliases = { "material" }, + aliases = { "/material" }, desc = "Set the brush material" ) @CommandPermissions("worldedit.brush.options.material") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java index 1bd79f2ff..d4845c5b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/TreeGenerator.java @@ -65,8 +65,8 @@ public class TreeGenerator { } }, JUNGLE("Jungle tree", "jungle"), - SMALL_JUNGLE("Small jungle tree", "shortjungle", "smalljungle"), - SHORT_JUNGLE("Short jungle tree") { + SMALL_JUNGLE("Small jungle tree", "smalljungle"), + SHORT_JUNGLE("Short jungle tree", "shortjungle") { @Override public boolean generate(EditSession editSession, BlockVector3 pos) throws MaxChangedBlocksException { return SMALL_JUNGLE.generate(editSession, pos); From 9b0fda9f83d7310696d9926408e7d06b0c98e3ca Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 19:36:22 -0700 Subject: [PATCH 27/57] Port utility commands --- .../java/com/sk89q/worldedit/EditSession.java | 6 +- .../worldedit/command/UtilityCommands.java | 706 +++++++----------- .../worldedit/command/WorldEditCommands.java | 1 - .../argument/EntityRemoverConverter.java | 53 ++ .../worldedit/command/util/EntityRemover.java | 20 +- .../command/util/PrintCommandHelp.java | 160 ++++ .../platform/PlatformCommandMananger.java | 21 +- .../worldedit/util/command/CommandUtil.java | 53 ++ .../formatting/component/CommandUsageBox.java | 67 +- 9 files changed, 574 insertions(+), 513 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EntityRemoverConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index a831c10b8..43843e8a3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -122,7 +122,6 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import static com.google.common.base.Preconditions.checkArgument; @@ -905,16 +904,15 @@ public class EditSession implements Extent, AutoCloseable { * Remove blocks of a certain type nearby a given position. * * @param position center position of cuboid - * @param blockType the block type to match + * @param mask the mask to match * @param apothem an apothem of the cuboid, where the minimum is 1 * @return number of blocks affected * @throws MaxChangedBlocksException thrown if too many blocks are changed */ - public int removeNear(BlockVector3 position, BlockType blockType, int apothem) throws MaxChangedBlocksException { + public int removeNear(BlockVector3 position, Mask mask, int apothem) throws MaxChangedBlocksException { checkNotNull(position); checkArgument(apothem >= 1, "apothem >= 1"); - Mask mask = new BlockTypeMask(this, blockType); BlockVector3 adjustment = BlockVector3.ONE.multiply(apothem - 1); Region region = new CuboidRegion( getWorld(), // Causes clamping of Y range 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 4d69452b2..d6f916bd9 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 @@ -19,28 +19,29 @@ package com.sk89q.worldedit.command; -import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.command.util.EntityRemover; import com.sk89q.worldedit.command.util.Logging; +import com.sk89q.worldedit.command.util.PrintCommandHelp; import com.sk89q.worldedit.entity.Entity; 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.Platform; +import com.sk89q.worldedit.function.EntityFunction; +import com.sk89q.worldedit.function.mask.BlockTypeMask; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operations; -import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.visitor.EntityVisitor; import com.sk89q.worldedit.internal.expression.Expression; @@ -50,22 +51,23 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.session.SessionOwner; -import com.sk89q.worldedit.util.command.CommandMapping; -import com.sk89q.worldedit.util.command.Dispatcher; -import com.sk89q.worldedit.util.command.binding.Text; 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 org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; import java.util.ArrayList; import java.util.List; -import java.util.Set; +import java.util.function.Supplier; + +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; /** * Utility commands. */ +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class UtilityCommands { private final WorldEdit we; @@ -75,357 +77,370 @@ public class UtilityCommands { } @Command( - aliases = { "/fill" }, - usage = " [depth]", - desc = "Fill a hole", - min = 2, - max = 3 + name = "/fill", + desc = "Fill a hole" ) @CommandPermissions("worldedit.fill") @Logging(PLACEMENT) - public void fill(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - ParserContext context = new ParserContext(); - context.setActor(player); - context.setWorld(player.getWorld()); - context.setSession(session); - Pattern pattern = we.getPatternFactory().parseFromInput(args.getString(0), context); - - double radius = Math.max(1, args.getDouble(1)); + public int fill(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The blocks to fill with") + Pattern pattern, + @Arg(desc = "The radius to fill in") + double radius, + @Arg(desc = "The depth to fill", def = "1") + int depth) throws WorldEditException { + radius = Math.max(1, radius); we.checkMaxRadius(radius); - int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : 1; + depth = Math.max(1, depth); BlockVector3 pos = session.getPlacementPosition(player); int affected = editSession.fillXZ(pos, pattern, radius, depth, false); player.print(affected + " block(s) have been created."); + return affected; } @Command( - aliases = { "/fillr" }, - usage = " [depth]", - desc = "Fill a hole recursively", - min = 2, - max = 3 + name = "/fillr", + desc = "Fill a hole recursively" ) @CommandPermissions("worldedit.fill.recursive") @Logging(PLACEMENT) - public void fillr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - ParserContext context = new ParserContext(); - context.setActor(player); - context.setWorld(player.getWorld()); - context.setSession(session); - Pattern pattern = we.getPatternFactory().parseFromInput(args.getString(0), context); - - double radius = Math.max(1, args.getDouble(1)); + public int fillr(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The blocks to fill with") + Pattern pattern, + @Arg(desc = "The radius to fill in") + double radius, + @Arg(desc = "The depth to fill", def = "") + Integer depth) throws WorldEditException { + radius = Math.max(1, radius); + we.checkMaxRadius(radius); + depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth); we.checkMaxRadius(radius); - int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE; BlockVector3 pos = session.getPlacementPosition(player); - int affected = 0; - if (pattern instanceof BlockPattern) { - affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, depth, true); - } else { - affected = editSession.fillXZ(pos, pattern, radius, depth, true); - } + int affected = editSession.fillXZ(pos, pattern, radius, depth, true); player.print(affected + " block(s) have been created."); + return affected; } @Command( - aliases = { "/drain" }, - usage = "", - flags = "w", - desc = "Drain a pool", - help = "Removes all connected water sources.\n" + - " If -w is specified, also makes waterlogged blocks non-waterlogged.", - min = 1, - max = 1 + name = "/drain", + desc = "Drain a pool" ) @CommandPermissions("worldedit.drain") @Logging(PLACEMENT) - public void drain(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - double radius = Math.max(0, args.getDouble(0)); - boolean waterlogged = args.hasFlag('w'); + public int drain(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius to drain") + double radius, + @Switch(name = 'w', desc = "Also un-waterlog blocks") + boolean waterlogged) throws WorldEditException { + radius = Math.max(0, radius); we.checkMaxRadius(radius); int affected = editSession.drainArea( - session.getPlacementPosition(player), radius, waterlogged); + session.getPlacementPosition(player), radius, waterlogged); player.print(affected + " block(s) have been changed."); + return affected; } @Command( - aliases = { "/fixlava", "fixlava" }, - usage = "", - desc = "Fix lava to be stationary", - min = 1, - max = 1 + name = "fixlava", + aliases = { "/fixlava" }, + desc = "Fix lava to be stationary" ) @CommandPermissions("worldedit.fixlava") @Logging(PLACEMENT) - public void fixLava(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - double radius = Math.max(0, args.getDouble(0)); + public int fixLava(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius to fix in") + double radius) throws WorldEditException { + radius = Math.max(0, radius); we.checkMaxRadius(radius); int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.LAVA); player.print(affected + " block(s) have been changed."); + return affected; } @Command( - aliases = { "/fixwater", "fixwater" }, - usage = "", - desc = "Fix water to be stationary", - min = 1, - max = 1 + name = "fixwater", + aliases = { "/fixwater" }, + desc = "Fix water to be stationary" ) @CommandPermissions("worldedit.fixwater") @Logging(PLACEMENT) - public void fixWater(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - double radius = Math.max(0, args.getDouble(0)); + public int fixWater(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius to fix in") + double radius) throws WorldEditException { + radius = Math.max(0, radius); we.checkMaxRadius(radius); int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.WATER); player.print(affected + " block(s) have been changed."); + return affected; } @Command( - aliases = { "/removeabove", "removeabove" }, - usage = "[size] [height]", - desc = "Remove blocks above your head.", - min = 0, - max = 2 + name = "removeabove", + aliases = { "/removeabove" }, + desc = "Remove blocks above your head." ) @CommandPermissions("worldedit.removeabove") @Logging(PLACEMENT) - public void removeAbove(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1; + public int removeAbove(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The apothem of the square to remove from", def = "1") + int size, + @Arg(desc = "The maximum height above you to remove from", def = "") + Integer height) throws WorldEditException { + size = Math.max(1, size); we.checkMaxRadius(size); World world = player.getWorld(); - int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1); + height = height != null ? Math.min((world.getMaxY() + 1), height + 2) : (world.getMaxY() + 1); int affected = editSession.removeAbove( - session.getPlacementPosition(player), size, height); + session.getPlacementPosition(player), size, height); player.print(affected + " block(s) have been removed."); + return affected; } @Command( - aliases = { "/removebelow", "removebelow" }, - usage = "[size] [height]", - desc = "Remove blocks below you.", - min = 0, - max = 2 + name = "removebelow", + aliases = { "/removebelow" }, + desc = "Remove blocks below you." ) @CommandPermissions("worldedit.removebelow") @Logging(PLACEMENT) - public void removeBelow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1; + public int removeBelow(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The apothem of the square to remove from", def = "1") + int size, + @Arg(desc = "The maximum height below you to remove from", def = "") + Integer height) throws WorldEditException { + size = Math.max(1, size); we.checkMaxRadius(size); World world = player.getWorld(); - int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1); + height = height != null ? Math.min((-world.getMaxY() + 1), height + 2) : (world.getMaxY() + 1); int affected = editSession.removeBelow(session.getPlacementPosition(player), size, height); player.print(affected + " block(s) have been removed."); + return affected; } @Command( - aliases = { "/removenear", "removenear" }, - usage = " [size]", - desc = "Remove blocks near you.", - min = 1, - max = 2 + name = "removenear", + aliases = { "/removenear" }, + desc = "Remove blocks near you." ) @CommandPermissions("worldedit.removenear") @Logging(PLACEMENT) - public void removeNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { + public int removeNear(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The mask of blocks to remove") + Mask mask, + @Arg(desc = "The radius of the square to remove from", def = "50") + int radius) throws WorldEditException { + radius = Math.max(1, radius); + we.checkMaxRadius(radius); - ParserContext context = new ParserContext(); - context.setActor(player); - context.setWorld(player.getWorld()); - context.setSession(session); - context.setRestricted(false); - context.setPreferringWildcard(false); - - BaseBlock block = we.getBlockFactory().parseFromInput(args.getString(0), context); - int size = Math.max(1, args.getInteger(1, 50)); - we.checkMaxRadius(size); - - int affected = editSession.removeNear(session.getPlacementPosition(player), block.getBlockType(), size); + int affected = editSession.removeNear(session.getPlacementPosition(player), mask, radius); player.print(affected + " block(s) have been removed."); + return affected; } @Command( - aliases = { "/replacenear", "replacenear" }, - usage = " ", - desc = "Replace nearby blocks", - flags = "f", - min = 3, - max = 3 + name = "replacenear", + aliases = { "/replacenear" }, + desc = "Replace nearby blocks" ) @CommandPermissions("worldedit.replacenear") @Logging(PLACEMENT) - public void replaceNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - int size = Math.max(1, args.getInteger(0)); - we.checkMaxRadius(size); - int affected; - Set from; - Pattern to; - - ParserContext context = new ParserContext(); - context.setActor(player); - context.setWorld(player.getWorld()); - context.setSession(session); - context.setRestricted(false); - context.setPreferringWildcard(!args.hasFlag('f')); - - if (args.argsLength() == 2) { - from = null; - context.setRestricted(true); - to = we.getPatternFactory().parseFromInput(args.getString(1), context); - } else { - from = we.getBlockFactory().parseFromListInput(args.getString(1), context); - context.setRestricted(true); - to = we.getPatternFactory().parseFromInput(args.getString(2), context); - } + public int replaceNear(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius of the square to remove in") + int radius, + @Arg(desc = "The mask matching blocks to remove", def = "") + Mask from, + @Arg(desc = "The pattern of blocks to replace with") + Pattern to) throws WorldEditException { + radius = Math.max(1, radius); + we.checkMaxRadius(radius); BlockVector3 base = session.getPlacementPosition(player); - BlockVector3 min = base.subtract(size, size, size); - BlockVector3 max = base.add(size, size, size); + BlockVector3 min = base.subtract(radius, radius, radius); + BlockVector3 max = base.add(radius, radius, radius); Region region = new CuboidRegion(player.getWorld(), min, max); - if (to instanceof BlockPattern) { - affected = editSession.replaceBlocks(region, from, ((BlockPattern) to).getBlock()); - } else { - affected = editSession.replaceBlocks(region, from, to); + if (from == null) { + from = new ExistingBlockMask(editSession); } + + int affected = editSession.replaceBlocks(region, from, to); player.print(affected + " block(s) have been replaced."); + return affected; } @Command( - aliases = { "/snow", "snow" }, - usage = "[radius]", - desc = "Simulates snow", - min = 0, - max = 1 + name = "snow", + aliases = { "/snow" }, + desc = "Simulates snow" ) @CommandPermissions("worldedit.snow") @Logging(PLACEMENT) - public void snow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10; + public int snow(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius of the circle to snow in", def = "10") + double size) throws WorldEditException { + size = Math.max(1, size); we.checkMaxRadius(size); int affected = editSession.simulateSnow(session.getPlacementPosition(player), size); - player.print(affected + " surfaces covered. Let it snow~"); + player.print(affected + " surface(s) covered. Let it snow~"); + return affected; } @Command( - aliases = {"/thaw", "thaw"}, - usage = "[radius]", - desc = "Thaws the area", - min = 0, - max = 1 + name = "thaw", + aliases = { "/thaw" }, + desc = "Thaws the area" ) @CommandPermissions("worldedit.thaw") @Logging(PLACEMENT) - public void thaw(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10; + public int thaw(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius of the circle to thaw in", def = "10") + double size) throws WorldEditException { + size = Math.max(1, size); we.checkMaxRadius(size); int affected = editSession.thaw(session.getPlacementPosition(player), size); - player.print(affected + " surfaces thawed."); + player.print(affected + " surface(s) thawed."); + return affected; } @Command( - aliases = { "/green", "green" }, - usage = "[radius]", - desc = "Greens the area", - help = "Converts dirt to grass blocks. -f also converts coarse dirt.", - flags = "f", - min = 0, - max = 1 + name = "green", + aliases = { "/green" }, + desc = "Converts dirt to grass blocks in the area" ) @CommandPermissions("worldedit.green") @Logging(PLACEMENT) - public void green(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - final double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10; + public int green(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius of the circle to convert in", def = "10") + double size, + @Switch(name = 'f', desc = "Also convert coarse dirt") + boolean convertCoarse) throws WorldEditException { + size = Math.max(1, size); we.checkMaxRadius(size); - final boolean onlyNormalDirt = !args.hasFlag('f'); + final boolean onlyNormalDirt = !convertCoarse; final int affected = editSession.green(session.getPlacementPosition(player), size, onlyNormalDirt); - player.print(affected + " surfaces greened."); + player.print(affected + " surface(s) greened."); + return affected; } @Command( - aliases = { "/ex", "/ext", "/extinguish", "ex", "ext", "extinguish" }, - usage = "[radius]", - desc = "Extinguish nearby fire", - min = 0, - max = 1 - ) + name = "extinguish", + aliases = { "/ex", "/ext", "/extinguish", "ex", "ext" }, + desc = "Extinguish nearby fire" + ) @CommandPermissions("worldedit.extinguish") @Logging(PLACEMENT) - public void extinguish(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { + public void extinguish(Player player, LocalSession session, EditSession editSession, + @Arg(desc = "The radius of the square to remove in", def = "") + Integer radius) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40; - int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) - : defaultRadius; + int size = radius != null ? Math.max(1, radius) : defaultRadius; we.checkMaxRadius(size); - int affected = editSession.removeNear(session.getPlacementPosition(player), BlockTypes.FIRE, size); + Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE); + int affected = editSession.removeNear(session.getPlacementPosition(player), mask, size); player.print(affected + " block(s) have been removed."); } @Command( - aliases = { "butcher" }, - usage = "[radius]", - flags = "plangbtfr", - desc = "Kill all or nearby mobs", - help = - "Kills nearby mobs, based on radius, if none is given uses default in configuration.\n" + - "Flags:\n" + - " -p also kills pets.\n" + - " -n also kills NPCs.\n" + - " -g also kills Golems.\n" + - " -a also kills animals.\n" + - " -b also kills ambient mobs.\n" + - " -t also kills mobs with name tags.\n" + - " -f compounds all previous flags.\n" + - " -r also destroys armor stands.\n" + - " -l currently does nothing.", - min = 0, - max = 1 + name = "butcher", + desc = "Kill all or nearby mobs" ) @CommandPermissions("worldedit.butcher") @Logging(PLACEMENT) - public void butcher(Actor actor, CommandContext args) throws WorldEditException { + public int butcher(Actor actor, + @Arg(desc = "Radius to kill mobs in", def = "") + Integer radius, + @Switch(name = 'p', desc = "Also kill pets") + boolean killPets, + @Switch(name = 'n', desc = "Also kill NPCs") + boolean killNpcs, + @Switch(name = 'g', desc = "Also kill golems") + boolean killGolems, + @Switch(name = 'a', desc = "Also kill animals") + boolean killAnimals, + @Switch(name = 'b', desc = "Also kill ambient mobs") + boolean killAmbient, + @Switch(name = 't', desc = "Also kill mobs with name tags") + boolean killWithName, + @Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)") + boolean killFriendly, + @Switch(name = 'r', desc = "Also destroy armor stands") + boolean killArmorStands, + @Switch(name = 'l', desc = "Kill via lightning. Currently non-functioning.") + boolean killWithLightning) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); Player player = actor instanceof Player ? (Player) actor : null; - // technically the default can be larger than the max, but that's not my problem - int radius = config.butcherDefaultRadius; - - // there might be a better way to do this but my brain is fried right now - if (args.argsLength() > 0) { // user inputted radius, override the default - radius = args.getInteger(0); - if (radius < -1) { - actor.printError("Use -1 to remove all mobs in loaded chunks"); - return; - } - if (config.butcherMaxRadius != -1) { // clamp if there is a max - if (radius == -1) { - radius = config.butcherMaxRadius; - } else { // Math.min does not work if radius is -1 (actually highest possible value) - radius = Math.min(radius, config.butcherMaxRadius); - } + int defaultRadius = config.butcherDefaultRadius; + if (radius == null) { + radius = config.butcherDefaultRadius; + } else if (radius < -1) { + actor.printError("Use -1 to remove all mobs in loaded chunks"); + return 0; + } else if (radius == -1) { + if (config.butcherMaxRadius != -1) { + radius = config.butcherMaxRadius; } } + if (config.butcherMaxRadius != -1) { + radius = Math.min(radius, config.butcherMaxRadius); + } CreatureButcher flags = new CreatureButcher(actor); - flags.fromCommand(args); + flags.or(CreatureButcher.Flags.FRIENDLY, killFriendly); // No permission check here. Flags will instead be filtered by the subsequent calls. + flags.or(CreatureButcher.Flags.PETS, killPets, "worldedit.butcher.pets"); + flags.or(CreatureButcher.Flags.NPCS, killNpcs, "worldedit.butcher.npcs"); + flags.or(CreatureButcher.Flags.GOLEMS, killGolems, "worldedit.butcher.golems"); + flags.or(CreatureButcher.Flags.ANIMALS, killAnimals, "worldedit.butcher.animals"); + flags.or(CreatureButcher.Flags.AMBIENT, killAmbient, "worldedit.butcher.ambient"); + flags.or(CreatureButcher.Flags.TAGGED, killWithName, "worldedit.butcher.tagged"); + flags.or(CreatureButcher.Flags.ARMOR_STAND, killArmorStands, "worldedit.butcher.armorstands"); + flags.or(CreatureButcher.Flags.WITH_LIGHTNING, killWithLightning, "worldedit.butcher.lightning"); + + int killed = killMatchingEntities(radius, player, flags::createFunction); + + actor.print("Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + "."); + + return killed; + } + + @Command( + name = "remove", + aliases = { "rem", "rement" }, + desc = "Remove all entities of a type" + ) + @CommandPermissions("worldedit.remove") + @Logging(PLACEMENT) + public int remove(Actor actor, + @Arg(desc = "The type of entity to remove") + EntityRemover remover, + @Arg(desc = "The radius of the cuboid to remove from") + int radius) throws WorldEditException { + Player player = actor instanceof Player ? (Player) actor : null; + + if (radius < -1) { + actor.printError("Use -1 to remove all entities in loaded chunks"); + return 0; + } + + int removed = killMatchingEntities(radius, player, remover::createFunction); + + actor.print("Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal."); + return removed; + } + + private int killMatchingEntities(Integer radius, Player player, Supplier func) throws IncompleteRegionException, MaxChangedBlocksException { List visitors = new ArrayList<>(); LocalSession session = null; EditSession editSession = null; @@ -441,12 +456,12 @@ public class UtilityCommands { } else { entities = editSession.getEntities(); } - visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction())); + visitors.add(new EntityVisitor(entities.iterator(), func.get())); } else { Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING); for (World world : platform.getWorlds()) { List entities = world.getEntities(); - visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction())); + visitors.add(new EntityVisitor(entities.iterator(), func.get())); } } @@ -456,246 +471,47 @@ public class UtilityCommands { killed += visitor.getAffected(); } - actor.print("Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + "."); - if (editSession != null) { session.remember(editSession); editSession.flushSession(); } + return killed; } @Command( - aliases = { "remove", "rem", "rement" }, - usage = " ", - desc = "Remove all entities of a type", - min = 2, - max = 2 - ) - @CommandPermissions("worldedit.remove") - @Logging(PLACEMENT) - public void remove(Actor actor, CommandContext args) throws WorldEditException, CommandException { - String typeStr = args.getString(0); - int radius = args.getInteger(1); - Player player = actor instanceof Player ? (Player) actor : null; - - if (radius < -1) { - actor.printError("Use -1 to remove all entities in loaded chunks"); - return; - } - - EntityRemover remover = new EntityRemover(); - remover.fromString(typeStr); - - List visitors = new ArrayList<>(); - LocalSession session = null; - EditSession editSession = null; - - if (player != null) { - session = we.getSessionManager().get(player); - BlockVector3 center = session.getPlacementPosition(player); - editSession = session.createEditSession(player); - List entities; - if (radius >= 0) { - CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius); - entities = editSession.getEntities(region); - } else { - entities = editSession.getEntities(); - } - visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction())); - } else { - Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING); - for (World world : platform.getWorlds()) { - List entities = world.getEntities(); - visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction())); - } - } - - int removed = 0; - for (EntityVisitor visitor : visitors) { - Operations.completeLegacy(visitor); - removed += visitor.getAffected(); - } - - actor.print("Marked " + removed + (removed != 1 ? " entities" : " entity") + " for removal."); - - if (editSession != null) { - session.remember(editSession); - editSession.flushSession(); - } - } - - @Command( - aliases = { "/calc", "/calculate", "/eval", "/evaluate", "/solve" }, - usage = "", + name = "/calculate", + aliases = { "/calc", "/eval", "/evaluate", "/solve" }, desc = "Evaluate a mathematical expression" ) @CommandPermissions("worldedit.calc") - public void calc(Actor actor, @Text String input) throws CommandException { + public void calc(Actor actor, + @Arg(desc = "Expression to evaluate") + String input) { try { Expression expression = Expression.compile(input); - if (actor instanceof SessionOwner) { - actor.print("= " + expression.evaluate( - new double[]{}, WorldEdit.getInstance().getSessionManager().get((SessionOwner) actor).getTimeout())); - } else { - actor.print("= " + expression.evaluate()); - } + actor.print("= " + expression.evaluate( + new double[] {}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout())); } catch (EvaluationException e) { actor.printError(String.format( - "'%s' could not be evaluated (error: %s)", input, e.getMessage())); + "'%s' could not be evaluated (error: %s)", input, e.getMessage())); } catch (ExpressionException e) { actor.printError(String.format( - "'%s' could not be parsed as a valid expression", input)); + "'%s' could not be parsed as a valid expression", input)); } } @Command( - aliases = { "/help" }, - usage = "[]", - desc = "Displays help for WorldEdit commands", - min = 0, - max = -1 + name = "/help", + desc = "Displays help for WorldEdit commands" ) @CommandPermissions("worldedit.help") - public void help(Actor actor, CommandContext args) throws WorldEditException { - help(args, we, actor); + public void help(Actor actor, + @Arg(desc = "The page to retrieve", def = "1") + int page, + @Arg(desc = "The command to retrieve help for", def = "", variable = true) + List commandPath) throws WorldEditException { + PrintCommandHelp.help(commandPath, page, we, actor); } - private static CommandMapping detectCommand(Dispatcher dispatcher, String command, boolean isRootLevel) { - CommandMapping mapping; - - // First try the command as entered - mapping = dispatcher.get(command); - if (mapping != null) { - return mapping; - } - - // Then if we're looking at root commands and the user didn't use - // any slashes, let's try double slashes and then single slashes. - // However, be aware that there exists different single slash - // and double slash commands in WorldEdit - if (isRootLevel && !command.contains("/")) { - mapping = dispatcher.get("//" + command); - if (mapping != null) { - return mapping; - } - - mapping = dispatcher.get("/" + command); - if (mapping != null) { - return mapping; - } - } - - return null; - } - - public static void help(CommandContext args, WorldEdit we, Actor actor) { - 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 - int effectiveLength = args.argsLength(); - - // Detect page from args - try { - if (args.argsLength() > 0) { - page = args.getInteger(args.argsLength() - 1); - if (page <= 0) { - page = 1; - } else { - page--; - } - - effectiveLength--; - } - } catch (NumberFormatException ignored) { - } - - boolean isRootLevel = true; - List visited = new ArrayList<>(); - - // Drill down to the command - for (int i = 0; i < effectiveLength; i++) { - String command = args.getString(i); - - 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) manager, command, isRootLevel); - if (mapping != null) { - manager = mapping.getCallable(); - } else { - if (isRootLevel) { - actor.printError(String.format("The command '%s' could not be found.", args.getString(i))); - return; - } else { - actor.printError(String.format("The sub-command '%s' under '%s' could not be found.", - command, Joiner.on(" ").join(visited))); - return; - } - } - - visited.add(args.getString(i)); - isRootLevel = false; - } else { - actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)", - Joiner.on(" ").join(visited), command)); - return; - } - } - - // Create the message - if (manager instanceof Dispatcher) { - Dispatcher dispatcher = (Dispatcher) manager; - - // Get a list of aliases - List aliases = new ArrayList<>(dispatcher.getCommands()); - aliases.sort(new PrimaryAliasComparator(PlatformCommandMananger.COMMAND_CLEAN_PATTERN)); - - // Calculate pagination - int offset = perPage * page; - int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage); - - // Box - CommandListBox box = new CommandListBox(String.format("Help: page %d/%d ", page + 1, pageTotal)); - StyledFragment contents = box.getContents(); - StyledFragment tip = contents.createFragment(Style.GRAY); - - if (offset >= aliases.size()) { - tip.createFragment(Style.RED).append(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal)).newLine(); - } else { - List list = aliases.subList(offset, Math.min(offset + perPage, aliases.size())); - - tip.append("Type "); - tip.append(new Code().append("//help ").append(" []")); - tip.append(" for more information.").newLine(); - - // Add each command - for (CommandMapping mapping : list) { - StringBuilder builder = new StringBuilder(); - if (isRootLevel) { - builder.append("/"); - } - if (!visited.isEmpty()) { - builder.append(Joiner.on(" ").join(visited)); - builder.append(" "); - } - builder.append(mapping.getPrimaryAlias()); - box.appendCommand(builder.toString(), mapping.getDescription().getDescription()); - } - } - - actor.printRaw(ColorCodeBuilder.asColorCodes(box)); - } else { - 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 5378d5819..aee7ba0f7 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 @@ -157,6 +157,5 @@ public class WorldEditCommands { ) @CommandPermissions("worldedit.help") public void help(Actor actor, CommandContext args) throws WorldEditException { - UtilityCommands.help(args, we, actor); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EntityRemoverConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EntityRemoverConverter.java new file mode 100644 index 000000000..03db41b28 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EntityRemoverConverter.java @@ -0,0 +1,53 @@ +/* + * 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.command.util.EntityRemover; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +public class EntityRemoverConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(EntityRemover.class), new EntityRemoverConverter()); + } + + private EntityRemoverConverter() { + } + + @Override + public String describeAcceptableArguments() { + return "projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all"; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + try { + return SuccessfulConversion.fromSingle(EntityRemover.fromString(argument)); + } catch (Exception e) { + return FailedConversion.from(e); + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java index cac57b0dc..516f33945 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java @@ -19,15 +19,13 @@ package com.sk89q.worldedit.command.util; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.worldedit.entity.metadata.EntityProperties; import com.sk89q.worldedit.function.EntityFunction; +import javax.annotation.Nullable; import java.util.regex.Pattern; -import javax.annotation.Nullable; +import static com.google.common.base.Preconditions.checkNotNull; /** * The implementation of /remove. @@ -125,17 +123,21 @@ public class EntityRemover { } } - private Type type; - - public void fromString(String str) throws CommandException { + public static EntityRemover fromString(String str) { Type type = Type.findByPattern(str); if (type != null) { - this.type = type; + return new EntityRemover(type); } else { - throw new CommandException("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all"); + throw new IllegalArgumentException("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all"); } } + private final Type type; + + private EntityRemover(Type type) { + this.type = type; + } + public EntityFunction createFunction() { final Type type = this.type; checkNotNull(type, "type can't be null"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java new file mode 100644 index 000000000..c22880f04 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java @@ -0,0 +1,160 @@ +/* + * 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.common.base.Joiner; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.formatting.ColorCodeBuilder; +import com.sk89q.worldedit.util.formatting.Style; +import com.sk89q.worldedit.util.formatting.StyledFragment; +import com.sk89q.worldedit.util.formatting.component.Code; +import com.sk89q.worldedit.util.formatting.component.CommandListBox; +import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; +import org.enginehub.piston.Command; +import org.enginehub.piston.CommandManager; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +import static com.sk89q.worldedit.util.command.CommandUtil.byCleanName; +import static com.sk89q.worldedit.util.command.CommandUtil.getSubCommands; +import static java.util.stream.Collectors.toList; + +/** + * Implementation of the //help command. + */ +// Stored in a separate class to prevent import conflicts. +public class PrintCommandHelp { + + private static Command detectCommand(CommandManager manager, String command) { + Optional mapping; + + // First try the command as entered + mapping = manager.getCommand(command); + if (mapping.isPresent()) { + return mapping.get(); + } + + // If tried with slashes, try dropping a slash + if (command.startsWith("/")) { + mapping = manager.getCommand(command.substring(1)); + return mapping.orElse(null); + } + + // Otherwise, check /command, since that's common + mapping = manager.getCommand("/" + command); + return mapping.orElse(null); + } + + public static void help(List commandPath, int page, WorldEdit we, Actor actor) { + if (page < 1) { + actor.printError("Page must be >= 1."); + return; + } + CommandManager manager = we.getPlatformManager().getPlatformCommandMananger().getCommandManager(); + + final int perPage = actor instanceof Player ? 8 : 20; // More pages for console + + if (commandPath.isEmpty()) { + printAllCommands(page, perPage, manager.getAllCommands(), actor, true); + return; + } + + List visited = new ArrayList<>(); + Command currentCommand = detectCommand(manager, commandPath.get(0)); + if (currentCommand == null) { + actor.printError(String.format("The command '%s' could not be found.", commandPath.get(0))); + return; + } + visited.add(commandPath.get(0)); + + // Drill down to the command + for (int i = 1; i < commandPath.size(); i++) { + String subCommand = commandPath.get(i); + Map subCommands = getSubCommands(currentCommand); + + if (subCommands.isEmpty()) { + actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)", + Joiner.on(" ").join(visited), subCommand)); + return; + } + + if (subCommands.containsKey(subCommand)) { + visited.add(subCommand); + currentCommand = subCommands.get(subCommand); + } else { + actor.printError(String.format("The sub-command '%s' under '%s' could not be found.", + subCommand, Joiner.on(" ").join(visited))); + return; + } + } + + Map subCommands = getSubCommands(currentCommand); + + if (subCommands.isEmpty()) { + // Create the message + CommandUsageBox box = new CommandUsageBox(currentCommand, String.join(" ", visited)); + actor.printRaw(ColorCodeBuilder.asColorCodes(box)); + } else { + printAllCommands(page, perPage, subCommands.values().stream(), actor, false); + } + } + + private static void printAllCommands(int page, int perPage, Stream commandStream, Actor actor, boolean isRootLevel) { + // Get a list of aliases + List commands = commandStream + .sorted(byCleanName()) + .collect(toList()); + + // Calculate pagination + int offset = perPage * (page - 1); + int pageTotal = (int) Math.ceil(commands.size() / (double) perPage); + + // Box + CommandListBox box = new CommandListBox(String.format("Help: page %d/%d ", page, pageTotal)); + StyledFragment contents = box.getContents(); + StyledFragment tip = contents.createFragment(Style.GRAY); + + if (offset >= commands.size()) { + tip.createFragment(Style.RED).append(String.format("There is no page %d (total number of pages is %d).", page, pageTotal)).newLine(); + } else { + List list = commands.subList(offset, Math.min(offset + perPage, commands.size())); + + tip.append("Type "); + tip.append(new Code().append("//help ").append("[] ")); + tip.append(" for more information.").newLine(); + + // Add each command + for (Command mapping : list) { + box.appendCommand((isRootLevel ? "/" : "") + mapping.getName(), mapping.getDescription()); + } + } + + actor.printRaw(ColorCodeBuilder.asColorCodes(box)); + } + + private PrintCommandHelp() { + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 016500666..25266047f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -60,10 +60,13 @@ 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; +import com.sk89q.worldedit.command.UtilityCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.BooleanConverter; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.DirectionConverter; +import com.sk89q.worldedit.command.argument.EntityRemoverConverter; import com.sk89q.worldedit.command.argument.EnumConverter; import com.sk89q.worldedit.command.argument.ExpandAmountConverter; import com.sk89q.worldedit.command.argument.MaskConverter; @@ -78,16 +81,11 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.annotation.Selection; -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.regions.Region; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; -import com.sk89q.worldedit.util.command.parametric.LegacyCommandsHandler; -import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.util.logging.DynamicStreamHandler; import com.sk89q.worldedit.util.logging.LogFormat; @@ -188,12 +186,6 @@ public final class PlatformCommandMananger { commandLog.addHandler(dynamicHandler); // Set up the commands manager - ParametricBuilder builder = new ParametricBuilder(); - builder.setAuthorizer(new ActorAuthorizer()); - builder.setDefaultCompleter(new UserCommandCompleter(platformManager)); - builder.addBinding(new WorldEditBinding(worldEdit)); - builder.addInvokeListener(new LegacyCommandsHandler()); - registerAlwaysInjectedValues(); registerArgumentConverters(); registerAllCommands(); @@ -215,6 +207,7 @@ public final class PlatformCommandMananger { ExpandAmountConverter.register(commandManager); ZonedDateTimeConverter.register(commandManager); BooleanConverter.register(commandManager); + EntityRemoverConverter.register(commandManager); } private void registerAlwaysInjectedValues() { @@ -383,13 +376,17 @@ public final class PlatformCommandMananger { ToolUtilCommandsRegistration.builder(), new ToolUtilCommands(worldEdit) ); + register( + commandManager, + UtilityCommandsRegistration.builder(), + new UtilityCommands(worldEdit) + ); // Unported commands are below. Delete once they're added to the main manager above. /* dispatcher = new CommandGraph() .builder(builder) .commands() - .registerMethods(new UtilityCommands(worldEdit)) .register(adapt(new SelectionCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within selection"), "worldedit.region.set")), "/set") .group("worldedit", "we") .describeAs("WorldEdit commands") diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java new file mode 100644 index 000000000..c583add43 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java @@ -0,0 +1,53 @@ +/* + * 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.util.command; + +import com.sk89q.worldedit.extension.platform.PlatformCommandMananger; +import org.enginehub.piston.Command; +import org.enginehub.piston.part.SubCommandPart; + +import java.util.Comparator; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class CommandUtil { + + public static Map getSubCommands(Command currentCommand) { + return currentCommand.getParts().stream() + .filter(p -> p instanceof SubCommandPart) + .flatMap(p -> ((SubCommandPart) p).getCommands().stream()) + .collect(Collectors.toMap(Command::getName, Function.identity())); + } + + private static String clean(String input) { + return PlatformCommandMananger.COMMAND_CLEAN_PATTERN.matcher(input).replaceAll(""); + } + + private static final Comparator BY_CLEAN_NAME = + Comparator.comparing(c -> clean(c.getName())); + + public static Comparator byCleanName() { + return BY_CLEAN_NAME; + } + + private CommandUtil() { + } +} 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 c7c5cf40d..03c01bf2a 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 @@ -19,21 +19,18 @@ 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.PlatformCommandMananger; -import com.sk89q.worldedit.util.command.CommandCallable; -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.util.command.PrimaryAliasComparator; import com.sk89q.worldedit.util.formatting.StyledFragment; - -import java.util.ArrayList; -import java.util.List; +import org.enginehub.piston.Command; +import org.enginehub.piston.CommandParameters; import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.util.command.CommandUtil.byCleanName; +import static com.sk89q.worldedit.util.command.CommandUtil.getSubCommands; /** * A box to describe usage of a command. @@ -46,7 +43,7 @@ public class CommandUsageBox extends StyledFragment { * @param command the command to describe * @param commandString the command that was used, such as "/we" or "/brush sphere" */ - public CommandUsageBox(CommandCallable command, String commandString) { + public CommandUsageBox(Command command, String commandString) { this(command, commandString, null); } @@ -55,54 +52,40 @@ public class CommandUsageBox extends StyledFragment { * * @param command the command to describe * @param commandString the command that was used, such as "/we" or "/brush sphere" - * @param locals list of locals to use + * @param parameters list of parameters to use */ - public CommandUsageBox(CommandCallable command, String commandString, @Nullable CommandLocals locals) { + public CommandUsageBox(Command command, String commandString, @Nullable CommandParameters parameters) { checkNotNull(command); checkNotNull(commandString); - if (command instanceof Dispatcher) { - attachDispatcherUsage((Dispatcher) command, commandString, locals); + Map subCommands = getSubCommands(command); + if (subCommands.isEmpty()) { + attachCommandUsage(command, commandString); } else { - attachCommandUsage(command.getDescription(), commandString); + attachSubcommandUsage(subCommands, commandString, parameters); } } - private void attachDispatcherUsage(Dispatcher dispatcher, String commandString, @Nullable CommandLocals locals) { + private void attachSubcommandUsage(Map dispatcher, String commandString, @Nullable CommandParameters parameters) { CommandListBox box = new CommandListBox("Subcommands"); String prefix = !commandString.isEmpty() ? commandString + " " : ""; - List list = new ArrayList<>(dispatcher.getCommands()); - list.sort(new PrimaryAliasComparator(PlatformCommandMananger.COMMAND_CLEAN_PATTERN)); + List list = dispatcher.values().stream() + .sorted(byCleanName()) + .collect(Collectors.toList()); - for (CommandMapping mapping : list) { - if (locals == null || mapping.getCallable().testPermission(locals)) { - box.appendCommand(prefix + mapping.getPrimaryAlias(), mapping.getDescription().getDescription()); + for (Command mapping : list) { + if (parameters == null || mapping.getCondition().satisfied(parameters)) { + box.appendCommand(prefix + mapping.getName(), mapping.getDescription()); } } append(box); } - private void attachCommandUsage(Description description, String commandString) { + private void attachCommandUsage(Command description, String commandString) { MessageBox box = new MessageBox("Help for " + commandString); - StyledFragment contents = box.getContents(); - if (description.getUsage() != null) { - contents.append(new Label().append("Usage: ")); - contents.append(description.getUsage()); - } else { - contents.append(new Subtle().append("Usage information is not available.")); - } - - contents.newLine(); - - if (description.getHelp() != null) { - contents.append(description.getHelp()); - } else if (description.getDescription() != null) { - contents.append(description.getDescription()); - } else { - contents.append(new Subtle().append("No further help is available.")); - } + box.getContents().append(description.getFullHelp()); append(box); } From d8290cbd8f5391cc4e248a8b14674b6b9a9239ec Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 21:03:28 -0700 Subject: [PATCH 28/57] Port worldedit commands --- .../worldedit/command/UtilityCommands.java | 4 +- .../worldedit/command/WorldEditCommands.java | 72 ++++++++++--------- .../platform/PlatformCommandMananger.java | 29 +++++--- 3 files changed, 60 insertions(+), 45 deletions(-) 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 d6f916bd9..dae704efc 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 @@ -509,8 +509,8 @@ public class UtilityCommands { @Arg(desc = "The page to retrieve", def = "1") int page, @Arg(desc = "The command to retrieve help for", def = "", variable = true) - List commandPath) throws WorldEditException { - PrintCommandHelp.help(commandPath, page, we, actor); + List command) throws WorldEditException { + PrintCommandHelp.help(command, page, we, actor); } 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 aee7ba0f7..1b7346cd0 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 @@ -20,12 +20,12 @@ package com.sk89q.worldedit.command; import com.google.common.io.Files; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.command.util.PrintCommandHelp; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent; import com.sk89q.worldedit.extension.platform.Actor; @@ -36,6 +36,10 @@ import com.sk89q.worldedit.util.paste.ActorCallbackPaste; import com.sk89q.worldedit.util.report.ConfigReport; import com.sk89q.worldedit.util.report.ReportList; import com.sk89q.worldedit.util.report.SystemInfoReport; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.Switch; import java.io.File; import java.io.IOException; @@ -44,8 +48,10 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.TextStyle; +import java.util.List; import java.util.Locale; +@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class WorldEditCommands { private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); @@ -56,11 +62,9 @@ public class WorldEditCommands { } @Command( - aliases = { "version", "ver" }, - usage = "", - desc = "Get WorldEdit version", - min = 0, - max = 0 + name = "version", + aliases = { "ver" }, + desc = "Get WorldEdit version" ) public void version(Actor actor) throws WorldEditException { actor.print("WorldEdit version " + WorldEdit.getVersion()); @@ -81,11 +85,8 @@ public class WorldEditCommands { } @Command( - aliases = { "reload" }, - usage = "", - desc = "Reload configuration", - min = 0, - max = 0 + name = "reload", + desc = "Reload configuration" ) @CommandPermissions("worldedit.reload") public void reload(Actor actor) throws WorldEditException { @@ -94,9 +95,14 @@ public class WorldEditCommands { actor.print("Configuration reloaded!"); } - @Command(aliases = {"report"}, desc = "Writes a report on WorldEdit", flags = "p", max = 0) + @Command( + name = "report", + desc = "Writes a report on WorldEdit" + ) @CommandPermissions({"worldedit.report"}) - public void report(Actor actor, CommandContext args) throws WorldEditException { + public void report(Actor actor, + @Switch(name = 'p', desc = "Pastebins the report") + boolean pastebin) throws WorldEditException { ReportList report = new ReportList("Report"); report.add(new SystemInfoReport()); report.add(new ConfigReport()); @@ -110,7 +116,7 @@ public class WorldEditCommands { actor.printError("Failed to write report: " + e.getMessage()); } - if (args.hasFlag('p')) { + if (pastebin) { actor.checkPermission("worldedit.report.pastebin"); ActorCallbackPaste.pastebin( we.getSupervisor(), actor, result, "WorldEdit report: %s.report", @@ -120,11 +126,8 @@ public class WorldEditCommands { } @Command( - aliases = { "cui" }, - usage = "", - desc = "Complete CUI handshake (internal usage)", - min = 0, - max = 0 + name = "cui", + desc = "Complete CUI handshake (internal usage)" ) public void cui(Player player, LocalSession session) throws WorldEditException { session.setCUISupport(true); @@ -132,14 +135,13 @@ public class WorldEditCommands { } @Command( - aliases = { "tz" }, - usage = "[timezone]", - desc = "Set your timezone for snapshots", - min = 1, - max = 1 + name = "tz", + desc = "Set your timezone for snapshots" ) - public void tz(Player player, LocalSession session, CommandContext args) throws WorldEditException { - ZoneId tz = ZoneId.of(args.getString(0)); + public void tz(Player player, LocalSession session, + @Arg(desc = "The timezone to set") + String timezone) throws WorldEditException { + ZoneId tz = ZoneId.of(timezone); session.setTimezone(tz); player.print("Timezone set for this session to: " + tz.getDisplayName( TextStyle.FULL, Locale.ENGLISH @@ -149,13 +151,15 @@ public class WorldEditCommands { } @Command( - aliases = { "help" }, - usage = "[]", - desc = "Displays help for WorldEdit commands", - min = 0, - max = -1 + name = "help", + desc = "Displays help for WorldEdit commands" ) @CommandPermissions("worldedit.help") - public void help(Actor actor, CommandContext args) throws WorldEditException { + public void help(Actor actor, + @Arg(desc = "The page to retrieve", def = "1") + int page, + @Arg(desc = "The command to retrieve help for", def = "", variable = true) + List command) throws WorldEditException { + PrintCommandHelp.help(command, page, we, actor); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index 25266047f..998371d0b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -62,6 +62,8 @@ import com.sk89q.worldedit.command.ToolUtilCommands; import com.sk89q.worldedit.command.ToolUtilCommandsRegistration; import com.sk89q.worldedit.command.UtilityCommands; import com.sk89q.worldedit.command.UtilityCommandsRegistration; +import com.sk89q.worldedit.command.WorldEditCommands; +import com.sk89q.worldedit.command.WorldEditCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.BooleanConverter; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; @@ -311,6 +313,24 @@ public final class PlatformCommandMananger { .required() .build()); }); + commandManager.register("worldedit", cmd -> { + cmd.aliases(ImmutableList.of("we")); + cmd.description("WorldEdit commands"); + cmd.action(Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + register( + manager, + WorldEditCommandsRegistration.builder(), + new WorldEditCommands(worldEdit) + ); + + cmd.addPart(SubCommandPart.builder("action", "Sub-command to run.") + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() + .build()); + }); register( commandManager, BiomeCommandsRegistration.builder(), @@ -388,10 +408,6 @@ public final class PlatformCommandMananger { .builder(builder) .commands() .register(adapt(new SelectionCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within selection"), "worldedit.region.set")), "/set") - .group("worldedit", "we") - .describeAs("WorldEdit commands") - .registerMethods(new WorldEditCommands(worldEdit)) - .parent() .group("brush", "br") .describeAs("Brushing commands") .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") @@ -402,11 +418,6 @@ public final class PlatformCommandMananger { .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise") .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower") .parent() - .group("tool") - .describeAs("Bind functions to held items") - .registerMethods(new ToolCommands(worldEdit)) - .parent() - .graph() .getDispatcher(); */ } From 8348ffa7cf267b5ea86504ff8c6cce9c0ce7f233 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 22:54:23 -0700 Subject: [PATCH 29/57] Drop translatable names for now --- worldedit-core/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/worldedit-core/build.gradle b/worldedit-core/build.gradle index 6724db672..9ed0f8b2a 100644 --- a/worldedit-core/build.gradle +++ b/worldedit-core/build.gradle @@ -35,6 +35,10 @@ dependencies { testCompile 'org.mockito:mockito-core:1.9.0-rc1' } +tasks.withType(JavaCompile).configureEach { + it.options.compilerArgs.add("-Aarg.name.key.prefix=") +} + sourceSets { main { java { From 2486388e18432a4235e2da292adb28e61dda0683 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 23:02:23 -0700 Subject: [PATCH 30/57] Fix help command suggestion --- .../worldedit/command/util/PrintCommandHelp.java | 14 ++++++++++---- .../util/formatting/component/CommandListBox.java | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java index 48f835a61..57337b322 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.command.util; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; @@ -35,6 +36,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import java.util.stream.Stream; import static com.sk89q.worldedit.util.command.CommandUtil.byCleanName; @@ -77,7 +79,7 @@ public class PrintCommandHelp { final int perPage = actor instanceof Player ? 8 : 20; // More pages for console if (commandPath.isEmpty()) { - printAllCommands(page, perPage, manager.getAllCommands(), actor, true); + printAllCommands(page, perPage, manager.getAllCommands(), actor, ImmutableList.of()); return; } @@ -117,11 +119,12 @@ public class PrintCommandHelp { CommandUsageBox box = new CommandUsageBox(currentCommand, String.join(" ", visited)); actor.print(box.create()); } else { - printAllCommands(page, perPage, subCommands.values().stream(), actor, false); + printAllCommands(page, perPage, subCommands.values().stream(), actor, visited); } } - private static void printAllCommands(int page, int perPage, Stream commandStream, Actor actor, boolean isRootLevel) { + private static void printAllCommands(int page, int perPage, Stream commandStream, Actor actor, + List commandList) { // Get a list of aliases List commands = commandStream .sorted(byCleanName()) @@ -147,7 +150,10 @@ public class PrintCommandHelp { // Add each command for (Command mapping : list) { - box.appendCommand((isRootLevel ? "/" : "") + mapping.getName(), mapping.getDescription()); + String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName(); + String command = Stream.concat(commandList.stream(), Stream.of(mapping.getName())) + .collect(Collectors.joining(" ", "/", "")); + box.appendCommand(alias, mapping.getDescription(), command); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java index c049006b6..f39a74656 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java @@ -53,7 +53,7 @@ public class CommandListBox extends MessageBox { TextComponent commandName = TextComponent.of(alias, TextColor.GOLD); if (insertion != null) { commandName = commandName - .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, insertion)) + .clickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, insertion)) .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to select"))); } getContents().append(commandName.append(TextComponent.of(": "))); From 46e0a7ba48d517cb49cab8ceae8b8c94f0a3f04d Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 25 Apr 2019 23:16:18 -0700 Subject: [PATCH 31/57] Port //set --- .../worldedit/command/RegionCommands.java | 30 +++++++++++++++++++ .../platform/PlatformCommandMananger.java | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 6c5bcbfc2..ae4333c04 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.command; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEditException; @@ -27,6 +29,8 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.GroundFunction; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.generator.FloraGenerator; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; @@ -34,6 +38,7 @@ import com.sk89q.worldedit.function.mask.NoiseFilter2D; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.visitor.LayerVisitor; +import com.sk89q.worldedit.function.visitor.RegionVisitor; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.expression.ExpressionException; @@ -76,6 +81,31 @@ public class RegionCommands { public RegionCommands() { } + @Command( + name = "/set", + desc = "Sets all the blocks in the region" + ) + @CommandPermissions("worldedit.region.set") + @Logging(REGION) + public int set(Player player, EditSession editSession, + @Selection Region region, + @Arg(desc = "The patter of blocks to set") + Pattern pattern) { + RegionFunction set = new BlockReplace(editSession, pattern); + RegionVisitor visitor = new RegionVisitor(region, set); + + Operations.completeBlindly(visitor); + List messages = Lists.newArrayList(); + visitor.addStatusMessages(messages); + if (messages.isEmpty()) { + player.print("Operation completed."); + } else { + player.print("Operation completed (" + Joiner.on(", ").join(messages) + ")."); + } + + return visitor.getAffected(); + } + @Command( name = "/line", desc = "Draws a line segment between cuboid selection corners", diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java index ead39bce3..eb8b4adbc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java @@ -377,7 +377,6 @@ public final class PlatformCommandMananger { dispatcher = new CommandGraph() .builder(builder) .commands() - .register(adapt(new SelectionCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within selection"), "worldedit.region.set")), "/set") .group("brush", "br") .describeAs("Brushing commands") .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") From b8c120e0c409d49f3e716ea30ecf3d69c3efc6dd Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Fri, 26 Apr 2019 01:18:02 -0700 Subject: [PATCH 32/57] Finish porting commands --- .../worldedit/bukkit/WorldEditListener.java | 4 +- .../worldedit/command/ApplyBrushCommands.java | 113 +++++++++++++++++ .../worldedit/command/BrushCommands.java | 114 ++++++++++++++++- .../worldedit/command/PaintBrushCommands.java | 119 ++++++++++++++++++ .../worldedit/command/WorldEditCommands.java | 2 +- ...rnConverter.java => FactoryConverter.java} | 28 ++++- .../command/argument/ItemParser.java | 82 ------------ .../command/argument/ItemUseParser.java | 90 ------------- .../command/argument/MaskConverter.java | 78 ------------ .../argument/RegionFactoryConverter.java | 72 +++++++++++ .../argument/RegionFunctionParser.java | 40 ------ .../command/argument/ReplaceParser.java | 78 ------------ .../command/composition/ApplyCommand.java | 68 ---------- .../command/composition/PaintCommand.java | 64 ---------- .../command/composition/SelectionCommand.java | 2 +- .../composition/ShapedBrushCommand.java | 2 +- .../command/factory/ItemUseFactory.java | 28 +++++ .../command/factory/ReplaceFactory.java | 30 +++++ .../command/factory/TreeGeneratorFactory.java | 25 ++++ .../command/util/PermissionCondition.java | 2 +- .../command/util/PrintCommandHelp.java | 2 +- .../extension/platform/Capability.java | 4 +- ...anger.java => PlatformCommandManager.java} | 88 +++++-------- .../extension/platform/PlatformManager.java | 8 +- .../worldedit/function/ItemUseFunction.java | 23 ++++ .../worldedit/util/command/CommandUtil.java | 33 ++++- 26 files changed, 618 insertions(+), 581 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java rename worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/{PatternConverter.java => FactoryConverter.java} (67%) delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemUseParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFunctionParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ApplyCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/PaintCommand.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java rename worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/{PlatformCommandMananger.java => PlatformCommandManager.java} (86%) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java 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 699263d50..7eea4312b 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 @@ -91,7 +91,7 @@ public class WorldEditListener implements Listener { if (split.length > 0) { split[0] = split[0].substring(1); - split = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().commandDetection(split); + split = plugin.getWorldEdit().getPlatformManager().getPlatformCommandManager().commandDetection(split); } final String newMessage = "/" + StringUtil.joinString(split, " "); @@ -118,7 +118,7 @@ public class WorldEditListener implements Listener { CommandParameters parameters = NoInputCommandParameters.builder() .injectedValues(MemoizingValueAccess.wrap(store)) .build(); - CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandMananger().getCommandManager(); + CommandManager commandManager = plugin.getWorldEdit().getPlatformManager().getPlatformCommandManager().getCommandManager(); event.getCommands().removeIf(name -> // remove if in the manager and not satisfied commandManager.getCommand(name) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java new file mode 100644 index 000000000..2e9297b24 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -0,0 +1,113 @@ +package com.sk89q.worldedit.command; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; +import com.sk89q.worldedit.command.factory.ItemUseFactory; +import com.sk89q.worldedit.command.factory.ReplaceFactory; +import com.sk89q.worldedit.command.util.PermissionCondition; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.function.factory.Apply; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.regions.factory.RegionFactory; +import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.command.CommandUtil; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.DefaultCommandManagerService; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.inject.Key; +import org.enginehub.piston.part.CommandArgument; +import org.enginehub.piston.part.SubCommandPart; + +import java.util.stream.Collectors; + +import static java.util.Objects.requireNonNull; +import static org.enginehub.piston.part.CommandParts.arg; + +@CommandContainer +public class ApplyBrushCommands { + + private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("regionFactory"), TextComponent.of("The shape of the region")) + .defaultsTo(ImmutableList.of()) + .ofTypes(ImmutableList.of(Key.of(RegionFactory.class))) + .build(); + + private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TextComponent.of("The size of the brush")) + .defaultsTo(ImmutableList.of("5")) + .ofTypes(ImmutableList.of(Key.of(double.class))) + .build(); + + public static void register(CommandManager commandManager) { + commandManager.register("apply", builder -> { + builder.description(TextComponent.of("Apply brush, apply a function to every block")); + builder.action(org.enginehub.piston.Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + CommandUtil.register( + manager, + ApplyBrushCommandsRegistration.builder(), + new ApplyBrushCommands() + ); + + builder.condition(new PermissionCondition(ImmutableSet.of("worldedit.brush.apply"))); + + builder.addParts(REGION_FACTORY, RADIUS); + builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use")) + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .build()); + }); + } + + private void setApplyBrush(CommandParameters parameters, Player player, LocalSession localSession, + Contextual generatorFactory) throws WorldEditException { + double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class)); + RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class); + BrushCommands.setOperationBasedBrush(player, localSession, radius, + new Apply(generatorFactory), regionFactory, "worldedit.brush.apply"); + } + + @Command( + name = "forest", + desc = "Plant trees" + ) + public void forest(CommandParameters parameters, + Player player, LocalSession localSession, + @Arg(desc = "The type of tree to plant") + TreeGenerator.TreeType type) throws WorldEditException { + setApplyBrush(parameters, player, localSession, new TreeGeneratorFactory(type)); + } + + @Command( + name = "item", + desc = "Use an item" + ) + public void item(CommandParameters parameters, + Player player, LocalSession localSession, + @Arg(desc = "The type of item to use") + BaseItem item) throws WorldEditException { + setApplyBrush(parameters, player, localSession, new ItemUseFactory(item)); + } + + @Command( + name = "set", + desc = "Place a block" + ) + public void set(CommandParameters parameters, + Player player, LocalSession localSession, + @Arg(desc = "The pattern of blocks to use") + Pattern pattern) throws WorldEditException { + setApplyBrush(parameters, player, localSession, new ReplaceFactory(pattern)); + } + +} 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 e310f136a..ebc2e9e5a 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 @@ -23,6 +23,8 @@ import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.factory.ReplaceFactory; +import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.brush.ButcherBrush; import com.sk89q.worldedit.command.tool.brush.ClipboardBrush; @@ -30,6 +32,7 @@ import com.sk89q.worldedit.command.tool.brush.CylinderBrush; import com.sk89q.worldedit.command.tool.brush.GravityBrush; import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush; import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush; +import com.sk89q.worldedit.command.tool.brush.OperationFactoryBrush; import com.sk89q.worldedit.command.tool.brush.SmoothBrush; import com.sk89q.worldedit.command.tool.brush.SphereBrush; import com.sk89q.worldedit.command.util.CommandPermissions; @@ -37,14 +40,21 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.factory.Apply; +import com.sk89q.worldedit.function.factory.Deform; +import com.sk89q.worldedit.function.factory.Paint; import com.sk89q.worldedit.function.mask.BlockTypeMask; import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.request.RequestExtent; import com.sk89q.worldedit.util.HandSide; +import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.world.block.BlockTypes; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; @@ -215,7 +225,7 @@ public class BrushCommands { player.print(String.format("Gravity brush equipped (%.0f).", radius)); } - + @Command( name = "butcher", aliases = { "kill" }, @@ -275,4 +285,106 @@ public class BrushCommands { player.print(String.format("Butcher brush equipped (%.0f).", radius)); } + + @Command( + name = "deform", + desc = "Deform brush, applies an expression to an area" + ) + @CommandPermissions("worldedit.brush.deform") + public void deform(Player player, LocalSession localSession, + @Arg(desc = "The shape of the region") + RegionFactory regionFactory, + @Arg(desc = "The size of the brush", def = "5") + double radius, + @Arg(desc = "Expression to apply", def = "y-=0.2") + String expression, + @Switch(name = 'r', desc = "Use the game's coordinate origin") + boolean useRawCoords, + @Switch(name = 'o', desc = "Use the placement position as the origin") + boolean usePlacement) throws WorldEditException { + Deform deform = new Deform(expression); + if (useRawCoords) { + deform.setMode(Deform.Mode.RAW_COORD); + } else if (usePlacement) { + deform.setMode(Deform.Mode.OFFSET); + deform.setOffset(localSession.getPlacementPosition(player).toVector3()); + } + setOperationBasedBrush(player, localSession, radius, + deform, regionFactory, "worldedit.brush.deform"); + } + + @Command( + name = "set", + desc = "Set brush, sets all blocks in the area" + ) + @CommandPermissions("worldedit.brush.set") + public void set(Player player, LocalSession localSession, + @Arg(desc = "The shape of the region") + RegionFactory regionFactory, + @Arg(desc = "The size of the brush", def = "5") + double radius, + @Arg(desc = "The pattern of blocks to set") + Pattern pattern) throws WorldEditException { + setOperationBasedBrush(player, localSession, radius, + new Apply(new ReplaceFactory(pattern)), regionFactory, "worldedit.brush.set"); + } + + @Command( + name = "forest", + desc = "Forest brush, creates a forest in the area" + ) + @CommandPermissions("worldedit.brush.forest") + public void forest(Player player, LocalSession localSession, + @Arg(desc = "The shape of the region") + RegionFactory regionFactory, + @Arg(desc = "The size of the brush", def = "5") + double radius, + @Arg(desc = "The density of the brush", def = "20") + double density, + @Arg(desc = "The type of tree to use") + TreeGenerator.TreeType type) throws WorldEditException { + setOperationBasedBrush(player, localSession, radius, + new Paint(new TreeGeneratorFactory(type), density / 100), regionFactory, "worldedit.brush.forest"); + } + + @Command( + name = "raise", + desc = "Raise brush, raise all blocks by one" + ) + @CommandPermissions("worldedit.brush.raise") + public void raise(Player player, LocalSession localSession, + @Arg(desc = "The shape of the region") + RegionFactory regionFactory, + @Arg(desc = "The size of the brush", def = "5") + double radius) throws WorldEditException { + setOperationBasedBrush(player, localSession, radius, + new Deform("y-=1"), regionFactory, "worldedit.brush.raise"); + } + + @Command( + name = "lower", + desc = "Lower brush, lower all blocks by one" + ) + @CommandPermissions("worldedit.brush.lower") + public void lower(Player player, LocalSession localSession, + @Arg(desc = "The shape of the region") + RegionFactory regionFactory, + @Arg(desc = "The size of the brush", def = "5") + double radius) throws WorldEditException { + setOperationBasedBrush(player, localSession, radius, + new Deform("y+=1"), regionFactory, "worldedit.brush.lower"); + } + + static void setOperationBasedBrush(Player player, LocalSession session, double radius, + Contextual factory, + RegionFactory regionFactory, + String permission) throws WorldEditException { + WorldEdit.getInstance().checkMaxBrushRadius(radius); + BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); + tool.setSize(radius); + tool.setFill(null); + tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission); + + player.print("Set brush to " + factory); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java new file mode 100644 index 000000000..649c2988b --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -0,0 +1,119 @@ +package com.sk89q.worldedit.command; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; +import com.sk89q.worldedit.command.factory.ItemUseFactory; +import com.sk89q.worldedit.command.factory.ReplaceFactory; +import com.sk89q.worldedit.command.util.PermissionCondition; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.function.factory.Paint; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.regions.factory.RegionFactory; +import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.util.command.CommandUtil; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.DefaultCommandManagerService; +import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.inject.Key; +import org.enginehub.piston.part.CommandArgument; +import org.enginehub.piston.part.SubCommandPart; + +import java.util.stream.Collectors; + +import static java.util.Objects.requireNonNull; +import static org.enginehub.piston.part.CommandParts.arg; + +@CommandContainer +public class PaintBrushCommands { + + private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("regionFactory"), TextComponent.of("The shape of the region")) + .defaultsTo(ImmutableList.of()) + .ofTypes(ImmutableList.of(Key.of(RegionFactory.class))) + .build(); + + private static final CommandArgument RADIUS = arg(TranslatableComponent.of("radius"), TextComponent.of("The size of the brush")) + .defaultsTo(ImmutableList.of("5")) + .ofTypes(ImmutableList.of(Key.of(double.class))) + .build(); + + private static final CommandArgument DENSITY = arg(TranslatableComponent.of("density"), TextComponent.of("The density of the brush")) + .defaultsTo(ImmutableList.of("20")) + .ofTypes(ImmutableList.of(Key.of(double.class))) + .build(); + + public static void register(CommandManager commandManager) { + commandManager.register("paint", builder -> { + builder.description(TextComponent.of("Paint brush, apply a function to a surface")); + builder.action(org.enginehub.piston.Command.Action.NULL_ACTION); + + CommandManager manager = DefaultCommandManagerService.getInstance() + .newCommandManager(); + CommandUtil.register( + manager, + PaintBrushCommandsRegistration.builder(), + new PaintBrushCommands() + ); + + builder.condition(new PermissionCondition(ImmutableSet.of("worldedit.brush.paint"))); + + builder.addParts(REGION_FACTORY, RADIUS, DENSITY); + builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use")) + .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .build()); + }); + } + + private void setPaintBrush(CommandParameters parameters, Player player, LocalSession localSession, + Contextual generatorFactory) throws WorldEditException { + double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class)); + double density = requireNonNull(DENSITY.value(parameters).asSingle(double.class)) / 100; + RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class); + BrushCommands.setOperationBasedBrush(player, localSession, radius, + new Paint(generatorFactory, density), regionFactory, "worldedit.brush.paint"); + } + + @Command( + name = "forest", + desc = "Plant trees" + ) + public void forest(CommandParameters parameters, + Player player, LocalSession localSession, + @Arg(desc = "The type of tree to plant") + TreeGenerator.TreeType type) throws WorldEditException { + setPaintBrush(parameters, player, localSession, new TreeGeneratorFactory(type)); + } + + @Command( + name = "item", + desc = "Use an item" + ) + public void item(CommandParameters parameters, + Player player, LocalSession localSession, + @Arg(desc = "The type of item to use") + BaseItem item) throws WorldEditException { + setPaintBrush(parameters, player, localSession, new ItemUseFactory(item)); + } + + @Command( + name = "set", + desc = "Place a block" + ) + public void set(CommandParameters parameters, + Player player, LocalSession localSession, + @Arg(desc = "The pattern of blocks to use") + Pattern pattern) throws WorldEditException { + setPaintBrush(parameters, player, localSession, new ReplaceFactory(pattern)); + } + +} 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 1b7346cd0..7586b0109 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 @@ -120,7 +120,7 @@ public class WorldEditCommands { actor.checkPermission("worldedit.report.pastebin"); ActorCallbackPaste.pastebin( we.getSupervisor(), actor, result, "WorldEdit report: %s.report", - WorldEdit.getInstance().getPlatformManager().getPlatformCommandMananger().getExceptionConverter() + WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter() ); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java similarity index 67% rename from worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternConverter.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java index 4202b4679..2e7eedb72 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/PatternConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java @@ -21,12 +21,15 @@ package com.sk89q.worldedit.command.argument; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.internal.registry.AbstractFactory; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.World; @@ -37,20 +40,33 @@ import org.enginehub.piston.converter.SuccessfulConversion; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; -public class PatternConverter implements ArgumentConverter { +import java.util.function.Function; + +public class FactoryConverter implements ArgumentConverter { public static void register(WorldEdit worldEdit, CommandManager commandManager) { - commandManager.registerConverter(Key.of(Pattern.class), new PatternConverter(worldEdit)); + commandManager.registerConverter(Key.of(Pattern.class), + new FactoryConverter<>(worldEdit, WorldEdit::getPatternFactory, "pattern")); + commandManager.registerConverter(Key.of(Mask.class), + new FactoryConverter<>(worldEdit, WorldEdit::getMaskFactory, "mask")); + commandManager.registerConverter(Key.of(BaseItem.class), + new FactoryConverter<>(worldEdit, WorldEdit::getItemFactory, "item")); } private final WorldEdit worldEdit; + private final Function> factoryExtractor; + private final String description; - private PatternConverter(WorldEdit worldEdit) { + private FactoryConverter(WorldEdit worldEdit, + Function> factoryExtractor, + String description) { this.worldEdit = worldEdit; + this.factoryExtractor = factoryExtractor; + this.description = description; } @Override - public ConversionResult convert(String argument, InjectedValueAccess context) { + public ConversionResult convert(String argument, InjectedValueAccess context) { Actor actor = context.injectedValue(Key.of(Actor.class)) .orElseThrow(() -> new IllegalStateException("No actor")); LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); @@ -67,7 +83,7 @@ public class PatternConverter implements ArgumentConverter { try { return SuccessfulConversion.fromSingle( - worldEdit.getPatternFactory().parseFromInput(argument, parserContext) + factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext) ); } catch (InputParseException e) { throw new IllegalArgumentException(e); @@ -76,6 +92,6 @@ public class PatternConverter implements ArgumentConverter { @Override public Component describeAcceptableArguments() { - return TextComponent.of("any pattern"); + return TextComponent.of("any " + description); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemParser.java deleted file mode 100644 index 880c17fb8..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemParser.java +++ /dev/null @@ -1,82 +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.command.argument; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.input.ParserContext; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; -import com.sk89q.worldedit.world.World; - -public class ItemParser extends SimpleCommand { - - private final StringParser stringParser; - - public ItemParser(String name) { - stringParser = addParameter(new StringParser(name, "The item name", null)); - } - - public ItemParser(String name, String defaultSuggestion) { - stringParser = addParameter(new StringParser(name, "The item name", defaultSuggestion)); - } - - @Override - public BaseItem call(CommandArgs args, CommandLocals locals) throws CommandException { - String itemString = stringParser.call(args, locals); - - Actor actor = locals.get(Actor.class); - LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); - - ParserContext parserContext = new ParserContext(); - parserContext.setActor(actor); - if (actor instanceof Entity) { - Extent extent = ((Entity) actor).getExtent(); - if (extent instanceof World) { - parserContext.setWorld((World) extent); - } - } - parserContext.setSession(session); - - try { - return WorldEdit.getInstance().getItemFactory().parseFromInput(itemString, parserContext); - } catch (InputParseException e) { - throw new CommandException(e.getMessage(), e); - } - } - - @Override - public String getDescription() { - return "Match an item"; - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemUseParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemUseParser.java deleted file mode 100644 index f6da447a1..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ItemUseParser.java +++ /dev/null @@ -1,90 +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.command.argument; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.EditContext; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.util.Direction; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; -import com.sk89q.worldedit.world.World; - -public class ItemUseParser extends SimpleCommand> { - - private final ItemParser itemParser = addParameter(new ItemParser("item", "minecraft:bone_meal")); - - @Override - public Contextual call(CommandArgs args, CommandLocals locals) throws CommandException { - BaseItem item = itemParser.call(args, locals); - return new ItemUseFactory(item); - } - - @Override - public String getDescription() { - return "Applies an item"; - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return true; - } - - private static final class ItemUseFactory implements Contextual { - private final BaseItem item; - - private ItemUseFactory(BaseItem item) { - this.item = item; - } - - @Override - public RegionFunction createFromContext(EditContext input) { - World world = ((EditSession) input.getDestination()).getWorld(); - return new ItemUseFunction(world, item); - } - - @Override - public String toString() { - return "application of the item " + item.getType() + ":" + item.getNbtData(); - } - } - - private static final class ItemUseFunction implements RegionFunction { - private final World world; - private final BaseItem item; - - private ItemUseFunction(World world, BaseItem item) { - this.world = world; - this.item = item; - } - - @Override - public boolean apply(BlockVector3 position) throws WorldEditException { - return world.useItem(position, item, Direction.UP); - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java deleted file mode 100644 index 37e71cbf4..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/MaskConverter.java +++ /dev/null @@ -1,78 +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.command.argument; - -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.input.ParserContext; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TextComponent; -import com.sk89q.worldedit.world.World; -import org.enginehub.piston.CommandManager; -import org.enginehub.piston.converter.ArgumentConverter; -import org.enginehub.piston.converter.ConversionResult; -import org.enginehub.piston.converter.FailedConversion; -import org.enginehub.piston.converter.SuccessfulConversion; -import org.enginehub.piston.inject.InjectedValueAccess; -import org.enginehub.piston.inject.Key; - -public class MaskConverter implements ArgumentConverter { - - public static void register(WorldEdit worldEdit, CommandManager commandManager) { - commandManager.registerConverter(Key.of(Mask.class), new MaskConverter(worldEdit)); - } - - private final WorldEdit worldEdit; - - private MaskConverter(WorldEdit worldEdit) { - this.worldEdit = worldEdit; - } - - @Override - public ConversionResult convert(String argument, InjectedValueAccess context) { - Actor actor = context.injectedValue(Key.of(Actor.class)) - .orElseThrow(() -> new IllegalStateException("No actor")); - ParserContext parserContext = new ParserContext(); - parserContext.setActor(actor); - if (actor instanceof Entity) { - Extent extent = ((Entity) actor).getExtent(); - if (extent instanceof World) { - parserContext.setWorld((World) extent); - } - } - parserContext.setSession(worldEdit.getSessionManager().get(actor)); - try { - return SuccessfulConversion.fromSingle( - worldEdit.getMaskFactory().parseFromInput(argument, parserContext) - ); - } catch (InputParseException e) { - return FailedConversion.from(e); - } - } - - @Override - public Component describeAcceptableArguments() { - return TextComponent.of("any mask"); - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java new file mode 100644 index 000000000..ed54327b1 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java @@ -0,0 +1,72 @@ +/* + * 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.regions.factory.CuboidRegionFactory; +import com.sk89q.worldedit.regions.factory.CylinderRegionFactory; +import com.sk89q.worldedit.regions.factory.RegionFactory; +import com.sk89q.worldedit.regions.factory.SphereRegionFactory; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +public class RegionFactoryConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(RegionFactory.class), new RegionFactoryConverter()); + } + + private RegionFactoryConverter() { + } + + @Override + public Component describeAcceptableArguments() { + return TextComponent.of("cuboid|sphere|cyl"); + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess context) { + try { + return SuccessfulConversion.fromSingle(parse(argument)); + } catch (Exception e) { + return FailedConversion.from(e); + } + } + + private RegionFactory parse(String argument) { + switch (argument) { + case "cuboid": + return new CuboidRegionFactory(); + case "sphere": + return new SphereRegionFactory(); + case "cyl": + case "cylinder": + return new CylinderRegionFactory(1); // TODO: Adjustable height + default: + throw new IllegalArgumentException("Not a known region type: " + argument); + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFunctionParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFunctionParser.java deleted file mode 100644 index be96b19bb..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFunctionParser.java +++ /dev/null @@ -1,40 +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.command.argument; - -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.util.command.composition.BranchingCommand; - -public class RegionFunctionParser extends BranchingCommand> { - - public RegionFunctionParser() { - super("functionTpe"); - putOption(new TreeGeneratorParser("treeType"), "forest"); - putOption(new ItemUseParser(), "item"); - putOption(new ReplaceParser(), "set"); - } - - @Override - public String getDescription() { - return "Choose a block function"; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java deleted file mode 100644 index eebfb4a16..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ReplaceParser.java +++ /dev/null @@ -1,78 +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.command.argument; - -import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.extent.NullExtent; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.EditContext; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.function.block.BlockReplace; -import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; - - -public class ReplaceParser extends SimpleCommand> { - - // TODO rewrite for new system -// private final PatternParser fillArg = addParameter(new PatternParser("fillPattern")); - - @Override - public Contextual call(CommandArgs args, CommandLocals locals) throws CommandException { -// Pattern fill = fillArg.call(args, locals); -// return new ReplaceFactory(fill); - return null; - } - - @Override - public String getDescription() { - return "Replaces blocks"; - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return true; - } - - private static class ReplaceFactory implements Contextual { - private final Pattern fill; - - private ReplaceFactory(Pattern fill) { - this.fill = fill; - } - - @Override - public RegionFunction createFromContext(EditContext context) { - return new BlockReplace( - firstNonNull(context.getDestination(), new NullExtent()), - firstNonNull(context.getFill(), fill)); - } - - @Override - public String toString() { - return "replace blocks"; - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ApplyCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ApplyCommand.java deleted file mode 100644 index a73748e4c..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ApplyCommand.java +++ /dev/null @@ -1,68 +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.command.composition; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.command.argument.RegionFunctionParser; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.function.factory.Apply; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; - -public class ApplyCommand extends SimpleCommand> { - - private final CommandExecutor> functionParser; - private final String description; - - public ApplyCommand() { - this(new RegionFunctionParser(), "Applies a function to every block"); - } - - public ApplyCommand(CommandExecutor> functionParser, String description) { - checkNotNull(functionParser, "functionParser"); - checkNotNull(description, "description"); - this.functionParser = functionParser; - this.description = description; - addParameter(functionParser); - } - - @Override - public Apply call(CommandArgs args, CommandLocals locals) throws CommandException { - Contextual function = functionParser.call(args, locals); - return new Apply(function); - } - - @Override - public String getDescription() { - return description; - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/PaintCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/PaintCommand.java deleted file mode 100644 index 8ce3e004c..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/PaintCommand.java +++ /dev/null @@ -1,64 +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.command.composition; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.command.argument.NumberParser; -import com.sk89q.worldedit.command.argument.RegionFunctionParser; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.function.factory.Paint; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; - -public class PaintCommand extends SimpleCommand { - - private final NumberParser densityCommand = addParameter(new NumberParser("density", "0-100", "20")); - private final CommandExecutor> functionParser; - - public PaintCommand() { - this(new RegionFunctionParser()); - } - - public PaintCommand(CommandExecutor> functionParser) { - this.functionParser = functionParser; - addParameter(functionParser); - } - - @Override - public Paint call(CommandArgs args, CommandLocals locals) throws CommandException { - double density = densityCommand.call(args, locals).doubleValue() / 100.0; - Contextual function = functionParser.call(args, locals); - return new Paint(function, density); - } - - @Override - public String getDescription() { - return "Applies a function to surfaces"; - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return true; - } - -} 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 dd51c64a2..c0f93463c 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().getPlatformCommandMananger().getExceptionConverter().convert(e); + WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().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 35fb758a3..911c4080e 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().getPlatformCommandMananger().getExceptionConverter().convert(e); + WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter().convert(e); } player.print("Set brush to " + factory); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java new file mode 100644 index 000000000..33cd470c8 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java @@ -0,0 +1,28 @@ +package com.sk89q.worldedit.command.factory; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.function.ItemUseFunction; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.EditContext; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.world.World; + +public final class ItemUseFactory implements Contextual { + private final BaseItem item; + + public ItemUseFactory(BaseItem item) { + this.item = item; + } + + @Override + public RegionFunction createFromContext(EditContext input) { + World world = ((EditSession) input.getDestination()).getWorld(); + return new ItemUseFunction(world, item); + } + + @Override + public String toString() { + return "application of the item " + item.getType() + ":" + item.getNbtData(); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java new file mode 100644 index 000000000..03453fcd7 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java @@ -0,0 +1,30 @@ +package com.sk89q.worldedit.command.factory; + +import com.sk89q.worldedit.extent.NullExtent; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.EditContext; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.function.block.BlockReplace; +import com.sk89q.worldedit.function.pattern.Pattern; + +import static com.sk89q.worldedit.util.GuavaUtil.firstNonNull; + +public class ReplaceFactory implements Contextual { + private final Pattern fill; + + public ReplaceFactory(Pattern fill) { + this.fill = fill; + } + + @Override + public RegionFunction createFromContext(EditContext context) { + return new BlockReplace( + firstNonNull(context.getDestination(), new NullExtent()), + firstNonNull(context.getFill(), fill)); + } + + @Override + public String toString() { + return "replace blocks"; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java new file mode 100644 index 000000000..47548b4d5 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java @@ -0,0 +1,25 @@ +package com.sk89q.worldedit.command.factory; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.function.Contextual; +import com.sk89q.worldedit.function.EditContext; +import com.sk89q.worldedit.function.generator.ForestGenerator; +import com.sk89q.worldedit.util.TreeGenerator; + +public final class TreeGeneratorFactory implements Contextual { + private final TreeGenerator.TreeType type; + + public TreeGeneratorFactory(TreeGenerator.TreeType type) { + this.type = type; + } + + @Override + public ForestGenerator createFromContext(EditContext input) { + return new ForestGenerator((EditSession) input.getDestination(), type); + } + + @Override + public String toString() { + return "tree of type " + type; + } +} 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 index 4b33675f9..48b6acc16 100644 --- 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 @@ -32,7 +32,7 @@ public final class PermissionCondition implements Command.Condition { private final Set permissions; - PermissionCondition(Set permissions) { + public PermissionCondition(Set permissions) { this.permissions = permissions; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java index 57337b322..b1971b0a9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java @@ -74,7 +74,7 @@ public class PrintCommandHelp { actor.printError("Page must be >= 1."); return; } - CommandManager manager = we.getPlatformManager().getPlatformCommandMananger().getCommandManager(); + CommandManager manager = we.getPlatformManager().getPlatformCommandManager().getCommandManager(); final int perPage = actor instanceof Player ? 8 : 20; // More pages for console 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 50aa913b4..e91c799bc 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.getPlatformCommandMananger().register(platform); + platformManager.getPlatformCommandManager().registerCommandsWith(platform); } @Override void unload(PlatformManager platformManager, Platform platform) { - platformManager.getPlatformCommandMananger().unregister(); + platformManager.getPlatformCommandManager().removeCommands(); } }, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java similarity index 86% rename from worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index eb8b4adbc..ed93a11b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandMananger.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.ApplyBrushCommands; import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BiomeCommandsRegistration; import com.sk89q.worldedit.command.BrushCommands; @@ -42,6 +43,7 @@ import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.HistoryCommandsRegistration; import com.sk89q.worldedit.command.NavigationCommands; import com.sk89q.worldedit.command.NavigationCommandsRegistration; +import com.sk89q.worldedit.command.PaintBrushCommands; import com.sk89q.worldedit.command.RegionCommands; import com.sk89q.worldedit.command.RegionCommandsRegistration; import com.sk89q.worldedit.command.SchematicCommands; @@ -71,11 +73,10 @@ import com.sk89q.worldedit.command.argument.DirectionConverter; import com.sk89q.worldedit.command.argument.EntityRemoverConverter; import com.sk89q.worldedit.command.argument.EnumConverter; import com.sk89q.worldedit.command.argument.ExpandAmountConverter; -import com.sk89q.worldedit.command.argument.MaskConverter; -import com.sk89q.worldedit.command.argument.PatternConverter; +import com.sk89q.worldedit.command.argument.FactoryConverter; +import com.sk89q.worldedit.command.argument.RegionFactoryConverter; import com.sk89q.worldedit.command.argument.VectorConverter; import com.sk89q.worldedit.command.argument.ZonedDateTimeConverter; -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; @@ -83,7 +84,6 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.annotation.Selection; -import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.request.Request; @@ -102,7 +102,6 @@ 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.gen.CommandCallListener; import org.enginehub.piston.gen.CommandRegistration; import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; @@ -116,29 +115,28 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.function.Consumer; 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.CommandUtil.COMMAND_LOG; +import static com.sk89q.worldedit.util.command.CommandUtil.register; /** * Handles the registration and invocation of commands. * *

This class is primarily for internal usage.

*/ -public final class PlatformCommandMananger { +public final class PlatformCommandManager { public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+"); - private static final Logger log = LoggerFactory.getLogger(PlatformCommandMananger.class); - private static final java.util.logging.Logger commandLog = - java.util.logging.Logger.getLogger(PlatformCommandMananger.class.getCanonicalName() + ".CommandLog"); + private static final Logger log = LoggerFactory.getLogger(PlatformCommandManager.class); private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$"); - private static final CommandPermissionsConditionGenerator PERM_GEN = new CommandPermissionsConditionGenerator(); private final WorldEdit worldEdit; private final PlatformManager platformManager; @@ -146,14 +144,13 @@ public final class PlatformCommandMananger { private final InjectedValueStore globalInjectedValues; private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); private final WorldEditExceptionConverter exceptionConverter; - private final List callListeners; /** * Create a new instance. * * @param worldEdit the WorldEdit instance */ - PlatformCommandMananger(final WorldEdit worldEdit, PlatformManager platformManager) { + PlatformCommandManager(final WorldEdit worldEdit, PlatformManager platformManager) { checkNotNull(worldEdit); checkNotNull(platformManager); this.worldEdit = worldEdit; @@ -162,32 +159,17 @@ public final class PlatformCommandMananger { this.commandManager = DefaultCommandManagerService.getInstance() .newCommandManager(); this.globalInjectedValues = MapBackedValueStore.create(); - this.callListeners = Collections.singletonList( - new CommandLoggingHandler(worldEdit, commandLog) - ); // setup separate from main constructor // ensures that everything is definitely assigned initialize(); } - private void register(CommandManager manager, CommandRegistration registration, CI instance) { - registration.containerInstance(instance) - .commandManager(manager) - .listeners(callListeners); - if (registration instanceof CommandPermissionsConditionGenerator.Registration) { - ((CommandPermissionsConditionGenerator.Registration) registration).commandPermissionsConditionGenerator( - PERM_GEN - ); - } - registration.build(); - } - private void initialize() { // Register this instance for command events worldEdit.getEventBus().register(this); // Setup the logger - commandLog.addHandler(dynamicHandler); + COMMAND_LOG.addHandler(dynamicHandler); // Set up the commands manager registerAlwaysInjectedValues(); @@ -197,8 +179,7 @@ public final class PlatformCommandMananger { private void registerArgumentConverters() { DirectionConverter.register(worldEdit, commandManager); - MaskConverter.register(worldEdit, commandManager); - PatternConverter.register(worldEdit, commandManager); + FactoryConverter.register(worldEdit, commandManager); for (int count = 2; count <= 3; count++) { commandManager.registerConverter(Key.of(double.class, Annotations.radii(count)), CommaSeparatedValuesConverter.wrapAndLimit(ArgumentConverters.get( @@ -212,6 +193,7 @@ public final class PlatformCommandMananger { ZonedDateTimeConverter.register(commandManager); BooleanConverter.register(commandManager); EntityRemoverConverter.register(commandManager); + RegionFactoryConverter.register(commandManager); } private void registerAlwaysInjectedValues() { @@ -243,7 +225,13 @@ public final class PlatformCommandMananger { } private void registerSubCommands(String name, List aliases, String desc, - CommandRegistration registration, CI instance) { + CommandRegistration registration, CI instance) { + registerSubCommands(name, aliases, desc, registration, instance, m -> {}); + } + + private void registerSubCommands(String name, List aliases, String desc, + CommandRegistration registration, CI instance, + Consumer additionalConfig) { commandManager.register(name, cmd -> { cmd.aliases(aliases); cmd.description(TextComponent.of(desc)); @@ -292,7 +280,11 @@ public final class PlatformCommandMananger { ImmutableList.of("br"), "Brushing commands", BrushCommandsRegistration.builder(), - new BrushCommands(worldEdit) + new BrushCommands(worldEdit), + manager -> { + PaintBrushCommands.register(manager); + ApplyBrushCommands.register(manager); + } ); registerSubCommands( "worldedit", @@ -371,31 +363,13 @@ public final class PlatformCommandMananger { UtilityCommandsRegistration.builder(), new UtilityCommands(worldEdit) ); - - // Unported commands are below. Delete once they're added to the main manager above. - /* - dispatcher = new CommandGraph() - .builder(builder) - .commands() - .group("brush", "br") - .describeAs("Brushing commands") - .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") - .register(adapt(new ShapedBrushCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within region"), "worldedit.brush.set")), "set") - .register(adapt(new ShapedBrushCommand(new PaintCommand(), "worldedit.brush.paint")), "paint") - .register(adapt(new ShapedBrushCommand(new ApplyCommand(), "worldedit.brush.apply")), "apply") - .register(adapt(new ShapedBrushCommand(new PaintCommand(new TreeGeneratorParser("treeType")), "worldedit.brush.forest")), "forest") - .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise") - .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower") - .parent() - .getDispatcher(); - */ } public ExceptionConverter getExceptionConverter() { return exceptionConverter; } - void register(Platform platform) { + void registerCommandsWith(Platform platform) { log.info("Registering commands with " + platform.getClass().getCanonicalName()); LocalConfiguration config = platform.getConfiguration(); @@ -405,10 +379,10 @@ public final class PlatformCommandMananger { // Register log if (!logging || path.isEmpty()) { dynamicHandler.setHandler(null); - commandLog.setLevel(Level.OFF); + COMMAND_LOG.setLevel(Level.OFF); } else { File file = new File(config.getWorkingDirectory(), path); - commandLog.setLevel(Level.ALL); + COMMAND_LOG.setLevel(Level.ALL); log.info("Logging WorldEdit commands to " + file.getAbsolutePath()); @@ -424,7 +398,7 @@ public final class PlatformCommandMananger { platform.registerCommands(commandManager); } - void unregister() { + void removeCommands() { dynamicHandler.setHandler(null); } @@ -581,8 +555,4 @@ public final class PlatformCommandMananger { return commandManager; } - public static java.util.logging.Logger getLogger() { - return commandLog; - } - } 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 692c1558e..f37c9b4a5 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 PlatformCommandMananger platformCommandMananger; + private final PlatformCommandManager platformCommandManager; 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.platformCommandMananger = new PlatformCommandMananger(worldEdit, this); + this.platformCommandManager = new PlatformCommandManager(worldEdit, this); // Register this instance for events worldEdit.getEventBus().register(this); @@ -277,8 +277,8 @@ public class PlatformManager { * * @return the command manager */ - public PlatformCommandMananger getPlatformCommandMananger() { - return platformCommandMananger; + public PlatformCommandManager getPlatformCommandManager() { + return platformCommandManager; } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java new file mode 100644 index 000000000..b3b8e4748 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java @@ -0,0 +1,23 @@ +package com.sk89q.worldedit.function; + +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.world.World; + +public final class ItemUseFunction implements RegionFunction { + private final World world; + private final BaseItem item; + + public ItemUseFunction(World world, BaseItem item) { + this.world = world; + this.item = item; + } + + @Override + public boolean apply(BlockVector3 position) throws WorldEditException { + return world.useItem(position, item, Direction.UP); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java index c583add43..ccf702e16 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java @@ -19,13 +19,22 @@ package com.sk89q.worldedit.util.command; -import com.sk89q.worldedit.extension.platform.PlatformCommandMananger; +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.extension.platform.PlatformCommandManager; +import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import org.enginehub.piston.Command; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.gen.CommandCallListener; +import org.enginehub.piston.gen.CommandRegistration; import org.enginehub.piston.part.SubCommandPart; import java.util.Comparator; +import java.util.List; import java.util.Map; import java.util.function.Function; +import java.util.logging.Logger; import java.util.stream.Collectors; public class CommandUtil { @@ -38,7 +47,7 @@ public class CommandUtil { } private static String clean(String input) { - return PlatformCommandMananger.COMMAND_CLEAN_PATTERN.matcher(input).replaceAll(""); + return PlatformCommandManager.COMMAND_CLEAN_PATTERN.matcher(input).replaceAll(""); } private static final Comparator BY_CLEAN_NAME = @@ -48,6 +57,26 @@ public class CommandUtil { return BY_CLEAN_NAME; } + private static final CommandPermissionsConditionGenerator PERM_GEN = new CommandPermissionsConditionGenerator(); + + public static final Logger COMMAND_LOG = + Logger.getLogger("com.sk89q.worldedit.CommandLog"); + private static final List CALL_LISTENERS = ImmutableList.of( + new CommandLoggingHandler(WorldEdit.getInstance(), COMMAND_LOG) + ); + + public static void register(CommandManager manager, CommandRegistration registration, CI instance) { + registration.containerInstance(instance) + .commandManager(manager) + .listeners(CALL_LISTENERS); + if (registration instanceof CommandPermissionsConditionGenerator.Registration) { + ((CommandPermissionsConditionGenerator.Registration) registration).commandPermissionsConditionGenerator( + PERM_GEN + ); + } + registration.build(); + } + private CommandUtil() { } } From 23279c007eab9e0897976861619751f6466786fc Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Fri, 26 Apr 2019 01:38:06 -0700 Subject: [PATCH 33/57] Fix intialization, rework registration --- .../worldedit/command/ApplyBrushCommands.java | 27 ++++++++-- .../worldedit/command/PaintBrushCommands.java | 27 ++++++++-- .../command/factory/ItemUseFactory.java | 19 +++++++ .../command/factory/ReplaceFactory.java | 19 +++++++ .../command/factory/TreeGeneratorFactory.java | 19 +++++++ .../platform/PlatformCommandManager.java | 45 +++++++++------- .../worldedit/function/ItemUseFunction.java | 19 +++++++ .../command/CommandRegistrationHandler.java | 54 +++++++++++++++++++ .../worldedit/util/command/CommandUtil.java | 29 ---------- 9 files changed, 202 insertions(+), 56 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index 2e9297b24..d324c3484 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -1,3 +1,22 @@ +/* + * 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; import com.google.common.collect.ImmutableList; @@ -5,9 +24,9 @@ import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; import com.sk89q.worldedit.command.factory.ItemUseFactory; import com.sk89q.worldedit.command.factory.ReplaceFactory; +import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.Contextual; @@ -16,7 +35,7 @@ import com.sk89q.worldedit.function.factory.Apply; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.command.CommandUtil; +import com.sk89q.worldedit.util.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.CommandManager; @@ -47,14 +66,14 @@ public class ApplyBrushCommands { .ofTypes(ImmutableList.of(Key.of(double.class))) .build(); - public static void register(CommandManager commandManager) { + public static void register(CommandManager commandManager, CommandRegistrationHandler registration) { commandManager.register("apply", builder -> { builder.description(TextComponent.of("Apply brush, apply a function to every block")); builder.action(org.enginehub.piston.Command.Action.NULL_ACTION); CommandManager manager = DefaultCommandManagerService.getInstance() .newCommandManager(); - CommandUtil.register( + registration.register( manager, ApplyBrushCommandsRegistration.builder(), new ApplyBrushCommands() diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java index 649c2988b..c365e129f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -1,3 +1,22 @@ +/* + * 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; import com.google.common.collect.ImmutableList; @@ -5,9 +24,9 @@ import com.google.common.collect.ImmutableSet; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; -import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; import com.sk89q.worldedit.command.factory.ItemUseFactory; import com.sk89q.worldedit.command.factory.ReplaceFactory; +import com.sk89q.worldedit.command.factory.TreeGeneratorFactory; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.Contextual; @@ -16,7 +35,7 @@ import com.sk89q.worldedit.function.factory.Paint; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.command.CommandUtil; +import com.sk89q.worldedit.util.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.CommandManager; @@ -52,14 +71,14 @@ public class PaintBrushCommands { .ofTypes(ImmutableList.of(Key.of(double.class))) .build(); - public static void register(CommandManager commandManager) { + public static void register(CommandManager commandManager, CommandRegistrationHandler registration) { commandManager.register("paint", builder -> { builder.description(TextComponent.of("Paint brush, apply a function to a surface")); builder.action(org.enginehub.piston.Command.Action.NULL_ACTION); CommandManager manager = DefaultCommandManagerService.getInstance() .newCommandManager(); - CommandUtil.register( + registration.register( manager, PaintBrushCommandsRegistration.builder(), new PaintBrushCommands() diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java index 33cd470c8..8b25780d4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ItemUseFactory.java @@ -1,3 +1,22 @@ +/* + * 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.factory; import com.sk89q.worldedit.EditSession; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java index 03453fcd7..4c1797b52 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/ReplaceFactory.java @@ -1,3 +1,22 @@ +/* + * 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.factory; import com.sk89q.worldedit.extent.NullExtent; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java index 47548b4d5..76d875851 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/factory/TreeGeneratorFactory.java @@ -1,3 +1,22 @@ +/* + * 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.factory; import com.sk89q.worldedit.EditSession; 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 ed93a11b8..b8e5f2101 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 @@ -84,9 +84,11 @@ import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.annotation.Selection; +import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.util.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.util.formatting.text.TextComponent; @@ -124,8 +126,6 @@ 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.CommandUtil.COMMAND_LOG; -import static com.sk89q.worldedit.util.command.CommandUtil.register; /** * Handles the registration and invocation of commands. @@ -136,6 +136,8 @@ public final class PlatformCommandManager { public static final Pattern COMMAND_CLEAN_PATTERN = Pattern.compile("^[/]+"); private static final Logger log = LoggerFactory.getLogger(PlatformCommandManager.class); + private static final java.util.logging.Logger COMMAND_LOG = + java.util.logging.Logger.getLogger("com.sk89q.worldedit.CommandLog"); private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$"); private final WorldEdit worldEdit; @@ -144,6 +146,7 @@ public final class PlatformCommandManager { private final InjectedValueStore globalInjectedValues; private final DynamicStreamHandler dynamicHandler = new DynamicStreamHandler(); private final WorldEditExceptionConverter exceptionConverter; + private final CommandRegistrationHandler registration; /** * Create a new instance. @@ -159,6 +162,10 @@ public final class PlatformCommandManager { this.commandManager = DefaultCommandManagerService.getInstance() .newCommandManager(); this.globalInjectedValues = MapBackedValueStore.create(); + this.registration = new CommandRegistrationHandler( + ImmutableList.of( + new CommandLoggingHandler(worldEdit, COMMAND_LOG) + )); // setup separate from main constructor // ensures that everything is definitely assigned initialize(); @@ -239,7 +246,7 @@ public final class PlatformCommandManager { CommandManager manager = DefaultCommandManagerService.getInstance() .newCommandManager(); - register( + this.registration.register( manager, registration, instance @@ -282,8 +289,8 @@ public final class PlatformCommandManager { BrushCommandsRegistration.builder(), new BrushCommands(worldEdit), manager -> { - PaintBrushCommands.register(manager); - ApplyBrushCommands.register(manager); + PaintBrushCommands.register(manager, registration); + ApplyBrushCommands.register(manager, registration); } ); registerSubCommands( @@ -293,72 +300,72 @@ public final class PlatformCommandManager { WorldEditCommandsRegistration.builder(), new WorldEditCommands(worldEdit) ); - register( + this.registration.register( commandManager, BiomeCommandsRegistration.builder(), new BiomeCommands() ); - register( + this.registration.register( commandManager, ChunkCommandsRegistration.builder(), new ChunkCommands(worldEdit) ); - register( + this.registration.register( commandManager, ClipboardCommandsRegistration.builder(), new ClipboardCommands() ); - register( + this.registration.register( commandManager, GeneralCommandsRegistration.builder(), new GeneralCommands(worldEdit) ); - register( + this.registration.register( commandManager, GenerationCommandsRegistration.builder(), new GenerationCommands(worldEdit) ); - register( + this.registration.register( commandManager, HistoryCommandsRegistration.builder(), new HistoryCommands(worldEdit) ); - register( + this.registration.register( commandManager, NavigationCommandsRegistration.builder(), new NavigationCommands(worldEdit) ); - register( + this.registration.register( commandManager, RegionCommandsRegistration.builder(), new RegionCommands() ); - register( + this.registration.register( commandManager, ScriptingCommandsRegistration.builder(), new ScriptingCommands(worldEdit) ); - register( + this.registration.register( commandManager, SelectionCommandsRegistration.builder(), new SelectionCommands(worldEdit) ); - register( + this.registration.register( commandManager, SnapshotUtilCommandsRegistration.builder(), new SnapshotUtilCommands(worldEdit) ); - register( + this.registration.register( commandManager, ToolCommandsRegistration.builder(), new ToolCommands(worldEdit) ); - register( + this.registration.register( commandManager, ToolUtilCommandsRegistration.builder(), new ToolUtilCommands(worldEdit) ); - register( + this.registration.register( commandManager, UtilityCommandsRegistration.builder(), new UtilityCommands(worldEdit) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java index b3b8e4748..4e439f0c3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/ItemUseFunction.java @@ -1,3 +1,22 @@ +/* + * 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.function; import com.sk89q.worldedit.WorldEditException; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java new file mode 100644 index 000000000..8e243be98 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java @@ -0,0 +1,54 @@ +/* + * 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.util.command; + +import com.google.common.collect.ImmutableList; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; +import com.sk89q.worldedit.internal.command.CommandLoggingHandler; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.gen.CommandCallListener; +import org.enginehub.piston.gen.CommandRegistration; + +import java.util.List; +import java.util.logging.Logger; + +public class CommandRegistrationHandler { + + private static final CommandPermissionsConditionGenerator PERM_GEN = new CommandPermissionsConditionGenerator(); + + private final List callListeners; + + public CommandRegistrationHandler(List callListeners) { + this.callListeners = ImmutableList.copyOf(callListeners); + } + + public void register(CommandManager manager, CommandRegistration registration, CI instance) { + registration.containerInstance(instance) + .commandManager(manager) + .listeners(callListeners); + if (registration instanceof CommandPermissionsConditionGenerator.Registration) { + ((CommandPermissionsConditionGenerator.Registration) registration).commandPermissionsConditionGenerator( + PERM_GEN + ); + } + registration.build(); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java index ccf702e16..3d86fbfb9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java @@ -19,22 +19,13 @@ package com.sk89q.worldedit.util.command; -import com.google.common.collect.ImmutableList; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.extension.platform.PlatformCommandManager; -import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import org.enginehub.piston.Command; -import org.enginehub.piston.CommandManager; -import org.enginehub.piston.gen.CommandCallListener; -import org.enginehub.piston.gen.CommandRegistration; import org.enginehub.piston.part.SubCommandPart; import java.util.Comparator; -import java.util.List; import java.util.Map; import java.util.function.Function; -import java.util.logging.Logger; import java.util.stream.Collectors; public class CommandUtil { @@ -57,26 +48,6 @@ public class CommandUtil { return BY_CLEAN_NAME; } - private static final CommandPermissionsConditionGenerator PERM_GEN = new CommandPermissionsConditionGenerator(); - - public static final Logger COMMAND_LOG = - Logger.getLogger("com.sk89q.worldedit.CommandLog"); - private static final List CALL_LISTENERS = ImmutableList.of( - new CommandLoggingHandler(WorldEdit.getInstance(), COMMAND_LOG) - ); - - public static void register(CommandManager manager, CommandRegistration registration, CI instance) { - registration.containerInstance(instance) - .commandManager(manager) - .listeners(CALL_LISTENERS); - if (registration instanceof CommandPermissionsConditionGenerator.Registration) { - ((CommandPermissionsConditionGenerator.Registration) registration).commandPermissionsConditionGenerator( - PERM_GEN - ); - } - registration.build(); - } - private CommandUtil() { } } From 968decf62eebde9ed77143a27edc6fa56e5036ac Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Fri, 26 Apr 2019 23:42:57 +1000 Subject: [PATCH 34/57] Remove the -l lightning flag from butcher --- build.gradle | 2 -- .../sk89q/worldedit/command/BrushCommands.java | 6 +----- .../sk89q/worldedit/command/UtilityCommands.java | 6 +----- .../worldedit/command/util/CreatureButcher.java | 15 --------------- 4 files changed, 2 insertions(+), 27 deletions(-) diff --git a/build.gradle b/build.gradle index 45076d4ed..41de17bb8 100644 --- a/build.gradle +++ b/build.gradle @@ -86,8 +86,6 @@ subprojects { mavenCentral() maven { url "http://maven.sk89q.com/repo/" } maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } - // temporary, for Piston - mavenLocal() } } 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 d187723ba..0b29fdede 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 @@ -257,9 +257,7 @@ public class BrushCommands { @Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)") boolean killFriendly, @Switch(name = 'r', desc = "Also destroy armor stands") - boolean killArmorStands, - @Switch(name = 'l', desc = "Kill via lightning. Currently non-functioning.") - boolean killWithLightning) throws WorldEditException { + boolean killArmorStands) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); double maxRadius = config.maxBrushRadius; @@ -284,8 +282,6 @@ public class BrushCommands { flags.or(CreatureButcher.Flags.TAGGED , killWithName, "worldedit.butcher.tagged"); flags.or(CreatureButcher.Flags.ARMOR_STAND , killArmorStands, "worldedit.butcher.armorstands"); - flags.or(CreatureButcher.Flags.WITH_LIGHTNING, killWithLightning, "worldedit.butcher.lightning"); - BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); tool.setSize(radius); tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher"); 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 12988ab56..ea292a855 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 @@ -375,9 +375,7 @@ public class UtilityCommands { @Switch(name = 'f', desc = "Also kill all friendly mobs (Applies the flags `-abgnpt`)") boolean killFriendly, @Switch(name = 'r', desc = "Also destroy armor stands") - boolean killArmorStands, - @Switch(name = 'l', desc = "Kill via lightning. Currently non-functioning.") - boolean killWithLightning) throws WorldEditException { + boolean killArmorStands) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); Player player = actor instanceof Player ? (Player) actor : null; @@ -406,8 +404,6 @@ public class UtilityCommands { flags.or(CreatureButcher.Flags.TAGGED, killWithName, "worldedit.butcher.tagged"); flags.or(CreatureButcher.Flags.ARMOR_STAND, killArmorStands, "worldedit.butcher.armorstands"); - flags.or(CreatureButcher.Flags.WITH_LIGHTNING, killWithLightning, "worldedit.butcher.lightning"); - int killed = killMatchingEntities(radius, player, flags::createFunction); actor.print("Killed " + killed + (killed != 1 ? " mobs" : " mob") + (radius < 0 ? "" : " in a radius of " + radius) + "."); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java index 940d6a99c..e43fee9d4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/CreatureButcher.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.command.util; -import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.worldedit.entity.metadata.EntityProperties; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.EntityFunction; @@ -39,7 +38,6 @@ public class CreatureButcher { public static final int TAGGED = 1 << 5; public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED; public static final int ARMOR_STAND = 1 << 6; - public static final int WITH_LIGHTNING = 1 << 20; private Flags() { } @@ -64,19 +62,6 @@ public class CreatureButcher { } } - public void fromCommand(CommandContext args) { - or(Flags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls. - or(Flags.PETS , args.hasFlag('p'), "worldedit.butcher.pets"); - or(Flags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs"); - or(Flags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems"); - or(Flags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals"); - or(Flags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient"); - or(Flags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged"); - or(Flags.ARMOR_STAND , args.hasFlag('r'), "worldedit.butcher.armorstands"); - - or(Flags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning"); - } - public EntityFunction createFunction() { return entity -> { boolean killPets = (flags & Flags.PETS) != 0; From f94093239f019c5be4a4d5b692414fdd2a4aa8c5 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sat, 27 Apr 2019 16:46:13 +1000 Subject: [PATCH 35/57] Setup a registry converter --- .../worldedit/command/WorldEditCommands.java | 20 ++-- .../command/argument/NumberParser.java | 6 +- .../command/argument/RegistryConverter.java | 98 +++++++++++++++++++ .../command/argument/StringParser.java | 6 +- .../platform/PlatformCommandManager.java | 2 + 5 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java 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 7586b0109..0d19d1538 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 @@ -48,6 +48,7 @@ import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.TextStyle; +import java.time.zone.ZoneRulesException; import java.util.List; import java.util.Locale; @@ -68,7 +69,7 @@ public class WorldEditCommands { ) public void version(Actor actor) throws WorldEditException { actor.print("WorldEdit version " + WorldEdit.getVersion()); - actor.print("https://github.com/sk89q/worldedit/"); + actor.print("https://github.com/EngineHub/worldedit/"); PlatformManager pm = we.getPlatformManager(); @@ -141,13 +142,16 @@ public class WorldEditCommands { public void tz(Player player, LocalSession session, @Arg(desc = "The timezone to set") String timezone) throws WorldEditException { - ZoneId tz = ZoneId.of(timezone); - session.setTimezone(tz); - player.print("Timezone set for this session to: " + tz.getDisplayName( - TextStyle.FULL, Locale.ENGLISH - )); - player.print("The current time in that timezone is: " - + dateFormat.format(ZonedDateTime.now(tz))); + try { + ZoneId tz = ZoneId.of(timezone); + session.setTimezone(tz); + player.print("Timezone set for this session to: " + tz.getDisplayName( + TextStyle.FULL, Locale.ENGLISH + )); + player.print("The current time in that timezone is: " + dateFormat.format(ZonedDateTime.now(tz))); + } catch (ZoneRulesException e) { + player.printError("Invalid timezone"); + } } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java index 349089e50..dcb06b4f9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java @@ -29,17 +29,19 @@ import com.sk89q.worldedit.util.command.composition.CommandExecutor; import java.util.Collections; import java.util.List; +import javax.annotation.Nullable; + public class NumberParser implements CommandExecutor { private final String name; private final String description; - private final String defaultSuggestion; + private final @Nullable String defaultSuggestion; public NumberParser(String name, String description) { this(name, description, null); } - public NumberParser(String name, String description, String defaultSuggestion) { + public NumberParser(String name, String description, @Nullable String defaultSuggestion) { this.name = name; this.description = description; this.defaultSuggestion = defaultSuggestion; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java new file mode 100644 index 000000000..5e9d2ed66 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java @@ -0,0 +1,98 @@ +/* + * 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.registry.Registry; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockCategory; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.entity.EntityType; +import com.sk89q.worldedit.world.fluid.FluidCategory; +import com.sk89q.worldedit.world.fluid.FluidType; +import com.sk89q.worldedit.world.gamemode.GameMode; +import com.sk89q.worldedit.world.item.ItemCategory; +import com.sk89q.worldedit.world.item.ItemType; +import com.sk89q.worldedit.world.weather.WeatherType; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.converter.ArgumentConverter; +import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; +import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; + +import java.util.List; +import java.util.stream.Collectors; + +public class RegistryConverter implements ArgumentConverter { + + public static void register(CommandManager commandManager) { + commandManager.registerConverter(Key.of(BlockType.class), + new RegistryConverter<>(BlockType.class, BlockType.REGISTRY)); + commandManager.registerConverter(Key.of(BlockCategory.class), + new RegistryConverter<>(BlockCategory.class, BlockCategory.REGISTRY)); + commandManager.registerConverter(Key.of(ItemType.class), + new RegistryConverter<>(ItemType.class, ItemType.REGISTRY)); + commandManager.registerConverter(Key.of(ItemCategory.class), + new RegistryConverter<>(ItemCategory.class, ItemCategory.REGISTRY)); + commandManager.registerConverter(Key.of(BiomeType.class), + new RegistryConverter<>(BiomeType.class, BiomeType.REGISTRY)); + commandManager.registerConverter(Key.of(EntityType.class), + new RegistryConverter<>(EntityType.class, EntityType.REGISTRY)); + commandManager.registerConverter(Key.of(FluidType.class), + new RegistryConverter<>(FluidType.class, FluidType.REGISTRY)); + commandManager.registerConverter(Key.of(FluidCategory.class), + new RegistryConverter<>(FluidCategory.class, FluidCategory.REGISTRY)); + commandManager.registerConverter(Key.of(GameMode.class), + new RegistryConverter<>(GameMode.class, GameMode.REGISTRY)); + commandManager.registerConverter(Key.of(WeatherType.class), + new RegistryConverter<>(WeatherType.class, WeatherType.REGISTRY)); + } + + private final Registry registry; + private final TextComponent choices; + + public RegistryConverter(Class clazz, Registry registry) { + this.registry = registry; + this.choices = TextComponent.of("any " + clazz.getSimpleName()); + } + + @Override + public Component describeAcceptableArguments() { + return this.choices; + } + + @Override + public ConversionResult convert(String argument, InjectedValueAccess injectedValueAccess) { + V result = registry.get(argument); + return result == null + ? FailedConversion.from(new IllegalArgumentException("Not a valid choice: " + argument)) + : SuccessfulConversion.fromSingle(result); + } + + @Override + public List getSuggestions(String input) { + return registry.keySet().stream() + .filter(string -> string.startsWith(input)) + .collect(Collectors.toList()); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java index 298f999e4..30c02381f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java @@ -29,17 +29,19 @@ import com.sk89q.worldedit.util.command.composition.CommandExecutor; import java.util.Collections; import java.util.List; +import javax.annotation.Nullable; + public class StringParser implements CommandExecutor { private final String name; private final String description; - private final String defaultSuggestion; + private final @Nullable String defaultSuggestion; public StringParser(String name, String description) { this(name, description, null); } - public StringParser(String name, String description, String defaultSuggestion) { + public StringParser(String name, String description, @Nullable String defaultSuggestion) { this.name = name; this.description = description; this.defaultSuggestion = defaultSuggestion; 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 b8e5f2101..c8f363a11 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 @@ -75,6 +75,7 @@ import com.sk89q.worldedit.command.argument.EnumConverter; import com.sk89q.worldedit.command.argument.ExpandAmountConverter; import com.sk89q.worldedit.command.argument.FactoryConverter; import com.sk89q.worldedit.command.argument.RegionFactoryConverter; +import com.sk89q.worldedit.command.argument.RegistryConverter; import com.sk89q.worldedit.command.argument.VectorConverter; import com.sk89q.worldedit.command.argument.ZonedDateTimeConverter; import com.sk89q.worldedit.command.util.PermissionCondition; @@ -196,6 +197,7 @@ public final class PlatformCommandManager { } VectorConverter.register(commandManager); EnumConverter.register(commandManager); + RegistryConverter.register(commandManager); ExpandAmountConverter.register(commandManager); ZonedDateTimeConverter.register(commandManager); BooleanConverter.register(commandManager); From 7dcf8f5a457715d9d9819d795c02503c457b8b8d Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sat, 27 Apr 2019 17:32:02 +1000 Subject: [PATCH 36/57] Fixed //setbiome --- .../main/java/com/sk89q/worldedit/command/BiomeCommands.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index 0bf6878dd..f6aad8a0d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -178,7 +178,7 @@ public class BiomeCommands { @Logging(REGION) @CommandPermissions("worldedit.biome.set") public void setBiome(Player player, LocalSession session, EditSession editSession, - BiomeType target, + @Arg(desc = "Biome type.") BiomeType target, @Switch(name = 'p', desc = "Use your current position") boolean atPosition) throws WorldEditException { World world = player.getWorld(); From 0960f70e6b50d875df82415d094d5c5ffc4d4be0 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sat, 27 Apr 2019 03:33:13 -0700 Subject: [PATCH 37/57] Update to latest Piston changes --- .../worldedit/command/SchematicCommands.java | 8 ++- .../command/util/PrintCommandHelp.java | 14 +++-- .../platform/PlatformCommandManager.java | 28 +++++++--- .../command/WorldEditExceptionConverter.java | 56 ++++++++++--------- .../formatting/component/CommandUsageBox.java | 26 +++++---- 5 files changed, 77 insertions(+), 55 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 5fd4c6d98..c06fe851f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -39,6 +39,7 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.file.FilenameException; import org.enginehub.piston.annotation.Command; @@ -159,7 +160,7 @@ public class SchematicCommands { boolean overwrite = f.exists(); if (overwrite) { if (!player.hasPermission("worldedit.schematic.delete")) { - throw new StopExecutionException("That schematic already exists!"); + throw new StopExecutionException(TextComponent.of("That schematic already exists!")); } if (!allowOverwrite) { player.printError("That schematic already exists. Use the -f flag to overwrite it."); @@ -186,7 +187,8 @@ public class SchematicCommands { File parent = f.getParentFile(); if (parent != null && !parent.exists()) { if (!parent.mkdirs()) { - throw new StopExecutionException("Could not create folder for schematics!"); + throw new StopExecutionException(TextComponent.of( + "Could not create folder for schematics!")); } } @@ -277,7 +279,7 @@ public class SchematicCommands { @Switch(name = 'n', desc = "Sort by date, newest first") boolean newFirst) { if (oldFirst && newFirst) { - throw new StopExecutionException("Cannot sort by oldest and newest."); + throw new StopExecutionException(TextComponent.of("Cannot sort by oldest and newest.")); } File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir); List fileList = allFiles(dir); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java index b1971b0a9..b59578a49 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java @@ -83,13 +83,13 @@ public class PrintCommandHelp { return; } - List visited = new ArrayList<>(); + List visited = new ArrayList<>(); Command currentCommand = detectCommand(manager, commandPath.get(0)); if (currentCommand == null) { actor.printError(String.format("The command '%s' could not be found.", commandPath.get(0))); return; } - visited.add(commandPath.get(0)); + visited.add(currentCommand); // Drill down to the command for (int i = 1; i < commandPath.size(); i++) { @@ -103,8 +103,8 @@ public class PrintCommandHelp { } if (subCommands.containsKey(subCommand)) { - visited.add(subCommand); currentCommand = subCommands.get(subCommand); + visited.add(currentCommand); } else { actor.printError(String.format("The sub-command '%s' under '%s' could not be found.", subCommand, Joiner.on(" ").join(visited))); @@ -116,7 +116,8 @@ public class PrintCommandHelp { if (subCommands.isEmpty()) { // Create the message - CommandUsageBox box = new CommandUsageBox(currentCommand, String.join(" ", visited)); + CommandUsageBox box = new CommandUsageBox(visited, visited.stream() + .map(Command::getName).collect(Collectors.joining(" "))); actor.print(box.create()); } else { printAllCommands(page, perPage, subCommands.values().stream(), actor, visited); @@ -124,7 +125,7 @@ public class PrintCommandHelp { } private static void printAllCommands(int page, int perPage, Stream commandStream, Actor actor, - List commandList) { + List commandList) { // Get a list of aliases List commands = commandStream .sorted(byCleanName()) @@ -151,7 +152,8 @@ public class PrintCommandHelp { // Add each command for (Command mapping : list) { String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName(); - String command = Stream.concat(commandList.stream(), Stream.of(mapping.getName())) + String command = Stream.concat(commandList.stream(), Stream.of(mapping)) + .map(Command::getName) .collect(Collectors.joining(" ", "/", "")); box.appendCommand(alias, mapping.getDescription(), command); } 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 c8f363a11..93ba549dd 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 @@ -94,9 +94,11 @@ import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.util.logging.DynamicStreamHandler; import com.sk89q.worldedit.util.logging.LogFormat; import com.sk89q.worldedit.world.World; +import org.enginehub.piston.ColorConfig; import org.enginehub.piston.Command; import org.enginehub.piston.CommandManager; import org.enginehub.piston.DefaultCommandManagerService; @@ -112,6 +114,7 @@ import org.enginehub.piston.inject.MapBackedValueStore; import org.enginehub.piston.inject.MemoizingValueAccess; import org.enginehub.piston.inject.MergedValueAccess; import org.enginehub.piston.part.SubCommandPart; +import org.enginehub.piston.util.HelpGenerator; import org.enginehub.piston.util.ValueProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -499,21 +502,28 @@ public final class PlatformCommandManager { actor.printError("You are not permitted to do that. Are you in the right mode?"); } } catch (UsageException e) { - String message = e.getMessage(); - actor.printError(message != null ? message : "The command was not used properly (no more help available)."); + actor.print(TextComponent.builder("") + .color(TextColor.RED) + .append(e.getRichMessage()) + .build()); + ImmutableList cmd = e.getCommands(); + if (cmd.size() > 0) { + actor.print(TextComponent.builder("Usage: ") + .color(TextColor.RED) + .append(TextComponent.of("/", ColorConfig.getMainText())) + .append(HelpGenerator.create(cmd).getUsage()) + .build()); + } } catch (CommandExecutionException e) { Throwable t = e.getCause(); actor.printError("Please report this error: [See console]"); actor.printRaw(t.getClass().getName() + ": " + t.getMessage()); log.error("An unexpected error while handling a WorldEdit command", t); } catch (CommandException e) { - String message = e.getMessage(); - if (message != null) { - actor.printError(e.getMessage()); - } else { - actor.printError("An unknown error has occurred! Please see console."); - log.error("An unknown error occurred", e); - } + actor.print(TextComponent.builder("") + .color(TextColor.RED) + .append(e.getRichMessage()) + .build()); } finally { Optional editSessionOpt = context.snapshotMemory().injectedValue(Key.of(EditSession.class)); 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 b75d1c5b3..a11294527 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,6 +21,7 @@ package com.sk89q.worldedit.internal.command; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.DisallowedItemException; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.IncompleteRegionException; @@ -39,6 +40,7 @@ import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.util.command.parametric.ExceptionConverterHelper; import com.sk89q.worldedit.util.command.parametric.ExceptionMatch; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException; import com.sk89q.worldedit.util.io.file.FilenameResolutionException; import com.sk89q.worldedit.util.io.file.InvalidFilenameException; @@ -61,110 +63,114 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { this.worldEdit = worldEdit; } + private CommandException newCommandException(String message, Throwable cause) { + return new CommandException(TextComponent.of(message), cause, ImmutableList.of()); + } + @ExceptionMatch public void convert(NumberFormatException e) throws CommandException { final Matcher matcher = numberFormat.matcher(e.getMessage()); if (matcher.matches()) { - throw new CommandException("Number expected; string \"" + matcher.group(1) - + "\" given.", e, null); + throw newCommandException("Number expected; string \"" + matcher.group(1) + + "\" given.", e); } else { - throw new CommandException("Number expected; string given.", e, null); + throw newCommandException("Number expected; string given.", e); } } @ExceptionMatch public void convert(IncompleteRegionException e) throws CommandException { - throw new CommandException("Make a region selection first.", e, null); + throw newCommandException("Make a region selection first.", e); } @ExceptionMatch public void convert(UnknownItemException e) throws CommandException { - throw new CommandException("Block name '" + e.getID() + "' was not recognized.", e, null); + throw newCommandException("Block name '" + e.getID() + "' was not recognized.", e); } @ExceptionMatch public void convert(InvalidItemException e) throws CommandException { - throw new CommandException(e.getMessage(), e, null); + throw newCommandException(e.getMessage(), e); } @ExceptionMatch public void convert(DisallowedItemException e) throws CommandException { - throw new CommandException("Block '" + e.getID() - + "' not allowed (see WorldEdit configuration).", e, null); + throw newCommandException("Block '" + e.getID() + + "' not allowed (see WorldEdit configuration).", e); } @ExceptionMatch public void convert(MaxChangedBlocksException e) throws CommandException { - throw new CommandException("Max blocks changed in an operation reached (" - + e.getBlockLimit() + ").", e, null); + throw newCommandException("Max blocks changed in an operation reached (" + + e.getBlockLimit() + ").", e); } @ExceptionMatch public void convert(MaxBrushRadiusException e) throws CommandException { - throw new CommandException("Maximum brush radius (in configuration): " + worldEdit.getConfiguration().maxBrushRadius, e, null); + throw newCommandException("Maximum brush radius (in configuration): " + worldEdit.getConfiguration().maxBrushRadius, e); } @ExceptionMatch public void convert(MaxRadiusException e) throws CommandException { - throw new CommandException("Maximum radius (in configuration): " + worldEdit.getConfiguration().maxRadius, e, null); + throw newCommandException("Maximum radius (in configuration): " + worldEdit.getConfiguration().maxRadius, e); } @ExceptionMatch public void convert(UnknownDirectionException e) throws CommandException { - throw new CommandException("Unknown direction: " + e.getDirection(), e, null); + throw newCommandException("Unknown direction: " + e.getDirection(), e); } @ExceptionMatch public void convert(InsufficientArgumentsException e) throws CommandException { - throw new CommandException(e.getMessage(), e, null); + throw newCommandException(e.getMessage(), e); } @ExceptionMatch public void convert(RegionOperationException e) throws CommandException { - throw new CommandException(e.getMessage(), e, null); + throw newCommandException(e.getMessage(), e); } @ExceptionMatch public void convert(ExpressionException e) throws CommandException { - throw new CommandException(e.getMessage(), e, null); + throw newCommandException(e.getMessage(), e); } @ExceptionMatch public void convert(EmptyClipboardException e) throws CommandException { - throw new CommandException("Your clipboard is empty. Use //copy first.", e, null); + throw newCommandException("Your clipboard is empty. Use //copy first.", e); } @ExceptionMatch public void convert(InvalidFilenameException e) throws CommandException { - throw new CommandException("Filename '" + e.getFilename() + "' invalid: " - + e.getMessage(), e, null); + throw newCommandException("Filename '" + e.getFilename() + "' invalid: " + + e.getMessage(), e); } @ExceptionMatch public void convert(FilenameResolutionException e) throws CommandException { - throw new CommandException( - "File '" + e.getFilename() + "' resolution error: " + e.getMessage(), e, null); + throw newCommandException( + "File '" + e.getFilename() + "' resolution error: " + e.getMessage(), e); } @ExceptionMatch public void convert(InvalidToolBindException e) throws CommandException { - throw new CommandException("Can't bind tool to " + e.getItemType().getName() + ": " + e.getMessage(), e, null); + throw newCommandException("Can't bind tool to " + e.getItemType().getName() + ": " + e.getMessage(), e); } @ExceptionMatch public void convert(FileSelectionAbortedException e) throws CommandException { - throw new CommandException("File selection aborted.", e, null); + throw newCommandException("File selection aborted.", e); } @ExceptionMatch public void convert(WorldEditException e) throws CommandException { - throw new CommandException(e.getMessage(), e, null); + throw newCommandException(e.getMessage(), e); } @ExceptionMatch public void convert(IllegalArgumentException e) throws CommandException { - throw new CommandException(e.getMessage(), e, null); + throw newCommandException(e.getMessage(), e); } } 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 69d5339f7..6b6314b73 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 @@ -19,8 +19,10 @@ package com.sk89q.worldedit.util.formatting.component; +import com.google.common.collect.Iterables; import org.enginehub.piston.Command; import org.enginehub.piston.CommandParameters; +import org.enginehub.piston.util.HelpGenerator; import javax.annotation.Nullable; import java.util.List; @@ -39,26 +41,26 @@ public class CommandUsageBox extends TextComponentProducer { /** * Create a new usage box. * - * @param command the command to describe - * @param commandString the command that was used, such as "/we" or "/brush sphere" + * @param commands the commands to describe + * @param commandString the commands that were used, such as "/we" or "/brush sphere" */ - public CommandUsageBox(Command command, String commandString) { - this(command, commandString, null); + public CommandUsageBox(List commands, String commandString) { + this(commands, commandString, null); } /** * Create a new usage box. * - * @param command the command to describe - * @param commandString the command that was used, such as "/we" or "/brush sphere" + * @param commands the commands to describe + * @param commandString the commands that were used, such as "/we" or "/brush sphere" * @param parameters list of parameters to use */ - public CommandUsageBox(Command command, String commandString, @Nullable CommandParameters parameters) { - checkNotNull(command); + public CommandUsageBox(List commands, String commandString, @Nullable CommandParameters parameters) { + checkNotNull(commands); checkNotNull(commandString); - Map subCommands = getSubCommands(command); + Map subCommands = getSubCommands(Iterables.getLast(commands)); if (subCommands.isEmpty()) { - attachCommandUsage(command, commandString); + attachCommandUsage(commands, commandString); } else { attachSubcommandUsage(subCommands, commandString, parameters); } @@ -81,9 +83,9 @@ public class CommandUsageBox extends TextComponentProducer { append(box.create()); } - private void attachCommandUsage(Command description, String commandString) { + private void attachCommandUsage(List commands, String commandString) { MessageBox box = new MessageBox("Help for " + commandString, - new TextComponentProducer().append(description.getFullHelp())); + new TextComponentProducer().append(HelpGenerator.create(commands).getFullHelp())); append(box.create()); } From 62353a46db6e04e85ebe80700477291775790bbd Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sat, 27 Apr 2019 21:57:25 +1000 Subject: [PATCH 38/57] Added a pagination box and use it in Biome List and Chunk List --- .../worldedit/bukkit/BukkitCommandSender.java | 4 +- .../sk89q/worldedit/bukkit/BukkitPlayer.java | 3 +- .../worldedit/command/BiomeCommands.java | 44 ++----- .../worldedit/command/ChunkCommands.java | 13 +- .../worldedit/extension/platform/Actor.java | 5 +- .../extension/platform/PlayerProxy.java | 4 +- .../component/InvalidComponentException.java | 29 +++++ .../util/formatting/component/MessageBox.java | 2 +- .../formatting/component/PaginationBox.java | 119 ++++++++++++++++++ .../component/TextComponentProducer.java | 15 +++ .../sk89q/worldedit/forge/ForgePlayer.java | 4 +- .../worldedit/sponge/SpongeCommandSender.java | 4 +- .../sk89q/worldedit/sponge/SpongePlayer.java | 7 +- 13 files changed, 201 insertions(+), 52 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/InvalidComponentException.java create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java index b82dfe458..2d4ea70cf 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java @@ -26,7 +26,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.auth.AuthorizationException; -import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -94,7 +94,7 @@ public class BukkitCommandSender implements Actor { } @Override - public void print(TextComponent component) { + public void print(Component component) { TextAdapter.sendComponent(sender, component); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 71941a69d..12d7551de 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -31,6 +31,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.HandSide; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -127,7 +128,7 @@ public class BukkitPlayer extends AbstractPlayerActor { } @Override - public void print(TextComponent component) { + public void print(Component component) { TextAdapter.sendComponent(player, component); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index f6aad8a0d..b751dfefe 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.command; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; + import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -42,6 +44,8 @@ import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.component.PaginationBox; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.biome.BiomeType; @@ -51,11 +55,10 @@ import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Switch; -import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; - -import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; +import java.util.stream.Collectors; /** * Implements biome-related commands such as "/biomelist". @@ -76,38 +79,15 @@ public class BiomeCommands { ) @CommandPermissions("worldedit.biome.list") public void biomeList(Player player, - @Arg(desc = "Page number.", def = "0") + @Arg(desc = "Page number.", def = "1") int page) throws WorldEditException { - int offset; - int count = 0; - - if (page < 2) { - page = 1; - offset = 0; - } else { - offset = (page - 1) * 19; - } - BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); - Collection biomes = BiomeType.REGISTRY.values(); - int totalPages = biomes.size() / 19 + 1; - player.print("Available Biomes (page " + page + "/" + totalPages + ") :"); - for (BiomeType biome : biomes) { - if (offset > 0) { - offset--; - } else { - BiomeData data = biomeRegistry.getData(biome); - if (data != null) { - player.print(" " + data.getName()); - if (++count == 19) { - break; - } - } else { - player.print(" "); - } - } - } + List biomes = BiomeType.REGISTRY.values().stream().map(biomeRegistry::getData).collect(Collectors.toList()); + + PaginationBox paginationBox = new PaginationBox("Available Biomes", "/biomelist %page%"); + paginationBox.setComponents(biomes.stream().map(biome -> TextComponent.of(biome.getName())).collect(Collectors.toList())); + player.print(paginationBox.create(page)); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java index 8f9dc6ceb..5dcce1699 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java @@ -33,15 +33,19 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.component.PaginationBox; +import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.storage.LegacyChunkStore; import com.sk89q.worldedit.world.storage.McRegionChunkStore; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; +import org.enginehub.piston.annotation.param.Arg; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.util.Set; +import java.util.stream.Collectors; /** * Commands for working with chunks. @@ -82,12 +86,13 @@ public class ChunkCommands { desc = "List chunks that your selection includes" ) @CommandPermissions("worldedit.listchunks") - public void listChunks(Player player, LocalSession session) throws WorldEditException { + public void listChunks(Player player, LocalSession session, + @Arg(desc = "Page number.", def = "1") int page) throws WorldEditException { Set chunks = session.getSelection(player.getWorld()).getChunks(); - for (BlockVector2 chunk : chunks) { - player.print(LegacyChunkStore.getFilename(chunk)); - } + PaginationBox paginationBox = new PaginationBox("Selected Chunks", "/listchunks %page%"); + paginationBox.setComponents(chunks.stream().map(chunk -> TextComponent.of(chunk.toString())).collect(Collectors.toList())); + player.print(paginationBox.create(page)); } @Command( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index 45160de66..319c9cb02 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -23,6 +23,7 @@ import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.session.SessionOwner; import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.auth.Subject; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import java.io.File; @@ -77,11 +78,11 @@ public interface Actor extends Identifiable, SessionOwner, Subject { void printError(String msg); /** - * Print a {@link TextComponent}. + * Print a {@link Component}. * * @param component The component to print */ - void print(TextComponent component); + void print(Component component); /** * Returns true if the actor can destroy bedrock. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index 2159a2fce..8ecf3cc10 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -31,10 +31,10 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.gamemode.GameMode; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import java.util.UUID; @@ -134,7 +134,7 @@ class PlayerProxy extends AbstractPlayerActor { } @Override - public void print(TextComponent component) { + public void print(Component component) { basePlayer.print(component); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/InvalidComponentException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/InvalidComponentException.java new file mode 100644 index 000000000..bcdfb7f10 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/InvalidComponentException.java @@ -0,0 +1,29 @@ +/* + * 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.util.formatting.component; + +import com.sk89q.worldedit.WorldEditException; + +public class InvalidComponentException extends WorldEditException { + + public InvalidComponentException(String message) { + super(message); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java index 6828589bc..549943541 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java @@ -32,7 +32,7 @@ public class MessageBox extends TextComponentProducer { private static final int GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH = 47; - private final TextComponentProducer contents; + private TextComponentProducer contents; /** * Create a new box. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java new file mode 100644 index 000000000..fecdac40c --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java @@ -0,0 +1,119 @@ +/* + * 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.util.formatting.component; + +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.event.HoverEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; + +import java.util.List; + +public class PaginationBox extends MessageBox { + + public static final int IDEAL_ROWS_FOR_PLAYER = 8; + + private String pageCommand; + private List components; + private int componentsPerPage = IDEAL_ROWS_FOR_PLAYER; + + /** + * Creates a Paginated component + * + * @param title The title + */ + public PaginationBox(String title) { + this(title, null); + } + + /** + * Sets the components to create pages for. + * + * @param components The components + */ + public void setComponents(List components) { + this.components = components; + } + + public void setComponentsPerPage(int componentsPerPage) { + this.componentsPerPage = componentsPerPage; + } + + /** + * Creates a Paginated component + * + * @param title The title + * @param pageCommand The command to run to switch page, with %page% representing page number + */ + public PaginationBox(String title, String pageCommand) { + super(title, new TextComponentProducer()); + + if (pageCommand != null && !pageCommand.contains("%page%")) { + throw new IllegalArgumentException("pageCommand must contain %page% if provided."); + } + this.pageCommand = pageCommand; + } + + public TextComponent create(int page) throws InvalidComponentException { + if (components == null) { + throw new IllegalStateException("You must provide components before creating."); + } + if (page == 1 && components.isEmpty()) { + return getContents().reset().append("There's nothing to see here").create(); + } + int pageCount = (int) Math.ceil(components.size() / (double) componentsPerPage); + if (page < 1 || page > pageCount) { + throw new InvalidComponentException("Invalid page number."); + } + getContents().reset(); + for (int i = (page - 1) * componentsPerPage; i < Math.min(page * componentsPerPage, components.size()); i++) { + getContents().append(components.get(i)).newline(); + } + TextComponent pageNumberComponent = TextComponent.of("Page ", TextColor.YELLOW) + .append(TextComponent.of(String.valueOf(page), TextColor.GOLD)) + .append(TextComponent.of(" of ")) + .append(TextComponent.of(String.valueOf(pageCount), TextColor.GOLD)); + + if (pageCommand != null) { + if (page > 1) { + TextComponent prevComponent = TextComponent.of("<<< ", TextColor.GOLD) + .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page - 1)))) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate"))); + getContents().append(prevComponent); + } + getContents().append(pageNumberComponent); + if (page < pageCount) { + TextComponent nextComponent = TextComponent.of(" >>>", TextColor.GOLD) + .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page + 1)))) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate"))); + getContents().append(nextComponent); + } + } else { + getContents().append(pageNumberComponent); + } + return TextComponent.of("").append(Component.newline()).append(super.create()); + } + + @Override + public TextComponent create() { + throw new IllegalStateException("Pagination components must be created with a page"); + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextComponentProducer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextComponentProducer.java index 32a9f8d30..fed34ea23 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextComponentProducer.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/TextComponentProducer.java @@ -62,7 +62,22 @@ public class TextComponentProducer { return this; } + /** + * Create a TextComponent from this producer. + * + * @return The component + */ public TextComponent create() { return builder.build(); } + + /** + * Reset the producer to a clean slate. + * + * @return The producer, for chaining + */ + public TextComponentProducer reset() { + builder = TextComponent.builder().content(""); + return this; + } } diff --git a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java index edc5275ab..c478934c5 100644 --- a/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java +++ b/worldedit-forge/src/main/java/com/sk89q/worldedit/forge/ForgePlayer.java @@ -31,7 +31,7 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.serializer.gson.GsonComponentSerializer; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -143,7 +143,7 @@ public class ForgePlayer extends AbstractPlayerActor { } @Override - public void print(TextComponent component) { + public void print(Component component) { this.player.sendMessage(ITextComponent.Serializer.fromJson(GsonComponentSerializer.INSTANCE.serialize(component))); } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java index e44146b3c..e6eac1f83 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongeCommandSender.java @@ -26,7 +26,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.auth.AuthorizationException; -import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.adapter.spongeapi.TextAdapter; import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.entity.living.player.Player; @@ -92,7 +92,7 @@ public class SpongeCommandSender implements Actor { } @Override - public void print(TextComponent component) { + public void print(Component component) { TextAdapter.sendComponent(sender, component); } diff --git a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java index 099780b3d..82723fe93 100644 --- a/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java +++ b/worldedit-sponge/src/main/java/com/sk89q/worldedit/sponge/SpongePlayer.java @@ -31,13 +31,12 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.session.SessionKey; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.adapter.spongeapi.TextAdapter; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemTypes; - -import com.sk89q.worldedit.util.formatting.text.TextComponent; -import com.sk89q.worldedit.util.formatting.text.adapter.spongeapi.TextAdapter; import org.spongepowered.api.Sponge; import org.spongepowered.api.data.type.HandTypes; import org.spongepowered.api.entity.living.player.Player; @@ -152,7 +151,7 @@ public class SpongePlayer extends AbstractPlayerActor { } @Override - public void print(TextComponent component) { + public void print(Component component) { TextAdapter.sendComponent(player, component); } From b3053f19ce07be2b5eb7b12cf59feb51574f8ae2 Mon Sep 17 00:00:00 2001 From: wizjany Date: Sun, 28 Apr 2019 01:12:05 -0400 Subject: [PATCH 39/57] Pagination changes and cleanup. Refactored PaginationBox to be abstract. Implementations can generate individual components as needed now. Add lots of Component usage to schematic list, help listings, etc. Fix a few schematic and file resolution issues. --- .../sk89q/worldedit/bukkit/BukkitPlayer.java | 1 - .../bukkit/BukkitServerInterface.java | 2 +- .../java/com/sk89q/worldedit/WorldEdit.java | 13 ++- .../worldedit/command/BiomeCommands.java | 12 +-- .../worldedit/command/ChunkCommands.java | 9 +- .../worldedit/command/SchematicCommands.java | 62 +++----------- .../worldedit/command/SelectionCommands.java | 4 +- .../worldedit/command/UtilityCommands.java | 23 ++++- .../command/util/PrintCommandHelp.java | 78 ++++++++--------- .../worldedit/extension/platform/Actor.java | 1 - .../platform/PlatformCommandManager.java | 23 +++-- .../clipboard/io/SpongeSchematicReader.java | 9 +- .../formatting/component/CommandListBox.java | 72 +++++++++++----- .../formatting/component/CommandUsageBox.java | 11 +-- .../util/formatting/component/MessageBox.java | 49 +++++++---- .../formatting/component/PaginationBox.java | 84 ++++++++++++------- .../component/SchematicPaginationBox.java | 56 +++++++++++++ 17 files changed, 307 insertions(+), 202 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 12d7551de..c0dc5c7e2 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -38,7 +38,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.adapter.bukkit.TextAdapter; import org.bukkit.Bukkit; import org.bukkit.Location; 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 8461826f9..34ad4c257 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 @@ -72,7 +72,7 @@ public class BukkitServerInterface implements MultiUserPlatform { if (plugin.getBukkitImplAdapter() != null) { return plugin.getBukkitImplAdapter().getDataVersion(); } - return 0; + return -1; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java index e206f383f..205cfde5f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -303,6 +303,17 @@ public final class WorldEdit { if (exts.size() != 1) { exts = exts.subList(0, 1); } + } else { + int dot = filename.lastIndexOf('.'); + if (dot < 0 || dot == filename.length() - 1) { + String currentExt = filename.substring(dot + 1); + if (exts.contains(currentExt) && checkFilename(filename)) { + File f = new File(dir, filename); + if (f.exists()) { + return f; + } + } + } } File result = null; for (Iterator iter = exts.iterator(); iter.hasNext() && (result == null || (!isSave && !result.exists()));) { @@ -317,7 +328,7 @@ public final class WorldEdit { private File getSafeFileWithExtension(File dir, String filename, String extension) { if (extension != null) { int dot = filename.lastIndexOf('.'); - if (dot < 0 || !filename.substring(dot).equalsIgnoreCase(extension)) { + if (dot < 0 || dot == filename.length() - 1 || !filename.substring(dot + 1).equalsIgnoreCase(extension)) { filename += "." + extension; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index b751dfefe..bb4788f9e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -45,7 +45,6 @@ import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.component.PaginationBox; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.biome.BiomeType; @@ -56,7 +55,7 @@ import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Switch; import java.util.HashSet; -import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -83,10 +82,11 @@ public class BiomeCommands { int page) throws WorldEditException { BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); - List biomes = BiomeType.REGISTRY.values().stream().map(biomeRegistry::getData).collect(Collectors.toList()); - PaginationBox paginationBox = new PaginationBox("Available Biomes", "/biomelist %page%"); - paginationBox.setComponents(biomes.stream().map(biome -> TextComponent.of(biome.getName())).collect(Collectors.toList())); + PaginationBox paginationBox = PaginationBox.fromStrings("Available Biomes", "/biomelist %page%", + BiomeType.REGISTRY.values().stream() + .map(biomeRegistry::getData).filter(Objects::nonNull) + .map(BiomeData::getName).collect(Collectors.toList())); player.print(paginationBox.create(page)); } @@ -152,7 +152,7 @@ public class BiomeCommands { @Command( name = "/setbiome", - desc = "Sets the biome of the player's current block or region.", + desc = "Sets the biome of your current block or region.", descFooter = "By default, uses all the blocks in your selection" ) @Logging(REGION) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java index 5dcce1699..8dc99dc15 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java @@ -34,7 +34,6 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.formatting.component.PaginationBox; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.world.storage.LegacyChunkStore; import com.sk89q.worldedit.world.storage.McRegionChunkStore; import org.enginehub.piston.annotation.Command; @@ -62,10 +61,10 @@ public class ChunkCommands { @Command( name = "chunkinfo", - desc = "Get information about the chunk that you are inside" + desc = "Get information about the chunk you're inside" ) @CommandPermissions("worldedit.chunkinfo") - public void chunkInfo(Player player) throws WorldEditException { + public void chunkInfo(Player player) { Location pos = player.getBlockIn(); int chunkX = (int) Math.floor(pos.getBlockX() / 16.0); int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0); @@ -90,8 +89,8 @@ public class ChunkCommands { @Arg(desc = "Page number.", def = "1") int page) throws WorldEditException { Set chunks = session.getSelection(player.getWorld()).getChunks(); - PaginationBox paginationBox = new PaginationBox("Selected Chunks", "/listchunks %page%"); - paginationBox.setComponents(chunks.stream().map(chunk -> TextComponent.of(chunk.toString())).collect(Collectors.toList())); + PaginationBox paginationBox = PaginationBox.fromStrings("Selected Chunks", "/listchunks %page%", + chunks.stream().map(BlockVector2::toString).collect(Collectors.toList())); player.print(paginationBox.create(page)); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index c06fe851f..fe4f5f1de 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.command; -import com.google.common.collect.Multimap; -import com.google.common.io.Files; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -39,6 +37,8 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.util.formatting.component.PaginationBox; +import com.sk89q.worldedit.util.formatting.component.SchematicPaginationBox; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.file.FilenameException; @@ -60,7 +60,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.regex.Pattern; import static com.google.common.base.Preconditions.checkNotNull; @@ -70,10 +69,6 @@ import static com.google.common.base.Preconditions.checkNotNull; @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class SchematicCommands { - /** - * 9 schematics per page fits in the MC chat window. - */ - private static final int SCHEMATICS_PER_PAGE = 9; private static final Logger log = LoggerFactory.getLogger(SchematicCommands.class); private final WorldEdit worldEdit; @@ -100,7 +95,9 @@ public class SchematicCommands { LocalConfiguration config = worldEdit.getConfiguration(); File dir = worldEdit.getWorkingDirectoryFile(config.saveDir); - File f = worldEdit.getSafeOpenFile(player, dir, filename, BuiltInClipboardFormat.SPONGE_SCHEMATIC.getPrimaryFileExtension(), ClipboardFormats.getFileExtensionArray()); + File f = worldEdit.getSafeOpenFile(player, dir, filename, + BuiltInClipboardFormat.SPONGE_SCHEMATIC.getPrimaryFileExtension(), + ClipboardFormats.getFileExtensionArray()); if (!f.exists()) { player.printError("Schematic " + filename + " does not exist!"); @@ -128,7 +125,7 @@ public class SchematicCommands { player.print(filename + " loaded. Paste it with //paste"); } catch (IOException e) { player.printError("Schematic could not read or it does not exist: " + e.getMessage()); - log.warn("Failed to load a saved clipboard", e); + log.warn("Failed to load schematic: " + e.getMessage()); } } @@ -277,7 +274,7 @@ public class SchematicCommands { @Switch(name = 'd', desc = "Sort by date, oldest first") boolean oldFirst, @Switch(name = 'n', desc = "Sort by date, newest first") - boolean newFirst) { + boolean newFirst) throws WorldEditException { if (oldFirst && newFirst) { throw new StopExecutionException(TextComponent.of("Cannot sort by oldest and newest.")); } @@ -292,16 +289,6 @@ public class SchematicCommands { File[] files = new File[fileList.size()]; fileList.toArray(files); - int pageCount = files.length / SCHEMATICS_PER_PAGE + 1; - if (page < 1) { - actor.printError("Page must be at least 1"); - return; - } - if (page > pageCount) { - actor.printError("Page must be less than " + (pageCount + 1)); - return; - } - final int sortType = oldFirst ? -1 : newFirst ? 1 : 0; // cleanup file list Arrays.sort(files, (f1, f2) -> { @@ -321,20 +308,9 @@ public class SchematicCommands { return res; }); - List schematics = listFiles(worldEdit.getConfiguration().saveDir, files); - int offset = (page - 1) * SCHEMATICS_PER_PAGE; - - actor.print("Available schematics (Filename: Format) [" + page + "/" + pageCount + "]:"); - StringBuilder build = new StringBuilder(); - int limit = Math.min(offset + SCHEMATICS_PER_PAGE, schematics.size()); - for (int i = offset; i < limit; ) { - build.append(schematics.get(i)); - if (++i != limit) { - build.append("\n"); - } - } - - actor.print(build.toString()); + String pageCommand = actor.isPlayer() ? "/schem list -p %page%" + (oldFirst ? " -d" : newFirst ? " -n" : "") : null; + PaginationBox paginationBox = new SchematicPaginationBox(worldEdit.getConfiguration().saveDir, files, pageCommand); + actor.print(paginationBox.create(page)); } private List allFiles(File root) { @@ -353,22 +329,4 @@ public class SchematicCommands { return fileList; } - private List listFiles(String prefix, File[] files) { - if (prefix == null) prefix = ""; - List result = new ArrayList<>(); - for (File file : files) { - StringBuilder build = new StringBuilder(); - - build.append("\u00a72"); - //ClipboardFormat format = ClipboardFormats.findByFile(file); - Multimap exts = ClipboardFormats.getFileExtensionMap(); - ClipboardFormat format = exts.get(Files.getFileExtension(file.getName())) - .stream().findFirst().orElse(null); - boolean inRoot = file.getParentFile().getName().equals(prefix); - build.append(inRoot ? file.getName() : file.getPath().split(Pattern.quote(prefix + File.separator))[1]) - .append(": ").append(format == null ? "Unknown" : format.getName() + "*"); - result.add(build.toString()); - } - return result; - } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index c8674b085..d2e2a3708 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -624,7 +624,7 @@ public class SelectionCommands { } case UNKNOWN: default: - CommandListBox box = new CommandListBox("Selection modes"); + CommandListBox box = new CommandListBox("Selection modes", null); TextComponentProducer contents = box.getContents(); contents.append(SubtleFormat.wrap("Select one of the modes below:")).newline(); @@ -636,7 +636,7 @@ public class SelectionCommands { box.appendCommand("cyl", "Select a cylinder", "//sel cyl"); box.appendCommand("convex", "Select a convex polyhedral", "//sel convex"); - player.print(box.create()); + player.print(box.create(1)); return; } 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 ea292a855..37facdddb 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 @@ -51,6 +51,10 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.formatting.component.InvalidComponentException; +import com.sk89q.worldedit.util.formatting.component.SubtleFormat; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockTypes; import org.enginehub.piston.annotation.Command; @@ -58,8 +62,11 @@ import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Switch; +import java.text.DecimalFormat; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.function.Supplier; import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; @@ -474,6 +481,12 @@ public class UtilityCommands { return killed; } + // get the formatter with the system locale. in the future, if we can get a local from a player, we can use that + private static final DecimalFormat formatter = (DecimalFormat) NumberFormat.getInstance(Locale.getDefault()); + static { + formatter.applyPattern("#,##0.#####"); // pattern is locale-insensitive. this can translate to "1.234,56789" + } + @Command( name = "/calculate", aliases = { "/calc", "/eval", "/evaluate", "/solve" }, @@ -485,8 +498,14 @@ public class UtilityCommands { String input) { try { Expression expression = Expression.compile(input); - actor.print("= " + expression.evaluate( - new double[] {}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout())); + double result = expression.evaluate( + new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout()); + String formatted = formatter.format(result); + actor.print(SubtleFormat.wrap(input + " = ") + .append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE))); + //actor.print(SubtleFormat.wrap(input).append(Component.newline()) + // .append(SubtleFormat.wrap("= ")) + // .append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE))); } catch (EvaluationException e) { actor.printError(String.format( "'%s' could not be evaluated (error: %s)", input, e.getMessage())); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java index b59578a49..df57539ba 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java @@ -22,13 +22,10 @@ package com.sk89q.worldedit.command.util; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.formatting.component.CodeFormat; import com.sk89q.worldedit.util.formatting.component.CommandListBox; import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; -import com.sk89q.worldedit.util.formatting.text.TextComponent; -import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.formatting.component.InvalidComponentException; import org.enginehub.piston.Command; import org.enginehub.piston.CommandManager; @@ -46,7 +43,7 @@ import static java.util.stream.Collectors.toList; /** * Implementation of the //help command. */ -// Stored in a separate class to prevent import conflicts. +// Stored in a separate class to prevent import conflicts, and because it's aliased via /we help. public class PrintCommandHelp { private static Command detectCommand(CommandManager manager, String command) { @@ -69,17 +66,11 @@ public class PrintCommandHelp { return mapping.orElse(null); } - public static void help(List commandPath, int page, WorldEdit we, Actor actor) { - if (page < 1) { - actor.printError("Page must be >= 1."); - return; - } + public static void help(List commandPath, int page, WorldEdit we, Actor actor) throws InvalidComponentException { CommandManager manager = we.getPlatformManager().getPlatformCommandManager().getCommandManager(); - final int perPage = actor instanceof Player ? 8 : 20; // More pages for console - if (commandPath.isEmpty()) { - printAllCommands(page, perPage, manager.getAllCommands(), actor, ImmutableList.of()); + printCommands(page, manager.getAllCommands(), actor, ImmutableList.of()); return; } @@ -98,7 +89,11 @@ public class PrintCommandHelp { if (subCommands.isEmpty()) { actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)", - Joiner.on(" ").join(visited), subCommand)); + Joiner.on(" ").join(visited.stream().map(Command::getName).iterator()), subCommand)); + // full help for single command + CommandUsageBox box = new CommandUsageBox(visited, visited.stream() + .map(Command::getName).collect(Collectors.joining(" "))); + actor.print(box.create()); return; } @@ -107,7 +102,11 @@ public class PrintCommandHelp { visited.add(currentCommand); } else { actor.printError(String.format("The sub-command '%s' under '%s' could not be found.", - subCommand, Joiner.on(" ").join(visited))); + subCommand, Joiner.on(" ").join(visited.stream().map(Command::getName).iterator()))); + // list subcommands for currentCommand + CommandUsageBox box = new CommandUsageBox(visited, visited.stream() + .map(Command::getName).collect(Collectors.joining(" "))); + actor.print(box.create()); return; } } @@ -120,46 +119,35 @@ public class PrintCommandHelp { .map(Command::getName).collect(Collectors.joining(" "))); actor.print(box.create()); } else { - printAllCommands(page, perPage, subCommands.values().stream(), actor, visited); + printCommands(page, subCommands.values().stream(), actor, visited); } } - private static void printAllCommands(int page, int perPage, Stream commandStream, Actor actor, - List commandList) { + private static void printCommands(int page, Stream commandStream, Actor actor, + List commandList) throws InvalidComponentException { // Get a list of aliases List commands = commandStream .sorted(byCleanName()) .collect(toList()); - // Calculate pagination - int offset = perPage * (page - 1); - int pageTotal = (int) Math.ceil(commands.size() / (double) perPage); - - // Box - CommandListBox box = new CommandListBox(String.format("Help: page %d/%d ", page, pageTotal)); - TextComponent.Builder tip = box.getContents().getBuilder().color(TextColor.GRAY); - - if (offset >= commands.size()) { - tip.color(TextColor.RED) - .append(TextComponent.of(String.format("There is no page %d (total number of pages is %d).\n", page, pageTotal))); - } else { - List list = commands.subList(offset, Math.min(offset + perPage, commands.size())); - - tip.append(TextComponent.of("Type ")); - tip.append(CodeFormat.wrap("//help [] ")); - tip.append(TextComponent.of(" for more information.\n")); - - // Add each command - for (Command mapping : list) { - String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName(); - String command = Stream.concat(commandList.stream(), Stream.of(mapping)) - .map(Command::getName) - .collect(Collectors.joining(" ", "/", "")); - box.appendCommand(alias, mapping.getDescription(), command); - } + String used = commandList.isEmpty() ? null + : Joiner.on(" ").join(commandList.stream().map(Command::getName).iterator()); + CommandListBox box = new CommandListBox( + (used == null ? "Help" : "Subcommands: " + used), + "//help %page%" + (used == null ? "" : " " + used)); + if (!actor.isPlayer()) { + box.formatForConsole(); } - actor.print(box.create()); + for (Command mapping : commands) { + String alias = (commandList.isEmpty() ? "/" : "") + mapping.getName(); + String command = Stream.concat(commandList.stream(), Stream.of(mapping)) + .map(Command::getName) + .collect(Collectors.joining(" ", "/", "")); + box.appendCommand(alias, mapping.getDescription(), command); + } + + actor.print(box.create(page)); } private PrintCommandHelp() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index 319c9cb02..cdcba32a2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -24,7 +24,6 @@ import com.sk89q.worldedit.session.SessionOwner; import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.auth.Subject; import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import java.io.File; 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 93ba549dd..34b5e0e82 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 @@ -94,6 +94,7 @@ import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.util.logging.DynamicStreamHandler; import com.sk89q.worldedit.util.logging.LogFormat; @@ -142,7 +143,6 @@ public final class PlatformCommandManager { private static final Logger log = LoggerFactory.getLogger(PlatformCommandManager.class); private static final java.util.logging.Logger COMMAND_LOG = java.util.logging.Logger.getLogger("com.sk89q.worldedit.CommandLog"); - private static final Pattern numberFormatExceptionPattern = Pattern.compile("^For input string: \"(.*)\"$"); private final WorldEdit worldEdit; private final PlatformManager platformManager; @@ -507,7 +507,7 @@ public final class PlatformCommandManager { .append(e.getRichMessage()) .build()); ImmutableList cmd = e.getCommands(); - if (cmd.size() > 0) { + if (!cmd.isEmpty()) { actor.print(TextComponent.builder("Usage: ") .color(TextColor.RED) .append(TextComponent.of("/", ColorConfig.getMainText())) @@ -515,15 +515,14 @@ public final class PlatformCommandManager { .build()); } } catch (CommandExecutionException e) { - Throwable t = e.getCause(); - actor.printError("Please report this error: [See console]"); - actor.printRaw(t.getClass().getName() + ": " + t.getMessage()); - log.error("An unexpected error while handling a WorldEdit command", t); + handleUnknownException(actor, e.getCause()); } catch (CommandException e) { actor.print(TextComponent.builder("") - .color(TextColor.RED) - .append(e.getRichMessage()) - .build()); + .color(TextColor.RED) + .append(e.getRichMessage()) + .build()); + } catch (Throwable t) { + handleUnknownException(actor, t); } finally { Optional editSessionOpt = context.snapshotMemory().injectedValue(Key.of(EditSession.class)); @@ -554,6 +553,12 @@ public final class PlatformCommandManager { event.setCancelled(true); } + private void handleUnknownException(Actor actor, Throwable t) { + actor.printError("Please report this error: [See console]"); + actor.printRaw(t.getClass().getName() + ": " + t.getMessage()); + log.error("An unexpected error while handling a WorldEdit command", t); + } + @Subscribe public void handleCommandSuggestion(CommandSuggestionEvent event) { try { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java index 556a60570..4d33e82b7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java @@ -102,10 +102,11 @@ public class SpongeSchematicReader extends NBTSchematicReader { return readVersion1(schematicTag); } else if (version == 2) { int dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue(); - if (dataVersion > WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.WORLD_EDITING).getDataVersion()) { - // maybe should just warn? simple schematics may be compatible still. - throw new IOException("Schematic was made in a newer Minecraft version. Data may be incompatible."); + int liveDataVersion = WorldEdit.getInstance().getPlatformManager() + .queryCapability(Capability.WORLD_EDITING).getDataVersion(); + if (dataVersion > liveDataVersion) { + log.warn("Schematic was made in a newer Minecraft version ({} > {}). Data may be incompatible.", + dataVersion, liveDataVersion); } BlockArrayClipboard clip = readVersion1(schematicTag); return readVersion2(clip, schematicTag); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java index f39a74656..4c08f6863 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java @@ -19,47 +19,75 @@ package com.sk89q.worldedit.util.formatting.component; +import com.google.common.collect.Lists; 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.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; -public class CommandListBox extends MessageBox { +import java.util.List; - private boolean first = true; +public class CommandListBox extends PaginationBox { + + private List commands = Lists.newArrayList(); /** * Create a new box. * * @param title the title */ - public CommandListBox(String title) { - super(title, new TextComponentProducer()); + public CommandListBox(String title, String pageCommand) { + super(title, pageCommand); } - public CommandListBox appendCommand(String alias, Component description) { - return appendCommand(alias, description, null); + @Override + public Component getComponent(int number) { + return commands.get(number).createComponent(); } - public CommandListBox appendCommand(String alias, String description, String insertion) { - return appendCommand(alias, TextComponent.of(description), insertion); + @Override + public int getComponentsSize() { + return commands.size(); } - public CommandListBox appendCommand(String alias, Component description, String insertion) { - if (!first) { - getContents().newline(); + public void appendCommand(String alias, Component description) { + appendCommand(alias, description, null); + } + + public void appendCommand(String alias, String description, String insertion) { + appendCommand(alias, TextComponent.of(description), insertion); + } + + public void appendCommand(String alias, Component description, String insertion) { + commands.add(new CommandEntry(alias, description, insertion)); + } + + private static class CommandEntry { + private final String alias; + private final Component description; + private final String insertion; + + CommandEntry(String alias, Component description, String insertion) { + this.alias = alias; + this.description = description; + this.insertion = insertion; } - TextComponent commandName = TextComponent.of(alias, TextColor.GOLD); - if (insertion != null) { - commandName = commandName - .clickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, insertion)) - .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to select"))); - } - getContents().append(commandName.append(TextComponent.of(": "))); - getContents().append(description); - first = false; - return this; - } + Component createComponent() { + TextComponentProducer line = new TextComponentProducer(); + line.append(SubtleFormat.wrap("? ") + .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "//help " + insertion)) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Additional Help")))); + TextComponent command = TextComponent.of(alias, TextColor.GOLD); + if (insertion == null) { + line.append(command); + } else { + line.append(command + .clickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, insertion)) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to select")))); + } + return line.append(TextComponent.of(": ")).append(description).create(); + } + } } 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 6b6314b73..d2a97fcf2 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 @@ -44,7 +44,7 @@ public class CommandUsageBox extends TextComponentProducer { * @param commands the commands to describe * @param commandString the commands that were used, such as "/we" or "/brush sphere" */ - public CommandUsageBox(List commands, String commandString) { + public CommandUsageBox(List commands, String commandString) throws InvalidComponentException { this(commands, commandString, null); } @@ -55,7 +55,7 @@ public class CommandUsageBox extends TextComponentProducer { * @param commandString the commands that were used, such as "/we" or "/brush sphere" * @param parameters list of parameters to use */ - public CommandUsageBox(List commands, String commandString, @Nullable CommandParameters parameters) { + public CommandUsageBox(List commands, String commandString, @Nullable CommandParameters parameters) throws InvalidComponentException { checkNotNull(commands); checkNotNull(commandString); Map subCommands = getSubCommands(Iterables.getLast(commands)); @@ -66,8 +66,9 @@ public class CommandUsageBox extends TextComponentProducer { } } - private void attachSubcommandUsage(Map dispatcher, String commandString, @Nullable CommandParameters parameters) { - CommandListBox box = new CommandListBox("Subcommands"); + private void attachSubcommandUsage(Map dispatcher, String commandString, @Nullable CommandParameters parameters) throws InvalidComponentException { + CommandListBox box = new CommandListBox(commandString.isEmpty() ? "Help" : "Subcommands:" + commandString, + "//help %page%" + (commandString.isEmpty() ? "" : " " + commandString)); String prefix = !commandString.isEmpty() ? commandString + " " : ""; List list = dispatcher.values().stream() @@ -80,7 +81,7 @@ public class CommandUsageBox extends TextComponentProducer { } } - append(box.create()); + append(box.create(1)); } private void attachCommandUsage(List commands, String commandString) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java index 549943541..1497ddbaa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/MessageBox.java @@ -21,9 +21,12 @@ package com.sk89q.worldedit.util.formatting.component; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Strings; +import com.google.common.collect.Sets; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import com.sk89q.worldedit.util.formatting.text.format.TextDecoration; /** * Makes for a box with a border above and below. @@ -40,28 +43,38 @@ public class MessageBox extends TextComponentProducer { public MessageBox(String title, TextComponentProducer contents) { checkNotNull(title); - int leftOver = GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - title.length() - 2; - int leftSide = (int) Math.floor(leftOver * 1.0/3); - int rightSide = (int) Math.floor(leftOver * 2.0/3); - if (leftSide > 0) { - append(TextComponent.of(createBorder(leftSide), TextColor.YELLOW)); - } - append(Component.space()); - append(title); - append(Component.space()); - if (rightSide > 0) { - append(TextComponent.of(createBorder(rightSide), TextColor.YELLOW)); - } - newline(); + append(centerAndBorder(TextComponent.of(title))).newline(); this.contents = contents; } - private String createBorder(int count) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < count; i++) { - builder.append("-"); + protected Component centerAndBorder(TextComponent text) { + TextComponentProducer line = new TextComponentProducer(); + int leftOver = GUARANTEED_NO_WRAP_CHAT_PAGE_WIDTH - getLength(text); + int side = (int) Math.floor(leftOver / 2.0); + if (side > 0) { + if (side > 1) { + line.append(createBorder(side - 1)); + } + line.append(Component.space()); } - return builder.toString(); + line.append(text); + if (side > 0) { + line.append(Component.space()); + if (side > 1) { + line.append(createBorder(side - 1)); + } + } + return line.create(); + } + + private static int getLength(TextComponent text) { + return text.content().length() + text.children().stream().filter(c -> c instanceof TextComponent) + .mapToInt(c -> getLength((TextComponent) c)).sum(); + } + + private TextComponent createBorder(int count) { + return TextComponent.of(Strings.repeat("-", count), + TextColor.YELLOW, Sets.newHashSet(TextDecoration.STRIKETHROUGH)); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java index fecdac40c..bba74a4db 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java @@ -25,14 +25,14 @@ import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; +import javax.annotation.Nullable; import java.util.List; -public class PaginationBox extends MessageBox { +public abstract class PaginationBox extends MessageBox { - public static final int IDEAL_ROWS_FOR_PLAYER = 8; + private static final int IDEAL_ROWS_FOR_PLAYER = 8; private String pageCommand; - private List components; private int componentsPerPage = IDEAL_ROWS_FOR_PLAYER; /** @@ -40,30 +40,30 @@ public class PaginationBox extends MessageBox { * * @param title The title */ - public PaginationBox(String title) { + protected PaginationBox(String title) { this(title, null); } - /** - * Sets the components to create pages for. - * - * @param components The components - */ - public void setComponents(List components) { - this.components = components; - } + public abstract Component getComponent(int number); + + public abstract int getComponentsSize(); public void setComponentsPerPage(int componentsPerPage) { this.componentsPerPage = componentsPerPage; } + public void formatForConsole() { + this.pageCommand = null; + this.componentsPerPage = 20; + } + /** * Creates a Paginated component * * @param title The title * @param pageCommand The command to run to switch page, with %page% representing page number */ - public PaginationBox(String title, String pageCommand) { + protected PaginationBox(String title, @Nullable String pageCommand) { super(title, new TextComponentProducer()); if (pageCommand != null && !pageCommand.contains("%page%")) { @@ -72,48 +72,76 @@ public class PaginationBox extends MessageBox { this.pageCommand = pageCommand; } - public TextComponent create(int page) throws InvalidComponentException { - if (components == null) { - throw new IllegalStateException("You must provide components before creating."); - } - if (page == 1 && components.isEmpty()) { + public Component create(int page) throws InvalidComponentException { + if (page == 1 && getComponentsSize() == 0) { return getContents().reset().append("There's nothing to see here").create(); } - int pageCount = (int) Math.ceil(components.size() / (double) componentsPerPage); + int pageCount = (int) Math.ceil(getComponentsSize() / (double) componentsPerPage); if (page < 1 || page > pageCount) { throw new InvalidComponentException("Invalid page number."); } - getContents().reset(); - for (int i = (page - 1) * componentsPerPage; i < Math.min(page * componentsPerPage, components.size()); i++) { - getContents().append(components.get(i)).newline(); + final int lastComp = Math.min(page * componentsPerPage, getComponentsSize()); + for (int i = (page - 1) * componentsPerPage; i < lastComp; i++) { + getContents().append(getComponent(i)); + if (i + 1 != lastComp) { + getContents().newline(); + } } + if (pageCount == 1) { + return super.create(); + } + getContents().newline(); TextComponent pageNumberComponent = TextComponent.of("Page ", TextColor.YELLOW) .append(TextComponent.of(String.valueOf(page), TextColor.GOLD)) .append(TextComponent.of(" of ")) .append(TextComponent.of(String.valueOf(pageCount), TextColor.GOLD)); - if (pageCommand != null) { + TextComponentProducer navProducer = new TextComponentProducer(); if (page > 1) { TextComponent prevComponent = TextComponent.of("<<< ", TextColor.GOLD) .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page - 1)))) .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate"))); - getContents().append(prevComponent); + navProducer.append(prevComponent); } - getContents().append(pageNumberComponent); + navProducer.append(pageNumberComponent); if (page < pageCount) { TextComponent nextComponent = TextComponent.of(" >>>", TextColor.GOLD) .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, pageCommand.replace("%page%", String.valueOf(page + 1)))) .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to navigate"))); - getContents().append(nextComponent); + navProducer.append(nextComponent); } + getContents().append(centerAndBorder(navProducer.create())); } else { - getContents().append(pageNumberComponent); + getContents().append(centerAndBorder(pageNumberComponent)); } - return TextComponent.of("").append(Component.newline()).append(super.create()); + return super.create(); } @Override public TextComponent create() { throw new IllegalStateException("Pagination components must be created with a page"); } + + public static PaginationBox fromStrings(String header, @Nullable String pageCommand, List lines) { + return new ListPaginationBox(header, pageCommand, lines); + } + + private static class ListPaginationBox extends PaginationBox { + private final List lines; + + ListPaginationBox(String header, String pageCommand, List lines) { + super(header, pageCommand); + this.lines = lines; + } + + @Override + public Component getComponent(int number) { + return TextComponent.of(lines.get(number)); + } + + @Override + public int getComponentsSize() { + return lines.size(); + } + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java new file mode 100644 index 000000000..6a1f0712c --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java @@ -0,0 +1,56 @@ +package com.sk89q.worldedit.util.formatting.component; + +import com.google.common.collect.Multimap; +import com.google.common.io.Files; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +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.event.HoverEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; + +import java.io.File; +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkArgument; + +public class SchematicPaginationBox extends PaginationBox { + private final String prefix; + private final File[] files; + + public SchematicPaginationBox(String rootDir, File[] files, String pageCommand) { + super("Available schematics", pageCommand); + this.prefix = rootDir == null ? "" : rootDir; + this.files = files; + } + + @Override + public Component getComponent(int number) { + checkArgument(number < files.length - 1 && number >= 0); + File file = files[number]; + Multimap exts = ClipboardFormats.getFileExtensionMap(); + String format = exts.get(Files.getFileExtension(file.getName())) + .stream().findFirst().map(ClipboardFormat::getName).orElse("Unknown"); + boolean inRoot = file.getParentFile().getName().equals(prefix); + + String path = inRoot ? file.getName() : file.getPath().split(Pattern.quote(prefix + File.separator))[1]; + + return TextComponent.builder() + .content("") + .append(TextComponent.of("[L]") + .color(TextColor.GOLD) + .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem load " + path)) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to load")))) + .append(Component.space()) + .append(TextComponent.of(path) + .color(TextColor.DARK_GREEN) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of(format)))) + .build(); + } + + @Override + public int getComponentsSize() { + return files.length; + } +} From 6e016a66f0fb0a2225625252188ec5eee14f0678 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 28 Apr 2019 16:05:01 +1000 Subject: [PATCH 40/57] Fixed //size on clipboards --- .../worldedit/command/SelectionCommands.java | 28 ++++++++----------- .../component/SchematicPaginationBox.java | 19 +++++++++++++ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index d2e2a3708..8a62dc529 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -457,33 +457,27 @@ public class SelectionCommands { public void size(Player player, LocalSession session, @Switch(name = 'c', desc = "Get clipboard info instead") boolean clipboardInfo) throws WorldEditException { + Region region; if (clipboardInfo) { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); - Region region = clipboard.getRegion(); - BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()); + region = clipboard.getRegion(); + BlockVector3 origin = clipboard.getOrigin(); - - player.print("Cuboid dimensions (max - min): " + size); player.print("Offset: " + origin); - player.print("Cuboid distance: " + size.distance(BlockVector3.ONE)); - player.print("# of blocks: " + (size.getX() * size.getY() * size.getZ())); - return; - } + } else { + region = session.getSelection(player.getWorld()); - Region region = session.getSelection(player.getWorld()); + player.print("Type: " + session.getRegionSelector(player.getWorld()).getTypeName()); + + for (String line : session.getRegionSelector(player.getWorld()).getInformationLines()) { + player.print(line); + } + } BlockVector3 size = region.getMaximumPoint() .subtract(region.getMinimumPoint()) .add(1, 1, 1); - player.print("Type: " + session.getRegionSelector(player.getWorld()) - .getTypeName()); - - for (String line : session.getRegionSelector(player.getWorld()) - .getInformationLines()) { - player.print(line); - } - player.print("Size: " + size); player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint())); player.print("# of blocks: " + region.getArea()); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java index 6a1f0712c..eb9598a49 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/SchematicPaginationBox.java @@ -1,3 +1,22 @@ +/* + * 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.util.formatting.component; import com.google.common.collect.Multimap; From 32d4b36419f734617d48765b568f0e5c74354d37 Mon Sep 17 00:00:00 2001 From: Matthew Miller Date: Sun, 28 Apr 2019 17:05:37 +1000 Subject: [PATCH 41/57] Fixed //drawsel --- worldedit-core/src/main/assembly/default.xml | 34 ------------------- .../worldedit/command/GeneralCommands.java | 2 +- .../worldedit/command/SchematicCommands.java | 2 +- .../worldedit/command/UtilityCommands.java | 6 ++-- 4 files changed, 4 insertions(+), 40 deletions(-) delete mode 100644 worldedit-core/src/main/assembly/default.xml diff --git a/worldedit-core/src/main/assembly/default.xml b/worldedit-core/src/main/assembly/default.xml deleted file mode 100644 index e6c1849ab..000000000 --- a/worldedit-core/src/main/assembly/default.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - false - - tar.gz - tar.bz2 - zip - - - - ${project.build.directory}/${artifactId}-${project.version}.jar - WorldEdit.jar - / - false - - - README.html - / - true - - - - - - LICENSE.txt - CHANGELOG.txt - contrib/craftscripts/* - - - - diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 220b30de2..08e46addc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -161,7 +161,7 @@ public class GeneralCommands { ) @CommandPermissions("worldedit.drawsel") public void drawSelection(Player player, LocalSession session, - @Arg(desc = "The new draw selection state", def = "toggle") + @Arg(desc = "The new draw selection state", def = "") Boolean drawSelection) throws WorldEditException { if (!WorldEdit.getInstance().getConfiguration().serverSideCUI) { throw new DisallowedUsageException("This functionality is disabled in the configuration!"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index fe4f5f1de..829af8a9c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -308,7 +308,7 @@ public class SchematicCommands { return res; }); - String pageCommand = actor.isPlayer() ? "/schem list -p %page%" + (oldFirst ? " -d" : newFirst ? " -n" : "") : null; + String pageCommand = actor.isPlayer() ? "//schem list -p %page%" + (oldFirst ? " -d" : newFirst ? " -n" : "") : null; PaginationBox paginationBox = new SchematicPaginationBox(worldEdit.getConfiguration().saveDir, files, pageCommand); actor.print(paginationBox.create(page)); } 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 37facdddb..da09cc5b3 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 @@ -19,6 +19,8 @@ package com.sk89q.worldedit.command; +import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; + import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalConfiguration; @@ -51,7 +53,6 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.formatting.component.InvalidComponentException; import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; @@ -69,8 +70,6 @@ import java.util.List; import java.util.Locale; import java.util.function.Supplier; -import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; - /** * Utility commands. */ @@ -386,7 +385,6 @@ public class UtilityCommands { LocalConfiguration config = we.getConfiguration(); Player player = actor instanceof Player ? (Player) actor : null; - int defaultRadius = config.butcherDefaultRadius; if (radius == null) { radius = config.butcherDefaultRadius; } else if (radius < -1) { From 6255ccce386214985c1c9d0ea5d2fb0ef6d3df16 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 17:27:33 -0700 Subject: [PATCH 42/57] Minor bug fixes --- .../worldedit/command/ApplyBrushCommands.java | 1 + .../worldedit/command/PaintBrushCommands.java | 1 + .../command/argument/FactoryConverter.java | 3 ++- .../platform/PlatformCommandManager.java | 5 +++-- .../command/WorldEditExceptionConverter.java | 13 ++++++++---- .../parametric/ExceptionConverterHelper.java | 21 ++++++++++--------- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index d324c3484..285dd272c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -84,6 +84,7 @@ public class ApplyBrushCommands { builder.addParts(REGION_FACTORY, RADIUS); builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use")) .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() .build()); }); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java index c365e129f..9b1aeef94 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -89,6 +89,7 @@ public class PaintBrushCommands { builder.addParts(REGION_FACTORY, RADIUS, DENSITY); builder.addPart(SubCommandPart.builder(TranslatableComponent.of("type"), TextComponent.of("Type of brush to use")) .withCommands(manager.getAllCommands().collect(Collectors.toList())) + .required() .build()); }); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java index 2e7eedb72..0de24e5a7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/FactoryConverter.java @@ -36,6 +36,7 @@ import com.sk89q.worldedit.world.World; import org.enginehub.piston.CommandManager; import org.enginehub.piston.converter.ArgumentConverter; import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; import org.enginehub.piston.converter.SuccessfulConversion; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; @@ -86,7 +87,7 @@ public class FactoryConverter implements ArgumentConverter { factoryExtractor.apply(worldEdit).parseFromInput(argument, parserContext) ); } catch (InputParseException e) { - throw new IllegalArgumentException(e); + return FailedConversion.from(e); } } 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 34b5e0e82..bfc362a6d 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 @@ -256,6 +256,7 @@ public final class PlatformCommandManager { registration, instance ); + additionalConfig.accept(manager); cmd.addPart(SubCommandPart.builder(TranslatableComponent.of("worldedit.argument.action"), TextComponent.of("Sub-command to run.")) @@ -443,7 +444,7 @@ public final class PlatformCommandManager { Request.reset(); Actor actor = platformManager.createProxyActor(event.getActor()); - String[] split = commandDetection(event.getArguments().split(" ")); + String[] split = commandDetection(event.getArguments().substring(1).split(" ")); // No command found! if (!commandManager.containsCommand(split[0])) { @@ -511,7 +512,7 @@ public final class PlatformCommandManager { actor.print(TextComponent.builder("Usage: ") .color(TextColor.RED) .append(TextComponent.of("/", ColorConfig.getMainText())) - .append(HelpGenerator.create(cmd).getUsage()) + .append(HelpGenerator.create(e.getCommandParseResult()).getUsage()) .build()); } } catch (CommandExecutionException e) { 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 a11294527..3dfafe349 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 @@ -19,8 +19,6 @@ package com.sk89q.worldedit.internal.command; -import static com.google.common.base.Preconditions.checkNotNull; - import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.DisallowedItemException; import com.sk89q.worldedit.EmptyClipboardException; @@ -35,7 +33,6 @@ 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; @@ -45,11 +42,13 @@ 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 org.enginehub.piston.exception.UsageException; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.google.common.base.Preconditions.checkNotNull; + /** * converts WorldEdit exceptions and converts them into {@link CommandException}s. */ @@ -173,4 +172,10 @@ public class WorldEditExceptionConverter extends ExceptionConverterHelper { throw newCommandException(e.getMessage(), e); } + // Prevent investigation into UsageExceptions + @ExceptionMatch + public void convert(UsageException e) throws CommandException { + throw e; + } + } 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 f13557487..039bd4cde 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,6 +19,7 @@ package com.sk89q.worldedit.util.command.parametric; +import com.google.common.collect.ImmutableList; import com.sk89q.minecraft.util.commands.WrappedCommandException; import org.enginehub.piston.exception.CommandException; import org.enginehub.piston.exception.CommandExecutionException; @@ -32,24 +33,24 @@ import java.util.List; /** * An implementation of an {@link ExceptionConverter} that automatically calls * the correct method defined on this object. - * + * *

Only public methods will be used. Methods will be called in order of decreasing * levels of inheritance (between classes where one inherits the other). For two * different inheritance branches, the order between them is undefined.

*/ public abstract class ExceptionConverterHelper implements ExceptionConverter { - + private final List handlers; @SuppressWarnings("unchecked") public ExceptionConverterHelper() { List handlers = new ArrayList<>(); - + for (Method method : this.getClass().getMethods()) { if (method.getAnnotation(ExceptionMatch.class) == null) { continue; } - + Class[] parameters = method.getParameterTypes(); if (parameters.length == 1) { Class cls = parameters[0]; @@ -59,9 +60,9 @@ public abstract class ExceptionConverterHelper implements ExceptionConverter { } } } - + Collections.sort(handlers); - + this.handlers = handlers; } @@ -76,18 +77,18 @@ public abstract class ExceptionConverterHelper implements ExceptionConverter { if (e.getCause() instanceof CommandException) { throw (CommandException) e.getCause(); } - throw new CommandExecutionException(e, null); + throw new CommandExecutionException(e, ImmutableList.of()); } catch (IllegalArgumentException | IllegalAccessException e) { - throw new CommandExecutionException(e, null); + throw new CommandExecutionException(e, ImmutableList.of()); } } } } - + private static class ExceptionHandler implements Comparable { final Class cls; final Method method; - + private ExceptionHandler(Class cls, Method method) { this.cls = cls; this.method = method; From 2580a0cf97d70ec7127a08675aa1be34600e050f Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 17:30:58 -0700 Subject: [PATCH 43/57] Use 'shape' instead of 'regionFactory' in user-facing ctx --- .../worldedit/command/ApplyBrushCommands.java | 2 +- .../worldedit/command/BrushCommands.java | 24 +++++++++---------- .../worldedit/command/PaintBrushCommands.java | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index 285dd272c..cfab5fbae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -56,7 +56,7 @@ import static org.enginehub.piston.part.CommandParts.arg; @CommandContainer public class ApplyBrushCommands { - private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("regionFactory"), TextComponent.of("The shape of the region")) + private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region")) .defaultsTo(ImmutableList.of()) .ofTypes(ImmutableList.of(Key.of(RegionFactory.class))) .build(); 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 0b29fdede..26553a087 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 @@ -296,7 +296,7 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.deform") public void deform(Player player, LocalSession localSession, @Arg(desc = "The shape of the region") - RegionFactory regionFactory, + RegionFactory shape, @Arg(desc = "The size of the brush", def = "5") double radius, @Arg(desc = "Expression to apply", def = "y-=0.2") @@ -313,7 +313,7 @@ public class BrushCommands { deform.setOffset(localSession.getPlacementPosition(player).toVector3()); } setOperationBasedBrush(player, localSession, radius, - deform, regionFactory, "worldedit.brush.deform"); + deform, shape, "worldedit.brush.deform"); } @Command( @@ -323,13 +323,13 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.set") public void set(Player player, LocalSession localSession, @Arg(desc = "The shape of the region") - RegionFactory regionFactory, + RegionFactory shape, @Arg(desc = "The size of the brush", def = "5") double radius, @Arg(desc = "The pattern of blocks to set") Pattern pattern) throws WorldEditException { setOperationBasedBrush(player, localSession, radius, - new Apply(new ReplaceFactory(pattern)), regionFactory, "worldedit.brush.set"); + new Apply(new ReplaceFactory(pattern)), shape, "worldedit.brush.set"); } @Command( @@ -339,7 +339,7 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.forest") public void forest(Player player, LocalSession localSession, @Arg(desc = "The shape of the region") - RegionFactory regionFactory, + RegionFactory shape, @Arg(desc = "The size of the brush", def = "5") double radius, @Arg(desc = "The density of the brush", def = "20") @@ -347,7 +347,7 @@ public class BrushCommands { @Arg(desc = "The type of tree to use") TreeGenerator.TreeType type) throws WorldEditException { setOperationBasedBrush(player, localSession, radius, - new Paint(new TreeGeneratorFactory(type), density / 100), regionFactory, "worldedit.brush.forest"); + new Paint(new TreeGeneratorFactory(type), density / 100), shape, "worldedit.brush.forest"); } @Command( @@ -357,11 +357,11 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.raise") public void raise(Player player, LocalSession localSession, @Arg(desc = "The shape of the region") - RegionFactory regionFactory, + RegionFactory shape, @Arg(desc = "The size of the brush", def = "5") double radius) throws WorldEditException { setOperationBasedBrush(player, localSession, radius, - new Deform("y-=1"), regionFactory, "worldedit.brush.raise"); + new Deform("y-=1"), shape, "worldedit.brush.raise"); } @Command( @@ -371,22 +371,22 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.lower") public void lower(Player player, LocalSession localSession, @Arg(desc = "The shape of the region") - RegionFactory regionFactory, + RegionFactory shape, @Arg(desc = "The size of the brush", def = "5") double radius) throws WorldEditException { setOperationBasedBrush(player, localSession, radius, - new Deform("y+=1"), regionFactory, "worldedit.brush.lower"); + new Deform("y+=1"), shape, "worldedit.brush.lower"); } static void setOperationBasedBrush(Player player, LocalSession session, double radius, Contextual factory, - RegionFactory regionFactory, + RegionFactory shape, String permission) throws WorldEditException { WorldEdit.getInstance().checkMaxBrushRadius(radius); BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); tool.setSize(radius); tool.setFill(null); - tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission); + tool.setBrush(new OperationFactoryBrush(factory, shape, session), permission); player.print("Set brush to " + factory); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java index 9b1aeef94..4f4064827 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -56,7 +56,7 @@ import static org.enginehub.piston.part.CommandParts.arg; @CommandContainer public class PaintBrushCommands { - private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("regionFactory"), TextComponent.of("The shape of the region")) + private static final CommandArgument REGION_FACTORY = arg(TranslatableComponent.of("shape"), TextComponent.of("The shape of the region")) .defaultsTo(ImmutableList.of()) .ofTypes(ImmutableList.of(Key.of(RegionFactory.class))) .build(); From 7d85df4575b9db73dae5efea38564363005fabfc Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 17:35:28 -0700 Subject: [PATCH 44/57] Cache SNAPSHOTs for only five minutes, since they change often --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index 41de17bb8..43ec9605a 100644 --- a/build.gradle +++ b/build.gradle @@ -87,6 +87,11 @@ subprojects { maven { url "http://maven.sk89q.com/repo/" } maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } + configurations.all { + resolutionStrategy { + cacheChangingModulesFor 5, 'minutes' + } + } } configure(['core', 'bukkit', 'forge', 'sponge'].collect { project(":worldedit-$it") }) { From d4fce65abc18257fdb4c14a864fa107b0b7b0b40 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 21:42:45 -0700 Subject: [PATCH 45/57] A few command fixes --- .../com/sk89q/worldedit/command/BrushCommands.java | 10 +++++++--- .../com/sk89q/worldedit/command/RegionCommands.java | 2 +- 2 files changed, 8 insertions(+), 4 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 26553a087..b6433a206 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 @@ -88,7 +88,9 @@ public class BrushCommands { desc = "Choose the sphere brush" ) @CommandPermissions("worldedit.brush.sphere") - public void sphereBrush(Player player, LocalSession session, Pattern fill, + public void sphereBrush(Player player, LocalSession session, + @Arg(desc = "The pattern of blocks to set") + Pattern fill, @Arg(desc = "The radius of the sphere", def = "2") double radius, @Switch(name = 'h', desc = "Create hollow spheres instead") @@ -114,7 +116,9 @@ public class BrushCommands { desc = "Choose the cylinder brush" ) @CommandPermissions("worldedit.brush.cylinder") - public void cylinderBrush(Player player, LocalSession session, Pattern fill, + public void cylinderBrush(Player player, LocalSession session, + @Arg(desc = "The pattern of blocks to set") + Pattern fill, @Arg(desc = "The radius of the cylinder", def = "2") double radius, @Arg(desc = "The height of the cylinder", def = "1") @@ -152,7 +156,7 @@ public class BrushCommands { boolean pasteEntities, @Switch(name = 'b', desc = "Paste biomes if available") boolean pasteBiomes, - @ArgFlag(name = 'm', desc = "Skip blocks matching this mask", def = "") + @ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "") Mask sourceMask) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index ae4333c04..b016128e8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -177,7 +177,7 @@ public class RegionCommands { @Arg(desc = "The mask representing blocks to replace", def = "") Mask from, @Arg(desc = "The pattern of blocks to replace with") - Pattern to) throws WorldEditException { + Pattern to) throws WorldEditException { if (from == null) { from = new ExistingBlockMask(editSession); } From 82c484643674968dc400f0d23e5c6e8c5df33081 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 22:03:54 -0700 Subject: [PATCH 46/57] Add more variable args for expressions, quoting --- .../worldedit/command/GenerationCommands.java | 12 +-- .../worldedit/command/RegionCommands.java | 6 +- .../worldedit/command/UtilityCommands.java | 6 +- .../platform/PlatformCommandManager.java | 8 +- .../util/command/CommandArgParser.java | 85 +++++++++++++++++++ 5 files changed, 103 insertions(+), 14 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 962243c9f..646672d2f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -273,8 +273,8 @@ public class GenerationCommands { @Selection Region region, @Arg(desc = "The pattern of blocks to set") Pattern pattern, - @Arg(desc = "Expression to test block placement locations and set block type") - String expression, + @Arg(desc = "Expression to test block placement locations and set block type", variable = true) + List expression, @Switch(name = 'h', desc = "Generate a hollow shape") boolean hollow, @Switch(name = 'r', desc = "Use the game's coordinate origin") @@ -312,7 +312,7 @@ public class GenerationCommands { } try { - final int affected = editSession.makeShape(region, zero, unit, pattern, expression, hollow, session.getTimeout()); + final int affected = editSession.makeShape(region, zero, unit, pattern, String.join(" ", expression), hollow, session.getTimeout()); player.findFreePosition(); player.print(affected + " block(s) have been created."); return affected; @@ -334,8 +334,8 @@ public class GenerationCommands { @Selection Region region, @Arg(desc = "The biome type to set") BiomeType target, - @Arg(desc = "Expression to test block placement locations and set biome type") - String expression, + @Arg(desc = "Expression to test block placement locations and set biome type", variable = true) + List expression, @Switch(name = 'h', desc = "Generate a hollow shape") boolean hollow, @Switch(name = 'r', desc = "Use the game's coordinate origin") @@ -372,7 +372,7 @@ public class GenerationCommands { } try { - final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow, session.getTimeout()); + final int affected = editSession.makeBiomeShape(region, zero, unit, target, String.join(" ", expression), hollow, session.getTimeout()); player.findFreePosition(); player.print("" + affected + " columns affected."); return affected; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index b016128e8..a8591e1de 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -382,8 +382,8 @@ public class RegionCommands { @Logging(ALL) public int deform(Player player, LocalSession session, EditSession editSession, @Selection Region region, - @Arg(desc = "The expression to use") - String expression, + @Arg(desc = "The expression to use", variable = true) + List expression, @Switch(name = 'r', desc = "Use the game's coordinate origin") boolean useRawCoords, @Switch(name = 'o', desc = "Use the selection's center as origin") @@ -410,7 +410,7 @@ public class RegionCommands { } try { - final int affected = editSession.deformRegion(region, zero, unit, expression, session.getTimeout()); + final int affected = editSession.deformRegion(region, zero, unit, String.join(" ", expression), session.getTimeout()); player.findFreePosition(); player.print(affected + " block(s) have been deformed."); return affected; 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 da09cc5b3..0bdcf7425 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 @@ -492,10 +492,10 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.calc") public void calc(Actor actor, - @Arg(desc = "Expression to evaluate") - String input) { + @Arg(desc = "Expression to evaluate", variable = true) + List input) { try { - Expression expression = Expression.compile(input); + Expression expression = Expression.compile(String.join(" ", input)); double result = expression.evaluate( new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout()); String formatted = formatter.format(result); 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 bfc362a6d..be9a03500 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 @@ -89,12 +89,12 @@ import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.util.command.CommandArgParser; import com.sk89q.worldedit.util.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; -import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.util.logging.DynamicStreamHandler; import com.sk89q.worldedit.util.logging.LogFormat; @@ -439,12 +439,16 @@ public final class PlatformCommandManager { return split; } + private String[] parseArgs(String input) { + return new CommandArgParser(input).parseArgs().toArray(String[]::new); + } + @Subscribe public void handleCommand(CommandEvent event) { Request.reset(); Actor actor = platformManager.createProxyActor(event.getActor()); - String[] split = commandDetection(event.getArguments().substring(1).split(" ")); + String[] split = commandDetection(parseArgs(event.getArguments().substring(1))); // No command found! if (!commandManager.containsCommand(split[0])) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java new file mode 100644 index 000000000..293664a07 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java @@ -0,0 +1,85 @@ +package com.sk89q.worldedit.util.command; + +import java.util.stream.Stream; + +public class CommandArgParser { + + private enum State { + NORMAL, + QUOTE + } + + private final Stream.Builder args = Stream.builder(); + private final StringBuilder currentArg = new StringBuilder(); + private final String input; + private int index = 0; + private State state = State.NORMAL; + + public CommandArgParser(String input) { + this.input = input; + } + + public Stream parseArgs() { + for (; index < input.length(); index++) { + char c = input.charAt(index); + switch (state) { + case NORMAL: + handleNormal(c); + break; + case QUOTE: + handleQuote(c); + } + } + finishArg(true); + return args.build(); + } + + private void handleNormal(char c) { + switch (c) { + case '"': + state = State.QUOTE; + break; + case ' ': + finishArg(true); + break; + case '\\': + if (index + 1 < input.length()) { + index++; + } + appendChar(input.charAt(index)); + break; + default: + appendChar(c); + } + } + + private void handleQuote(char c) { + switch (c) { + case '"': + state = State.NORMAL; + finishArg(false); + break; + case '\\': + if (index + 1 < input.length()) { + index++; + } + appendChar(input.charAt(index)); + break; + default: + appendChar(c); + } + } + + private void finishArg(boolean requireText) { + if (currentArg.length() == 0 && requireText) { + return; + } + args.add(currentArg.toString()); + currentArg.setLength(0); + } + + private void appendChar(char c) { + currentArg.append(c); + } + +} From 462843c3df4834600208f31a4ae779891ad8f448 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 22:07:08 -0700 Subject: [PATCH 47/57] Add license --- .../util/command/CommandArgParser.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java index 293664a07..5c414d08a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java @@ -1,3 +1,22 @@ +/* + * 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.util.command; import java.util.stream.Stream; From 6c21ae5c8339d205f9ed1d12e106f01f82bfeb56 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Sun, 28 Apr 2019 22:09:48 -0700 Subject: [PATCH 48/57] Drop old calc message --- .../main/java/com/sk89q/worldedit/command/UtilityCommands.java | 3 --- 1 file changed, 3 deletions(-) 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 0bdcf7425..0e18dbcbd 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 @@ -501,9 +501,6 @@ public class UtilityCommands { String formatted = formatter.format(result); actor.print(SubtleFormat.wrap(input + " = ") .append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE))); - //actor.print(SubtleFormat.wrap(input).append(Component.newline()) - // .append(SubtleFormat.wrap("= ")) - // .append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE))); } catch (EvaluationException e) { actor.printError(String.format( "'%s' could not be evaluated (error: %s)", input, e.getMessage())); From 8baf221c954534b04934f3ad531cb439937b8894 Mon Sep 17 00:00:00 2001 From: wizjany Date: Mon, 29 Apr 2019 17:38:26 -0400 Subject: [PATCH 49/57] Hide help buttons in //sel selector box. --- .../worldedit/command/SelectionCommands.java | 1 + .../formatting/component/CommandListBox.java | 21 ++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 8a62dc529..bac02819a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -619,6 +619,7 @@ public class SelectionCommands { case UNKNOWN: default: CommandListBox box = new CommandListBox("Selection modes", null); + box.setHidingHelp(true); TextComponentProducer contents = box.getContents(); contents.append(SubtleFormat.wrap("Select one of the modes below:")).newline(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java index 4c08f6863..e1b889059 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/CommandListBox.java @@ -31,6 +31,7 @@ import java.util.List; public class CommandListBox extends PaginationBox { private List commands = Lists.newArrayList(); + private boolean hideHelp; /** * Create a new box. @@ -43,7 +44,7 @@ public class CommandListBox extends PaginationBox { @Override public Component getComponent(int number) { - return commands.get(number).createComponent(); + return commands.get(number).createComponent(hideHelp); } @Override @@ -63,6 +64,14 @@ public class CommandListBox extends PaginationBox { commands.add(new CommandEntry(alias, description, insertion)); } + public boolean isHidingHelp() { + return hideHelp; + } + + public void setHidingHelp(boolean hideHelp) { + this.hideHelp = hideHelp; + } + private static class CommandEntry { private final String alias; private final Component description; @@ -74,11 +83,13 @@ public class CommandListBox extends PaginationBox { this.insertion = insertion; } - Component createComponent() { + Component createComponent(boolean hideHelp) { TextComponentProducer line = new TextComponentProducer(); - line.append(SubtleFormat.wrap("? ") - .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "//help " + insertion)) - .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Additional Help")))); + if (!hideHelp) { + line.append(SubtleFormat.wrap("? ") + .clickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "//help " + insertion)) + .hoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Additional Help")))); + } TextComponent command = TextComponent.of(alias, TextColor.GOLD); if (insertion == null) { line.append(command); From 3c04a83852f66017be902117cc13ea89d56fe5ae Mon Sep 17 00:00:00 2001 From: wizjany Date: Mon, 29 Apr 2019 17:39:30 -0400 Subject: [PATCH 50/57] Add nicer error when using player commands as console. Also fix slash counts for Bukkit. --- .../main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java | 4 ++-- .../worldedit/extension/platform/PlatformCommandManager.java | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index 1c824dcec..99652499d 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -289,7 +289,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { // code of WorldEdit expects it String[] split = new String[args.length + 1]; System.arraycopy(args, 0, split, 1, args.length); - split[0] = cmd.getName(); + split[0] = "/" + cmd.getName(); CommandEvent event = new CommandEvent(wrapCommandSender(sender), Joiner.on(" ").join(split)); getWorldEdit().getEventBus().post(event); @@ -303,7 +303,7 @@ public class WorldEditPlugin extends JavaPlugin implements TabCompleter { // code of WorldEdit expects it String[] split = new String[args.length + 1]; System.arraycopy(args, 0, split, 1, args.length); - split[0] = cmd.getName(); + split[0] = "/" + cmd.getName(); CommandSuggestionEvent event = new CommandSuggestionEvent(wrapCommandSender(sender), Joiner.on(" ").join(split)); getWorldEdit().getEventBus().post(event); 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 be9a03500..f1f7380a4 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 @@ -469,6 +469,10 @@ public final class PlatformCommandManager { store.injectValue(Key.of(Actor.class), ValueProvider.constant(actor)); if (actor instanceof Player) { store.injectValue(Key.of(Player.class), ValueProvider.constant((Player) actor)); + } else { + store.injectValue(Key.of(Player.class), context -> { + throw new CommandException(TextComponent.of("This command must be used with a player."), ImmutableList.of()); + }); } store.injectValue(Key.of(Arguments.class), ValueProvider.constant(event::getArguments)); store.injectValue(Key.of(LocalSession.class), From d0f9a71d53e1a3f76bb8fe344ce898486cb37af8 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 29 Apr 2019 21:57:03 -0700 Subject: [PATCH 51/57] Re-implement many converters using Piston utility converters --- .../command/argument/BooleanConverter.java | 48 ++++--------- .../CommaSeparatedValuesConverter.java | 2 +- .../command/argument/DirectionConverter.java | 5 +- .../command/argument/EnumConverter.java | 71 ++++--------------- .../argument/ExpandAmountConverter.java | 9 +-- .../argument/RegionFactoryConverter.java | 51 ++++--------- .../command/argument/RegistryConverter.java | 66 ++++++++++------- .../sk89q/worldedit/registry/Registry.java | 4 ++ 8 files changed, 91 insertions(+), 165 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java index a024cb792..5d4ad5891 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java @@ -19,49 +19,27 @@ package com.sk89q.worldedit.command.argument; -import com.google.common.collect.ImmutableSortedSet; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.google.common.collect.ImmutableSetMultimap; import org.enginehub.piston.CommandManager; -import org.enginehub.piston.converter.ArgumentConverter; -import org.enginehub.piston.converter.ConversionResult; -import org.enginehub.piston.converter.FailedConversion; -import org.enginehub.piston.converter.SuccessfulConversion; -import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.converter.MultiKeyConverter; import org.enginehub.piston.inject.Key; -public class BooleanConverter implements ArgumentConverter { +public class BooleanConverter { public static void register(CommandManager commandManager) { - commandManager.registerConverter(Key.of(Boolean.class), new BooleanConverter()); + commandManager.registerConverter(Key.of(Boolean.class), + MultiKeyConverter.builder( + ImmutableSetMultimap.builder() + .putAll(false, "off", "f", "false", "n", "no") + .putAll(true, "on", "t", "true", "y", "yes") + .build() + ) + .errorMessage(arg -> "Not a boolean value" + arg) + .build() + ); } - private static final ImmutableSortedSet TRUE = ImmutableSortedSet - .orderedBy(String.CASE_INSENSITIVE_ORDER) - .add("on", "t", "true", "y", "yes") - .build(); - - private static final ImmutableSortedSet FALSE = ImmutableSortedSet - .orderedBy(String.CASE_INSENSITIVE_ORDER) - .add("off", "f", "false", "n", "no") - .build(); - private BooleanConverter() { } - @Override - public Component describeAcceptableArguments() { - return TextComponent.of("on|off|true|false"); - } - - @Override - public ConversionResult convert(String argument, InjectedValueAccess context) { - if (TRUE.contains(argument)) { - return SuccessfulConversion.fromSingle(true); - } - if (FALSE.contains(argument)) { - return SuccessfulConversion.fromSingle(false); - } - return FailedConversion.from(new IllegalArgumentException("Not a strictly boolean value: " + argument)); - } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java index ba35fa6e4..7479ff375 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/CommaSeparatedValuesConverter.java @@ -71,7 +71,7 @@ public class CommaSeparatedValuesConverter implements ArgumentConverter { @Override public List getSuggestions(String input) { - String lastInput = Iterables.getLast(COMMA.split(input)); + String lastInput = Iterables.getLast(COMMA.split(input), ""); return delegate.getSuggestions(lastInput); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java index f9e1c4f1f..aacfe4bf5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/DirectionConverter.java @@ -41,6 +41,7 @@ import org.enginehub.piston.inject.Key; import java.util.List; import static java.util.stream.Collectors.toList; +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; public class DirectionConverter implements ArgumentConverter { @@ -113,8 +114,6 @@ public class DirectionConverter implements ArgumentConverter { @Override public List getSuggestions(String input) { - return suggestions.stream() - .filter(s -> s.startsWith(input)) - .collect(toList()); + return limitByPrefix(suggestions.stream(), input); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java index a408a2793..14a49b38c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/EnumConverter.java @@ -19,31 +19,20 @@ package com.sk89q.worldedit.command.argument; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedMap; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import org.enginehub.piston.CommandManager; import org.enginehub.piston.converter.ArgumentConverter; -import org.enginehub.piston.converter.ConversionResult; -import org.enginehub.piston.converter.FailedConversion; -import org.enginehub.piston.converter.SuccessfulConversion; -import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.converter.MultiKeyConverter; import org.enginehub.piston.inject.Key; import javax.annotation.Nullable; import java.util.EnumSet; import java.util.Set; import java.util.function.Function; -import java.util.stream.Stream; -import static com.google.common.base.Preconditions.checkState; -import static java.util.stream.Collectors.joining; - -public class EnumConverter> implements ArgumentConverter { +public class EnumConverter { public static void register(CommandManager commandManager) { commandManager.registerConverter(Key.of(SelectorChoice.class), @@ -58,59 +47,25 @@ public class EnumConverter> implements ArgumentConverter { null)); } - private static > EnumConverter basic(Class enumClass) { + private static > ArgumentConverter basic(Class enumClass) { return full(enumClass, e -> ImmutableSet.of(e.name()), null); } - private static > EnumConverter basic(Class enumClass, E unknownValue) { + private static > ArgumentConverter basic(Class enumClass, E unknownValue) { return full(enumClass, e -> ImmutableSet.of(e.name()), unknownValue); } - private static > EnumConverter full(Class enumClass, - Function> lookupKeys, - @Nullable E unknownValue) { - return new EnumConverter<>(enumClass, lookupKeys, unknownValue); + private static > ArgumentConverter full(Class enumClass, + Function> lookupKeys, + @Nullable E unknownValue) { + return MultiKeyConverter.from( + EnumSet.allOf(enumClass), + lookupKeys, + unknownValue + ); } - private final Component choices; - private final ImmutableMap map; - @Nullable - private final E unknownValue; - - private EnumConverter(Class enumClass, - Function> lookupKeys, - @Nullable E unknownValue) { - ImmutableSortedMap.Builder map = ImmutableSortedMap.orderedBy(String.CASE_INSENSITIVE_ORDER); - Stream.Builder> choices = Stream.builder(); - EnumSet validValues = EnumSet.allOf(enumClass); - if (unknownValue != null) { - validValues.remove(unknownValue); - } - for (E e : validValues) { - Set keys = lookupKeys.apply(e); - checkState(keys.size() > 0, "No lookup keys for enum value %s", e); - choices.add(keys); - for (String key : keys) { - map.put(key, e); - } - } - this.choices = TextComponent.of(choices.build() - .map(choice -> choice.stream().collect(joining("|", "[", "]"))) - .collect(joining("|"))); - this.map = map.build(); - this.unknownValue = unknownValue; + private EnumConverter() { } - @Override - public Component describeAcceptableArguments() { - return choices; - } - - @Override - public ConversionResult convert(String argument, InjectedValueAccess context) { - E result = map.getOrDefault(argument, unknownValue); - return result == null - ? FailedConversion.from(new IllegalArgumentException("Not a valid choice: " + argument)) - : SuccessfulConversion.fromSingle(result); - } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java index c7a4b5bdd..4d431ebca 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/ExpandAmountConverter.java @@ -31,9 +31,10 @@ import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; + public class ExpandAmountConverter implements ArgumentConverter { public static void register(CommandManager commandManager) { @@ -53,9 +54,9 @@ public class ExpandAmountConverter implements ArgumentConverter { @Override public List getSuggestions(String input) { - return Stream.concat(Stream.of("vert"), integerConverter.getSuggestions(input).stream()) - .filter(x -> x.startsWith(input)) - .collect(Collectors.toList()); + return limitByPrefix(Stream.concat( + Stream.of("vert"), integerConverter.getSuggestions(input).stream() + ), input); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java index ed54327b1..15624d31b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryConverter.java @@ -19,54 +19,31 @@ package com.sk89q.worldedit.command.argument; +import com.google.common.collect.ImmutableSetMultimap; import com.sk89q.worldedit.regions.factory.CuboidRegionFactory; import com.sk89q.worldedit.regions.factory.CylinderRegionFactory; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.regions.factory.SphereRegionFactory; -import com.sk89q.worldedit.util.formatting.text.Component; -import com.sk89q.worldedit.util.formatting.text.TextComponent; import org.enginehub.piston.CommandManager; -import org.enginehub.piston.converter.ArgumentConverter; -import org.enginehub.piston.converter.ConversionResult; -import org.enginehub.piston.converter.FailedConversion; -import org.enginehub.piston.converter.SuccessfulConversion; -import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.converter.MultiKeyConverter; import org.enginehub.piston.inject.Key; -public class RegionFactoryConverter implements ArgumentConverter { +public class RegionFactoryConverter { public static void register(CommandManager commandManager) { - commandManager.registerConverter(Key.of(RegionFactory.class), new RegionFactoryConverter()); + commandManager.registerConverter(Key.of(RegionFactory.class), + MultiKeyConverter.builder( + ImmutableSetMultimap.builder() + .put(new CuboidRegionFactory(), "cuboid") + .put(new SphereRegionFactory(), "sphere") + .putAll(new CylinderRegionFactory(1), "cyl", "cylinder") + .build() + ) + .errorMessage(arg -> "Not a known region type: " + arg) + .build() + ); } private RegionFactoryConverter() { } - - @Override - public Component describeAcceptableArguments() { - return TextComponent.of("cuboid|sphere|cyl"); - } - - @Override - public ConversionResult convert(String argument, InjectedValueAccess context) { - try { - return SuccessfulConversion.fromSingle(parse(argument)); - } catch (Exception e) { - return FailedConversion.from(e); - } - } - - private RegionFactory parse(String argument) { - switch (argument) { - case "cuboid": - return new CuboidRegionFactory(); - case "sphere": - return new SphereRegionFactory(); - case "cyl": - case "cylinder": - return new CylinderRegionFactory(1); // TODO: Adjustable height - default: - throw new IllegalArgumentException("Not a known region type: " + argument); - } - } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java index 5e9d2ed66..7bafb86e9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegistryConverter.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.command.argument; +import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.registry.Registry; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; @@ -40,40 +41,52 @@ import org.enginehub.piston.converter.SuccessfulConversion; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; +import java.lang.reflect.Field; import java.util.List; -import java.util.stream.Collectors; + +import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix; public class RegistryConverter implements ArgumentConverter { + @SuppressWarnings("unchecked") public static void register(CommandManager commandManager) { - commandManager.registerConverter(Key.of(BlockType.class), - new RegistryConverter<>(BlockType.class, BlockType.REGISTRY)); - commandManager.registerConverter(Key.of(BlockCategory.class), - new RegistryConverter<>(BlockCategory.class, BlockCategory.REGISTRY)); - commandManager.registerConverter(Key.of(ItemType.class), - new RegistryConverter<>(ItemType.class, ItemType.REGISTRY)); - commandManager.registerConverter(Key.of(ItemCategory.class), - new RegistryConverter<>(ItemCategory.class, ItemCategory.REGISTRY)); - commandManager.registerConverter(Key.of(BiomeType.class), - new RegistryConverter<>(BiomeType.class, BiomeType.REGISTRY)); - commandManager.registerConverter(Key.of(EntityType.class), - new RegistryConverter<>(EntityType.class, EntityType.REGISTRY)); - commandManager.registerConverter(Key.of(FluidType.class), - new RegistryConverter<>(FluidType.class, FluidType.REGISTRY)); - commandManager.registerConverter(Key.of(FluidCategory.class), - new RegistryConverter<>(FluidCategory.class, FluidCategory.REGISTRY)); - commandManager.registerConverter(Key.of(GameMode.class), - new RegistryConverter<>(GameMode.class, GameMode.REGISTRY)); - commandManager.registerConverter(Key.of(WeatherType.class), - new RegistryConverter<>(WeatherType.class, WeatherType.REGISTRY)); + ImmutableList.of( + BlockType.class, + BlockCategory.class, + ItemType.class, + ItemCategory.class, + BiomeType.class, + EntityType.class, + FluidType.class, + FluidCategory.class, + GameMode.class, + WeatherType.class + ).stream() + .map(c -> (Class) c) + .forEach(registryType -> + commandManager.registerConverter(Key.of(registryType), from(registryType)) + ); + } + + @SuppressWarnings("unchecked") + private static RegistryConverter from(Class registryType) { + try { + Field registryField = registryType.getDeclaredField("REGISTRY"); + Registry registry = (Registry) registryField.get(null); + return new RegistryConverter<>(registryType, registry); + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException("Not a registry-backed type: " + registryType.getName()); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Registry field inaccessible on " + registryType.getName()); + } } private final Registry registry; private final TextComponent choices; - public RegistryConverter(Class clazz, Registry registry) { + private RegistryConverter(Class clazz, Registry registry) { this.registry = registry; - this.choices = TextComponent.of("any " + clazz.getSimpleName()); + this.choices = TextComponent.of("any " + registry.getName()); } @Override @@ -85,14 +98,13 @@ public class RegistryConverter implements ArgumentConverter { public ConversionResult convert(String argument, InjectedValueAccess injectedValueAccess) { V result = registry.get(argument); return result == null - ? FailedConversion.from(new IllegalArgumentException("Not a valid choice: " + argument)) + ? FailedConversion.from(new IllegalArgumentException( + "Not a valid " + registry.getName() + ": " + argument)) : SuccessfulConversion.fromSingle(result); } @Override public List getSuggestions(String input) { - return registry.keySet().stream() - .filter(string -> string.startsWith(input)) - .collect(Collectors.toList()); + return limitByPrefix(registry.keySet().stream(), input); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java index 7545068de..e7d7e9e58 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/registry/Registry.java @@ -39,6 +39,10 @@ public class Registry implements Iterable { this.name = name; } + public String getName() { + return name; + } + public @Nullable V get(final String key) { checkState(key.equals(key.toLowerCase()), "key must be lowercase"); return this.map.get(key); From 7188d27aaae7a2ad8fa53d0cd71b5be6db9f5e96 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 29 Apr 2019 22:11:15 -0700 Subject: [PATCH 52/57] Fix minor bugs in converters --- .../sk89q/worldedit/command/argument/BooleanConverter.java | 2 +- .../com/sk89q/worldedit/command/argument/VectorConverter.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java index 5d4ad5891..731a736b3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanConverter.java @@ -34,7 +34,7 @@ public class BooleanConverter { .putAll(true, "on", "t", "true", "y", "yes") .build() ) - .errorMessage(arg -> "Not a boolean value" + arg) + .errorMessage(arg -> "Not a boolean value: " + arg) .build() ); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java index bc91296d6..05ac95573 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/VectorConverter.java @@ -53,14 +53,14 @@ public class VectorConverter implements ArgumentConverter { commandManager.registerConverter(Key.of(Vector2.class), new VectorConverter<>( doubleConverter, - 3, + 2, cmps -> Vector2.at(cmps.get(0), cmps.get(1)), "vector with x and z" )); commandManager.registerConverter(Key.of(BlockVector3.class), new VectorConverter<>( intConverter, - 2, + 3, cmps -> BlockVector3.at(cmps.get(0), cmps.get(1), cmps.get(2)), "block vector with x, y, and z" )); From 1e51bebc46c4cc897a2d25e9dc7fdb2e3e140736 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 29 Apr 2019 22:15:52 -0700 Subject: [PATCH 53/57] Update to release Piston version --- worldedit-libs/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-libs/build.gradle b/worldedit-libs/build.gradle index 610cd0752..00d33be30 100644 --- a/worldedit-libs/build.gradle +++ b/worldedit-libs/build.gradle @@ -89,7 +89,7 @@ configure(subprojects + project("core:ap")) { } project("core") { - def pistonVersion = '0.0.1-SNAPSHOT' + def pistonVersion = '0.1.0' dependencies { shade 'net.kyori:text-api:2.0.0' From b1c042b1962364d8fa164f2bc6d0f7926083e3d8 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Mon, 29 Apr 2019 22:40:32 -0700 Subject: [PATCH 54/57] Add checkstyle validation for formatting, fix issues --- config/checkstyle/checkstyle.xml | 8 ++++++++ .../java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java | 8 ++++---- .../java/com/sk89q/worldedit/command/BiomeCommands.java | 8 ++++---- .../java/com/sk89q/worldedit/command/GeneralCommands.java | 4 ++-- .../com/sk89q/worldedit/command/GenerationCommands.java | 4 ++-- .../java/com/sk89q/worldedit/command/ToolCommands.java | 8 ++++---- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index a2d043d73..0fe76dff3 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -53,5 +53,13 @@ + + + + + + + + diff --git a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java index c74c8f382..eb0c2e382 100644 --- a/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java +++ b/worldedit-core/src/legacy/java/com/sk89q/worldedit/blocks/MobSpawnerBlock.java @@ -90,7 +90,7 @@ public class MobSpawnerBlock extends BaseBlock { /** * Get the spawn delay. - * + * * @return the delay */ public short getDelay() { @@ -99,13 +99,13 @@ public class MobSpawnerBlock extends BaseBlock { /** * Set the spawn delay. - * + * * @param delay the delay to set */ public void setDelay(short delay) { this.delay = delay; } - + @Override public boolean hasNbtData() { return true; @@ -208,7 +208,7 @@ public class MobSpawnerBlock extends BaseBlock { this.spawnCount = spawnCountTag.getValue(); } if (spawnRangeTag != null) { - this.spawnRange =spawnRangeTag.getValue(); + this.spawnRange = spawnRangeTag.getValue(); } if (minSpawnDelayTag != null) { this.minSpawnDelay = minSpawnDelayTag.getValue(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index bb4788f9e..ef6e38981 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -19,8 +19,6 @@ package com.sk89q.worldedit.command; -import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; - import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -59,6 +57,8 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; + /** * Implements biome-related commands such as "/biomelist". */ @@ -97,9 +97,9 @@ public class BiomeCommands { ) @CommandPermissions("worldedit.biome.info") public void biomeInfo(Player player, LocalSession session, - @Switch(name = 't', desc="Use the block you are looking at.") + @Switch(name = 't', desc = "Use the block you are looking at.") boolean useLineOfSight, - @Switch(name = 'p', desc="Use the block you are currently in.") + @Switch(name = 'p', desc = "Use the block you are currently in.") boolean usePosition) throws WorldEditException { BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index 08e46addc..a84c3d1a0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -223,9 +223,9 @@ public class GeneralCommands { @Arg(desc = "Item query") String query, @Switch(name = 'b', desc = "Only search for blocks") - boolean blocksOnly, + boolean blocksOnly, @Switch(name = 'i', desc = "Only search for items") - boolean itemsOnly) throws WorldEditException { + boolean itemsOnly) throws WorldEditException { ItemType type = ItemTypes.get(query); if (type != null) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 646672d2f..5f5229aeb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -227,8 +227,8 @@ public class GenerationCommands { } @Command( - name = "/hpyramid", - desc = "Generate a hollow pyramid" + name = "/hpyramid", + desc = "Generate a hollow pyramid" ) @CommandPermissions("worldedit.generation.pyramid") @Logging(PLACEMENT) 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 2af2b8750..8242cfec9 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 @@ -137,8 +137,8 @@ public class ToolCommands { } @Command( - name = "deltree", - desc = "Floating tree remover tool" + name = "deltree", + desc = "Floating tree remover tool" ) @CommandPermissions("worldedit.tool.deltree") public void deltree(Player player, LocalSession session) throws WorldEditException { @@ -150,8 +150,8 @@ public class ToolCommands { } @Command( - name = "farwand", - desc = "Wand at a distance tool" + name = "farwand", + desc = "Wand at a distance tool" ) @CommandPermissions("worldedit.tool.farwand") public void farwand(Player player, LocalSession session) throws WorldEditException { From 7c1764548d5a0e92eb1d9e775122b9c9d04635d1 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 30 Apr 2019 13:53:14 -0700 Subject: [PATCH 55/57] Deprecate old system, still in use by WG/CB --- .../util/CommandsManagerRegistration.java | 2 ++ .../bukkit/util/DynamicPluginCommand.java | 1 + .../util/DynamicPluginCommandHelpTopic.java | 1 + .../util/commands/CommandsManager.java | 1 + .../minecraft/util/commands/package-info.java | 24 +++++++++++++++++++ 5 files changed, 29 insertions(+) create mode 100644 worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/package-info.java diff --git a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java index 5f8bfbc8c..7e64bf319 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/CommandsManagerRegistration.java @@ -31,6 +31,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +@Deprecated +@SuppressWarnings("deprecation") public class CommandsManagerRegistration extends CommandRegistration { protected CommandsManager commands; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java index 479681c6b..9f1912587 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommand.java @@ -35,6 +35,7 @@ import java.util.List; /** * An implementation of a dynamically registered {@link org.bukkit.command.Command} attached to a plugin */ +@SuppressWarnings("deprecation") public class DynamicPluginCommand extends org.bukkit.command.Command implements PluginIdentifiableCommand { protected final CommandExecutor owner; diff --git a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommandHelpTopic.java b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommandHelpTopic.java index 6f4cec526..7635d174e 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommandHelpTopic.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/bukkit/util/DynamicPluginCommandHelpTopic.java @@ -30,6 +30,7 @@ import org.bukkit.help.HelpTopicFactory; import java.util.Map; +@SuppressWarnings("deprecation") public class DynamicPluginCommandHelpTopic extends HelpTopic { private final DynamicPluginCommand cmd; diff --git a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java b/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java index df3b0806b..5263d3aba 100644 --- a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java +++ b/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/CommandsManager.java @@ -60,6 +60,7 @@ import java.util.Set; * @param command sender class */ @SuppressWarnings("ProtectedField") +@Deprecated public abstract class CommandsManager { protected static final Logger logger = diff --git a/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/package-info.java b/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/package-info.java new file mode 100644 index 000000000..8dd9c94ff --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/minecraft/util/commands/package-info.java @@ -0,0 +1,24 @@ +/* + * 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 . + */ + +/** + * This package contains the old command system. It is no longer in use. Please switch + * to Piston, Intake, ACF, or similar systems. + */ +package com.sk89q.minecraft.util.commands; \ No newline at end of file From 743d7f08ab3bc3ca2362fb64283ee6fd2310a5cb Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 30 Apr 2019 14:59:45 -0700 Subject: [PATCH 56/57] Purge intake-like command system --- .../command/argument/BooleanFlag.java | 63 --- .../command/argument/NumberParser.java | 85 ---- .../command/argument/RegionFactoryParser.java | 81 --- .../command/argument/StringParser.java | 80 --- .../command/argument/TreeGeneratorParser.java | 106 ---- .../command/composition/DeformCommand.java | 84 --- .../command/composition/SelectionCommand.java | 115 ----- .../composition/ShapedBrushCommand.java | 103 ---- .../extension/platform/Platform.java | 4 +- .../command/UserCommandCompleter.java | 72 --- .../internal/command/WorldEditBinding.java | 331 ------------ .../util/command/CommandCallable.java | 59 --- .../util/command/CommandCompleter.java | 42 -- .../util/command/CommandMapping.java | 55 -- .../worldedit/util/command/Description.java | 70 --- .../worldedit/util/command/Dispatcher.java | 86 ---- .../util/command/InvalidUsageException.java | 107 ---- .../command/MissingParameterException.java | 29 -- .../worldedit/util/command/NullCompleter.java | 38 -- .../worldedit/util/command/Parameter.java | 66 --- .../util/command/PrimaryAliasComparator.java | 60 --- .../util/command/SimpleCommandMapping.java | 72 --- .../util/command/SimpleDescription.java | 135 ----- .../util/command/SimpleDispatcher.java | 189 ------- .../util/command/SimpleParameter.java | 134 ----- .../command/UnconsumedParameterException.java | 40 -- .../command/argument/ArgumentException.java | 39 -- .../argument/ArgumentParseException.java | 39 -- .../util/command/argument/ArgumentUtils.java | 45 -- .../util/command/argument/CommandArgs.java | 162 ------ .../argument/MissingArgumentException.java | 39 -- .../argument/UnusedArgumentsException.java | 39 -- .../command/binding/PrimitiveBindings.java | 294 ----------- .../worldedit/util/command/binding/Range.java | 50 -- .../command/binding/StandardBindings.java | 46 -- .../util/command/binding/Switch.java | 44 -- .../worldedit/util/command/binding/Text.java | 41 -- .../util/command/binding/Validate.java | 45 -- .../command/composition/BranchingCommand.java | 111 ---- .../command/composition/CommandExecutor.java | 41 -- .../util/command/composition/FlagParser.java | 196 ------- .../composition/LegacyCommandAdapter.java | 87 ---- .../command/composition/ParameterCommand.java | 79 --- .../command/composition/ProvidedValue.java | 69 --- .../command/composition/SimpleCommand.java | 54 -- .../util/command/fluent/CommandGraph.java | 84 --- .../util/command/fluent/DispatcherNode.java | 139 ----- .../parametric/AbstractInvokeListener.java | 36 -- .../command/parametric/ArgumentStack.java | 78 --- .../util/command/parametric/Binding.java | 93 ---- .../command/parametric/BindingBehavior.java | 52 -- .../command/parametric/BindingHelper.java | 224 -------- .../util/command/parametric/BindingMatch.java | 71 --- .../parametric/ContextArgumentStack.java | 178 ------- .../parametric/ExceptionConverter.java | 17 +- .../command/parametric/InvokeHandler.java | 82 --- .../command/parametric/InvokeListener.java | 58 --- .../parametric/LegacyCommandsHandler.java | 97 ---- .../util/command/parametric/Optional.java | 41 -- .../command/parametric/ParameterData.java | 194 ------- .../parametric/ParameterException.java | 43 -- .../command/parametric/ParametricBuilder.java | 230 --------- .../parametric/ParametricCallable.java | 479 ------------------ .../parametric/ParametricException.java | 44 -- .../parametric/StringArgumentStack.java | 128 ----- .../worldedit/sponge/SpongePlatform.java | 5 +- 66 files changed, 10 insertions(+), 6189 deletions(-) delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanFlag.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/TreeGeneratorParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/DeformCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ShapedBrushCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditBinding.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandMapping.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Description.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Dispatcher.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/InvalidUsageException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/MissingParameterException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Parameter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/PrimaryAliasComparator.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleCommandMapping.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDescription.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDispatcher.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleParameter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/UnconsumedParameterException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentParseException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentUtils.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/CommandArgs.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/MissingArgumentException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/UnusedArgumentsException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Range.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/StandardBindings.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Switch.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Text.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Validate.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/BranchingCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/CommandExecutor.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/FlagParser.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/LegacyCommandAdapter.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ParameterCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ProvidedValue.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/SimpleCommand.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/CommandGraph.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AbstractInvokeListener.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ArgumentStack.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Binding.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingBehavior.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingHelper.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingMatch.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ContextArgumentStack.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeHandler.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeListener.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/LegacyCommandsHandler.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Optional.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterData.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricException.java delete mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/StringArgumentStack.java diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanFlag.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanFlag.java deleted file mode 100644 index 3e849a099..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/BooleanFlag.java +++ /dev/null @@ -1,63 +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.command.argument; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; - -import java.util.Collections; -import java.util.List; - -public class BooleanFlag implements CommandExecutor { - - private final String description; - - public BooleanFlag(String description) { - this.description = description; - } - - @Override - public Boolean call(CommandArgs args, CommandLocals locals) throws CommandException { - return true; - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) { - return Collections.emptyList(); - } - - @Override - public String getUsage() { - return ""; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java deleted file mode 100644 index dcb06b4f9..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/NumberParser.java +++ /dev/null @@ -1,85 +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.command.argument; - -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; - -import java.util.Collections; -import java.util.List; - -import javax.annotation.Nullable; - -public class NumberParser implements CommandExecutor { - - private final String name; - private final String description; - private final @Nullable String defaultSuggestion; - - public NumberParser(String name, String description) { - this(name, description, null); - } - - public NumberParser(String name, String description, @Nullable String defaultSuggestion) { - this.name = name; - this.description = description; - this.defaultSuggestion = defaultSuggestion; - } - - @Override - public Number call(CommandArgs args, CommandLocals locals) throws CommandException { - try { - String next = args.next(); - try { - return Double.parseDouble(next); - } catch (NumberFormatException ignored) { - throw new CommandException("The value for <" + name + "> should be a number. '" + next + "' is not a number."); - } - } catch (MissingArgumentException e) { - throw new CommandException("Missing value for <" + name + "> (try a number)."); - } - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - String value = args.next(); - return value.isEmpty() && defaultSuggestion != null ? Lists.newArrayList(defaultSuggestion) : Collections.emptyList(); - } - - @Override - public String getUsage() { - return "<" + name + ">"; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryParser.java deleted file mode 100644 index 9ec0ce101..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/RegionFactoryParser.java +++ /dev/null @@ -1,81 +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.command.argument; - -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.regions.factory.CuboidRegionFactory; -import com.sk89q.worldedit.regions.factory.CylinderRegionFactory; -import com.sk89q.worldedit.regions.factory.RegionFactory; -import com.sk89q.worldedit.regions.factory.SphereRegionFactory; -import com.sk89q.worldedit.util.command.argument.ArgumentUtils; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; - -import java.util.List; - -public class RegionFactoryParser implements CommandExecutor { - - @Override - public RegionFactory call(CommandArgs args, CommandLocals locals) throws CommandException { - try { - String type = args.next(); - - switch (type) { - case "cuboid": - return new CuboidRegionFactory(); - case "sphere": - return new SphereRegionFactory(); - case "cyl": - case "cylinder": - return new CylinderRegionFactory(1); // TODO: Adjustable height - - default: - throw new CommandException("Unknown shape type: " + type + " (try one of " + getUsage() + ")"); - } - } catch (MissingArgumentException e) { - throw new CommandException("Missing shape type (try one of " + getUsage() + ")"); - - } - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - return ArgumentUtils.getMatchingSuggestions(Lists.newArrayList("cuboid", "sphere", "cyl"), args.next()); - } - - @Override - public String getUsage() { - return "(cuboid | sphere | cyl)"; - } - - @Override - public String getDescription() { - return "Defines a region"; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java deleted file mode 100644 index 30c02381f..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/StringParser.java +++ /dev/null @@ -1,80 +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.command.argument; - -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; - -import java.util.Collections; -import java.util.List; - -import javax.annotation.Nullable; - -public class StringParser implements CommandExecutor { - - private final String name; - private final String description; - private final @Nullable String defaultSuggestion; - - public StringParser(String name, String description) { - this(name, description, null); - } - - public StringParser(String name, String description, @Nullable String defaultSuggestion) { - this.name = name; - this.description = description; - this.defaultSuggestion = defaultSuggestion; - } - - @Override - public String call(CommandArgs args, CommandLocals locals) throws CommandException { - try { - return args.next(); - } catch (MissingArgumentException e) { - throw new CommandException("Missing value for <" + name + ">."); - } - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - String value = args.next(); - return value.isEmpty() && defaultSuggestion != null ? Lists.newArrayList(defaultSuggestion) : Collections.emptyList(); - } - - @Override - public String getUsage() { - return "<" + name + ">"; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/TreeGeneratorParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/TreeGeneratorParser.java deleted file mode 100644 index 3d3f73d6b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/argument/TreeGeneratorParser.java +++ /dev/null @@ -1,106 +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.command.argument; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.EditContext; -import com.sk89q.worldedit.function.generator.ForestGenerator; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.TreeGenerator.TreeType; -import com.sk89q.worldedit.util.command.argument.ArgumentUtils; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; - -import java.util.Arrays; -import java.util.List; - -public class TreeGeneratorParser implements CommandExecutor> { - - private final String name; - - public TreeGeneratorParser(String name) { - this.name = name; - } - - private String getOptionsList() { - return Joiner.on(" | ").join(Arrays.asList(TreeType.values())); - } - - @Override - public Contextual call(CommandArgs args, CommandLocals locals) throws CommandException { - try { - String input = args.next(); - TreeType type = TreeGenerator.lookup(input); - if (type != null) { - return new GeneratorFactory(type); - } else { - throw new CommandException("Unknown value for <" + name + "> (try one of " + getOptionsList() + ")."); - } - } catch (MissingArgumentException e) { - throw new CommandException("Missing value for <" + name + "> (try one of " + getOptionsList() + ")."); - } - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - String s = args.next(); - return s.isEmpty() ? Lists.newArrayList(TreeType.getPrimaryAliases()) : ArgumentUtils.getMatchingSuggestions(TreeType.getAliases(), s); - } - - @Override - public String getUsage() { - return "<" + name + ">"; - } - - @Override - public String getDescription() { - return "Choose a tree generator"; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - - private static final class GeneratorFactory implements Contextual { - private final TreeType type; - - private GeneratorFactory(TreeType type) { - this.type = type; - } - - @Override - public ForestGenerator createFromContext(EditContext input) { - return new ForestGenerator((EditSession) input.getDestination(), type); - } - - @Override - public String toString() { - return "tree of type " + type; - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/DeformCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/DeformCommand.java deleted file mode 100644 index cae499dce..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/DeformCommand.java +++ /dev/null @@ -1,84 +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.command.composition; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.minecraft.util.commands.WrappedCommandException; -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.argument.BooleanFlag; -import com.sk89q.worldedit.command.argument.StringParser; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.factory.Deform; -import com.sk89q.worldedit.function.factory.Deform.Mode; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.FlagParser.Flag; -import com.sk89q.worldedit.util.command.composition.FlagParser.FlagData; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; - -public class DeformCommand extends SimpleCommand> { - - private final Flag rawCoordsFlag = addFlag('r', new BooleanFlag("Raw coords mode")); - private final Flag offsetFlag = addFlag('o', new BooleanFlag("Offset mode")); - private final StringParser expressionParser = addParameter(new StringParser("expression", "Expression to apply", "y-=0.2")); - - @Override - public Deform call(CommandArgs args, CommandLocals locals) throws CommandException { - FlagData flagData = getFlagParser().call(args, locals); - String expression = expressionParser.call(args, locals); - boolean rawCoords = rawCoordsFlag.get(flagData, false); - boolean offset = offsetFlag.get(flagData, false); - - Deform deform = new Deform(expression); - - if (rawCoords) { - deform.setMode(Mode.RAW_COORD); - } else if (offset) { - deform.setMode(Mode.OFFSET); - Player player = (Player) locals.get(Actor.class); - LocalSession session = WorldEdit.getInstance().getSessionManager().get(locals.get(Actor.class)); - try { - deform.setOffset(session.getPlacementPosition(player).toVector3()); - } catch (IncompleteRegionException e) { - throw new WrappedCommandException(e); - } - } else { - deform.setMode(Mode.UNIT_CUBE); - } - - return deform; - } - - @Override - public String getDescription() { - return "Apply math expression to area"; - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return true; - } - -} 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 deleted file mode 100644 index c0f93463c..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/SelectionCommand.java +++ /dev/null @@ -1,115 +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.command.composition; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.minecraft.util.commands.CommandPermissionsException; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.EditContext; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.function.operation.Operations; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; - -import java.util.List; - -public class SelectionCommand extends SimpleCommand { - - private final CommandExecutor> delegate; - private final String permission; - - public SelectionCommand(CommandExecutor> delegate, String permission) { - checkNotNull(delegate, "delegate"); - checkNotNull(permission, "permission"); - this.delegate = delegate; - this.permission = permission; - addParameter(delegate); - } - - @Override - public Operation call(CommandArgs args, CommandLocals locals) throws CommandException { - if (!testPermission(locals)) { - throw new CommandPermissionsException(); - } - - Contextual operationFactory = delegate.call(args, locals); - - Actor actor = locals.get(Actor.class); - if (actor instanceof Player) { - try { - Player player = (Player) actor; - LocalSession session = WorldEdit.getInstance().getSessionManager().get(player); - Region selection = session.getSelection(player.getWorld()); - - EditSession editSession = session.createEditSession(player); - editSession.enableStandardMode(); - locals.put(EditSession.class, editSession); - session.tellVersion(player); - - EditContext editContext = new EditContext(); - editContext.setDestination(locals.get(EditSession.class)); - editContext.setRegion(selection); - editContext.setSession(session); - - Operation operation = operationFactory.createFromContext(editContext); - Operations.completeBlindly(operation); - - List messages = Lists.newArrayList(); - operation.addStatusMessages(messages); - if (messages.isEmpty()) { - actor.print("Operation completed."); - } else { - actor.print("Operation completed (" + Joiner.on(", ").join(messages) + ")."); - } - - return operation; - } catch (IncompleteRegionException e) { - WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter().convert(e); - return null; - } - } else { - throw new CommandException("This command can only be used by players."); - } - } - - @Override - public String getDescription() { - return delegate.getDescription(); - } - - @Override - protected boolean testPermission0(CommandLocals locals) { - return locals.get(Actor.class).hasPermission(permission); - } - -} 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 deleted file mode 100644 index 911c4080e..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/composition/ShapedBrushCommand.java +++ /dev/null @@ -1,103 +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.command.composition; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.minecraft.util.commands.CommandPermissionsException; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.MaxBrushRadiusException; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.argument.NumberParser; -import com.sk89q.worldedit.command.argument.RegionFactoryParser; -import com.sk89q.worldedit.command.tool.BrushTool; -import com.sk89q.worldedit.command.tool.InvalidToolBindException; -import com.sk89q.worldedit.command.tool.brush.OperationFactoryBrush; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.function.Contextual; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.regions.factory.RegionFactory; -import com.sk89q.worldedit.util.HandSide; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.composition.CommandExecutor; -import com.sk89q.worldedit.util.command.composition.SimpleCommand; - -public class ShapedBrushCommand extends SimpleCommand { - - private final CommandExecutor> delegate; - private final String permission; - - private final RegionFactoryParser regionFactoryParser = addParameter(new RegionFactoryParser()); - private final NumberParser radiusCommand = addParameter(new NumberParser("size", "The size of the brush", "5")); - - public ShapedBrushCommand(CommandExecutor> delegate, String permission) { - checkNotNull(delegate, "delegate"); - this.permission = permission; - this.delegate = delegate; - addParameter(delegate); - } - - @Override - public Object call(CommandArgs args, CommandLocals locals) throws CommandException { - if (!testPermission(locals)) { - throw new CommandPermissionsException(); - } - - RegionFactory regionFactory = regionFactoryParser.call(args, locals); - int radius = radiusCommand.call(args, locals).intValue(); - Contextual factory = delegate.call(args, locals); - - Player player = (Player) locals.get(Actor.class); - LocalSession session = WorldEdit.getInstance().getSessionManager().get(player); - - try { - WorldEdit.getInstance().checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - tool.setSize(radius); - tool.setFill(null); - tool.setBrush(new OperationFactoryBrush(factory, regionFactory, session), permission); - } catch (MaxBrushRadiusException | InvalidToolBindException e) { - WorldEdit.getInstance().getPlatformManager().getPlatformCommandManager().getExceptionConverter().convert(e); - } - - player.print("Set brush to " + factory); - - return true; - } - - @Override - public String getDescription() { - return delegate.getDescription(); - } - - @Override - public boolean testPermission0(CommandLocals locals) { - Actor sender = locals.get(Actor.class); - if (sender == null) { - throw new RuntimeException("Uh oh! No 'Actor' specified so that we can check permissions"); - } else { - return sender.hasPermission(permission); - } - } - -} 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 79fac2c57..1a25497f5 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 @@ -21,16 +21,14 @@ package com.sk89q.worldedit.extension.platform; import com.sk89q.worldedit.LocalConfiguration; 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 javax.annotation.Nullable; import java.util.List; import java.util.Map; -import javax.annotation.Nullable; - /** * Represents a platform that WorldEdit has been implemented for. * diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java deleted file mode 100644 index a93363295..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/UserCommandCompleter.java +++ /dev/null @@ -1,72 +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.internal.command; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -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.Platform; -import com.sk89q.worldedit.extension.platform.PlatformManager; -import com.sk89q.worldedit.util.command.CommandCompleter; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Provides the names of connected users as suggestions. - */ -public class UserCommandCompleter implements CommandCompleter { - - private final PlatformManager platformManager; - - /** - * Create a new instance. - * - * @param platformManager the platform manager - */ - public UserCommandCompleter(PlatformManager platformManager) { - checkNotNull(platformManager); - this.platformManager = platformManager; - } - - @Override - public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { - Platform platform = platformManager.queryCapability(Capability.USER_COMMANDS); - if (platform instanceof MultiUserPlatform) { - List suggestions = new ArrayList<>(); - Collection users = ((MultiUserPlatform) platform).getConnectedUsers(); - for (Actor user : users) { - if (user.getName().toLowerCase().startsWith(arguments.toLowerCase().trim())) { - suggestions.add(user.getName()); - } - } - return suggestions; - } else { - return Collections.emptyList(); - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditBinding.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditBinding.java deleted file mode 100644 index b13924e72..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditBinding.java +++ /dev/null @@ -1,331 +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.internal.command; - -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.IncompleteRegionException; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.UnknownDirectionException; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.input.NoMatchException; -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.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.internal.annotation.Direction; -import com.sk89q.worldedit.internal.annotation.Selection; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.TreeGenerator.TreeType; -import com.sk89q.worldedit.util.command.parametric.ArgumentStack; -import com.sk89q.worldedit.util.command.parametric.BindingBehavior; -import com.sk89q.worldedit.util.command.parametric.BindingHelper; -import com.sk89q.worldedit.util.command.parametric.BindingMatch; -import com.sk89q.worldedit.util.command.parametric.ParameterException; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.Biomes; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.registry.BiomeRegistry; - -import java.util.Collection; - -/** - * Binds standard WorldEdit classes such as {@link Player} and {@link LocalSession}. - */ -public class WorldEditBinding extends BindingHelper { - - private final WorldEdit worldEdit; - - /** - * Create a new instance. - * - * @param worldEdit the WorldEdit instance to bind to - */ - public WorldEditBinding(WorldEdit worldEdit) { - this.worldEdit = worldEdit; - } - - /** - * Gets a selection from a {@link ArgumentStack}. - * - * @param context the context - * @param selection the annotation - * @return a selection - * @throws IncompleteRegionException if no selection is available - * @throws ParameterException on other error - */ - @BindingMatch(classifier = Selection.class, - type = Region.class, - behavior = BindingBehavior.PROVIDES) - public Object getSelection(ArgumentStack context, @SuppressWarnings("unused") Selection selection) throws IncompleteRegionException, ParameterException { - Player sender = getPlayer(context); - LocalSession session = worldEdit.getSessionManager().get(sender); - return session.getSelection(sender.getWorld()); - } - - /** - * Gets an {@link EditSession} from a {@link ArgumentStack}. - * - * @param context the context - * @return an edit session - * @throws ParameterException on other error - */ - @BindingMatch(type = EditSession.class, - behavior = BindingBehavior.PROVIDES) - public EditSession getEditSession(ArgumentStack context) throws ParameterException { - Player sender = getPlayer(context); - LocalSession session = worldEdit.getSessionManager().get(sender); - EditSession editSession = session.createEditSession(sender); - editSession.enableStandardMode(); - context.getContext().getLocals().put(EditSession.class, editSession); - session.tellVersion(sender); - return editSession; - } - - /** - * Gets an {@link LocalSession} from a {@link ArgumentStack}. - * - * @param context the context - * @return a local session - * @throws ParameterException on error - */ - @BindingMatch(type = LocalSession.class, - behavior = BindingBehavior.PROVIDES) - public LocalSession getLocalSession(ArgumentStack context) throws ParameterException { - Player sender = getPlayer(context); - return worldEdit.getSessionManager().get(sender); - } - - /** - * Gets an {@link Actor} from a {@link ArgumentStack}. - * - * @param context the context - * @return a local player - * @throws ParameterException on error - */ - @BindingMatch(type = Actor.class, - behavior = BindingBehavior.PROVIDES) - public Actor getActor(ArgumentStack context) throws ParameterException { - Actor sender = context.getContext().getLocals().get(Actor.class); - if (sender == null) { - throw new ParameterException("Missing 'Actor'"); - } else { - return sender; - } - } - - /** - * Gets an {@link Player} from a {@link ArgumentStack}. - * - * @param context the context - * @return a local player - * @throws ParameterException on error - */ - @BindingMatch(type = Player.class, - behavior = BindingBehavior.PROVIDES) - public Player getPlayer(ArgumentStack context) throws ParameterException { - Actor sender = context.getContext().getLocals().get(Actor.class); - if (sender == null) { - throw new ParameterException("No player to get a session for"); - } else if (sender instanceof Player) { - return (Player) sender; - } else { - throw new ParameterException("Caller is not a player"); - } - } - - /** - * Gets an {@link BaseBlock} from a {@link ArgumentStack}. - * - * @param context the context - * @return a pattern - * @throws ParameterException on error - * @throws WorldEditException on error - */ - @BindingMatch(type = {BaseBlock.class, BlockState.class, BlockStateHolder.class}, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BaseBlock getBaseBlock(ArgumentStack context) throws ParameterException, WorldEditException { - Actor actor = context.getContext().getLocals().get(Actor.class); - ParserContext parserContext = new ParserContext(); - parserContext.setActor(context.getContext().getLocals().get(Actor.class)); - if (actor instanceof Entity) { - Extent extent = ((Entity) actor).getExtent(); - if (extent instanceof World) { - parserContext.setWorld((World) extent); - } - } - parserContext.setSession(worldEdit.getSessionManager().get(actor)); - try { - return worldEdit.getBlockFactory().parseFromInput(context.next(), parserContext); - } catch (NoMatchException e) { - throw new ParameterException(e.getMessage(), e); - } - } - - /** - * Gets an {@link Pattern} from a {@link ArgumentStack}. - * - * @param context the context - * @return a pattern - * @throws ParameterException on error - * @throws WorldEditException on error - */ - @BindingMatch(type = Pattern.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public Pattern getPattern(ArgumentStack context) throws ParameterException, WorldEditException { - Actor actor = context.getContext().getLocals().get(Actor.class); - ParserContext parserContext = new ParserContext(); - parserContext.setActor(context.getContext().getLocals().get(Actor.class)); - if (actor instanceof Entity) { - Extent extent = ((Entity) actor).getExtent(); - if (extent instanceof World) { - parserContext.setWorld((World) extent); - } - } - parserContext.setSession(worldEdit.getSessionManager().get(actor)); - try { - return worldEdit.getPatternFactory().parseFromInput(context.next(), parserContext); - } catch (NoMatchException e) { - throw new ParameterException(e.getMessage(), e); - } - } - - /** - * Gets an {@link Mask} from a {@link ArgumentStack}. - * - * @param context the context - * @return a pattern - * @throws ParameterException on error - * @throws WorldEditException on error - */ - @BindingMatch(type = Mask.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public Mask getMask(ArgumentStack context) throws ParameterException, WorldEditException { - Actor actor = context.getContext().getLocals().get(Actor.class); - ParserContext parserContext = new ParserContext(); - parserContext.setActor(context.getContext().getLocals().get(Actor.class)); - if (actor instanceof Entity) { - Extent extent = ((Entity) actor).getExtent(); - if (extent instanceof World) { - parserContext.setWorld((World) extent); - } - } - parserContext.setSession(worldEdit.getSessionManager().get(actor)); - try { - return worldEdit.getMaskFactory().parseFromInput(context.next(), parserContext); - } catch (NoMatchException e) { - throw new ParameterException(e.getMessage(), e); - } - } - - /** - * Get a direction from the player. - * - * @param context the context - * @param direction the direction annotation - * @return a pattern - * @throws ParameterException on error - * @throws UnknownDirectionException on an unknown direction - */ - @BindingMatch(classifier = Direction.class, - type = BlockVector3.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BlockVector3 getDirection(ArgumentStack context, Direction direction) - throws ParameterException, UnknownDirectionException { - Player sender = getPlayer(context); - if (direction.includeDiagonals()) { - return worldEdit.getDiagonalDirection(sender, context.next()); - } else { - return worldEdit.getDirection(sender, context.next()); - } - } - - /** - * Gets an {@link TreeType} from a {@link ArgumentStack}. - * - * @param context the context - * @return a pattern - * @throws ParameterException on error - * @throws WorldEditException on error - */ - @BindingMatch(type = TreeType.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public TreeType getTreeType(ArgumentStack context) throws ParameterException, WorldEditException { - String input = context.next(); - if (input != null) { - TreeType type = TreeGenerator.lookup(input); - if (type != null) { - return type; - } else { - throw new ParameterException( - String.format("Can't recognize tree type '%s' -- choose from: %s", input, - TreeType.getPrimaryAliases())); - } - } else { - return TreeType.TREE; - } - } - - /** - * Gets an {@link BiomeType} from a {@link ArgumentStack}. - * - * @param context the context - * @return a pattern - * @throws ParameterException on error - * @throws WorldEditException on error - */ - @BindingMatch(type = BiomeType.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BiomeType getBiomeType(ArgumentStack context) throws ParameterException, WorldEditException { - String input = context.next(); - if (input != null) { - BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); - Collection knownBiomes = BiomeType.REGISTRY.values(); - BiomeType biome = Biomes.findBiomeByName(knownBiomes, input, biomeRegistry); - if (biome != null) { - return biome; - } else { - throw new ParameterException( - String.format("Can't recognize biome type '%s' -- use /biomelist to list available types", input)); - } - } else { - throw new ParameterException( - "This command takes a 'default' biome if one is not set, except there is no particular " + - "biome that should be 'default', so the command should not be taking a default biome"); - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java deleted file mode 100644 index a40660d19..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCallable.java +++ /dev/null @@ -1,59 +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.util.command; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; - -/** - * A command that can be executed. - */ -public interface CommandCallable extends CommandCompleter { - - /** - * Execute the correct command based on the input. - * - *

The implementing class must perform the necessary permission - * checks.

- * - * @param arguments the arguments - * @param locals the locals - * @param parentCommands a list of parent commands, with the first most entry being the top-level command - * @return the called command, or null if there was no command found - * @throws CommandException thrown on a command error - */ - Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException; - - /** - * Get an object describing this command. - * - * @return the command description - */ - Description getDescription(); - - /** - * Test whether this command can be executed with the given context. - * - * @param locals the locals - * @return true if execution is permitted - */ - boolean testPermission(CommandLocals locals); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java deleted file mode 100644 index 19bf47d60..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandCompleter.java +++ /dev/null @@ -1,42 +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.util.command; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; - -import java.util.List; - -/** - * Provides a method that can provide tab completion for commands. - */ -public interface CommandCompleter { - - /** - * Get a list of suggestions based on input. - * - * @param arguments the arguments entered up to this point - * @param locals the locals - * @return a list of suggestions - * @throws CommandException thrown if there was a parsing error - */ - List getSuggestions(String arguments, CommandLocals locals) throws CommandException; - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandMapping.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandMapping.java deleted file mode 100644 index 093850728..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandMapping.java +++ /dev/null @@ -1,55 +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.util.command; - -/** - * Provides information about a mapping between a command and its aliases. - */ -public interface CommandMapping { - - /** - * Get the primary alias. - * - * @return the primary alias - */ - String getPrimaryAlias(); - - /** - * Get a list of all aliases. - * - * @return aliases - */ - String[] getAllAliases(); - - /** - * Get the callable - * - * @return the callable - */ - CommandCallable getCallable(); - - /** - * Get the {@link Description} form the callable. - * - * @return the description - */ - Description getDescription(); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Description.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Description.java deleted file mode 100644 index 89c8af2a4..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Description.java +++ /dev/null @@ -1,70 +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.util.command; - -import java.util.List; - -/** - * A description of a command. - */ -public interface Description { - - /** - * Get the list of parameters for this command. - * - * @return a list of parameters - */ - List getParameters(); - - /** - * Get a short one-line description of this command. - * - * @return a description, or null if no description is available - */ - String getDescription(); - - /** - * Get a longer help text about this command. - * - * @return a help text, or null if no help is available - */ - String getHelp(); - - /** - * Get the usage string of this command. - * - *

A usage string may look like - * {@code [-w <world>] <var1> <var2>}.

- * - * @return a usage string - */ - String getUsage(); - - /** - * Get a list of permissions that the player may have to have permission. - * - *

Permission data may or may not be available. This is only useful as a - * potential hint.

- * - * @return the list of permissions - */ - List getPermissions(); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Dispatcher.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Dispatcher.java deleted file mode 100644 index a7f1405f8..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Dispatcher.java +++ /dev/null @@ -1,86 +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.util.command; - -import java.util.Collection; -import java.util.Set; - -import javax.annotation.Nullable; - -/** - * Executes a command based on user input. - */ -public interface Dispatcher extends CommandCallable { - - /** - * Register a command with this dispatcher. - * - * @param callable the command executor - * @param alias a list of aliases, where the first alias is the primary name - */ - void registerCommand(CommandCallable callable, String... alias); - - /** - * Get a list of commands. Each command, regardless of how many aliases - * it may have, will only appear once in the returned set. - * - *

The returned collection cannot be modified.

- * - * @return a list of registrations - */ - Set getCommands(); - - /** - * Get a list of primary aliases. - * - *

The returned collection cannot be modified.

- * - * @return a list of aliases - */ - Collection getPrimaryAliases(); - - /** - * Get a list of all the command aliases, which includes the primary alias. - * - *

A command may have more than one alias assigned to it. The returned - * collection cannot be modified.

- * - * @return a list of aliases - */ - Collection getAliases(); - - /** - * Get the {@link CommandCallable} associated with an alias. Returns - * null if no command is named by the given alias. - * - * @param alias the alias - * @return the command mapping (null if not found) - */ - @Nullable CommandMapping get(String alias); - - /** - * Returns whether the dispatcher contains a registered command for the given alias. - * - * @param alias the alias - * @return true if a registered command exists - */ - boolean contains(String alias); - -} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/InvalidUsageException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/InvalidUsageException.java deleted file mode 100644 index 0ffbc4c1e..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/InvalidUsageException.java +++ /dev/null @@ -1,107 +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.util.command; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.sk89q.minecraft.util.commands.CommandException; - -import javax.annotation.Nullable; - -/** - * Thrown when a command is not used properly. - * - *

When handling this exception, print the error message if it is not null. - * Print a one line help instruction unless {@link #isFullHelpSuggested()} - * is true, which, in that case, the full help of the command should be - * shown.

- * - *

If no error message is set and full help is not to be shown, then a generic - * "you used this command incorrectly" message should be shown.

- */ -public class InvalidUsageException extends CommandException { - - private final CommandCallable command; - private final boolean fullHelpSuggested; - - /** - * Create a new instance with no error message and with no suggestion - * that full and complete help for the command should be shown. This will - * result in a generic error message. - * - * @param command the command - */ - public InvalidUsageException(CommandCallable command) { - this(null, command); - } - - /** - * Create a new instance with a message and with no suggestion - * that full and complete help for the command should be shown. - * - * @param message the message - * @param command the command - */ - public InvalidUsageException(@Nullable String message, CommandCallable command) { - this(message, command, false); - } - - /** - * Create a new instance with a message. - * - * @param message the message - * @param command the command - * @param fullHelpSuggested true if the full help for the command should be shown - */ - public InvalidUsageException(@Nullable String message, CommandCallable command, boolean fullHelpSuggested) { - super(message); - checkNotNull(command); - this.command = command; - this.fullHelpSuggested = fullHelpSuggested; - } - - /** - * Get the command. - * - * @return the command - */ - public CommandCallable getCommand() { - return command; - } - - /** - * Get a simple usage string. - * - * @param prefix the command shebang (such as "/") -- may be blank - * @return a usage string - */ - public String getSimpleUsageString(String prefix) { - return getCommandUsed(prefix, command.getDescription().getUsage()); - } - - /** - * Return whether the full usage of the command should be shown. - * - * @return show full usage - */ - public boolean isFullHelpSuggested() { - return fullHelpSuggested; - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/MissingParameterException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/MissingParameterException.java deleted file mode 100644 index bbdf0e0d5..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/MissingParameterException.java +++ /dev/null @@ -1,29 +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.util.command; - -import com.sk89q.worldedit.util.command.parametric.ParameterException; - -/** - * Thrown when there is a missing parameter. - */ -public class MissingParameterException extends ParameterException { - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java deleted file mode 100644 index 10850c696..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/NullCompleter.java +++ /dev/null @@ -1,38 +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.util.command; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; - -import java.util.Collections; -import java.util.List; - -/** - * Always returns an empty list of suggestions. - */ -public class NullCompleter implements CommandCompleter { - - @Override - public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { - return Collections.emptyList(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Parameter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Parameter.java deleted file mode 100644 index a2ac4e343..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/Parameter.java +++ /dev/null @@ -1,66 +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.util.command; - -/** - * Describes a parameter. - * - * @see Description - */ -public interface Parameter { - - /** - * The name of the parameter. - * - * @return the name - */ - String getName(); - - /** - * Get the flag associated with this parameter. - * - * @return the flag, or null if there is no flag associated - * @see #isValueFlag() - */ - Character getFlag(); - - /** - * Return whether the flag is a value flag. - * - * @return true if the flag is a value flag - * @see #getFlag() - */ - boolean isValueFlag(); - - /** - * Get whether this parameter is optional. - * - * @return true if the parameter does not have to be specified - */ - boolean isOptional(); - - /** - * Get the default value as a string to be parsed by the binding. - * - * @return a default value, or null if none is set - */ - String[] getDefaultValue(); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/PrimaryAliasComparator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/PrimaryAliasComparator.java deleted file mode 100644 index bca779d4b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/PrimaryAliasComparator.java +++ /dev/null @@ -1,60 +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.util.command; - -import java.util.Comparator; -import java.util.regex.Pattern; - -import javax.annotation.Nullable; - -/** - * Compares the primary aliases of two {@link CommandMapping} using - * {@link String#compareTo(String)}. - */ -public final class PrimaryAliasComparator implements Comparator { - - /** - * An instance of this class. - */ - public static final PrimaryAliasComparator INSTANCE = new PrimaryAliasComparator(null); - private final @Nullable Pattern removalPattern; - - /** - * Create a new instance. - * - * @param removalPattern a regex to remove unwanted characters from the compared aliases - */ - public PrimaryAliasComparator(@Nullable Pattern removalPattern) { - this.removalPattern = removalPattern; - } - - private String clean(String alias) { - if (removalPattern != null) { - return removalPattern.matcher(alias).replaceAll(""); - } - return alias; - } - - @Override - public int compare(CommandMapping o1, CommandMapping o2) { - return clean(o1.getPrimaryAlias()).compareTo(clean(o2.getPrimaryAlias())); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleCommandMapping.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleCommandMapping.java deleted file mode 100644 index 982832c48..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleCommandMapping.java +++ /dev/null @@ -1,72 +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.util.command; - -import java.util.Arrays; - -/** - * Tracks a command registration. - */ -public class SimpleCommandMapping implements CommandMapping { - - private final String[] aliases; - private final CommandCallable callable; - - /** - * Create a new instance. - * - * @param callable the command callable - * @param alias a list of all aliases, where the first one is the primary one - */ - public SimpleCommandMapping(CommandCallable callable, String... alias) { - super(); - this.aliases = alias; - this.callable = callable; - } - - @Override - public String getPrimaryAlias() { - return aliases[0]; - } - - @Override - public String[] getAllAliases() { - return aliases; - } - - @Override - public CommandCallable getCallable() { - return callable; - } - - @Override - public Description getDescription() { - return getCallable().getDescription(); - } - - @Override - public String toString() { - return "CommandMapping{" + - "aliases=" + Arrays.toString(aliases) + - ", callable=" + callable + - '}'; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDescription.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDescription.java deleted file mode 100644 index 4bea65d91..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDescription.java +++ /dev/null @@ -1,135 +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.util.command; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A simple implementation of {@link Description} which has setters. - */ -public class SimpleDescription implements Description { - - private List parameters = new ArrayList<>(); - private List permissions = new ArrayList<>(); - private String description; - private String help; - private String overrideUsage; - - @Override - public List getParameters() { - return parameters; - } - - /** - * Set the list of parameters. - * - * @param parameters the list of parameters - * @see #getParameters() - */ - public SimpleDescription setParameters(List parameters) { - this.parameters = Collections.unmodifiableList(parameters); - return this; - } - - @Override - public String getDescription() { - return description; - } - - /** - * Set the description of the command. - * - * @param description the description - * @see #getDescription() - */ - public SimpleDescription setDescription(String description) { - this.description = description; - return this; - } - - @Override - public String getHelp() { - return help; - } - - /** - * Set the help text of the command. - * - * @param help the help text - * @see #getHelp() - */ - public SimpleDescription setHelp(String help) { - this.help = help; - return this; - } - - @Override - public List getPermissions() { - return permissions; - } - - /** - * Set the permissions of this command. - * - * @param permissions the permissions - */ - public SimpleDescription setPermissions(List permissions) { - this.permissions = Collections.unmodifiableList(permissions); - return this; - } - - /** - * Override the usage string returned with a given one. - * - * @param usage usage string, or null - */ - public SimpleDescription overrideUsage(String usage) { - this.overrideUsage = usage; - return this; - } - - @Override - public String getUsage() { - if (overrideUsage != null) { - return overrideUsage; - } - - StringBuilder builder = new StringBuilder(); - boolean first = true; - - for (Parameter parameter : parameters) { - if (!first) { - builder.append(" "); - } - builder.append(parameter); - first = false; - } - - return builder.toString(); - } - - @Override - public String toString() { - return getUsage(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDispatcher.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDispatcher.java deleted file mode 100644 index 8bb73a880..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleDispatcher.java +++ /dev/null @@ -1,189 +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.util.command; - -import com.google.common.base.Joiner; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.minecraft.util.commands.CommandPermissionsException; -import com.sk89q.minecraft.util.commands.WrappedCommandException; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * A simple implementation of {@link Dispatcher}. - */ -public class SimpleDispatcher implements Dispatcher { - - private final Map commands = new HashMap<>(); - private final SimpleDescription description = new SimpleDescription(); - - /** - * Create a new instance. - */ - public SimpleDispatcher() { - description.getParameters().add(new SimpleParameter("subcommand")); - SimpleParameter extraArgs = new SimpleParameter("..."); - extraArgs.setOptional(true); - description.getParameters().add(extraArgs); - } - - @Override - public void registerCommand(CommandCallable callable, String... alias) { - CommandMapping mapping = new SimpleCommandMapping(callable, alias); - - // Check for replacements - for (String a : alias) { - String lower = a.toLowerCase(); - if (commands.containsKey(lower)) { - throw new IllegalArgumentException( - "Replacing commands is currently undefined behavior"); - } - } - - for (String a : alias) { - String lower = a.toLowerCase(); - commands.put(lower, mapping); - } - } - - @Override - public Set getCommands() { - return Collections.unmodifiableSet(new HashSet<>(commands.values())); - } - - @Override - public Set getAliases() { - return Collections.unmodifiableSet(commands.keySet()); - } - - @Override - public Set getPrimaryAliases() { - Set aliases = new HashSet<>(); - for (CommandMapping mapping : getCommands()) { - aliases.add(mapping.getPrimaryAlias()); - } - return Collections.unmodifiableSet(aliases); - } - - @Override - public boolean contains(String alias) { - return commands.containsKey(alias.toLowerCase()); - } - - @Override - public CommandMapping get(String alias) { - return commands.get(alias.toLowerCase()); - } - - @Override - public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException { - // We have permission for this command if we have permissions for subcommands - if (parentCommands.length != 0 && !testPermission(locals)) { - throw new CommandPermissionsException(); - } - - String[] split = CommandContext.split(arguments); - Set aliases = getPrimaryAliases(); - - if (aliases.isEmpty()) { - throw new InvalidUsageException("This command has no sub-commands.", this); - } else if (split.length > 0) { - String subCommand = split[0]; - String subArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length)); - String[] subParents = Arrays.copyOf(parentCommands, parentCommands.length + 1); - subParents[parentCommands.length] = subCommand; - CommandMapping mapping = get(subCommand); - - if (mapping != null) { - try { - return mapping.getCallable().call(subArguments, locals, subParents); - } catch (CommandException e) { - e.prependStack(subCommand); - throw e; - } catch (Throwable t) { - throw new WrappedCommandException(t); - } - } - - } - - throw new InvalidUsageException("Please choose a sub-command.", this, true); - } - - @Override - public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { - String[] split = CommandContext.split(arguments); - - if (split.length <= 1) { - String prefix = split.length > 0 ? split[0] : ""; - - List suggestions = new ArrayList<>(); - - for (CommandMapping mapping : getCommands()) { - if (mapping.getCallable().testPermission(locals)) { - for (String alias : mapping.getAllAliases()) { - if (prefix.isEmpty() || alias.startsWith(arguments)) { - suggestions.add(mapping.getPrimaryAlias()); - break; - } - } - } - } - - return suggestions; - } else { - String subCommand = split[0]; - CommandMapping mapping = get(subCommand); - String passedArguments = Joiner.on(" ").join(Arrays.copyOfRange(split, 1, split.length)); - - if (mapping != null) { - return mapping.getCallable().getSuggestions(passedArguments, locals); - } else { - return Collections.emptyList(); - } - } - } - - @Override - public SimpleDescription getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - for (CommandMapping mapping : getCommands()) { - if (mapping.getCallable().testPermission(locals)) { - return true; - } - } - - return false; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleParameter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleParameter.java deleted file mode 100644 index ac9fcfdaa..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/SimpleParameter.java +++ /dev/null @@ -1,134 +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.util.command; - -/** - * A simple implementation of {@link Parameter} that has setters. - */ -public class SimpleParameter implements Parameter { - - private String name; - private Character flag; - private boolean isValue; - private boolean isOptional; - private String[] defaultValue; - - /** - * Create a new parameter with no name defined yet. - */ - public SimpleParameter() { - } - - /** - * Create a new parameter of the given name. - * - * @param name the name - */ - public SimpleParameter(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - /** - * Set the name of the parameter. - * - * @param name the parameter name - */ - public SimpleParameter setName(String name) { - this.name = name; - return this; - } - - @Override - public Character getFlag() { - return flag; - } - - @Override - public boolean isValueFlag() { - return flag != null && isValue; - } - - /** - * Set the flag used by this parameter. - * @param flag the flag, or null if there is no flag - * @param isValue true if the flag is a value flag - */ - public SimpleParameter setFlag(Character flag, boolean isValue) { - this.flag = flag; - this.isValue = isValue; - return this; - } - - @Override - public boolean isOptional() { - return isOptional || getFlag() != null; - } - - /** - * Set whether this parameter is optional. - * - * @param isOptional true if this parameter is optional - */ - public SimpleParameter setOptional(boolean isOptional) { - this.isOptional = isOptional; - return this; - } - - @Override - public String[] getDefaultValue() { - return defaultValue; - } - - /** - * Set the default value. - * - * @param defaultValue a default value, or null if none - */ - public SimpleParameter setDefaultValue(String[] defaultValue) { - this.defaultValue = defaultValue; - return this; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - if (getFlag() != null) { - if (isValueFlag()) { - builder.append("[-") - .append(getFlag()).append(" <").append(getName()).append(">]"); - } else { - builder.append("[-").append(getFlag()).append("]"); - } - } else { - if (isOptional()) { - builder.append("[<").append(getName()).append(">]"); - } else { - builder.append("<").append(getName()).append(">"); - } - } - return builder.toString(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/UnconsumedParameterException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/UnconsumedParameterException.java deleted file mode 100644 index 0a399f64d..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/UnconsumedParameterException.java +++ /dev/null @@ -1,40 +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.util.command; - -import com.sk89q.worldedit.util.command.parametric.ParameterException; - -/** - * Thrown when there are leftover parameters that were not consumed, particular in the - * case of the user providing too many parameters. - */ -public class UnconsumedParameterException extends ParameterException { - - private String unconsumed; - - public UnconsumedParameterException(String unconsumed) { - this.unconsumed = unconsumed; - } - - public String getUnconsumed() { - return unconsumed; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentException.java deleted file mode 100644 index 37dc70f86..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentException.java +++ /dev/null @@ -1,39 +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.util.command.argument; - -public class ArgumentException extends Exception { - - public ArgumentException() { - } - - public ArgumentException(String message) { - super(message); - } - - public ArgumentException(String message, Throwable cause) { - super(message, cause); - } - - public ArgumentException(Throwable cause) { - super(cause); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentParseException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentParseException.java deleted file mode 100644 index fd2fc6f4f..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentParseException.java +++ /dev/null @@ -1,39 +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.util.command.argument; - -public class ArgumentParseException extends ArgumentException { - - public ArgumentParseException() { - } - - public ArgumentParseException(String message) { - super(message); - } - - public ArgumentParseException(String message, Throwable cause) { - super(message, cause); - } - - public ArgumentParseException(Throwable cause) { - super(cause); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentUtils.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentUtils.java deleted file mode 100644 index 22141fedd..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/ArgumentUtils.java +++ /dev/null @@ -1,45 +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.util.command.argument; - -import com.google.common.collect.Lists; - -import java.util.Collection; -import java.util.List; - -public final class ArgumentUtils { - - private ArgumentUtils() { - } - - public static List getMatchingSuggestions(Collection items, String s) { - if (s.isEmpty()) { - return Lists.newArrayList(items); - } - List suggestions = Lists.newArrayList(); - for (String item : items) { - if (item.toLowerCase().startsWith(s)) { - suggestions.add(item); - } - } - return suggestions; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/CommandArgs.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/CommandArgs.java deleted file mode 100644 index 7c91149e8..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/CommandArgs.java +++ /dev/null @@ -1,162 +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.util.command.argument; - -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; - -import java.util.Collections; -import java.util.List; - -public class CommandArgs { - - private final List arguments; - private int position = 0; - - public CommandArgs(List arguments) { - this.arguments = arguments; - } - - public CommandArgs(CommandArgs args) { - this(Lists.newArrayList(args.arguments)); - } - - public boolean hasNext() { - return position < arguments.size(); - } - - public String next() throws MissingArgumentException { - try { - return arguments.get(position++); - } catch (IndexOutOfBoundsException ignored) { - throw new MissingArgumentException("Too few arguments specified."); - } - } - - public String uncheckedNext() { - if (hasNext()) { - return arguments.get(position); - } else { - return null; - } - } - - public String peek() throws MissingArgumentException { - try { - return arguments.get(position); - } catch (IndexOutOfBoundsException ignored) { - throw new MissingArgumentException("Too few arguments specified."); - } - } - - public String uncheckedPeek() { - if (hasNext()) { - return arguments.get(position); - } else { - return null; - } - } - - public String remaining() throws MissingArgumentException { - if (hasNext()) { - StringBuilder builder = new StringBuilder(); - boolean first = true; - while (hasNext()) { - if (!first) { - builder.append(" "); - } - builder.append(next()); - first = false; - } - return builder.toString(); - } else { - throw new MissingArgumentException("Too few arguments specified."); - } - } - - public String peekRemaining() throws MissingArgumentException { - if (hasNext()) { - StringBuilder builder = new StringBuilder(); - boolean first = true; - while (hasNext()) { - if (!first) { - builder.append(" "); - } - builder.append(next()); - first = false; - } - return builder.toString(); - } else { - throw new MissingArgumentException(); - } - } - - public int position() { - return position; - } - - public int size() { - return arguments.size(); - } - - public void markConsumed() { - position = arguments.size(); - } - - public void requireAllConsumed() throws UnusedArgumentsException { - if (hasNext()) { - StringBuilder builder = new StringBuilder(); - try { - builder.append(peekRemaining()); - } catch (MissingArgumentException e) { - throw new RuntimeException("This should not have happened", e); - } - throw new UnusedArgumentsException("There were unused arguments: " + builder); - } - } - - public static class Parser { - private boolean usingHangingArguments = false; - - public boolean isUsingHangingArguments() { - return usingHangingArguments; - } - - public Parser setUsingHangingArguments(boolean usingHangingArguments) { - this.usingHangingArguments = usingHangingArguments; - return this; - } - - public CommandArgs parse(String arguments) throws CommandException { - CommandContext context = new CommandContext(CommandContext.split("_ " + arguments), Collections.emptySet(), false, null, false); - List args = Lists.newArrayList(); - for (int i = 0; i < context.argsLength(); i++) { - args.add(context.getString(i)); - } - if (isUsingHangingArguments()) { - if (arguments.isEmpty() || arguments.endsWith(" ")) { - args.add(""); - } - } - return new CommandArgs(args); - } - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/MissingArgumentException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/MissingArgumentException.java deleted file mode 100644 index db0267727..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/MissingArgumentException.java +++ /dev/null @@ -1,39 +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.util.command.argument; - -public class MissingArgumentException extends ArgumentException { - - public MissingArgumentException() { - } - - public MissingArgumentException(String message) { - super(message); - } - - public MissingArgumentException(String message, Throwable cause) { - super(message, cause); - } - - public MissingArgumentException(Throwable cause) { - super(cause); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/UnusedArgumentsException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/UnusedArgumentsException.java deleted file mode 100644 index efd7984e5..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/argument/UnusedArgumentsException.java +++ /dev/null @@ -1,39 +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.util.command.argument; - -public class UnusedArgumentsException extends ArgumentException { - - public UnusedArgumentsException() { - } - - public UnusedArgumentsException(String message) { - super(message); - } - - public UnusedArgumentsException(String message, Throwable cause) { - super(message, cause); - } - - public UnusedArgumentsException(Throwable cause) { - super(cause); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java deleted file mode 100644 index 3a4d78edf..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/PrimitiveBindings.java +++ /dev/null @@ -1,294 +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.util.command.binding; - -import com.sk89q.worldedit.internal.expression.Expression; -import com.sk89q.worldedit.internal.expression.ExpressionException; -import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; -import com.sk89q.worldedit.util.command.parametric.ArgumentStack; -import com.sk89q.worldedit.util.command.parametric.BindingBehavior; -import com.sk89q.worldedit.util.command.parametric.BindingHelper; -import com.sk89q.worldedit.util.command.parametric.BindingMatch; -import com.sk89q.worldedit.util.command.parametric.ParameterException; - -import java.lang.annotation.Annotation; - -import javax.annotation.Nullable; - -/** - * Handles basic Java types such as {@link String}s, {@link Byte}s, etc. - * - *

Handles both the object and primitive types.

- */ -public final class PrimitiveBindings extends BindingHelper { - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @param text the text annotation - * @param modifiers a list of modifiers - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(classifier = Text.class, - type = String.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = -1, - provideModifiers = true) - public String getText(ArgumentStack context, Text text, Annotation[] modifiers) - throws ParameterException { - String v = context.remaining(); - validate(v, modifiers); - return v; - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @param modifiers a list of modifiers - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = String.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public String getString(ArgumentStack context, Annotation[] modifiers) - throws ParameterException { - String v = context.next(); - validate(v, modifiers); - return v; - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = { Boolean.class, boolean.class }, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public Boolean getBoolean(ArgumentStack context) throws ParameterException { - return context.nextBoolean(); - } - - /** - * Try to parse numeric input as either a number or a mathematical expression. - * - * @param input input - * @return a number - * @throws ParameterException thrown on parse error - */ - private @Nullable Double parseNumericInput(@Nullable String input) throws ParameterException { - if (input == null) { - return null; - } - - try { - return Double.parseDouble(input); - } catch (NumberFormatException e1) { - try { - Expression expression = Expression.compile(input); - return expression.evaluate(); - } catch (EvaluationException e) { - throw new ParameterException(String.format( - "Expected '%s' to be a valid number (or a valid mathematical expression)", input)); - } catch (ExpressionException e) { - throw new ParameterException(String.format( - "Expected '%s' to be a number or valid math expression (error: %s)", input, e.getMessage())); - } - - } - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @param modifiers a list of modifiers - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = { Integer.class, int.class }, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Integer getInteger(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - Double v = parseNumericInput(context.next()); - if (v != null) { - int intValue = v.intValue(); - validate(intValue, modifiers); - return intValue; - } else { - return null; - } - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @param modifiers a list of modifiers - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = { Short.class, short.class }, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Short getShort(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - Integer v = getInteger(context, modifiers); - if (v != null) { - return v.shortValue(); - } - return null; - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @param modifiers a list of modifiers - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = { Double.class, double.class }, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Double getDouble(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - Double v = parseNumericInput(context.next()); - if (v != null) { - validate(v, modifiers); - return v; - } else { - return null; - } - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @param modifiers a list of modifiers - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = { Float.class, float.class }, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Float getFloat(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - Double v = getDouble(context, modifiers); - if (v != null) { - return v.floatValue(); - } - return null; - } - - /** - * Validate a number value using relevant modifiers. - * - * @param number the number - * @param modifiers the list of modifiers to scan - * @throws ParameterException on a validation error - */ - private static void validate(double number, Annotation[] modifiers) - throws ParameterException { - for (Annotation modifier : modifiers) { - if (modifier instanceof Range) { - Range range = (Range) modifier; - if (number < range.min()) { - throw new ParameterException( - String.format( - "A valid value is greater than or equal to %s " + - "(you entered %s)", range.min(), number)); - } else if (number > range.max()) { - throw new ParameterException( - String.format( - "A valid value is less than or equal to %s " + - "(you entered %s)", range.max(), number)); - } - } - } - } - - /** - * Validate a number value using relevant modifiers. - * - * @param number the number - * @param modifiers the list of modifiers to scan - * @throws ParameterException on a validation error - */ - private static void validate(int number, Annotation[] modifiers) - throws ParameterException { - for (Annotation modifier : modifiers) { - if (modifier instanceof Range) { - Range range = (Range) modifier; - if (number < range.min()) { - throw new ParameterException( - String.format( - "A valid value is greater than or equal to %s " + - "(you entered %s)", range.min(), number)); - } else if (number > range.max()) { - throw new ParameterException( - String.format( - "A valid value is less than or equal to %s " + - "(you entered %s)", range.max(), number)); - } - } - } - } - - /** - * Validate a string value using relevant modifiers. - * - * @param string the string - * @param modifiers the list of modifiers to scan - * @throws ParameterException on a validation error - */ - private static void validate(String string, Annotation[] modifiers) - throws ParameterException { - if (string == null) { - return; - } - - for (Annotation modifier : modifiers) { - if (modifier instanceof Validate) { - Validate validate = (Validate) modifier; - - if (!validate.regex().isEmpty()) { - if (!string.matches(validate.regex())) { - throw new ParameterException( - String.format( - "The given text doesn't match the right " + - "format (technically speaking, the 'format' is %s)", - validate.regex())); - } - } - } - } - } - -} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Range.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Range.java deleted file mode 100644 index 0ff21ca12..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Range.java +++ /dev/null @@ -1,50 +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.util.command.binding; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Specifies a range of values for numbers. - * - * @see PrimitiveBindings a user of this annotation as a modifier - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -public @interface Range { - - /** - * The minimum value that the number can be at, inclusive. - * - * @return the minimum value - */ - double min() default Double.MIN_VALUE; - - /** - * The maximum value that the number can be at, inclusive. - * - * @return the maximum value - */ - double max() default Double.MAX_VALUE; - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/StandardBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/StandardBindings.java deleted file mode 100644 index a5a06e5fe..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/StandardBindings.java +++ /dev/null @@ -1,46 +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.util.command.binding; - -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.worldedit.util.command.parametric.ArgumentStack; -import com.sk89q.worldedit.util.command.parametric.BindingBehavior; -import com.sk89q.worldedit.util.command.parametric.BindingHelper; -import com.sk89q.worldedit.util.command.parametric.BindingMatch; - -/** - * Standard bindings that should be available to most configurations. - */ -public final class StandardBindings extends BindingHelper { - - /** - * Gets a {@link CommandContext} from a {@link ArgumentStack}. - * - * @param context the context - * @return a selection - */ - @BindingMatch(type = CommandContext.class, - behavior = BindingBehavior.PROVIDES) - public CommandContext getCommandContext(ArgumentStack context) { - context.markConsumed(); // Consume entire stack - return context.getContext(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Switch.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Switch.java deleted file mode 100644 index 8d0e122ff..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Switch.java +++ /dev/null @@ -1,44 +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.util.command.binding; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates a command flag, such as {@code /command -f}. - * - *

If used on a boolean type, then the flag will be a non-value flag. If - * used on any other type, then the flag will be a value flag.

- */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -public @interface Switch { - - /** - * The flag character. - * - * @return the flag character (A-Z a-z 0-9 is acceptable) - */ - char value(); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Text.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Text.java deleted file mode 100644 index 030bc9ad4..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Text.java +++ /dev/null @@ -1,41 +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.util.command.binding; - -import com.sk89q.worldedit.util.command.parametric.ArgumentStack; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates a {@link String} parameter will call {@link ArgumentStack#remaining()} and - * therefore consume all remaining arguments. - * - *

This should only be used at the end of a list of parameters (of parameters that - * need to consume from the stack of arguments), otherwise following parameters will - * have no values left to consume.

- */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -public @interface Text { - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Validate.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Validate.java deleted file mode 100644 index 3686aa359..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/binding/Validate.java +++ /dev/null @@ -1,45 +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.util.command.binding; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import java.util.regex.Pattern; - -/** - * Used to validate a string. - * - * @see PrimitiveBindings where this validation is used - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) -public @interface Validate { - - /** - * An optional regular expression that must match the string. - * - * @see Pattern regular expression class - * @return the pattern - */ - String regex() default ""; - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/BranchingCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/BranchingCommand.java deleted file mode 100644 index ce4ba58fe..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/BranchingCommand.java +++ /dev/null @@ -1,111 +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.util.command.composition; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.ArgumentUtils; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public abstract class BranchingCommand implements CommandExecutor { - - private final String name; - private final Map> options = Maps.newHashMap(); - private final Set primaryAliases = Sets.newHashSet(); - - public BranchingCommand(String name) { - this.name = name; - } - - public void putOption(CommandExecutor executor, String primaryAlias, String... aliases) { - options.put(primaryAlias, executor); - primaryAliases.add(primaryAlias); - for (String alias : aliases) { - options.put(alias, executor); - } - } - - @Override - public T call(CommandArgs args, CommandLocals locals) throws CommandException { - try { - String classifier = args.next(); - CommandExecutor executor = options.get(classifier.toLowerCase()); - if (executor != null) { - return executor.call(args, locals); - } else { - throw new CommandException("'" + classifier + "' isn't a valid option for '" + name + "'. " + - "Try one of: " + Joiner.on(", ").join(primaryAliases)); - } - } catch (MissingArgumentException e) { - throw new CommandException("Missing value for <" + name + "> " + - "(try one of " + Joiner.on(" | ").join(primaryAliases) + ")."); - } - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - String classifier = args.next(); - try { - CommandExecutor executor = options.get(classifier.toLowerCase()); - if (executor != null) { - return executor.getSuggestions(args, locals); - } - } catch (MissingArgumentException ignored) { - } - - return ArgumentUtils.getMatchingSuggestions((classifier.isEmpty() ? primaryAliases : options.keySet()), classifier); - } - - @Override - public String getUsage() { - List optionUsages = Lists.newArrayList(); - for (String alias : primaryAliases) { - CommandExecutor executor = options.get(alias); - String usage = executor.getUsage(); - if (usage.isEmpty()) { - optionUsages.add(alias); - } else { - optionUsages.add(alias + " " + executor.getUsage()); - } - } - - return "(" + Joiner.on(" | ").join(optionUsages) + ")"; - } - - @Override - public boolean testPermission(CommandLocals locals) { - for (CommandExecutor executor : options.values()) { - if (!executor.testPermission(locals)) { - return false; - } - } - return true; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/CommandExecutor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/CommandExecutor.java deleted file mode 100644 index a9729884b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/CommandExecutor.java +++ /dev/null @@ -1,41 +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.util.command.composition; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; - -import java.util.List; - -public interface CommandExecutor { - - T call(CommandArgs args, CommandLocals locals) throws CommandException; - - List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException; - - String getUsage(); - - String getDescription(); - - boolean testPermission(CommandLocals locals); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/FlagParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/FlagParser.java deleted file mode 100644 index fd64dd82d..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/FlagParser.java +++ /dev/null @@ -1,196 +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.util.command.composition; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; -import com.sk89q.worldedit.util.command.composition.FlagParser.FlagData; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import javax.annotation.Nullable; - -public class FlagParser implements CommandExecutor { - - private final Map> flags = Maps.newHashMap(); - - public Flag registerFlag(char flag, CommandExecutor executor) { - Flag ret = new Flag<>(flag); - flags.put(flag, executor); - return ret; - } - - @Override - public FlagData call(CommandArgs args, CommandLocals locals) throws CommandException { - Map values = Maps.newHashMap(); - try { - while (true) { - String next = args.peek(); - if (next.equals("--")) { - args.next(); - break; - } else if (next.length() > 0 && next.charAt(0) == '-') { - args.next(); - - if (next.length() == 1) { - throw new CommandException("- must be followed by a flag (like -a), otherwise use -- before the - (i.e. /cmd -- - is a dash)."); - } else { - for (int i = 1; i < next.length(); i++) { - char flag = next.charAt(i); - CommandExecutor executor = flags.get(flag); - if (executor != null) { - values.put(flag, executor.call(args, locals)); - } else { - throw new CommandException("Unknown flag: -" + flag + " (try one of -" + Joiner.on("").join(flags.keySet()) + " or put -- to skip flag parsing, i.e. /cmd -- -this begins with a dash)."); - } - } - } - } else { - break; - } - } - } catch (MissingArgumentException ignored) { - } - - return new FlagData(values); - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - List suggestions = Collections.emptyList(); - - while (true) { - String next = args.peek(); - if (next.equals("--")) { - args.next(); - break; - } else if (next.length() > 0 && next.charAt(0) == '-') { - args.next(); - - if (!args.hasNext()) { // Completing -| or -???| - List flagSuggestions = Lists.newArrayList(); - for (Character flag : flags.keySet()) { - if (next.indexOf(flag) < 1) { // Don't add any flags that the user has entered - flagSuggestions.add(next + flag); - } - } - return flagSuggestions; - } else { // Completing -??? ???| - for (int i = 1; i < next.length(); i++) { - char flag = next.charAt(i); - CommandExecutor executor = flags.get(flag); - if (executor != null) { - suggestions = executor.getSuggestions(args, locals); - } else { - return suggestions; - } - } - } - } else { - return suggestions; - } - } - - return suggestions; - } - - @Override - public String getUsage() { - List options = Lists.newArrayList(); - for (Entry> entry : flags.entrySet()) { - String usage = entry.getValue().getUsage(); - options.add("[-" + entry.getKey() + (!usage.isEmpty() ? " " + usage : "") + "]"); - } - return Joiner.on(" ").join(options); - } - - @Override - public String getDescription() { - return "Read flags"; - } - - @Override - public boolean testPermission(CommandLocals locals) { - for (CommandExecutor executor : flags.values()) { - if (!executor.testPermission(locals)) { - return false; - } - } - - return true; - } - - public static class FlagData { - private final Map data; - - private FlagData(Map data) { - this.data = data; - } - - public int size() { - return data.size(); - } - - public boolean isEmpty() { - return data.isEmpty(); - } - - public Object get(char key) { - return data.get(key); - } - - public boolean containsKey(char key) { - return data.containsKey(key); - } - - } - - public static final class Flag { - private final char flag; - - private Flag(char flag) { - this.flag = flag; - } - - @SuppressWarnings("unchecked") - @Nullable - public T get(FlagData data) { - return (T) data.get(flag); - } - - public T get(FlagData data, T fallback) { - T value = get(data); - if (value == null) { - return fallback; - } else { - return value; - } - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/LegacyCommandAdapter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/LegacyCommandAdapter.java deleted file mode 100644 index f3470b67b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/LegacyCommandAdapter.java +++ /dev/null @@ -1,87 +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.util.command.composition; - -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.Description; -import com.sk89q.worldedit.util.command.SimpleDescription; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; -import com.sk89q.worldedit.util.command.argument.UnusedArgumentsException; - -import java.util.List; - -public class LegacyCommandAdapter implements CommandCallable { - - private final CommandExecutor executor; - - private LegacyCommandAdapter(CommandExecutor executor) { - this.executor = executor; - } - - @Override - public final Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException { - CommandArgs args = new CommandArgs.Parser().parse(arguments); - - if (args.hasNext()) { - if (args.uncheckedPeek().equals("-?")) { - throw new CommandException(executor.getUsage()); - } - } - - Object ret = executor.call(args, locals); - try { - args.requireAllConsumed(); - } catch (UnusedArgumentsException e) { - throw new CommandException(e.getMessage()); - } - return ret; - } - - @Override - public Description getDescription() { - return new SimpleDescription() - .setDescription(executor.getDescription()) - .overrideUsage(executor.getUsage()); - } - - @Override - public boolean testPermission(CommandLocals locals) { - return executor.testPermission(locals); - } - - @Override - public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { - CommandArgs args = new CommandArgs.Parser().setUsingHangingArguments(true).parse(arguments); - try { - return executor.getSuggestions(args, locals); - } catch (MissingArgumentException e) { - return Lists.newArrayList(); - } - } - - public static LegacyCommandAdapter adapt(CommandExecutor executor) { - return new LegacyCommandAdapter(executor); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ParameterCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ParameterCommand.java deleted file mode 100644 index 8580f4f6d..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ParameterCommand.java +++ /dev/null @@ -1,79 +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.util.command.composition; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.composition.FlagParser.Flag; - -import java.util.List; - -public abstract class ParameterCommand implements CommandExecutor { - - private final List> parameters = Lists.newArrayList(); - private final FlagParser flagParser = new FlagParser(); - - public ParameterCommand() { - addParameter(flagParser); - } - - protected List> getParameters() { - return parameters; - } - - public > E addParameter(E executor) { - parameters.add(executor); - return executor; - } - - public Flag addFlag(char flag, CommandExecutor executor) { - return flagParser.registerFlag(flag, executor); - } - - protected FlagParser getFlagParser() { - return flagParser; - } - - @Override - public final String getUsage() { - List parts = Lists.newArrayList(); - for (CommandExecutor executor : parameters) { - String usage = executor.getUsage(); - if (!usage.isEmpty()) { - parts.add(executor.getUsage()); - } - } - return Joiner.on(" ").join(parts); - } - - @Override - public final boolean testPermission(CommandLocals locals) { - for (CommandExecutor executor : parameters) { - if (!executor.testPermission(locals)) { - return false; - } - } - return testPermission0(locals); - } - - protected abstract boolean testPermission0(CommandLocals locals); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ProvidedValue.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ProvidedValue.java deleted file mode 100644 index 5528728b7..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/ProvidedValue.java +++ /dev/null @@ -1,69 +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.util.command.composition; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; - -import java.util.Collections; -import java.util.List; - -public class ProvidedValue implements CommandExecutor { - - private final T value; - private final String description; - - private ProvidedValue(T value, String description) { - this.value = value; - this.description = description; - } - - @Override - public T call(CommandArgs args, CommandLocals locals) throws CommandException { - return value; - } - - @Override - public List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - return Collections.emptyList(); - } - - @Override - public String getUsage() { - return ""; - } - - @Override - public String getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - return true; - } - - public static ProvidedValue create(T value, String description) { - return new ProvidedValue<>(value, description); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/SimpleCommand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/SimpleCommand.java deleted file mode 100644 index fbcf9602b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/composition/SimpleCommand.java +++ /dev/null @@ -1,54 +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.util.command.composition; - -import com.google.common.collect.Lists; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.argument.CommandArgs; -import com.sk89q.worldedit.util.command.argument.MissingArgumentException; - -import java.util.List; - -public abstract class SimpleCommand extends ParameterCommand { - - @Override - public final List getSuggestions(CommandArgs args, CommandLocals locals) throws MissingArgumentException { - List suggestions = Lists.newArrayList(); - boolean seenParameter = false; - for (CommandExecutor parameter : getParameters()) { - try { - suggestions = parameter.getSuggestions(args, locals); - seenParameter = true; - } catch (MissingArgumentException e) { - if (seenParameter) { - return suggestions; - } else { - throw e; - } - } - - // There's nothing more anyway - if (args.position() == args.size()) { - return suggestions; - } - } - return suggestions; - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/CommandGraph.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/CommandGraph.java deleted file mode 100644 index 1b9dacb32..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/CommandGraph.java +++ /dev/null @@ -1,84 +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.util.command.fluent; - -import com.sk89q.worldedit.util.command.Dispatcher; -import com.sk89q.worldedit.util.command.SimpleDispatcher; -import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; - -/** - * A fluent interface to creating a command graph. - * - *

A command graph may have multiple commands, and multiple sub-commands below that, - * and possibly below that.

- */ -public class CommandGraph { - - private final DispatcherNode rootDispatcher; - private ParametricBuilder builder; - - /** - * Create a new command graph. - */ - public CommandGraph() { - SimpleDispatcher dispatcher = new SimpleDispatcher(); - rootDispatcher = new DispatcherNode(this, null, dispatcher); - } - - /** - * Get the root dispatcher node. - * - * @return the root dispatcher node - */ - public DispatcherNode commands() { - return rootDispatcher; - } - - /** - * Get the {@link ParametricBuilder}. - * - * @return the builder, or null. - */ - public ParametricBuilder getBuilder() { - return builder; - } - - /** - * Set the {@link ParametricBuilder} used for calls to - * {@link DispatcherNode#registerMethods(Object)}. - * - * @param builder the builder, or null - * @return this object - */ - public CommandGraph builder(ParametricBuilder builder) { - this.builder = builder; - return this; - } - - /** - * Get the root dispatcher. - * - * @return the root dispatcher - */ - public Dispatcher getDispatcher() { - return rootDispatcher.getDispatcher(); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java deleted file mode 100644 index 8bcbbfe85..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java +++ /dev/null @@ -1,139 +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.util.command.fluent; - -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.Dispatcher; -import com.sk89q.worldedit.util.command.SimpleDispatcher; -import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; - -/** - * A collection of commands. - */ -public class DispatcherNode { - - private final CommandGraph graph; - private final DispatcherNode parent; - private final SimpleDispatcher dispatcher; - - /** - * Create a new instance. - * - * @param graph the root fluent graph object - * @param parent the parent node, or null - * @param dispatcher the dispatcher for this node - */ - DispatcherNode(CommandGraph graph, DispatcherNode parent, - SimpleDispatcher dispatcher) { - this.graph = graph; - this.parent = parent; - this.dispatcher = dispatcher; - } - - /** - * Set the description. - * - *

This can only be used on {@link DispatcherNode}s returned by - * {@link #group(String...)}.

- * - * @param description the description - * @return this object - */ - public DispatcherNode describeAs(String description) { - dispatcher.getDescription().setDescription(description); - return this; - } - - /** - * Register a command with this dispatcher. - * - * @param callable the executor - * @param alias the list of aliases, where the first alias is the primary one - */ - public DispatcherNode register(CommandCallable callable, String... alias) { - dispatcher.registerCommand(callable, alias); - return this; - } - - /** - * Build and register a command with this dispatcher using the - * {@link ParametricBuilder} assigned on the root {@link CommandGraph}. - * - * @param object the object provided to the {@link ParametricBuilder} - * @return this object - * @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object) - */ - public DispatcherNode registerMethods(Object object) { - ParametricBuilder builder = graph.getBuilder(); - if (builder == null) { - throw new RuntimeException("No ParametricBuilder set"); - } - builder.registerMethodsAsCommands(getDispatcher(), object); - return this; - } - - /** - * Create a new command that will contain sub-commands. - * - *

The object returned by this method can be used to add sub-commands. To - * return to this "parent" context, use {@link DispatcherNode#graph()}.

- * - * @param alias the list of aliases, where the first alias is the primary one - * @return an object to place sub-commands - */ - public DispatcherNode group(String... alias) { - SimpleDispatcher command = new SimpleDispatcher(); - getDispatcher().registerCommand(command, alias); - return new DispatcherNode(graph, this, command); - } - - /** - * Return the parent node. - * - * @return the parent node - * @throws RuntimeException if there is no parent node. - */ - public DispatcherNode parent() { - if (parent != null) { - return parent; - } - - throw new RuntimeException("This node does not have a parent"); - } - - /** - * Get the root command graph. - * - * @return the root command graph - */ - public CommandGraph graph() { - return graph; - } - - /** - * Get the underlying dispatcher of this object. - * - * @return the dispatcher - */ - public Dispatcher getDispatcher() { - return dispatcher; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AbstractInvokeListener.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AbstractInvokeListener.java deleted file mode 100644 index 65fadc101..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/AbstractInvokeListener.java +++ /dev/null @@ -1,36 +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.util.command.parametric; - -import com.sk89q.worldedit.util.command.SimpleDescription; - -import java.lang.reflect.Method; - -/** - * An abstract listener. - */ -public abstract class AbstractInvokeListener implements InvokeListener { - - @Override - public void updateDescription(Object object, Method method, - ParameterData[] parameters, SimpleDescription description) { - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ArgumentStack.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ArgumentStack.java deleted file mode 100644 index 0f0b9a52b..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ArgumentStack.java +++ /dev/null @@ -1,78 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandContext; - -public interface ArgumentStack { - - /** - * Get the next string, which may come from the stack or a value flag. - * - * @return the value - * @throws ParameterException on a parameter error - */ - String next() throws ParameterException; - - /** - * Get the next integer, which may come from the stack or a value flag. - * - * @return the value - * @throws ParameterException on a parameter error - */ - Integer nextInt() throws ParameterException; - - /** - * Get the next double, which may come from the stack or a value flag. - * - * @return the value - * @throws ParameterException on a parameter error - */ - Double nextDouble() throws ParameterException; - - /** - * Get the next boolean, which may come from the stack or a value flag. - * - * @return the value - * @throws ParameterException on a parameter error - */ - Boolean nextBoolean() throws ParameterException; - - /** - * Get all remaining string values, which will consume the rest of the stack. - * - * @return the value - * @throws ParameterException on a parameter error - */ - String remaining() throws ParameterException; - - /** - * Set as completely consumed. - */ - void markConsumed(); - - /** - * Get the underlying context. - * - * @return the context - */ - CommandContext getContext(); - -} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Binding.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Binding.java deleted file mode 100644 index 108fc1bf8..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Binding.java +++ /dev/null @@ -1,93 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.worldedit.util.command.binding.PrimitiveBindings; -import com.sk89q.worldedit.util.command.binding.StandardBindings; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; -import java.util.List; - -/** - * Used to parse user input for a command, based on available method types - * and annotations. - * - *

A binding can be used to handle several types at once. For a binding to be - * called, it must be registered with a {@link ParametricBuilder} with - * {@link ParametricBuilder#addBinding(Binding, java.lang.reflect.Type...)}.

- * - * @see PrimitiveBindings an example of primitive bindings - * @see StandardBindings standard bindings - */ -public interface Binding { - - /** - * Get the types that this binding handles. - * - * @return the types - */ - Type[] getTypes(); - - /** - * Get how this binding consumes from a {@link ArgumentStack}. - * - * @param parameter information about the parameter - * @return the behavior - */ - BindingBehavior getBehavior(ParameterData parameter); - - /** - * Get the number of arguments that this binding will consume, if this - * information is available. - * - *

This method must return -1 for binding behavior types that are not - * {@link BindingBehavior#CONSUMES}.

- * - * @param parameter information about the parameter - * @return the number of consumed arguments, or -1 if unknown or irrelevant - */ - int getConsumedCount(ParameterData parameter); - - /** - * Attempt to consume values (if required) from the given {@link ArgumentStack} - * in order to instantiate an object for the given parameter. - * - * @param parameter information about the parameter - * @param scoped the arguments the user has input - * @param onlyConsume true to only consume arguments - * @return an object parsed for the given parameter - * @throws ParameterException thrown if the parameter could not be formulated - * @throws CommandException on a command exception - */ - Object bind(ParameterData parameter, ArgumentStack scoped, boolean onlyConsume) - throws ParameterException, CommandException, InvocationTargetException; - - /** - * Get a list of suggestions for the given parameter and user arguments. - * - * @param parameter information about the parameter - * @param prefix what the user has typed so far (may be an empty string) - * @return a list of suggestions - */ - List getSuggestions(ParameterData parameter, String prefix); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingBehavior.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingBehavior.java deleted file mode 100644 index eeef23dbd..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingBehavior.java +++ /dev/null @@ -1,52 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.worldedit.util.command.binding.Switch; - -/** - * Determines the type of binding. - */ -public enum BindingBehavior { - - /** - * Always consumes from a {@link ArgumentStack}. - */ - CONSUMES, - - /** - * Sometimes consumes from a {@link ArgumentStack}. - * - *

Bindings that exhibit this behavior must be defined as a {@link Switch} - * by commands utilizing the given binding.

- */ - INDETERMINATE, - - /** - * Never consumes from a {@link ArgumentStack}. - * - *

Bindings that exhibit this behavior generate objects from other sources, - * such as from a {@link CommandLocals}. These are "magic" bindings that inject - * variables.

- */ - PROVIDES - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingHelper.java deleted file mode 100644 index 73b59f087..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingHelper.java +++ /dev/null @@ -1,224 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandException; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * A binding helper that uses the {@link BindingMatch} annotation to make - * writing bindings extremely easy. - * - *

Methods must have the following and only the following parameters:

- * - *
    - *
  • A {@link ArgumentStack}
  • - *
  • A {@link Annotation} if there is a classifier set
  • - *
  • A {@link Annotation}[] - * if there {@link BindingMatch#provideModifiers()} is true
  • - *
- * - *

Methods may throw any exception. Exceptions may be converted using a - * {@link ExceptionConverter} registered with the {@link ParametricBuilder}.

- */ -public class BindingHelper implements Binding { - - private final List bindings; - private final Type[] types; - - /** - * Create a new instance. - */ - public BindingHelper() { - List bindings = new ArrayList<>(); - List types = new ArrayList<>(); - - for (Method method : this.getClass().getMethods()) { - BindingMatch info = method.getAnnotation(BindingMatch.class); - if (info != null) { - Class classifier = null; - - // Set classifier - if (!info.classifier().equals(Annotation.class)) { - classifier = info.classifier(); - types.add(classifier); - } - - for (Type t : info.type()) { - Type type = null; - - // Set type - if (!t.equals(Class.class)) { - type = t; - if (classifier == null) { - types.add(type); // Only if there is no classifier set! - } - } - - // Check to see if at least one is set - if (type == null && classifier == null) { - throw new RuntimeException( - "A @BindingMatch needs either a type or classifier set"); - } - - BoundMethod handler = new BoundMethod(info, type, classifier, method); - bindings.add(handler); - } - } - } - - Collections.sort(bindings); - - this.bindings = bindings; - - Type[] typesArray = new Type[types.size()]; - types.toArray(typesArray); - this.types = typesArray; - - } - - /** - * Match a {@link BindingMatch} according to the given parameter. - * - * @param parameter the parameter - * @return a binding - */ - private BoundMethod match(ParameterData parameter) { - for (BoundMethod binding : bindings) { - Annotation classifer = parameter.getClassifier(); - Type type = parameter.getType(); - - if (binding.classifier != null) { - if (classifer != null && classifer.annotationType().equals(binding.classifier)) { - if (binding.type == null || binding.type.equals(type)) { - return binding; - } - } - } else if (binding.type.equals(type)) { - return binding; - } - } - - throw new RuntimeException("Unknown type"); - } - - @Override - public Type[] getTypes() { - return types; - } - - @Override - public int getConsumedCount(ParameterData parameter) { - return match(parameter).annotation.consumedCount(); - } - - @Override - public BindingBehavior getBehavior(ParameterData parameter) { - return match(parameter).annotation.behavior(); - } - - @Override - public Object bind(ParameterData parameter, ArgumentStack scoped, - boolean onlyConsume) throws ParameterException, CommandException, InvocationTargetException { - BoundMethod binding = match(parameter); - List args = new ArrayList<>(); - args.add(scoped); - - if (binding.classifier != null) { - args.add(parameter.getClassifier()); - } - - if (binding.annotation.provideModifiers()) { - args.add(parameter.getModifiers()); - } - - if (onlyConsume && binding.annotation.behavior() == BindingBehavior.PROVIDES) { - return null; // Nothing to consume, nothing to do - } - - Object[] argsArray = new Object[args.size()]; - args.toArray(argsArray); - - try { - return binding.method.invoke(this, argsArray); - } catch (IllegalArgumentException e) { - throw new RuntimeException( - "Processing of classifier " + parameter.getClassifier() + - " and type " + parameter.getType() + " failed for method\n" + - binding.method + "\nbecause the parameters for that method are wrong", e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof ParameterException) { - throw (ParameterException) e.getCause(); - } else if (e.getCause() instanceof CommandException) { - throw (CommandException) e.getCause(); - } - throw e; - } - } - - @Override - public List getSuggestions(ParameterData parameter, String prefix) { - return new ArrayList<>(); - } - - private static class BoundMethod implements Comparable { - private final BindingMatch annotation; - private final Type type; - private final Class classifier; - private final Method method; - - BoundMethod(BindingMatch annotation, Type type, - Class classifier, Method method) { - this.annotation = annotation; - this.type = type; - this.classifier = classifier; - this.method = method; - } - - @Override - public int compareTo(BoundMethod o) { - if (classifier != null && o.classifier == null) { - return -1; - } else if (classifier == null && o.classifier != null) { - return 1; - } else if (classifier != null && o.classifier != null) { - if (type != null && o.type == null) { - return -1; - } else if (type == null && o.type != null) { - return 1; - } else { - return 0; - } - } else { - return 0; - } - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingMatch.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingMatch.java deleted file mode 100644 index 049d3dc4d..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/BindingMatch.java +++ /dev/null @@ -1,71 +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.util.command.parametric; - -import java.lang.annotation.Annotation; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Denotes a match of a binding. - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface BindingMatch { - - /** - * The classifier. - * - * @return the classifier, or {@link Annotation} if not set - */ - Class classifier() default Annotation.class; - - /** - * The type. - * - * @return the type, or {@link Class} if not set - */ - Class[] type() default Class.class; - - /** - * The binding behavior. - * - * @return the behavior - */ - BindingBehavior behavior(); - - /** - * Get the number of arguments that this binding consumes. - * - * @return -1 if unknown or irrelevant - */ - int consumedCount() default -1; - - /** - * Set whether an array of modifier annotations is provided in the list of - * arguments. - * - * @return true to provide modifiers - */ - boolean provideModifiers() default false; - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ContextArgumentStack.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ContextArgumentStack.java deleted file mode 100644 index c7222b9e1..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ContextArgumentStack.java +++ /dev/null @@ -1,178 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.worldedit.util.command.MissingParameterException; - -/** - * Makes an instance of a {@link CommandContext} into a stack of arguments - * that can be consumed. - * - * @see ParametricBuilder a user of this class - */ -public class ContextArgumentStack implements ArgumentStack { - - private final CommandContext context; - private int index = 0; - private int markedIndex = 0; - - /** - * Create a new instance using the given context. - * - * @param context the context - */ - public ContextArgumentStack(CommandContext context) { - this.context = context; - } - - @Override - public String next() throws ParameterException { - try { - return context.getString(index++); - } catch (IndexOutOfBoundsException e) { - throw new MissingParameterException(); - } - } - - @Override - public Integer nextInt() throws ParameterException { - try { - return Integer.parseInt(next()); - } catch (NumberFormatException e) { - throw new ParameterException( - "Expected a number, got '" + context.getString(index - 1) + "'"); - } - } - - @Override - public Double nextDouble() throws ParameterException { - try { - return Double.parseDouble(next()); - } catch (NumberFormatException e) { - throw new ParameterException( - "Expected a number, got '" + context.getString(index - 1) + "'"); - } - } - - @Override - public Boolean nextBoolean() throws ParameterException { - try { - return next().equalsIgnoreCase("true"); - } catch (IndexOutOfBoundsException e) { - throw new MissingParameterException(); - } - } - - @Override - public String remaining() throws ParameterException { - try { - String value = context.getJoinedStrings(index); - index = context.argsLength(); - return value; - } catch (IndexOutOfBoundsException e) { - throw new MissingParameterException(); - } - } - - /** - * Get the unconsumed arguments left over, without touching the stack. - * - * @return the unconsumed arguments - */ - public String getUnconsumed() { - if (index >= context.argsLength()) { - return null; - } - - return context.getJoinedStrings(index); - } - - @Override - public void markConsumed() { - index = context.argsLength(); - } - - /** - * Return the current position. - * - * @return the position - */ - public int position() { - return index; - } - - /** - * Mark the current position of the stack. - * - *

The marked position initially starts at 0.

- */ - public void mark() { - markedIndex = index; - } - - /** - * Reset to the previously {@link #mark()}ed position of the stack, and return - * the arguments that were consumed between this point and that previous point. - * - *

The marked position initially starts at 0.

- * - * @return the consumed arguments - */ - public String reset() { - String value = context.getString(markedIndex, index); - index = markedIndex; - return value; - } - - /** - * Return whether any arguments were consumed between the marked position - * and the current position. - * - *

The marked position initially starts at 0.

- * - * @return true if values were consumed. - */ - public boolean wasConsumed() { - return markedIndex != index; - } - - /** - * Return the arguments that were consumed between this point and that marked point. - * - *

The marked position initially starts at 0.

- * - * @return the consumed arguments - */ - public String getConsumed() { - return context.getString(markedIndex, index); - } - - /** - * Get the underlying context. - * - * @return the context - */ - @Override - public CommandContext getContext() { - return context; - } - -} 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 3ab0dda59..e943cd6e9 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 @@ -24,27 +24,26 @@ import org.enginehub.piston.exception.CommandException; import org.enginehub.piston.exception.CommandExecutionException; /** - * Used to convert a recognized {@link Throwable} into an appropriate + * Used to convert a recognized {@link Throwable} into an appropriate * {@link CommandException}. - * - *

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 + * + *

Methods 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 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}.

- * + * *

This also allows the code calling the command to not need be aware of these * application-specific exceptions, as they will all be converted to * {@link CommandException}s that are handled normally.

*/ public interface ExceptionConverter { - + /** * Attempt to convert the given throwable into a {@link CommandException}. - * + * *

If the exception is not recognized, then nothing should be thrown.

- * + * * @param t the throwable * @throws CommandException a command exception */ diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeHandler.java deleted file mode 100644 index 465f89689..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeHandler.java +++ /dev/null @@ -1,82 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; - -import java.lang.reflect.Method; - -/** - * Called before and after a command is invoked for commands executed by a command - * created using {@link ParametricBuilder}. - * - *

Invocation handlers are created by {@link InvokeListener}s. Multiple - * listeners and handlers can be registered, and all be run. However, if one handler - * throws an exception, future handlers will not execute and the command will - * not execute (if thrown in - * {@link #preInvoke(Object, Method, ParameterData[], Object[], CommandContext)}).

- * - * @see InvokeListener the factory - */ -public interface InvokeHandler { - - /** - * Called before parameters are processed. - * - * @param object the object - * @param method the method - * @param parameters the list of parameters - * @param context the context - * @throws CommandException can be thrown for an error, which will stop invocation - * @throws ParameterException on parameter error - */ - void preProcess(Object object, Method method, ParameterData[] parameters, - CommandContext context) throws CommandException, ParameterException; - - /** - * Called before the parameter is invoked. - * - * @param object the object - * @param method the method - * @param parameters the list of parameters - * @param args the arguments to be given to the method - * @param context the context - * @throws CommandException can be thrown for an error, which will stop invocation - * @throws ParameterException on parameter error - */ - void preInvoke(Object object, Method method, ParameterData[] parameters, - Object[] args, CommandContext context) throws CommandException, ParameterException; - - /** - * Called after the parameter is invoked. - * - * @param object the object - * @param method the method - * @param parameters the list of parameters - * @param args the arguments to be given to the method - * @param context the context - * @throws CommandException can be thrown for an error - * @throws ParameterException on parameter error - */ - void postInvoke(Object object, Method method, ParameterData[] parameters, - Object[] args, CommandContext context) throws CommandException, ParameterException; - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeListener.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeListener.java deleted file mode 100644 index f30f86c9f..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/InvokeListener.java +++ /dev/null @@ -1,58 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.SimpleDescription; - -import java.lang.reflect.Method; - -/** - * Listens to events related to {@link ParametricBuilder}. - */ -public interface InvokeListener { - - /** - * Create a new invocation handler. - * - *

An example use of an {@link InvokeHandler} would be to verify permissions - * added by the {@link CommandPermissions} annotation.

- * - *

For simple {@link InvokeHandler}, an object can implement both this - * interface and {@link InvokeHandler}.

- * - * @return a new invocation handler - */ - InvokeHandler createInvokeHandler(); - - /** - * During creation of a {@link CommandCallable} by a {@link ParametricBuilder}, - * this will be called in case the description needs to be updated. - * - * @param object the object - * @param method the method - * @param parameters a list of parameters - * @param description the description to be updated - */ - void updateDescription(Object object, Method method, ParameterData[] parameters, - SimpleDescription description); - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/LegacyCommandsHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/LegacyCommandsHandler.java deleted file mode 100644 index fbc1794c2..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/LegacyCommandsHandler.java +++ /dev/null @@ -1,97 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.worldedit.util.command.MissingParameterException; -import com.sk89q.worldedit.util.command.SimpleDescription; -import com.sk89q.worldedit.util.command.UnconsumedParameterException; - -import java.lang.reflect.Method; - -/** - * Handles legacy properties on {@link Command} such as {@link Command#min()} and - * {@link Command#max()}. - */ -public class LegacyCommandsHandler extends AbstractInvokeListener implements InvokeHandler { - - @Override - public InvokeHandler createInvokeHandler() { - return this; - } - - @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 ParameterException { - Command annotation = method.getAnnotation(Command.class); - - if (annotation != null) { - if (context.argsLength() < annotation.min()) { - throw new MissingParameterException(); - } - - if (annotation.max() != -1 && context.argsLength() > annotation.max()) { - throw new UnconsumedParameterException( - context.getRemainingString(annotation.max())); - } - } - } - - @Override - public void postInvoke(Object object, Method method, - ParameterData[] parameters, Object[] args, CommandContext context) { - - } - - @Override - public void updateDescription(Object object, Method method, - ParameterData[] parameters, SimpleDescription description) { - Command annotation = method.getAnnotation(Command.class); - - // Handle the case for old commands where no usage is set and all of its - // parameters are provider bindings, so its usage information would - // be blank and would imply that there were no accepted parameters - if (annotation != null && annotation.usage().isEmpty() - && (annotation.min() > 0 || annotation.max() > 0)) { - boolean hasUserParameters = false; - - for (ParameterData parameter : parameters) { - if (parameter.getBinding().getBehavior(parameter) != BindingBehavior.PROVIDES) { - hasUserParameters = true; - break; - } - } - - if (!hasUserParameters) { - description.overrideUsage("(unknown usage information)"); - } - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Optional.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Optional.java deleted file mode 100644 index bd6d5448f..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/Optional.java +++ /dev/null @@ -1,41 +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.util.command.parametric; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Indicates an optional parameter. - */ -@Target(ElementType.PARAMETER) -@Retention(RetentionPolicy.RUNTIME) -public @interface Optional { - - /** - * The default value to use if no value is set. - * - * @return a string value, or an empty list - */ - String[] value() default {}; - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterData.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterData.java deleted file mode 100644 index 649c576b4..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterData.java +++ /dev/null @@ -1,194 +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.util.command.parametric; - -import com.sk89q.worldedit.util.command.SimpleParameter; -import com.sk89q.worldedit.util.command.binding.PrimitiveBindings; -import com.sk89q.worldedit.util.command.binding.Range; -import com.sk89q.worldedit.util.command.binding.Text; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.lang.reflect.Type; - -/** - * Describes a parameter in detail. - */ -public class ParameterData extends SimpleParameter { - - private Binding binding; - private Annotation classifier; - private Annotation[] modifiers; - private Type type; - - /** - * Get the binding associated with this parameter. - * - * @return the binding - */ - public Binding getBinding() { - return binding; - } - - /** - * Set the binding associated with this parameter. - * - * @param binding the binding - */ - void setBinding(Binding binding) { - this.binding = binding; - } - - /** - * Set the main type of this parameter. - * - *

The type is normally that is used to determine which binding is used - * for a particular method's parameter.

- * - * @return the main type - * @see #getClassifier() which can override the type - */ - public Type getType() { - return type; - } - - /** - * Set the main type of this parameter. - * - * @param type the main type - */ - void setType(Type type) { - this.type = type; - } - - /** - * Get the classifier annotation. - * - *

Normally, the type determines what binding is called, but classifiers - * take precedence if one is found (and registered with - * {@link ParametricBuilder#addBinding(Binding, Type...)}). - * An example of a classifier annotation is {@link Text}.

- * - * @return the classifier annotation, null is possible - */ - public Annotation getClassifier() { - return classifier; - } - - /** - * Set the classifier annotation. - * - * @param classifier the classifier annotation, null is possible - */ - void setClassifier(Annotation classifier) { - this.classifier = classifier; - } - - /** - * Get a list of modifier annotations. - * - *

Modifier annotations are not considered in the process of choosing a binding - * for a method parameter, but they can be used to modify the behavior of a binding. - * An example of a modifier annotation is {@link Range}, which can restrict - * numeric values handled by {@link PrimitiveBindings} to be within a range. The list - * of annotations may contain a classifier and other unrelated annotations.

- * - * @return a list of annotations - */ - public Annotation[] getModifiers() { - return modifiers; - } - - /** - * Set the list of modifiers. - * - * @param modifiers a list of annotations - */ - void setModifiers(Annotation[] modifiers) { - this.modifiers = modifiers; - } - - /** - * Return the number of arguments this binding consumes. - * - * @return -1 if unknown or unavailable - */ - int getConsumedCount() { - return getBinding().getConsumedCount(this); - } - - /** - * Get whether this parameter is entered by the user. - * - * @return true if this parameter is entered by the user. - */ - boolean isUserInput() { - return getBinding().getBehavior(this) != BindingBehavior.PROVIDES; - } - - /** - * Get whether this parameter consumes non-flag arguments. - * - * @return true if this parameter consumes non-flag arguments - */ - boolean isNonFlagConsumer() { - return getBinding().getBehavior(this) != BindingBehavior.PROVIDES && !isValueFlag(); - } - - /** - * Validate this parameter and its binding. - */ - void validate(Method method, int parameterIndex) throws ParametricException { - // We can't have indeterminate consumers without @Switches otherwise - // it may screw up parameter processing for later bindings - BindingBehavior behavior = getBinding().getBehavior(this); - boolean indeterminate = (behavior == BindingBehavior.INDETERMINATE); - if (!isValueFlag() && indeterminate) { - throw new ParametricException( - "@Switch missing for indeterminate consumer\n\n" + - "Notably:\nFor the type " + type + ", the binding " + - getBinding().getClass().getCanonicalName() + - "\nmay or may not consume parameters (isIndeterminateConsumer(" + type + ") = true)" + - "\nand therefore @Switch(flag) is required for parameter #" + parameterIndex + " of \n" + - method.toGenericString()); - } - - // getConsumedCount() better return -1 if the BindingBehavior is not CONSUMES - if (behavior != BindingBehavior.CONSUMES && binding.getConsumedCount(this) != -1) { - throw new ParametricException( - "getConsumedCount() does not return -1 for binding " + - getBinding().getClass().getCanonicalName() + - "\neven though its behavior type is " + behavior.name() + - "\nfor parameter #" + parameterIndex + " of \n" + - method.toGenericString()); - } - - // getConsumedCount() should not return 0 if the BindingBehavior is not PROVIDES - if (behavior != BindingBehavior.PROVIDES && binding.getConsumedCount(this) == 0) { - throw new ParametricException( - "getConsumedCount() must not return 0 for binding " + - getBinding().getClass().getCanonicalName() + - "\nwhen its behavior type is " + behavior.name() + " and not PROVIDES " + - "\nfor parameter #" + parameterIndex + " of \n" + - method.toGenericString()); - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterException.java deleted file mode 100644 index 2fe681ba7..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParameterException.java +++ /dev/null @@ -1,43 +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.util.command.parametric; - -/** - * Thrown if there is an error with a parameter. - */ -public class ParameterException extends Exception { - - public ParameterException() { - super(); - } - - public ParameterException(String message) { - super(message); - } - - public ParameterException(Throwable cause) { - super(cause); - } - - public ParameterException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java deleted file mode 100644 index 422cd9982..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java +++ /dev/null @@ -1,230 +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.util.command.parametric; - -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.collect.ImmutableBiMap.Builder; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.worldedit.util.auth.Authorizer; -import com.sk89q.worldedit.util.auth.NullAuthorizer; -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.CommandCompleter; -import com.sk89q.worldedit.util.command.Dispatcher; -import com.sk89q.worldedit.util.command.NullCompleter; -import com.sk89q.worldedit.util.command.binding.PrimitiveBindings; -import com.sk89q.worldedit.util.command.binding.StandardBindings; -import com.sk89q.worldedit.util.command.binding.Switch; -import com.thoughtworks.paranamer.CachingParanamer; -import com.thoughtworks.paranamer.Paranamer; - -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Creates commands using annotations placed on methods and individual parameters of - * such methods. - * - * @see Command defines a command - * @see Switch defines a flag - */ -public class ParametricBuilder { - - private final Map bindings = new HashMap<>(); - private final Paranamer paranamer = new CachingParanamer(); - private final List invokeListeners = new ArrayList<>(); - private Authorizer authorizer = new NullAuthorizer(); - private CommandCompleter defaultCompleter = new NullCompleter(); - - /** - * Create a new builder. - * - *

This method will install {@link PrimitiveBindings} and - * {@link StandardBindings} and default bindings.

- */ - public ParametricBuilder() { - addBinding(new PrimitiveBindings()); - addBinding(new StandardBindings()); - } - - /** - * Add a binding for a given type or classifier (annotation). - * - *

Whenever a method parameter is encountered, a binding must be found for it - * so that it can be called later to consume the stack of arguments provided by - * the user and return an object that is later passed to - * {@link Method#invoke(Object, Object...)}.

- * - *

Normally, a {@link Type} is used to discern between different bindings, but - * if this is not specific enough, an annotation can be defined and used. This - * makes it a "classifier" and it will take precedence over the base type. For - * example, even if there is a binding that handles {@link String} parameters, - * a special {@code @MyArg} annotation can be assigned to a {@link String} - * parameter, which will cause the {@link Builder} to consult the {@link Binding} - * associated with {@code @MyArg} rather than with the binding for - * the {@link String} type.

- * - * @param binding the binding - * @param type a list of types (if specified) to override the binding's types - */ - public void addBinding(Binding binding, Type... type) { - if (type == null || type.length == 0) { - type = binding.getTypes(); - } - - for (Type t : type) { - bindings.put(t, binding); - } - } - - /** - * Attach an invocation listener. - * - *

Invocation handlers are called in order that their listeners are - * registered with a {@link ParametricBuilder}. It is not guaranteed that - * a listener may be called, in the case of a {@link CommandException} being - * thrown at any time before the appropriate listener or handler is called. - * It is possible for a - * {@link InvokeHandler#preInvoke(Object, Method, ParameterData[], Object[], CommandContext)} to - * be called for a invocation handler, but not the associated - * {@link InvokeHandler#postInvoke(Object, Method, ParameterData[], Object[], CommandContext)}.

- * - *

An example of an invocation listener is one to handle - * {@link CommandPermissions}, by first checking to see if permission is available - * in a {@link InvokeHandler#preInvoke(Object, Method, ParameterData[], Object[], CommandContext)} - * call. If permission is not found, then an appropriate {@link CommandException} - * can be thrown to cease invocation.

- * - * @param listener the listener - * @see InvokeHandler the handler - */ - public void addInvokeListener(InvokeListener listener) { - invokeListeners.add(listener); - } - - /** - * Build a list of commands from methods specially annotated with {@link Command} - * (and other relevant annotations) and register them all with the given - * {@link Dispatcher}. - * - * @param dispatcher the dispatcher to register commands with - * @param object the object contain the methods - * @throws ParametricException thrown if the commands cannot be registered - */ - public void registerMethodsAsCommands(Dispatcher dispatcher, Object object) throws ParametricException { - for (Method method : object.getClass().getDeclaredMethods()) { - Command definition = method.getAnnotation(Command.class); - if (definition != null) { - CommandCallable callable = build(object, method, definition); - dispatcher.registerCommand(callable, definition.aliases()); - } - } - } - - /** - * Build a {@link CommandCallable} for the given method. - * - * @param object the object to be invoked on - * @param method the method to invoke - * @param definition the command definition annotation - * @return the command executor - * @throws ParametricException thrown on an error - */ - private CommandCallable build(Object object, Method method, Command definition) - throws ParametricException { - return new ParametricCallable(this, object, method, definition); - } - - /** - * Get the object used to get method names on Java versions before 8 (assuming - * that Java 8 is given the ability to reliably reflect method names at runtime). - * - * @return the paranamer - */ - Paranamer getParanamer() { - return paranamer; - } - - /** - * Get the map of bindings. - * - * @return the map of bindings - */ - Map getBindings() { - return bindings; - } - - /** - * Get a list of invocation listeners. - * - * @return a list of invocation listeners - */ - List getInvokeListeners() { - return invokeListeners; - } - - /** - * Get the authorizer. - * - * @return the authorizer - */ - public Authorizer getAuthorizer() { - return authorizer; - } - - /** - * Set the authorizer. - * - * @param authorizer the authorizer - */ - public void setAuthorizer(Authorizer authorizer) { - checkNotNull(authorizer); - this.authorizer = authorizer; - } - - /** - * Get the default command suggestions provider that will be used if - * no suggestions are available. - * - * @return the default command completer - */ - public CommandCompleter getDefaultCompleter() { - return defaultCompleter; - } - - /** - * Set the default command suggestions provider that will be used if - * no suggestions are available. - * - * @param defaultCompleter the default command completer - */ - public void setDefaultCompleter(CommandCompleter defaultCompleter) { - checkNotNull(defaultCompleter); - this.defaultCompleter = defaultCompleter; - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java deleted file mode 100644 index 39f47b20e..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricCallable.java +++ /dev/null @@ -1,479 +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.util.command.parametric; - -import com.google.common.primitives.Chars; -import com.sk89q.minecraft.util.commands.Command; -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.minecraft.util.commands.CommandPermissionsException; -import com.sk89q.minecraft.util.commands.WrappedCommandException; -import com.sk89q.worldedit.util.command.CommandCallable; -import com.sk89q.worldedit.util.command.InvalidUsageException; -import com.sk89q.worldedit.util.command.MissingParameterException; -import com.sk89q.worldedit.util.command.Parameter; -import com.sk89q.worldedit.util.command.SimpleDescription; -import com.sk89q.worldedit.util.command.UnconsumedParameterException; -import com.sk89q.worldedit.util.command.binding.Switch; - -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * The implementation of a {@link CommandCallable} for the {@link ParametricBuilder}. - */ -class ParametricCallable implements CommandCallable { - - private final ParametricBuilder builder; - private final Object object; - private final Method method; - private final ParameterData[] parameters; - private final Set valueFlags = new HashSet<>(); - private final boolean anyFlags; - private final Set legacyFlags = new HashSet<>(); - private final SimpleDescription description = new SimpleDescription(); - private final CommandPermissions commandPermissions; - - /** - * Create a new instance. - * - * @param builder the parametric builder - * @param object the object to invoke on - * @param method the method to invoke - * @param definition the command definition annotation - * @throws ParametricException thrown on an error - */ - ParametricCallable(ParametricBuilder builder, Object object, Method method, Command definition) throws ParametricException { - this.builder = builder; - this.object = object; - this.method = method; - - Annotation[][] annotations = method.getParameterAnnotations(); - String[] names = builder.getParanamer().lookupParameterNames(method, false); - Type[] types = method.getGenericParameterTypes(); - parameters = new ParameterData[types.length]; - List userParameters = new ArrayList<>(); - - // This helps keep tracks of @Nullables that appear in the middle of a list - // of parameters - int numOptional = 0; - - // Set permission hint - CommandPermissions permHint = method.getAnnotation(CommandPermissions.class); - if (permHint != null) { - description.setPermissions(Arrays.asList(permHint.value())); - } - - // Go through each parameter - for (int i = 0; i < types.length; i++) { - Type type = types[i]; - - ParameterData parameter = new ParameterData(); - parameter.setType(type); - parameter.setModifiers(annotations[i]); - - // Search for annotations - for (Annotation annotation : annotations[i]) { - if (annotation instanceof Switch) { - parameter.setFlag(((Switch) annotation).value(), type != boolean.class); - } else if (annotation instanceof Optional) { - parameter.setOptional(true); - String[] value = ((Optional) annotation).value(); - if (value.length > 0) { - parameter.setDefaultValue(value); - } - // Special annotation bindings - } else if (parameter.getBinding() == null) { - parameter.setBinding(builder.getBindings().get(annotation.annotationType())); - parameter.setClassifier(annotation); - } - } - - parameter.setName(names.length > 0 ? names[i] : generateName(type, parameter.getClassifier(), i)); - - // Track all value flags - if (parameter.isValueFlag()) { - valueFlags.add(parameter.getFlag()); - } - - // No special @annotation binding... let's check for the type - if (parameter.getBinding() == null) { - parameter.setBinding(builder.getBindings().get(type)); - - // Don't know how to parse for this type of value - if (parameter.getBinding() == null) { - throw new ParametricException("Don't know how to handle the parameter type '" + type + "' in\n" + method.toGenericString()); - } - } - - // Do some validation of this parameter - parameter.validate(method, i + 1); - - // Keep track of optional parameters - if (parameter.isOptional() && parameter.getFlag() == null) { - numOptional++; - } else { - if (numOptional > 0 && parameter.isNonFlagConsumer()) { - if (parameter.getConsumedCount() < 0) { - throw new ParametricException( - "Found an parameter using the binding " + - parameter.getBinding().getClass().getCanonicalName() + - "\nthat does not know how many arguments it consumes, but " + - "it follows an optional parameter\nMethod: " + - method.toGenericString()); - } - } - } - - parameters[i] = parameter; - - // Make a list of "real" parameters - if (parameter.isUserInput()) { - userParameters.add(parameter); - } - } - - // Gather legacy flags - anyFlags = definition.anyFlags(); - legacyFlags.addAll(Chars.asList(definition.flags().toCharArray())); - - // Finish description - description.setDescription(!definition.desc().isEmpty() ? definition.desc() : null); - description.setHelp(!definition.help().isEmpty() ? definition.help() : null); - description.overrideUsage(!definition.usage().isEmpty() ? definition.usage() : null); - - for (InvokeListener listener : builder.getInvokeListeners()) { - listener.updateDescription(object, method, parameters, description); - } - - // Set parameters - description.setParameters(userParameters); - - // Get permissions annotation - commandPermissions = method.getAnnotation(CommandPermissions.class); - } - - @Override - public Object call(String stringArguments, CommandLocals locals, String[] parentCommands) throws CommandException { - // Test permission - if (parentCommands.length != 0 && !testPermission(locals)) { - throw new CommandPermissionsException(); - } - - String calledCommand = parentCommands.length > 0 ? parentCommands[parentCommands.length - 1] : "_"; - String[] split = CommandContext.split(calledCommand + " " + stringArguments); - CommandContext context = new CommandContext(split, getValueFlags(), false, locals); - - // Provide help if -? is specified - if (context.hasFlag('?')) { - throw new InvalidUsageException(null, this, true); - } - - Object[] args = new Object[parameters.length]; - ContextArgumentStack arguments = new ContextArgumentStack(context); - ParameterData parameter = null; - - try { - // preProcess handlers - List handlers = new ArrayList<>(); - for (InvokeListener listener : builder.getInvokeListeners()) { - InvokeHandler handler = listener.createInvokeHandler(); - handlers.add(handler); - handler.preProcess(object, method, parameters, context); - } - - // Collect parameters - for (int i = 0; i < parameters.length; i++) { - parameter = parameters[i]; - - if (mayConsumeArguments(i, arguments)) { - // Parse the user input into a method argument - ArgumentStack usedArguments = getScopedContext(parameter, arguments); - - try { - args[i] = parameter.getBinding().bind(parameter, usedArguments, false); - } catch (MissingParameterException e) { - // Not optional? Then we can't execute this command - if (!parameter.isOptional()) { - throw e; - } - - args[i] = getDefaultValue(i, arguments); - } - } else { - args[i] = getDefaultValue(i, arguments); - } - } - - // Check for unused arguments - checkUnconsumed(arguments); - - // preInvoke handlers - for (InvokeHandler handler : handlers) { - handler.preInvoke(object, method, parameters, args, context); - } - - // Execute! - method.invoke(object, args); - - // postInvoke handlers - for (InvokeHandler handler : handlers) { - handler.postInvoke(handler, method, parameters, args, context); - } - } catch (MissingParameterException e) { - throw new InvalidUsageException("Too few parameters!", this); - } catch (UnconsumedParameterException e) { - throw new InvalidUsageException("Too many parameters! Unused parameters: " + e.getUnconsumed(), this); - } catch (ParameterException e) { - assert parameter != null; - String name = parameter.getName(); - - throw new InvalidUsageException("For parameter '" + name + "': " + e.getMessage(), this); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof CommandException) { - throw (CommandException) e.getCause(); - } - throw new WrappedCommandException(e); - } catch (Throwable t) { - throw new WrappedCommandException(t); - } - - return true; - } - - @Override - public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { - return builder.getDefaultCompleter().getSuggestions(arguments, locals); - } - - /** - * Get a list of value flags used by this command. - * - * @return a list of value flags - */ - public Set getValueFlags() { - return valueFlags; - } - - @Override - public SimpleDescription getDescription() { - return description; - } - - @Override - public boolean testPermission(CommandLocals locals) { - if (commandPermissions != null) { - for (String perm : commandPermissions.value()) { - if (builder.getAuthorizer().testPermission(locals, perm)) { - return true; - } - } - - return false; - } else { - return true; - } - } - - /** - * Get the right {@link ArgumentStack}. - * - * @param parameter the parameter - * @param existing the existing scoped context - * @return the context to use - */ - private static ArgumentStack getScopedContext(Parameter parameter, ArgumentStack existing) { - if (parameter.getFlag() != null) { - CommandContext context = existing.getContext(); - - if (parameter.isValueFlag()) { - return new StringArgumentStack(context, context.getFlag(parameter.getFlag()), false); - } else { - String v = context.hasFlag(parameter.getFlag()) ? "true" : "false"; - return new StringArgumentStack(context, v, true); - } - } - - return existing; - } - - /** - * Get whether a parameter is allowed to consume arguments. - * - * @param i the index of the parameter - * @param scoped the scoped context - * @return true if arguments may be consumed - */ - private boolean mayConsumeArguments(int i, ContextArgumentStack scoped) { - CommandContext context = scoped.getContext(); - ParameterData parameter = parameters[i]; - - // Flag parameters: Always consume - // Required non-flag parameters: Always consume - // Optional non-flag parameters: - // - Before required parameters: Consume if there are 'left over' args - // - At the end: Always consumes - - if (parameter.isOptional()) { - if (parameter.getFlag() != null) { - return !parameter.isValueFlag() || context.hasFlag(parameter.getFlag()); - } else { - int numberFree = context.argsLength() - scoped.position(); - for (int j = i; j < parameters.length; j++) { - if (parameters[j].isNonFlagConsumer() && !parameters[j].isOptional()) { - // We already checked if the consumed count was > -1 - // when we created this object - numberFree -= parameters[j].getConsumedCount(); - } - } - - // Skip this optional parameter - if (numberFree < 1) { - return false; - } - } - } - - return true; - } - - /** - * Get the default value for a parameter. - * - * @param i the index of the parameter - * @param scoped the scoped context - * @return a value - * @throws ParameterException on an error - * @throws CommandException on an error - */ - private Object getDefaultValue(int i, ContextArgumentStack scoped) throws ParameterException, CommandException, InvocationTargetException { - CommandContext context = scoped.getContext(); - ParameterData parameter = parameters[i]; - - String[] defaultValue = parameter.getDefaultValue(); - if (defaultValue != null) { - try { - return parameter.getBinding().bind(parameter, new StringArgumentStack(context, defaultValue, false), false); - } catch (MissingParameterException e) { - throw new ParametricException( - "The default value of the parameter using the binding " + - parameter.getBinding().getClass() + " in the method\n" + - method.toGenericString() + "\nis invalid"); - } - } - - return null; - } - - - /** - * Check to see if all arguments, including flag arguments, were consumed. - * - * @param scoped the argument scope - * @throws UnconsumedParameterException thrown if parameters were not consumed - */ - private void checkUnconsumed(ContextArgumentStack scoped) throws UnconsumedParameterException { - CommandContext context = scoped.getContext(); - String unconsumed; - String unconsumedFlags = getUnusedFlags(context); - - if ((unconsumed = scoped.getUnconsumed()) != null) { - throw new UnconsumedParameterException(unconsumed + " " + unconsumedFlags); - } - - if (unconsumedFlags != null) { - throw new UnconsumedParameterException(unconsumedFlags); - } - } - - /** - * Get any unused flag arguments. - * - * @param context the command context - */ - private String getUnusedFlags(CommandContext context) { - if (!anyFlags) { - Set unusedFlags = null; - for (char flag : context.getFlags()) { - boolean found = false; - - if (legacyFlags.contains(flag)) { - break; - } - - for (ParameterData parameter : parameters) { - Character paramFlag = parameter.getFlag(); - if (paramFlag != null && flag == paramFlag) { - found = true; - break; - } - } - - if (!found) { - if (unusedFlags == null) { - unusedFlags = new HashSet<>(); - } - unusedFlags.add(flag); - } - } - - if (unusedFlags != null) { - StringBuilder builder = new StringBuilder(); - for (Character flag : unusedFlags) { - builder.append("-").append(flag).append(" "); - } - - return builder.toString().trim(); - } - } - - return null; - } - - /** - * Generate a name for a parameter. - * - * @param type the type - * @param classifier the classifier - * @param index the index - * @return a generated name - */ - private static String generateName(Type type, Annotation classifier, int index) { - if (classifier != null) { - return classifier.annotationType().getSimpleName().toLowerCase(); - } else { - if (type instanceof Class) { - return ((Class) type).getSimpleName().toLowerCase(); - } else { - return "unknown" + index; - } - } - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricException.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricException.java deleted file mode 100644 index 346816330..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricException.java +++ /dev/null @@ -1,44 +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.util.command.parametric; - -/** - * Thrown if the {@link ParametricBuilder} can't build commands from - * an object for whatever reason. - */ -public class ParametricException extends RuntimeException { - - public ParametricException() { - super(); - } - - public ParametricException(String message, Throwable cause) { - super(message, cause); - } - - public ParametricException(String message) { - super(message); - } - - public ParametricException(Throwable cause) { - super(cause); - } - -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/StringArgumentStack.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/StringArgumentStack.java deleted file mode 100644 index 9d4142adc..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/StringArgumentStack.java +++ /dev/null @@ -1,128 +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.util.command.parametric; - -import com.sk89q.minecraft.util.commands.CommandContext; -import com.sk89q.util.StringUtil; -import com.sk89q.worldedit.util.command.MissingParameterException; - -/** - * A virtual scope that does not actually read from the underlying - * {@link CommandContext}. - */ -public class StringArgumentStack implements ArgumentStack { - - private final boolean nonNullBoolean; - private final CommandContext context; - private final String[] arguments; - private int index = 0; - - /** - * Create a new instance using the given context. - * - * @param context the context - * @param arguments a list of arguments - * @param nonNullBoolean true to have {@link #nextBoolean()} return false instead of null - */ - public StringArgumentStack( - CommandContext context, String[] arguments, boolean nonNullBoolean) { - this.context = context; - this.arguments = arguments; - this.nonNullBoolean = nonNullBoolean; - } - - /** - * Create a new instance using the given context. - * - * @param context the context - * @param arguments an argument string to be parsed - * @param nonNullBoolean true to have {@link #nextBoolean()} return false instead of null - */ - public StringArgumentStack( - CommandContext context, String arguments, boolean nonNullBoolean) { - this.context = context; - this.arguments = CommandContext.split(arguments); - this.nonNullBoolean = nonNullBoolean; - } - - @Override - public String next() throws ParameterException { - try { - return arguments[index++]; - } catch (ArrayIndexOutOfBoundsException e) { - throw new MissingParameterException(); - } - } - - @Override - public Integer nextInt() throws ParameterException { - try { - return Integer.parseInt(next()); - } catch (NumberFormatException e) { - throw new ParameterException( - "Expected a number, got '" + context.getString(index - 1) + "'"); - } - } - - @Override - public Double nextDouble() throws ParameterException { - try { - return Double.parseDouble(next()); - } catch (NumberFormatException e) { - throw new ParameterException( - "Expected a number, got '" + context.getString(index - 1) + "'"); - } - } - - @Override - public Boolean nextBoolean() throws ParameterException { - try { - return next().equalsIgnoreCase("true"); - } catch (IndexOutOfBoundsException e) { - if (nonNullBoolean) { // Special case - return false; - } - - throw new MissingParameterException(); - } - } - - @Override - public String remaining() throws ParameterException { - try { - String value = StringUtil.joinString(arguments, " ", index); - markConsumed(); - return value; - } catch (IndexOutOfBoundsException e) { - throw new MissingParameterException(); - } - } - - @Override - public void markConsumed() { - index = arguments.length; - } - - @Override - public CommandContext getContext() { - return context; - } - -} 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 07cb23fba..dcaeca0b3 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 @@ -30,8 +30,6 @@ 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.sponge.config.SpongeConfiguration; -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; @@ -44,6 +42,7 @@ import org.spongepowered.api.entity.EntityType; import org.spongepowered.api.scheduler.Task; import org.spongepowered.api.world.Location; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.EnumMap; @@ -51,8 +50,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; -import javax.annotation.Nullable; - import static java.util.stream.Collectors.toList; class SpongePlatform extends AbstractPlatform implements MultiUserPlatform { From fb4fb980e07503939238a049bc6cce798dcb5835 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Tue, 30 Apr 2019 15:03:18 -0700 Subject: [PATCH 57/57] Condense some command packages --- .../com/sk89q/worldedit/command/ApplyBrushCommands.java | 2 +- .../com/sk89q/worldedit/command/PaintBrushCommands.java | 2 +- .../sk89q/worldedit/command/util/AsyncCommandHelper.java | 2 +- .../worldedit/command/util/MessageFutureCallback.java | 2 +- .../sk89q/worldedit/command/util/PrintCommandHelp.java | 4 ++-- .../extension/platform/PlatformCommandManager.java | 8 ++++---- .../{util => internal}/command/CommandArgParser.java | 2 +- .../command/CommandRegistrationHandler.java | 2 +- .../worldedit/{util => internal}/command/CommandUtil.java | 2 +- .../command/exception}/ExceptionConverter.java | 2 +- .../command/exception}/ExceptionConverterHelper.java | 3 +-- .../command/exception}/ExceptionMatch.java | 2 +- .../{ => exception}/WorldEditExceptionConverter.java | 4 +--- .../util/formatting/component/CommandUsageBox.java | 4 ++-- .../sk89q/worldedit/util/paste/ActorCallbackPaste.java | 2 +- 15 files changed, 20 insertions(+), 23 deletions(-) rename worldedit-core/src/main/java/com/sk89q/worldedit/{util => internal}/command/CommandArgParser.java (98%) rename worldedit-core/src/main/java/com/sk89q/worldedit/{util => internal}/command/CommandRegistrationHandler.java (97%) rename worldedit-core/src/main/java/com/sk89q/worldedit/{util => internal}/command/CommandUtil.java (97%) rename worldedit-core/src/main/java/com/sk89q/worldedit/{util/command/parametric => internal/command/exception}/ExceptionConverter.java (97%) rename worldedit-core/src/main/java/com/sk89q/worldedit/{util/command/parametric => internal/command/exception}/ExceptionConverterHelper.java (97%) rename worldedit-core/src/main/java/com/sk89q/worldedit/{util/command/parametric => internal/command/exception}/ExceptionMatch.java (95%) rename worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/{ => exception}/WorldEditExceptionConverter.java (97%) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java index cfab5fbae..f9ceadd3e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ApplyBrushCommands.java @@ -35,7 +35,7 @@ import com.sk89q.worldedit.function.factory.Apply; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.command.CommandRegistrationHandler; +import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.CommandManager; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java index 4f4064827..cc53ec5b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PaintBrushCommands.java @@ -35,7 +35,7 @@ import com.sk89q.worldedit.function.factory.Paint; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.factory.RegionFactory; import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.util.command.CommandRegistrationHandler; +import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; import org.enginehub.piston.CommandManager; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java index 7557b0834..842cd5752 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/AsyncCommandHelper.java @@ -24,7 +24,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; +import com.sk89q.worldedit.internal.command.exception.ExceptionConverter; import com.sk89q.worldedit.util.task.FutureForwardingTask; import com.sk89q.worldedit.util.task.Supervisor; import com.sk89q.worldedit.world.World; 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 58b25770d..2a330259e 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 @@ -23,7 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.util.concurrent.FutureCallback; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; +import com.sk89q.worldedit.internal.command.exception.ExceptionConverter; import org.enginehub.piston.exception.CommandException; import javax.annotation.Nullable; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java index df57539ba..aa911b705 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/PrintCommandHelp.java @@ -36,8 +36,8 @@ import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; -import static com.sk89q.worldedit.util.command.CommandUtil.byCleanName; -import static com.sk89q.worldedit.util.command.CommandUtil.getSubCommands; +import static com.sk89q.worldedit.internal.command.CommandUtil.byCleanName; +import static com.sk89q.worldedit.internal.command.CommandUtil.getSubCommands; import static java.util.stream.Collectors.toList; /** 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 f1f7380a4..65df87e16 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 @@ -86,12 +86,12 @@ import com.sk89q.worldedit.event.platform.CommandSuggestionEvent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.command.CommandLoggingHandler; -import com.sk89q.worldedit.internal.command.WorldEditExceptionConverter; +import com.sk89q.worldedit.internal.command.exception.WorldEditExceptionConverter; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.session.request.Request; -import com.sk89q.worldedit.util.command.CommandArgParser; -import com.sk89q.worldedit.util.command.CommandRegistrationHandler; -import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; +import com.sk89q.worldedit.internal.command.CommandArgParser; +import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; +import com.sk89q.worldedit.internal.command.exception.ExceptionConverter; import com.sk89q.worldedit.util.eventbus.Subscribe; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandArgParser.java similarity index 98% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandArgParser.java index 5c414d08a..e3605b6f8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandArgParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandArgParser.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util.command; +package com.sk89q.worldedit.internal.command; import java.util.stream.Stream; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandRegistrationHandler.java similarity index 97% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandRegistrationHandler.java index 8e243be98..dec0d6e24 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandRegistrationHandler.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandRegistrationHandler.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util.command; +package com.sk89q.worldedit.internal.command; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.WorldEdit; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java similarity index 97% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java index 3d86fbfb9..861c7926d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/CommandUtil.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/CommandUtil.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util.command; +package com.sk89q.worldedit.internal.command; import com.sk89q.worldedit.extension.platform.PlatformCommandManager; import org.enginehub.piston.Command; 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/internal/command/exception/ExceptionConverter.java similarity index 97% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverter.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverter.java index e943cd6e9..27a494175 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util.command.parametric; +package com.sk89q.worldedit.internal.command.exception; import org.enginehub.piston.exception.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/internal/command/exception/ExceptionConverterHelper.java similarity index 97% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverterHelper.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverterHelper.java index 039bd4cde..99a9bce68 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionConverterHelper.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionConverterHelper.java @@ -17,10 +17,9 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util.command.parametric; +package com.sk89q.worldedit.internal.command.exception; import com.google.common.collect.ImmutableList; -import com.sk89q.minecraft.util.commands.WrappedCommandException; import org.enginehub.piston.exception.CommandException; import org.enginehub.piston.exception.CommandExecutionException; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionMatch.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionMatch.java similarity index 95% rename from worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionMatch.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionMatch.java index 619bc9d46..99acf81fa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/command/parametric/ExceptionMatch.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/ExceptionMatch.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.util.command.parametric; +package com.sk89q.worldedit.internal.command.exception; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; 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/exception/WorldEditExceptionConverter.java similarity index 97% rename from worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditExceptionConverter.java rename to worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/exception/WorldEditExceptionConverter.java index 3dfafe349..a0100fc4c 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/exception/WorldEditExceptionConverter.java @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.internal.command; +package com.sk89q.worldedit.internal.command.exception; import com.google.common.collect.ImmutableList; import com.sk89q.worldedit.DisallowedItemException; @@ -35,8 +35,6 @@ import com.sk89q.worldedit.command.InsufficientArgumentsException; import com.sk89q.worldedit.command.tool.InvalidToolBindException; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.regions.RegionOperationException; -import com.sk89q.worldedit.util.command.parametric.ExceptionConverterHelper; -import com.sk89q.worldedit.util.command.parametric.ExceptionMatch; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException; import com.sk89q.worldedit.util.io.file.FilenameResolutionException; 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 d2a97fcf2..46347d107 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 @@ -30,8 +30,8 @@ import java.util.Map; import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.worldedit.util.command.CommandUtil.byCleanName; -import static com.sk89q.worldedit.util.command.CommandUtil.getSubCommands; +import static com.sk89q.worldedit.internal.command.CommandUtil.byCleanName; +import static com.sk89q.worldedit.internal.command.CommandUtil.getSubCommands; /** * A box to describe usage of a command. diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java index 4c86e6866..0509275f6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/paste/ActorCallbackPaste.java @@ -24,7 +24,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.sk89q.worldedit.command.util.AsyncCommandHelper; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.command.parametric.ExceptionConverter; +import com.sk89q.worldedit.internal.command.exception.ExceptionConverter; import com.sk89q.worldedit.util.task.Supervisor; import org.slf4j.Logger; import org.slf4j.LoggerFactory;