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'