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 65c466ff3..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 @@ -19,8 +19,8 @@ package com.sk89q.bukkit.util; -import org.enginehub.piston.annotation.Command; -import com.sk89q.worldedit.command.util.CommandPermissions; +import com.sk89q.minecraft.util.commands.Command; +import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandsManager; import org.bukkit.command.CommandExecutor; import org.bukkit.plugin.Plugin; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java index d9fe50c22..5f6378ca3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java @@ -216,6 +216,7 @@ public class Fawe { } public TextureUtil getCachedTextureUtil(boolean randomize, int min, int max) { + // TODO NOT IMPLEMENTED - optimize this by caching the default true/0/100 texture util TextureUtil tu = getTextureUtil(); try { tu = min == 0 && max == 100 ? tu : new CleanTextureUtil(tu, min, max); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java index 0311666d8..ee7bc6cca 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java @@ -10,6 +10,7 @@ import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.WorldWrapper; +import com.google.common.util.concurrent.Futures; import com.sk89q.worldedit.world.World; import java.lang.ref.WeakReference; @@ -24,6 +25,7 @@ import java.util.concurrent.ForkJoinTask; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.ThreadPoolExecutor; +import java.util.function.Supplier; /** * Class which handles all the queues {@link IQueueExtent} @@ -136,6 +138,10 @@ public abstract class QueueHandler implements Trimable, Runnable { } public Future sync(final Runnable run, final T value) { + if (Fawe.isMainThread()) { + run.run(); + return Futures.immediateFuture(value); + } final FutureTask result = new FutureTask<>(run, value); syncTasks.add(result); notifySync(); @@ -143,19 +149,36 @@ public abstract class QueueHandler implements Trimable, Runnable { } public Future sync(final Runnable run) { + if (Fawe.isMainThread()) { + run.run(); + return Futures.immediateCancelledFuture(); + } final FutureTask result = new FutureTask<>(run, null); syncTasks.add(result); notifySync(); return result; } - public Future sync(final Callable call) { + public Future sync(final Callable call) throws Exception { + if (Fawe.isMainThread()) { + return Futures.immediateFuture(call.call()); + } final FutureTask result = new FutureTask<>(call); syncTasks.add(result); notifySync(); return result; } + public Future sync(final Supplier call) { + if (Fawe.isMainThread()) { + return Futures.immediateFuture(call.get()); + } + final FutureTask result = new FutureTask<>(call::get); + syncTasks.add(result); + notifySync(); + return result; + } + private void notifySync() { synchronized (syncTasks) { syncTasks.notifyAll(); @@ -163,9 +186,9 @@ public abstract class QueueHandler implements Trimable, Runnable { } public > T submit(final IChunk chunk) { - if (MemUtil.isMemoryFree()) { +// if (MemUtil.isMemoryFree()) { TODO NOT IMPLEMENTED - optimize this // return (T) forkJoinPoolSecondary.submit(chunk); - } +// } return (T) blockingExecutor.submit(chunk); } @@ -193,6 +216,10 @@ public abstract class QueueHandler implements Trimable, Runnable { public abstract IQueueExtent create(); + public abstract void startSet(boolean value); + + public abstract void endSet(boolean value); + public IQueueExtent getQueue(final World world) { final IQueueExtent queue = queuePool.get(); queue.init(getOrCreate(world)); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommand.java b/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommand.java index ae93d2751..3eba33eb6 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommand.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommand.java @@ -1,102 +1,90 @@ package com.boydti.fawe.command; import com.boydti.fawe.config.Commands; -import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator; import com.boydti.fawe.object.changeset.CFIChangeSet; -import org.enginehub.piston.annotation.Command; -import org.enginehub.piston.inject.InjectedValueAccess; -import com.sk89q.minecraft.util.commands.CommandException; -import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.MethodCommands; -import com.sk89q.worldedit.util.command.SimpleDispatcher; -import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import org.enginehub.piston.CommandManager; +import org.enginehub.piston.exception.StopExecutionException; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.Key; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; -public class CFICommand extends MethodCommands { +public class CFICommand extends CommandProcessor { - private final CFICommands child; - private final SimpleDispatcher dispatcher; - - public CFICommand(WorldEdit worldEdit, ParametricBuilder builder) { - super(worldEdit); - this.dispatcher = new SimpleDispatcher(); - this.child = new CFICommands(worldEdit, dispatcher); - builder.registerMethodsAsCommands(dispatcher, child); + public CFICommand(CommandManager manager) { + super(manager); } - @Command( - name = "cfi", - aliases = {"cfi", "createfromimage"}, - desc = "Start CreateFromImage" - ) - @CommandPermissions("worldedit.anvil.cfi") - public void cfi(FawePlayer fp, InjectedValueAccess context) throws CommandException, IOException { - CFICommands.CFISettings settings = child.getSettings(fp); + @Override + public List preprocess(InjectedValueAccess context, List args) { + FawePlayer fp = context.injectedValue(Key.of(FawePlayer.class)).orElseThrow(() -> new IllegalStateException("No player")); + CFICommands.CFISettings settings = CFICommands.getSettings(fp); settings.popMessages(fp); - dispatch(fp, settings, context); + args = dispatch(fp, settings, args, context); HeightMapMCAGenerator gen = settings.getGenerator(); if (gen != null && gen.isModified()) { - gen.update(); - CFIChangeSet set = new CFIChangeSet(gen, fp.getUUID()); - LocalSession session = fp.getSession(); - session.remember(fp.getPlayer(), gen, set, fp.getLimit()); + try { + gen.update(); + CFIChangeSet set = new CFIChangeSet(gen, fp.getUUID()); + LocalSession session = fp.getSession(); + session.remember(fp.getPlayer(), gen, set, fp.getLimit()); + } catch (IOException e) { + throw new StopExecutionException(TextComponent.of(e.getMessage())); + } } + return args; } - private void dispatch(FawePlayer fp, CFICommands.CFISettings settings, InjectedValueAccess context) throws CommandException { + @Override + public Object process(InjectedValueAccess context, List args, Object result) { + return result; + } + + private List dispatch(FawePlayer fp, CFICommands.CFISettings settings, List args, InjectedValueAccess context) { if (!settings.hasGenerator()) { - if (context.argsLength() == 0) { - String hmCmd = child.alias() + " "; + if (args.size() == 0) { + String hmCmd = CFICommands.alias() + " "; if (settings.image == null) { hmCmd += "image"; } else { hmCmd = Commands.getAlias(CFICommands.class, "heightmap") + " " + settings.imageArg; } - child.msg("What do you want to use as the base?").newline() + CFICommands.msg("What do you want to use as the base?").newline() .text("[HeightMap]").cmdTip(hmCmd).text(" - A heightmap like ") .text("[this]").linkTip("http://i.imgur.com/qCd30MR.jpg") .newline() - .text("[Empty]").cmdTip(child.alias() + " empty") + .text("[Empty]").cmdTip(CFICommands.alias() + " empty") .text("- An empty map of a specific size") .send(fp); } else { - String remaining = context.getJoinedStrings(0); - if (!dispatcher.contains(context.getString(0))) { - switch (context.argsLength()) { - case 1: { - String cmd = - Commands.getAlias(CFICommands.class, "heightmap") + " " + context - .getJoinedStrings(0); - dispatcher.call(cmd, context.getLocals(), new String[0]); - return; - } - case 2: { - String cmd = - Commands.getAlias(CFICommands.class, "empty") + " " + context - .getJoinedStrings(0); - dispatcher.call(cmd, context.getLocals(), new String[0]); - return; - } - case 2: - String cmd = Commands.getAlias(CFICommands.class, "empty") + " " + context.getJoinedStrings(0); - dispatcher.call(cmd, context.getLocals(), new String[0]); - return; + args = new ArrayList<>(args); + switch (args.size()) { + case 1: { + args.add(0, "heightmap"); + break; + } + case 2: { + args.add(0, "empty"); + break; } } - dispatcher.call(remaining, context.getLocals(), new String[0]); + return args; } } else { - if (context.argsLength() == 0) { - settings.setCategory(""); - child.mainMenu(fp); - } else { - dispatcher.call(context.getJoinedStrings(0), context.getLocals(), new String[0]); + if (args.isEmpty()) { + settings.setCategory(null); + CFICommands.mainMenu(fp); + return null; } } + return args; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java b/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java index 985d73ace..bd5e3a657 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/CFICommands.java @@ -2,6 +2,7 @@ package com.boydti.fawe.command; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweAPI; +import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.SingleFilterBlock; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Commands; @@ -19,8 +20,14 @@ import com.boydti.fawe.util.TextureUtil; import com.boydti.fawe.util.chat.Message; import com.boydti.fawe.util.image.ImageUtil; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; + +import java.nio.file.Path; +import java.util.function.Consumer; import java.util.stream.IntStream; + +import com.sk89q.worldedit.util.formatting.text.TextComponent; import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.exception.StopExecutionException; import org.enginehub.piston.inject.InjectedValueAccess; import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.worldedit.command.util.CommandPermissions; @@ -75,23 +82,34 @@ import static com.boydti.fawe.util.image.ImageUtil.load; @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class CFICommands extends MethodCommands { - private final Dispatcher dispathcer; + private final WorldEdit worldEdit; /** * Create a new instance. * * @param worldEdit reference to WorldEdit */ - public CFICommands(WorldEdit worldEdit, Dispatcher dispatcher) { - super(worldEdit); - this.dispathcer = dispatcher; + public CFICommands(WorldEdit worldEdit) { + this.worldEdit = worldEdit; } public static File getFolder(String worldName) { Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING); List worlds = platform.getWorlds(); - IQueueExtent queue = SetQueue.IMP.getNewQueue(worlds.get(0), true, false); - return new File(queue.getSaveFolder().getParentFile().getParentFile(), worldName + File.separator + "region"); + Path path = worlds.get(0).getStoragePath(); + return new File(path.toFile().getParentFile().getParentFile(), worldName + File.separator + "region"); + } + + @Command( + name = "", + desc = "CFI command" + ) + @CommandPermissions("worldedit.anvil.cfi") + public void cfi(FawePlayer fp, List args) { + CFISettings settings = getSettings(fp); + if (!settings.hasGenerator()) { + + } } @Command( @@ -99,7 +117,7 @@ public class CFICommands extends MethodCommands { desc = "Start CFI with a height map as a base" ) @CommandPermissions("worldedit.anvil.cfi") - public void heightmap(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Arg(name = "yscale", desc = "double", def = "1") double yscale) throws ParameterException { + public void heightmap(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Arg(name = "yscale", desc = "double", def = "1") double yscale) { if (yscale != 0) { int[] raw = ((DataBufferInt) image.load().getRaster().getDataBuffer()).getData(); int[] table = IntStream.range(0, 256).map(i -> Math.min(255, (int) (i * yscale))) @@ -145,7 +163,7 @@ public class CFICommands extends MethodCommands { desc = "Info about using brushes with CFI" ) @CommandPermissions("worldedit.anvil.cfi") - public void brush(FawePlayer fp) throws ParameterException { + public void brush(FawePlayer fp) { CFISettings settings = assertSettings(fp); settings.popMessages(fp); Message msg; @@ -232,7 +250,7 @@ public class CFICommands extends MethodCommands { desc = "Set the floor and main block" ) @CommandPermissions("worldedit.anvil.cfi") - public void column(FawePlayer fp, Pattern pattern, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void column(FawePlayer fp, Pattern pattern, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (image != null) { gen.setColumn(load(image), pattern, !disableWhiteOnly); @@ -251,14 +269,14 @@ public class CFICommands extends MethodCommands { desc = "Set the floor (default: grass)" ) @CommandPermissions("worldedit.anvil.cfi") - public void floorCmd(FawePlayer fp, Pattern pattern, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void floorCmd(FawePlayer fp, Pattern pattern, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ floor(fp, pattern, image, mask, disableWhiteOnly); fp.sendMessage("Set floor!"); assertSettings(fp).resetComponent(); component(fp); } - private void floor(FawePlayer fp, Pattern pattern, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException { + private void floor(FawePlayer fp, Pattern pattern, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) { HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (image != null) { gen.setFloor(load(image), pattern, !disableWhiteOnly); @@ -274,14 +292,14 @@ public class CFICommands extends MethodCommands { desc = "Set the main block (default: stone)" ) @CommandPermissions("worldedit.anvil.cfi") - public void mainCmd(FawePlayer fp, Pattern pattern, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void mainCmd(FawePlayer fp, Pattern pattern, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ main(fp, pattern, image, mask, disableWhiteOnly); fp.sendMessage("Set main!"); assertSettings(fp).resetComponent(); component(fp); } - public void main(FawePlayer fp, Pattern pattern, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void main(FawePlayer fp, Pattern pattern, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (image != null) { gen.setMain(load(image), pattern, !disableWhiteOnly); @@ -300,7 +318,7 @@ public class CFICommands extends MethodCommands { "e.g. Tallgrass" ) @CommandPermissions("worldedit.anvil.cfi") - public void overlay(FawePlayer fp, Pattern pattern, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void overlay(FawePlayer fp, Pattern pattern, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (image != null) { gen.setOverlay(load(image), pattern, !disableWhiteOnly); @@ -322,13 +340,13 @@ public class CFICommands extends MethodCommands { " - A good value for radius and iterations would be 1 8." ) @CommandPermissions("worldedit.anvil.cfi") - public void smoothCmd(FawePlayer fp, int radius, int iterations, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void smoothCmd(FawePlayer fp, int radius, int iterations, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ smooth(fp, radius, iterations, image, mask, disableWhiteOnly); assertSettings(fp).resetComponent(); component(fp); } - private void smooth(FawePlayer fp, int radius, int iterations, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + private void smooth(FawePlayer fp, int radius, int iterations, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (image != null) { gen.smooth(load(image), !disableWhiteOnly, radius, iterations); @@ -342,7 +360,7 @@ public class CFICommands extends MethodCommands { desc = "Create some snow" ) @CommandPermissions("worldedit.anvil.cfi") - public void snow(FawePlayer fp, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void snow(FawePlayer fp, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); floor(fp, BlockTypes.SNOW.getDefaultState().with(PropertyKey.LAYERS, 7), image, mask, disableWhiteOnly); main(fp, BlockTypes.SNOW_BLOCK, image, mask, disableWhiteOnly); @@ -361,7 +379,7 @@ public class CFICommands extends MethodCommands { "Below 50 will prefer to color with blocks" ) @CommandPermissions("worldedit.anvil.cfi") - public void biomepriority(FawePlayer fp, int value) throws ParameterException { + public void biomepriority(FawePlayer fp, int value) { assertSettings(fp).getGenerator().setBiomePriority(value); coloring(fp); } @@ -374,7 +392,7 @@ public class CFICommands extends MethodCommands { "`#clipboard` will only use the blocks present in your clipboard." ) @CommandPermissions("worldedit.anvil.cfi") - public void paletteblocks(FawePlayer fp, Player player, LocalSession session, @Arg(name = "arg", desc = "String", def = "") String arg) throws ParameterException, EmptyClipboardException, InputParseException, FileNotFoundException { + public void paletteblocks(FawePlayer fp, Player player, LocalSession session, @Arg(name = "arg", desc = "String", def = "") String arg) throws EmptyClipboardException, InputParseException, FileNotFoundException { if (arg == null) { msg("What blocks do you want to color with?").newline() .text("[All]").cmdTip(alias() + " PaletteBlocks *").text(" - All available blocks") @@ -452,7 +470,7 @@ public class CFICommands extends MethodCommands { "Randomization will allow mixing biomes when coloring with biomes" ) @CommandPermissions("worldedit.anvil.cfi") - public void randomization(FawePlayer fp, boolean enabled) throws ParameterException { + public void randomization(FawePlayer fp, boolean enabled) { assertSettings(fp).getGenerator().setTextureRandomVariation(enabled); coloring(fp); } @@ -466,7 +484,7 @@ public class CFICommands extends MethodCommands { "Using 0 73 for the min/max would use the simplest 73% of blocks for coloring, and is a reasonable value." ) @CommandPermissions("worldedit.anvil.cfi") - public void complexity(FawePlayer fp, int min, int max) throws ParameterException, FileNotFoundException { + public void complexity(FawePlayer fp, int min, int max) throws FileNotFoundException { HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (min == 0 && max == 100) { gen.setTextureUtil(Fawe.get().getTextureUtil()); @@ -485,7 +503,7 @@ public class CFICommands extends MethodCommands { " - The distance is the spacing between each schematic" ) @CommandPermissions("worldedit.anvil.cfi") - public void schem(FawePlayer fp, @Optional FawePrimitiveBinding.ImageUri imageMask, Mask mask, String schematic, int rarity, int distance, boolean rotate) throws ParameterException, IOException, WorldEditException { + public void schem(FawePlayer fp, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri imageMask, Mask mask, String schematic, int rarity, int distance, boolean rotate)throws IOException, WorldEditException { HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); World world = fp.getWorld(); @@ -511,7 +529,7 @@ public class CFICommands extends MethodCommands { " - If a mask is used, the biome will be set anywhere the mask applies" ) @CommandPermissions("worldedit.anvil.cfi") - public void biome(FawePlayer fp, BiomeType biome, @Optional FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException{ + public void biome(FawePlayer fp, BiomeType biome, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly){ HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (image != null) { gen.setBiome(load(image), biome, !disableWhiteOnly); @@ -530,7 +548,7 @@ public class CFICommands extends MethodCommands { desc = "Generate vanilla caves" ) @CommandPermissions("worldedit.anvil.cfi") - public void caves(FawePlayer fp) throws ParameterException, WorldEditException { + public void caves(FawePlayer fp) throws WorldEditException { assertSettings(fp).getGenerator().addCaves(); msg("Added caves!").send(fp); populate(fp); @@ -542,7 +560,7 @@ public class CFICommands extends MethodCommands { descFooter = "Use a specific pattern and settings to generate ore" ) @CommandPermissions("worldedit.anvil.cfi") - public void ore(FawePlayer fp, Mask mask, Pattern pattern, int size, int frequency, int rariry, int minY, int maxY) throws ParameterException, WorldEditException { + public void ore(FawePlayer fp, Mask mask, Pattern pattern, int size, int frequency, int rariry, int minY, int maxY) throws WorldEditException { assertSettings(fp).getGenerator().addOre(mask, pattern, size, frequency, rariry, minY, maxY); msg("Added ore!").send(fp); populate(fp); @@ -553,7 +571,7 @@ public class CFICommands extends MethodCommands { desc = "Generate the vanilla ores" ) @CommandPermissions("worldedit.anvil.cfi") - public void ores(FawePlayer fp, Mask mask) throws ParameterException, WorldEditException { + public void ores(FawePlayer fp, Mask mask) throws WorldEditException { assertSettings(fp).getGenerator().addDefaultOres(mask); msg("Added ores!").send(fp); populate(fp); @@ -565,7 +583,7 @@ public class CFICommands extends MethodCommands { descFooter = "Set the terrain height either based on an image heightmap, or a numeric value." ) @CommandPermissions("worldedit.anvil.cfi") - public void height(FawePlayer fp, String arg) throws ParameterException, WorldEditException { + public void height(FawePlayer fp, String arg) throws WorldEditException { HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); if (!MathMan.isInteger(arg)) { gen.setHeight(ImageUtil.getImage(arg)); @@ -581,7 +599,7 @@ public class CFICommands extends MethodCommands { desc = "Change the block used for water\ne.g. Lava" ) @CommandPermissions("worldedit.anvil.cfi") - public void waterId(FawePlayer fp, BlockStateHolder block) throws ParameterException, WorldEditException { + public void waterId(FawePlayer fp, BlockStateHolder block) throws WorldEditException { CFISettings settings = assertSettings(fp); settings.getGenerator().setWaterId(block.getBlockType().getInternalId()); msg("Set water id!").send(fp); @@ -595,7 +613,7 @@ public class CFICommands extends MethodCommands { desc = "Change the block used for the base\ne.g. Bedrock" ) @CommandPermissions("worldedit.anvil.cfi") - public void baseId(FawePlayer fp, BlockStateHolder block) throws ParameterException, WorldEditException { + public void baseId(FawePlayer fp, BlockStateHolder block) throws WorldEditException { CFISettings settings = assertSettings(fp); settings.getGenerator().setBedrockId(block.getBlockType().getInternalId()); msg("Set base id!").send(fp); @@ -610,7 +628,7 @@ public class CFICommands extends MethodCommands { " - A value of 0 is the default and will not modify the height" ) @CommandPermissions("worldedit.anvil.cfi") - public void worldthickness(FawePlayer fp, int height) throws ParameterException, WorldEditException { + public void worldthickness(FawePlayer fp, int height) throws WorldEditException { assertSettings(fp).getGenerator().setWorldThickness(height); msg("Set world thickness!").send(fp); component(fp); @@ -623,7 +641,7 @@ public class CFICommands extends MethodCommands { " - A value of 0 is the default and will only set the top block" ) @CommandPermissions("worldedit.anvil.cfi") - public void floorthickness(FawePlayer fp, int height) throws ParameterException, WorldEditException { + public void floorthickness(FawePlayer fp, int height) throws WorldEditException { assertSettings(fp).getGenerator().setFloorThickness(height); msg("Set floor thickness!").send(fp); component(fp); @@ -635,7 +653,7 @@ public class CFICommands extends MethodCommands { desc = "Resend the CFI chunks" ) @CommandPermissions("worldedit.anvil.cfi") - public void update(FawePlayer fp) throws ParameterException, WorldEditException { + public void update(FawePlayer fp) throws WorldEditException { assertSettings(fp).getGenerator().update(); msg("Chunks refreshed!").send(fp); mainMenu(fp); @@ -647,7 +665,7 @@ public class CFICommands extends MethodCommands { desc = "Teleport to the CFI virtual world" ) @CommandPermissions("worldedit.anvil.cfi") - public void tp(FawePlayer fp) throws ParameterException, WorldEditException { + public void tp(FawePlayer fp) throws WorldEditException { HeightMapMCAGenerator gen = assertSettings(fp).getGenerator(); msg("Teleporting...").send(fp); Vector3 origin = gen.getOrigin(); @@ -665,7 +683,7 @@ public class CFICommands extends MethodCommands { " - By default water is disabled (with a value of 0)" ) @CommandPermissions("worldedit.anvil.cfi") - public void waterheight(FawePlayer fp, int height) throws ParameterException, WorldEditException { + public void waterheight(FawePlayer fp, int height) throws WorldEditException { assertSettings(fp).getGenerator().setWaterHeight(height); msg("Set water height!").send(fp); component(fp); @@ -678,7 +696,7 @@ public class CFICommands extends MethodCommands { ) // ![79,174,212,5:3,5:4,18,161,20] @CommandPermissions("worldedit.anvil.cfi") - public void glass(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Optional FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException, WorldEditException { + public void glass(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws WorldEditException { CFISettings settings = assertSettings(fp); settings.getGenerator().setColorWithGlass(load(image)); msg("Set color with glass!").send(fp); @@ -695,7 +713,7 @@ public class CFICommands extends MethodCommands { "The -w (disableWhiteOnly) will randomly apply depending on the pixel luminance" ) @CommandPermissions("worldedit.anvil.cfi") - public void color(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Optional FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException, WorldEditException { + public void color(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws WorldEditException { CFISettings settings = assertSettings(fp); HeightMapMCAGenerator gen = settings.getGenerator(); if (imageMask != null) { @@ -719,7 +737,7 @@ public class CFICommands extends MethodCommands { "The -w (disableWhiteOnly) will randomly apply depending on the pixel luminance" ) @CommandPermissions("worldedit.anvil.cfi") - public void blockbiome(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Optional FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException, WorldEditException { + public void blockbiome(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws WorldEditException { CFISettings settings = assertSettings(fp); settings.getGenerator().setBlockAndBiomeColor(load(image), mask, load(imageMask), !disableWhiteOnly); msg("Set color with blocks and biomes!").send(fp); @@ -735,7 +753,7 @@ public class CFICommands extends MethodCommands { " - If you changed the block to something other than grass you will not see anything." ) @CommandPermissions("worldedit.anvil.cfi") - public void biomecolor(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Optional FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws ParameterException, WorldEditException { + public void biomecolor(FawePlayer fp, FawePrimitiveBinding.ImageUri image, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly) throws WorldEditException { CFISettings settings = assertSettings(fp); settings.getGenerator().setBiomeColor(load(image)); msg("Set color with biomes!").send(fp); @@ -750,10 +768,10 @@ public class CFICommands extends MethodCommands { desc = "Color the world using an image" ) @CommandPermissions("worldedit.anvil.cfi") - public void coloring(FawePlayer fp) throws ParameterException { + public void coloring(FawePlayer fp) { CFISettings settings = assertSettings(fp); settings.popMessages(fp); - settings.setCategory("coloring"); + settings.setCategory(this::coloring); HeightMapMCAGenerator gen = settings.getGenerator(); boolean rand = gen.getTextureRandomVariation(); String mask; @@ -834,7 +852,7 @@ public class CFICommands extends MethodCommands { desc = "Select a mask" ) @CommandPermissions("worldedit.anvil.cfi") - public void mask(FawePlayer fp, @Optional FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly, InjectedValueAccess context) throws ParameterException{ + public void mask(FawePlayer fp, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri imageMask, @Arg(name = "mask", desc = "Mask", def = "") Mask mask, @Switch(name='w', desc = "TODO") boolean disableWhiteOnly, InjectedValueAccess context){ CFISettings settings = assertSettings(fp); String[] split = getArguments(context).split(" "); int index = 2; @@ -859,7 +877,7 @@ public class CFICommands extends MethodCommands { desc = "Select a pattern" ) @CommandPermissions("worldedit.anvil.cfi") - public void pattern(FawePlayer fp, @Arg(name = "pattern", desc = "Pattern", def = "") Pattern pattern, InjectedValueAccess context) throws ParameterException, CommandException { + public void pattern(FawePlayer fp, @Arg(name = "pattern", desc = "Pattern", def = "") Pattern pattern, InjectedValueAccess context)throws CommandException { CFISettings settings = assertSettings(fp); String[] split = getArguments(context).split(" "); int index = 2; @@ -869,7 +887,7 @@ public class CFICommands extends MethodCommands { StringBuilder cmd = new StringBuilder(alias() + " pattern "); if (pattern != null) { - dispathcer.call(settings.getCategory(), context.getLocals(), new String[0]); + settings.getCategory().accept(fp); } else { msg(">> Current Settings <<").newline() .text("Pattern ").text("[Click Here]").suggestTip(cmd + " stone") @@ -883,7 +901,7 @@ public class CFICommands extends MethodCommands { desc = "Download the current image" ) @CommandPermissions("worldedit.anvil.cfi") - public void download(FawePlayer fp) throws ParameterException, IOException { + public void download(FawePlayer fp)throws IOException { CFISettings settings = assertSettings(fp); BufferedImage image = settings.getGenerator().draw(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -899,14 +917,13 @@ public class CFICommands extends MethodCommands { desc = "Select an image" ) @CommandPermissions("worldedit.anvil.cfi") - public void image(FawePlayer fp, @Optional FawePrimitiveBinding.ImageUri image, InjectedValueAccess context) throws ParameterException, CommandException { + public void image(FawePlayer fp, @Arg(def = "", desc = "image url or filename") FawePrimitiveBinding.ImageUri image, InjectedValueAccess context)throws CommandException { CFISettings settings = getSettings(fp); String[] split = getArguments(context).split(" "); int index = 2; settings.image = image; settings.imageArg = image != null ? split[index++] : null; - String maskArg = settings.maskArg == null ? "Click Here" : settings.maskArg; StringBuilder cmd = new StringBuilder(alias() + " image "); if (image == null) { @@ -920,8 +937,7 @@ public class CFICommands extends MethodCommands { coloring(fp); return; } else { - String next = Commands.getAlias(CFICommands.class, "heightmap " + settings.imageArg); - dispathcer.call(next, context.getLocals(), new String[0]); + heightmap(fp, image, 1); return; } } @@ -932,10 +948,10 @@ public class CFICommands extends MethodCommands { desc = "" ) @CommandPermissions("worldedit.anvil.cfi") - public void populate(FawePlayer fp) throws ParameterException { + public void populate(FawePlayer fp) { CFISettings settings = assertSettings(fp); settings.popMessages(fp); - settings.setCategory("populate"); + settings.setCategory(this::populate); msg("What would you like to populate?").newline() .text("(You will need to type these commands)").newline() .cmdOptions(alias() + " ", "", "Ores", "Ore", "Caves", "Schematics", "Smooth") @@ -949,10 +965,10 @@ public class CFICommands extends MethodCommands { desc = "Components menu" ) @CommandPermissions("worldedit.anvil.cfi") - public void component(FawePlayer fp) throws ParameterException { + public void component(FawePlayer fp) { CFISettings settings = assertSettings(fp); settings.popMessages(fp); - settings.setCategory("component"); + settings.setCategory(this::component); String mask; if (settings.imageMask != null) { @@ -1027,16 +1043,16 @@ public class CFICommands extends MethodCommands { } - private CFISettings assertSettings(FawePlayer fp) throws ParameterException { + private static CFISettings assertSettings(FawePlayer fp) { CFISettings settings = getSettings(fp); if (!settings.hasGenerator()) { - throw new ParameterException("Please use /" + alias()); + throw new StopExecutionException(TextComponent.of("Please use /" + alias())); } return settings; } - protected CFISettings getSettings(FawePlayer fp) { + protected static CFISettings getSettings(FawePlayer fp) { CFISettings settings = fp.getMeta("CFISettings"); return settings == null ? new CFISettings(fp) : settings; } @@ -1057,7 +1073,7 @@ public class CFICommands extends MethodCommands { protected Pattern pattern; protected String patternArg; - protected String category; + protected Consumer category; private boolean bound; @@ -1108,11 +1124,11 @@ public class CFICommands extends MethodCommands { pattern = null; } - public String getCategory() { + public Consumer getCategory() { return category; } - public void setCategory(String category) { + public void setCategory(Consumer methodRef) { this.category = category; } @@ -1162,21 +1178,21 @@ public class CFICommands extends MethodCommands { } } - protected String alias() { + protected static String alias() { return Commands.getAlias(CFICommand.class, "/cfi"); } - protected String alias(String command) { + protected static String alias(String command) { return Commands.getAlias(CFICommands.class, command); } - protected Message msg(String text) { + protected static Message msg(String text) { return new Message().newline() .text(BBC.getPrefix()) .text(text); } - protected void mainMenu(FawePlayer fp) { + protected static void mainMenu(FawePlayer fp) { msg("What do you want to do now?").newline() .cmdOptions(alias() + " ", "", "Coloring", "Component", "Populate", "Brush") .newline().text("<> [View]").command(alias() + " " + Commands.getAlias(CFICommands.class, "download")).tooltip("View full resolution image") diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/CommandProcessor.java b/worldedit-core/src/main/java/com/boydti/fawe/command/CommandProcessor.java index d5d3c2563..5db5d712b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/CommandProcessor.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/command/CommandProcessor.java @@ -14,7 +14,7 @@ import java.util.Optional; import java.util.function.Consumer; import java.util.stream.Stream; -public class CommandProcessor implements CommandManager { +public abstract class CommandProcessor implements CommandManager { private final CommandManager parent; public CommandProcessor(CommandManager parent) { @@ -22,62 +22,72 @@ public class CommandProcessor implements CommandManager { } @Override - public Command.Builder newCommand(String s) { + public final Command.Builder newCommand(String s) { return parent.newCommand(s); } @Override - public void register(Command command) { + public final void register(Command command) { parent.register(command); } @Override - public void register(String name, Consumer registrationProcess) { + public final void register(String name, Consumer registrationProcess) { parent.register(name, registrationProcess); } @Override - public void registerManager(CommandManager manager) { + public final void registerManager(CommandManager manager) { parent.registerManager(manager); } @Override - public Stream getAllCommands() { + public final Stream getAllCommands() { return parent.getAllCommands(); } @Override - public boolean containsCommand(String name) { + public final boolean containsCommand(String name) { return parent.containsCommand(name); } @Override - public Optional getCommand(String s) { + public final Optional getCommand(String s) { return parent.getCommand(s); } @Override - public ImmutableSet getSuggestions(InjectedValueAccess injectedValueAccess, List list) { + public final ImmutableSet getSuggestions(InjectedValueAccess injectedValueAccess, List list) { return parent.getSuggestions(injectedValueAccess, list); } @Override - public CommandParseResult parse(InjectedValueAccess injectedValueAccess, List list) { + public final CommandParseResult parse(InjectedValueAccess injectedValueAccess, List list) { return parent.parse(injectedValueAccess, list); } @Override - public int execute(InjectedValueAccess context, List args) { - return parent.execute(context, args); + public final O /* Need to recompile with FAWE-piston */ execute(InjectedValueAccess context, List args) { + args = preprocess(context, args); + if (args != null) { + I result = (I) (Object) parent.execute(context, args); + return process(context, args, result); // TODO NOT IMPLEMENTED (recompile piston) + } else { + return null; + } } @Override - public void registerConverter(Key key, ArgumentConverter argumentConverter) { + public final void registerConverter(Key key, ArgumentConverter argumentConverter) { parent.registerConverter(key, argumentConverter); } @Override - public Optional> getConverter(Key key) { + public final Optional> getConverter(Key key) { return parent.getConverter(key); } + + public abstract List preprocess(InjectedValueAccess context, List args); + + public abstract O process(InjectedValueAccess context, List args, I result); } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java b/worldedit-core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java deleted file mode 100644 index dfe0f51ca..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/command/FawePrimitiveBinding.java +++ /dev/null @@ -1,586 +0,0 @@ -package com.boydti.fawe.command; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.extent.NullExtent; -import com.boydti.fawe.object.extent.ResettableExtent; -import com.boydti.fawe.util.TextureUtil; -import com.boydti.fawe.util.image.ImageUtil; - -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extension.factory.DefaultTransformParser; -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.internal.expression.Expression; -import com.sk89q.worldedit.internal.expression.ExpressionException; -import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; -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 com.sk89q.worldedit.session.request.Request; -import com.sk89q.worldedit.internal.annotation.Range; -import com.sk89q.worldedit.util.command.binding.Text; -import com.sk89q.worldedit.internal.annotation.Validate; -import com.sk89q.worldedit.util.command.parametric.ArgumentStack; -import com.sk89q.worldedit.util.command.parametric.BindingBehavior; -import com.sk89q.worldedit.util.command.parametric.BindingMatch; -import com.sk89q.worldedit.util.command.parametric.ParameterException; -import com.sk89q.worldedit.world.World; - -import javax.annotation.Nullable; -import java.awt.image.BufferedImage; -import java.lang.annotation.Annotation; -import java.net.URI; - -public class FawePrimitiveBinding { - @BindingMatch(type = {Long.class, long.class}, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Long getLong(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - try { - Long v = Long.parseLong(context.next()); - validate(v, modifiers); - return v; - - } catch (NumberFormatException ignore) { - return null; - } - } - - private static void validate(long 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)); - } - } - } - } - - public class ImageUri { - public final URI uri; - private BufferedImage image; - - ImageUri(URI uri) { - this.uri = uri; - } - - public BufferedImage load() throws ParameterException { - if (image != null) { - return image; - } - return image = ImageUtil.load(uri); - } - } - - @BindingMatch( - type = {ImageUri.class}, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true - ) - public ImageUri getImage(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - return new ImageUri(ImageUtil.getImageURI(context.next())); - } - - @BindingMatch( - type = {TextureUtil.class}, - behavior = BindingBehavior.PROVIDES - ) - public TextureUtil getTexture(ArgumentStack context) { - Actor actor = context.getContext().getLocals().get(Actor.class); - if (actor == null) { - return Fawe.get().getCachedTextureUtil(true, 0, 100); - } - LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); - return session.getTextureUtil(); - } - - - @BindingMatch( - type = {Extent.class}, - behavior = BindingBehavior.PROVIDES - ) - public Extent getExtent(ArgumentStack context) throws ParameterException { - Extent extent = context.getContext().getLocals().get(EditSession.class); - if (extent != null) { - return extent; - } - extent = Request.request().getExtent(); - if (extent != null) { - return extent; - } - Actor actor = context.getContext().getLocals().get(Actor.class); - if (actor == null) { - throw new ParameterException("No player to get a session for"); - } - if (!(actor instanceof Player)) { - throw new ParameterException("Caller is not a player"); - } - LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); - EditSession editSession = session.createEditSession((Player) actor); - editSession.enableQueue(); - context.getContext().getLocals().put(EditSession.class, editSession); - session.tellVersion(actor); - return editSession; - } - - /** - * Gets an {@link com.boydti.fawe.object.FawePlayer} from a {@link ArgumentStack}. - * - * @param context the context - * @return a FawePlayer - * @throws ParameterException on other error - */ - @BindingMatch(type = FawePlayer.class, - behavior = BindingBehavior.PROVIDES) - public FawePlayer getFawePlayer(ArgumentStack context) throws ParameterException, InputParseException { - Actor sender = context.getContext().getLocals().get(Actor.class); - if (sender == null) { - throw new ParameterException("Missing 'Actor'"); - } else { - return FawePlayer.wrap(sender); - } - } - - /** - * Gets an {@link com.sk89q.worldedit.extent.Extent} from a {@link ArgumentStack}. - * - * @param context the context - * @return an extent - * @throws ParameterException on other error - */ - @BindingMatch(type = ResettableExtent.class, - behavior = BindingBehavior.PROVIDES) - public ResettableExtent getResettableExtent(ArgumentStack context) throws ParameterException, InputParseException { - String input = context.next(); - if (input.equalsIgnoreCase("#null")) { - return new NullExtent(); - } - DefaultTransformParser parser = Fawe.get().getTransformParser(); - 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.getInstance().getSessionManager().get(actor)); - return parser.parseFromInput(input, parserContext); - } - - /** - * 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; - } - - @BindingMatch(type = {Expression.class}, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public Expression getExpression(ArgumentStack context) throws ParameterException, ExpressionException { - String input = context.next(); - try { - return new Expression(Double.parseDouble(input)); - } catch (NumberFormatException e1) { - try { - Expression expression = Expression.compile(input); - expression.optimize(); - return expression; - } 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 = 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(); - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = Vector3.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Vector3 getVector3(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - String radiusString = context.next(); - String[] radii = radiusString.split(","); - final double radiusX, radiusY, radiusZ; - switch (radii.length) { - case 1: - radiusX = radiusY = radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - break; - - case 3: - radiusX = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - radiusY = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[1])); - radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[2])); - break; - - default: - throw new ParameterException("You must either specify 1 or 3 radius values."); - } - return Vector3.at(radiusX, radiusY, radiusZ); - } - - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = Vector2.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public Vector2 getVector2(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - String radiusString = context.next(); - String[] radii = radiusString.split(","); - final double radiusX, radiusZ; - switch (radii.length) { - case 1: - radiusX = radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - break; - - case 2: - radiusX = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[1])); - break; - - default: - throw new ParameterException("You must either specify 1 or 2 radius values."); - } - return Vector2.at(radiusX, radiusZ); - } - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = BlockVector3.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public BlockVector3 getBlockVector3(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - String radiusString = context.next(); - String[] radii = radiusString.split(","); - final double radiusX, radiusY, radiusZ; - switch (radii.length) { - case 1: - radiusX = radiusY = radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - break; - - case 3: - radiusX = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - radiusY = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[1])); - radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[2])); - break; - - default: - throw new ParameterException("You must either specify 1 or 3 radius values."); - } - return BlockVector3.at(radiusX, radiusY, radiusZ); - } - - - /** - * Gets a type from a {@link ArgumentStack}. - * - * @param context the context - * @return the requested type - * @throws ParameterException on error - */ - @BindingMatch(type = BlockVector2.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1, - provideModifiers = true) - public BlockVector2 getBlockVector2(ArgumentStack context, Annotation[] modifiers) throws ParameterException { - String radiusString = context.next(); - String[] radii = radiusString.split(","); - final double radiusX, radiusZ; - switch (radii.length) { - case 1: - radiusX = radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - break; - - case 2: - radiusX = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[0])); - radiusZ = Math.max(1, FawePrimitiveBinding.parseNumericInput(radii[1])); - break; - - default: - throw new ParameterException("You must either specify 1 or 2 radius values."); - } - return BlockVector2.at(radiusX, radiusZ); - } - - /** - * 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 - */ - public static - @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())); - } - } - } - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java deleted file mode 100644 index 27cab80fe..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.boydti.fawe.object.extent; - -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.object.HasIQueueExtent; -import com.boydti.fawe.util.ReflectionUtils; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.DoubleTag; -import com.sk89q.jnbt.FloatTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.StringTag; -import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.entity.BaseEntity; -import com.sk89q.worldedit.entity.Entity; -import com.sk89q.worldedit.extent.AbstractDelegateExtent; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.biome.BiomeType; -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.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class FastWorldEditExtent extends AbstractDelegateExtent implements HasIQueueExtent { - - private final World world; - private IQueueExtent queue; - - public FastWorldEditExtent(final World world, IQueueExtent queue) { - super(queue); - this.world = world; - this.queue = queue; - } - - @Override - public IQueueExtent getQueue() { - return queue; - } - - @Override - public int getMaxY() { - return queue.getMaxY(); - } - - @Override - public int getLight(int x, int y, int z) { - return queue.getLight(x, y, z); - } - - @Override - public int getBlockLight(int x, int y, int z) { - return queue.getEmmittedLight(x, y, z); - } - - @Override - public int getSkyLight(int x, int y, int z) { - return queue.getSkyLight(x, y, z); - } - - @Override - public int getBrightness(int x, int y, int z) { - return queue.getBrightness(x, y, z); - } - - @Override - public int getOpacity(int x, int y, int z) { - return queue.getOpacity(x, y, z); - } - - @Override - public Entity createEntity(final Location loc, final BaseEntity entity) { - if (entity != null) { - CompoundTag tag = entity.getNbtData(); - if (tag == null) { - HashMap map = new HashMap<>(); - tag = new CompoundTag(map); - } - Map map = ReflectionUtils.getMap(tag.getValue()); - map.put("Id", new StringTag(entity.getType().getId())); - ListTag pos = (ListTag) map.get("Pos"); - if (pos == null) { - map.put("Pos", new ListTag(DoubleTag.class, Arrays.asList(new DoubleTag(loc.getX()), new DoubleTag(loc.getY()), new DoubleTag(loc.getZ())))); - } else { - List posList = ReflectionUtils.getList(pos.getValue()); - posList.set(0, new DoubleTag(loc.getX())); - posList.set(1, new DoubleTag(loc.getY())); - posList.set(2, new DoubleTag(loc.getZ())); - } - ListTag rot = (ListTag) map.get("Rotation"); - if (rot == null) { - map.put("Rotation", new ListTag(FloatTag.class, Arrays.asList(new FloatTag(loc.getYaw()), new DoubleTag(loc.getPitch())))); - } - queue.setEntity(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), tag); - } - return null; - } - - @Override - public String toString() { - return super.toString() + ":" + queue + "(" + getExtent() + ")"; - } - - @Override - public BiomeType getBiome(final BlockVector2 position) { - return queue.getBiomeType(position.getBlockX(), position.getBlockZ()); - } - - @Override - public > boolean setBlock(final BlockVector3 location, final B block) throws WorldEditException { - return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); - } - - - - @Override - public > boolean setBlock(int x, int y, int z, final B block) throws WorldEditException { - return queue.setBlock(x, y, z, block); - } - - @Override - public BlockState getBlock(BlockVector3 location) { - return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ()); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - int combinedId4Data = queue.getCombinedId4Data(x, y, z, 0); - BlockType type = BlockTypes.getFromStateId(combinedId4Data); - return type.withStateId(combinedId4Data); - } - - @Override - public BaseBlock getFullBlock(BlockVector3 pos) { - int combinedId4Data = queue.getCombinedId4Data(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), 0); - BlockType type = BlockTypes.getFromStateId(combinedId4Data); - BaseBlock base = type.withStateId(combinedId4Data).toBaseBlock(); - if (type.getMaterial().hasContainer()) { - CompoundTag tile = queue.getTileEntity(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); - if (tile != null) { - return base.toBaseBlock(tile); - } - } - return base; - } - - @Override - public List getEntities() { - return world.getEntities(); - } - - @Override - public List getEntities(final Region region) { - return world.getEntities(region); - } - - @Override - public boolean setBiome(final BlockVector2 position, final BiomeType biome) { - queue.setBiome(position.getBlockX(), position.getBlockZ(), biome); - return true; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/Fast2DIterator.java b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/Fast2DIterator.java deleted file mode 100644 index ceeb138c6..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/Fast2DIterator.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.boydti.fawe.object.visitor; - -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.MappedIQueueExtent; -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.object.HasIQueueExtent; -import com.boydti.fawe.util.ExtentTraverser; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; - -import java.util.Iterator; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class Fast2DIterator implements Iterable { - - private final Iterable iterable; - private final MappedIQueueExtent queue; - - public Fast2DIterator(@Nonnull Iterable iter, @Nullable EditSession extent) { - this(iter, (HasIQueueExtent) extent); - } - - public Fast2DIterator(@Nonnull Iterable iter, @Nullable Extent extent) { - this(iter, (HasIQueueExtent) (extent != null ? (extent instanceof HasIQueueExtent ? extent : new ExtentTraverser(extent).findAndGet(HasIQueueExtent.class)) : null)); - } - - public Fast2DIterator(@Nonnull Iterable iter, @Nullable HasIQueueExtent editSession) { - this(iter, editSession != null ? editSession.getQueue() : null); - } - - public Fast2DIterator(@Nonnull Iterable iter, @Nullable IQueueExtent IQueueExtent) { - this.iterable = iter; - this.queue = IQueueExtent instanceof MappedIQueueExtent ? (MappedIQueueExtent) IQueueExtent : null; - } - - public Iterable getIterable() { - return iterable; - } - - @Override - public Iterator iterator() { - if (queue == null || Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) { - return (Iterator) iterable.iterator(); - } - return new Iterator() { - Iterator trailIter = iterable.iterator(); - Iterator leadIter = iterable.iterator(); - int lastTrailChunkX = Integer.MIN_VALUE; - int lastTrailChunkZ = Integer.MIN_VALUE; - int lastLeadChunkX = Integer.MIN_VALUE; - int lastLeadChunkZ = Integer.MIN_VALUE; - int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS; - int cx, cz; - - @Override - public void remove() { - trailIter.remove(); - } - - @Override - public boolean hasNext() { - return trailIter.hasNext(); - } - - @Override - public BlockVector2 next() { - BlockVector2 pt = trailIter.next(); - if (lastTrailChunkX != (lastTrailChunkX = pt.getBlockX() >> 4) || lastTrailChunkZ != (lastTrailChunkZ = pt.getBlockZ() >> 4)) { - if (leadIter.hasNext()) { - try { - int amount; - if (lastLeadChunkX == Integer.MIN_VALUE) { - lastLeadChunkX = cx; - lastLeadChunkZ = cz; - amount = loadingTarget; - } else { - amount = 1; - } - for (int count = 0; count < amount; ) { - BlockVector2 v = leadIter.next(); - int vcx = v.getBlockX() >> 4; - int vcz = v.getBlockZ() >> 4; - if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) { - lastLeadChunkX = vcx; - lastLeadChunkZ = vcz; - queue.queueChunkLoad(vcx, vcz); - count++; - } - } - } catch (Throwable ignore) { - } - } - } - return pt; - } - }; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FastChunkIterator.java b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FastChunkIterator.java deleted file mode 100644 index cca9c38d1..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FastChunkIterator.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.boydti.fawe.object.visitor; - -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.MappedIQueueExtent; -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.object.HasIQueueExtent; -import com.boydti.fawe.util.ExtentTraverser; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector2; -import org.jetbrains.annotations.NotNull; - -import java.util.Iterator; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class FastChunkIterator implements Iterable { - - private final Iterable iterable; - private final MappedIQueueExtent queue; - - public FastChunkIterator(@Nonnull Iterable iter, @Nullable EditSession extent) { - this(iter, (HasIQueueExtent) extent); - } - - public FastChunkIterator(@Nonnull Iterable iter, @Nullable Extent extent) { - this(iter, (HasIQueueExtent) (extent != null ? (extent instanceof HasIQueueExtent ? extent : new ExtentTraverser(extent).findAndGet(HasIQueueExtent.class)) : null)); - } - - public FastChunkIterator(@Nonnull Iterable iter, @Nullable HasIQueueExtent editSession) { - this(iter, editSession != null ? editSession.getQueue() : null); - } - - public FastChunkIterator(@Nonnull Iterable iter, @Nullable IQueueExtent IQueueExtent) { - this.iterable = iter; - this.queue = IQueueExtent instanceof MappedIQueueExtent ? (MappedIQueueExtent) IQueueExtent : null; - } - - public Iterable getIterable() { - return iterable; - } - - @NotNull - @Override - public Iterator iterator() { - if (queue == null || Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) { - return (Iterator) iterable.iterator(); - } - final Iterator trailIter = iterable.iterator(); - final Iterator leadIter = iterable.iterator(); - int amount = Settings.IMP.QUEUE.PRELOAD_CHUNKS; - for (int i = 0; i < Settings.IMP.QUEUE.PRELOAD_CHUNKS && leadIter.hasNext(); i++) { - BlockVector2 toLoad = leadIter.next(); - queue.queueChunkLoad(toLoad.getBlockX(), toLoad.getBlockZ()); - } - if (!leadIter.hasNext()) { - return (Iterator) trailIter; - } - return new Iterator() { - @Override - public void remove() { - trailIter.remove(); - } - - @Override - public boolean hasNext() { - return trailIter.hasNext(); - } - - @Override - public BlockVector2 next() { - if (leadIter.hasNext()) { - BlockVector2 toLoad = leadIter.next(); - queue.queueChunkLoad(toLoad.getBlockX(), toLoad.getBlockZ()); - } - return trailIter.next(); - } - }; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FastIterator.java b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FastIterator.java deleted file mode 100644 index 1c8dc2633..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FastIterator.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.boydti.fawe.object.visitor; - -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.MappedIQueueExtent; -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.object.HasIQueueExtent; -import com.boydti.fawe.util.ExtentTraverser; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.math.BlockVector3; - -import java.util.Iterator; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class FastIterator implements Iterable { - - private final Iterable iterable; - private final MappedIQueueExtent queue; - - public FastIterator(@Nonnull Iterable iter, @Nullable EditSession extent) { - this(iter, (HasIQueueExtent) extent); - } - - public FastIterator(@Nonnull Iterable iter, @Nullable Extent extent) { - this(iter, (HasIQueueExtent) (extent != null ? (extent instanceof HasIQueueExtent ? extent : new ExtentTraverser(extent).findAndGet(HasIQueueExtent.class)) : null)); - } - - public FastIterator(@Nonnull Iterable iter, @Nullable HasIQueueExtent editSession) { - this(iter, (IQueueExtent) (editSession != null ? editSession.getQueue() : null)); - } - - public FastIterator(@Nonnull Iterable iter, @Nullable IQueueExtent IQueueExtent) { - this.iterable = iter; - this.queue = IQueueExtent != null && IQueueExtent instanceof MappedIQueueExtent ? (MappedIQueueExtent) IQueueExtent : null; - } - - public Iterable getIterable() { - return iterable; - } - - @Override - public Iterator iterator() { - if (queue == null || Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) { - return (Iterator) iterable.iterator(); - } - return new Iterator() { - Iterator trailIter = iterable.iterator(); - Iterator leadIter = iterable.iterator(); - int lastTrailChunkX = Integer.MIN_VALUE; - int lastTrailChunkZ = Integer.MIN_VALUE; - int lastLeadChunkX = Integer.MIN_VALUE; - int lastLeadChunkZ = Integer.MIN_VALUE; - int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS; - int cx, cz; - - @Override - public void remove() { - trailIter.remove(); - } - - @Override - public boolean hasNext() { - return trailIter.hasNext(); - } - - @Override - public BlockVector3 next() { - BlockVector3 pt = trailIter.next(); - if (lastTrailChunkX != (lastTrailChunkX = pt.getBlockX() >> 4) || lastTrailChunkZ != (lastTrailChunkZ = pt.getBlockZ() >> 4)) { - if (leadIter.hasNext()) { - try { - int amount; - if (lastLeadChunkX == Integer.MIN_VALUE) { - lastLeadChunkX = cx; - lastLeadChunkZ = cz; - amount = loadingTarget; - } else { - amount = 1; - } - for (int count = 0; count < amount; ) { - BlockVector3 v = leadIter.next(); - int vcx = v.getBlockX() >> 4; - int vcz = v.getBlockZ() >> 4; - if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) { - lastLeadChunkX = vcx; - lastLeadChunkZ = vcz; - queue.queueChunkLoad(vcx, vcz); - count++; - } - } - } catch (Throwable ignore) { - } - } - } - return pt; - } - }; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FaweChunkVisitor.java b/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FaweChunkVisitor.java deleted file mode 100644 index 33a535303..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/visitor/FaweChunkVisitor.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.boydti.fawe.object.visitor; - -public interface FaweChunkVisitor { - /** - * The will run for each set block in the chunk - * - * @param localX The x position in the chunk (0-15) - * @param y The y position (0 - 255) - * @param localZ The z position in the chunk (0-15) - * @param combined The combined id - */ - void run(int localX, int y, int localZ, int combined); -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java index 07a25cea6..534ed7c84 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java @@ -3,24 +3,20 @@ package com.boydti.fawe.regions.general.plot; import com.boydti.fawe.FaweAPI; import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.util.SetQueue; import com.github.intellectualsites.plotsquared.plot.object.PlotBlock; import com.github.intellectualsites.plotsquared.plot.util.StringMan; import com.github.intellectualsites.plotsquared.plot.util.block.LocalBlockQueue; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; -import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.Biomes; import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.registry.BiomeRegistry; import com.sk89q.worldedit.world.registry.LegacyMapper; import java.util.Collection; -import java.util.List; // TODO FIXME public class FaweLocalBlockQueue extends LocalBlockQueue { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java b/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java deleted file mode 100644 index 5a271d337..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/regions/general/plot/PlotTrim.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.boydti.fawe.regions.general.plot; - -import com.boydti.fawe.jnbt.anvil.MCAChunk; -import com.boydti.fawe.jnbt.anvil.MCAFile; -import com.boydti.fawe.jnbt.anvil.MCAFilter; -import com.boydti.fawe.jnbt.anvil.MCAQueue; -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.SetQueue; - -import com.github.intellectualsites.plotsquared.plot.PlotSquared; -import com.github.intellectualsites.plotsquared.plot.object.ChunkLoc; -import com.github.intellectualsites.plotsquared.plot.object.Location; -import com.github.intellectualsites.plotsquared.plot.object.Plot; -import com.github.intellectualsites.plotsquared.plot.object.PlotArea; -import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; -import com.github.intellectualsites.plotsquared.plot.util.expiry.ExpireManager; -import static com.google.common.base.Preconditions.checkNotNull; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class PlotTrim { - private final MCAQueue queue; - private final PlotArea area; - private final PlotPlayer player; - private final MCAQueue originalQueue; - private final File root; - private int[][] ids; - private boolean deleteUnowned; - - public PlotTrim(PlotPlayer player, PlotArea area, String worldName, boolean deleteUnowned) { - IQueueExtent tmpQueue = SetQueue.IMP.getNewQueue(worldName, true, false); - File saveFolder = tmpQueue.getSaveFolder(); - this.root = new File(saveFolder.getParentFile().getParentFile(), worldName + "-Copy" + File.separator + "region"); - this.originalQueue = new MCAQueue(worldName, saveFolder, true); - this.queue = new MCAQueue(worldName + "-Copy", root, true); - this.area = area; - this.player = player; - this.deleteUnowned = deleteUnowned; - } - - public void setChunk(int[][] ids) { - checkNotNull(ids); - this.ids = ids; - } - - public void setChunk(int x, int z) { - this.ids = ((MCAChunk) originalQueue.getFaweChunk(x, z)).ids; - } - - private Map chunks = new ConcurrentHashMap<>(); - private Object PRESENT = new Object(); - - private void removeChunks(Plot plot) { - Location pos1 = plot.getBottom(); - Location pos2 = plot.getTop(); - int ccx1 = pos1.getX() >> 4; - int ccz1 = pos1.getZ() >> 4; - int ccx2 = pos2.getX() >> 4; - int ccz2 = pos2.getZ() >> 4; - for (int x = ccx1; x <= ccx2; x++) { - for (int z = ccz1; z <= ccz2; z++) { - long pair = MathMan.pairInt(x, z); - chunks.remove(pair); - } - } - } - - public void run() { - final Set mcas = new HashSet<>(); - if (deleteUnowned && area != null) { - originalQueue.filterWorld(new MCAFilter() { - @Override - public boolean appliesFile(int mcaX, int mcaZ) { - mcas.add(new ChunkLoc(mcaX, mcaZ)); - return false; - } - }); - ArrayList plots = new ArrayList<>(PlotSquared.get().getPlots(area)); - if (ExpireManager.IMP != null) { - plots.removeAll(ExpireManager.IMP.getPendingExpired()); - } - for (Plot plot : plots) { - Location pos1 = plot.getBottom(); - Location pos2 = plot.getTop(); - int ccx1 = pos1.getX() >> 9; - int ccz1 = pos1.getZ() >> 9; - int ccx2 = pos2.getX() >> 9; - int ccz2 = pos2.getZ() >> 9; - for (int x = ccx1; x <= ccx2; x++) { - for (int z = ccz1; z <= ccz2; z++) { - ChunkLoc loc = new ChunkLoc(x, z); - mcas.remove(loc); - } - } - } - for (ChunkLoc mca : mcas) { - int bx = mca.x << 5; - int bz = mca.z << 5; - for (int x = 0; x < 32; x++) { - for (int z = 0; z < 32; z++) { - long pair = MathMan.pairInt(bx + x, bz + z); - chunks.put(pair, PRESENT); - } - } - } - for (Plot plot : plots) { - removeChunks(plot); - } - } - originalQueue.filterWorld(new MCAFilter() { - @Override - public boolean appliesFile(int mcaX, int mcaZ) { - ChunkLoc loc = new ChunkLoc(mcaX, mcaZ); - return !mcas.contains(loc); - } - - @Override - public MCAFile applyFile(MCAFile mca) { - int mcaX = mca.getX(); - int mcaZ = mca.getZ(); - ChunkLoc loc = new ChunkLoc(mcaX, mcaZ); - if (mcas.contains(loc)) { - player.sendMessage("Delete MCA " + mca); - mca.setDeleted(true); - return null; - } - try { - File copy = new File(root, mca.getFile().getName()); - if (!copy.exists()) { - copy = MainUtil.copyFile(mca.getFile(), copy); - player.sendMessage("Filter copy -> " + copy); - } else { - player.sendMessage("Filter existing: " + mcaX + "," + mcaZ); - } - return new MCAFile(mca.getParent(), copy); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - - @Override - public MCAChunk applyChunk(MCAChunk chunk, Object ignore) { - long pair = MathMan.pairInt(chunk.getX(), chunk.getZ()); - if (chunks.containsKey(pair)) { - chunk.setDeleted(true); - return null; - } - if (ids != null) { - for (int i = 0; i < ids.length; i++) { - if (!isEqual(ids[i], chunk.ids[i])) { - return null; - } - } - chunk.setDeleted(true); - } - return null; - } - }); - player.sendMessage("Done!"); - } - - private boolean isEqual(int[] a, int[] b) { - if (a == b) { - return true; - } - if (a != null) { - if (b != null) { - return Arrays.equals(a, b); - } - return isEmpty(a); - } - return isEmpty(b); - } - - private boolean isEmpty(int[] a) { - for (int b : a) { - if (!BlockTypes.getFromStateId(b).getMaterial().isAir()) { - return false; - } - } - return true; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java b/worldedit-core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java index 54dd39cae..752c5cb98 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java @@ -21,6 +21,9 @@ package com.boydti.fawe.util; import com.boydti.fawe.command.AnvilCommands; import com.boydti.fawe.command.CFICommands; +import com.sk89q.minecraft.util.commands.Step; +import com.sk89q.worldedit.command.ToolUtilCommands; +import com.sk89q.worldedit.internal.annotation.Range; import org.enginehub.piston.annotation.Command; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.minecraft.util.commands.NestedCommand; @@ -33,7 +36,6 @@ import com.sk89q.worldedit.command.GenerationCommands; import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.MaskCommands; import com.sk89q.worldedit.command.NavigationCommands; -import com.sk89q.worldedit.command.OptionsCommands; import com.sk89q.worldedit.command.PatternCommands; import com.sk89q.worldedit.command.RegionCommands; import com.sk89q.worldedit.command.SchematicCommands; @@ -46,10 +48,19 @@ import com.sk89q.worldedit.command.ToolCommands; import com.sk89q.worldedit.command.TransformCommands; import com.sk89q.worldedit.command.UtilityCommands; import com.sk89q.worldedit.command.WorldEditCommands; +import org.enginehub.piston.annotation.param.Arg; +import org.enginehub.piston.annotation.param.ArgFlag; +import org.enginehub.piston.annotation.param.Switch; + import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; @SuppressWarnings("UseOfSystemOutOrSystemErr") public final class DocumentationPrinter { @@ -113,7 +124,7 @@ public final class DocumentationPrinter { writePermissionsWikiTable(stream, builder, "/", SnapshotUtilCommands.class); writePermissionsWikiTable(stream, builder, "/", ScriptingCommands.class); writePermissionsWikiTable(stream, builder, "/", ChunkCommands.class); - writePermissionsWikiTable(stream, builder, "/", OptionsCommands.class); + writePermissionsWikiTable(stream, builder, "/", ToolUtilCommands.class); writePermissionsWikiTable(stream, builder, "/", BrushOptionsCommands.class); writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class); writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class); @@ -153,7 +164,6 @@ public final class DocumentationPrinter { } private static void writePermissionsWikiTable(StringBuilder stream, String prefix, Class cls, String name, boolean title) { - // //setbiome || worldedit.biome.set || //setbiome || p || Sets the biome of the player's current block or region. if (title) { String path = "https://github.com/boy0001/FastAsyncWorldedit/edit/master/core/src/main/java/" + cls.getName().replaceAll("\\.", "/") + ".java"; stream.append("### **" + name + "** `[`[`edit`](" + path + ")`|`[`top`](#overview)`]`"); @@ -163,8 +173,8 @@ public final class DocumentationPrinter { if (!cmd.desc().isEmpty()) { stream.append("> (" + (cmd.desc()) + ") \n"); } - if (!cmd.help().isEmpty()) { - stream.append("" + (cmd.help()) + " \n"); + if (!cmd.descFooter().isEmpty()) { + stream.append("" + (cmd.descFooter()) + " \n"); } } stream.append("\n"); @@ -176,22 +186,16 @@ public final class DocumentationPrinter { if (!method.isAnnotationPresent(Command.class)) { continue; } - Command cmd = method.getAnnotation(Command.class); String[] aliases = cmd.aliases(); - String usage = prefix + aliases[0] + " " + cmd.usage(); - if (!cmd.flags().isEmpty()) { - for (char c : cmd.flags().toCharArray()) { - usage += " [-" + c + "]"; - } - } -// stream.append("#### [`" + usage + "`](" + "https://github.com/boy0001/FastAsyncWorldedit/wiki/" + aliases[0] + ")\n"); + String usage = prefix + aliases[0] + " " + getUsage(cmd, method); + stream.append("#### `" + usage + "`\n"); if (method.isAnnotationPresent(CommandPermissions.class)) { CommandPermissions perms = method.getAnnotation(CommandPermissions.class); stream.append("**Perm**: `" + StringMan.join(perms.value(), "`, `") + "` \n"); } - String help = cmd.help() == null || cmd.help().isEmpty() ? cmd.desc() : cmd.help(); + String help = getDesc(cmd, method); stream.append("**Desc**: " + help.trim().replaceAll("\n", "
") + " \n"); if (method.isAnnotationPresent(NestedCommand.class)) { @@ -209,4 +213,78 @@ public final class DocumentationPrinter { stream.append("\n"); stream.append("\n"); } + + public static String getDesc(Command command, Method method) { + Parameter[] params = method.getParameters(); + List desc = new ArrayList<>(); + for (Parameter param : params) { + String[] info = getParamInfo(param); + if (info != null) { + desc.add(info[0].replace("%s0", info[1]) + " - " + info[2] + ": " + info[3]); + } + } + String footer = command.descFooter(); + if (!footer.isEmpty()) footer += "\n"; + return footer + StringMan.join(desc, "\n"); + } + + public static String getUsage(Command command, Method method) { + Parameter[] params = method.getParameters(); + List usage = new ArrayList<>(); + for (Parameter param : params) { + String[] info = getParamInfo(param); + if (info != null) { + usage.add(info[0].replace("%s0", info[1])); + } + } + return StringMan.join(usage, " "); + } + + /* + Return format, name, type, description + */ + public static String[] getParamInfo(Parameter param) { + Switch switchAnn = param.getAnnotation(Switch.class); + Arg argAnn = param.getAnnotation(Arg.class); + Range rangeAnn = param.getAnnotation(Range.class); + Step stepAnn = param.getAnnotation(Step.class); + if (switchAnn != null || argAnn != null || rangeAnn != null || stepAnn != null) { + String[] result = new String[] { "[%s0]", param.getName(), param.getType().getSimpleName(), ""}; + boolean optional = argAnn != null && argAnn.def().length != 0; + if (optional) { + result[0] = "<%s0>"; + } + if (argAnn != null) result[1] = argAnn.name(); + if (argAnn != null) { + if (argAnn.def().length != 0) { + result[0] = result[0].replace("%s0", "%s0=" + argAnn.def()); + } + result[3] = argAnn.desc(); + } else if (switchAnn != null) { + result[0] = result[0].replace("%s0", "-" + switchAnn.name() + " %s0"); + } + if (switchAnn != null) result[3] = switchAnn.desc(); + if (rangeAnn != null) { + String step; + String min = rangeAnn.min() == Double.MIN_VALUE ? "(-∞" : ("[" + rangeAnn.min()); + String max = rangeAnn.max() == Double.MAX_VALUE ? "∞)" : (rangeAnn.max() + "]"); + result[0] += min + "," + max; + } + if (stepAnn != null) { + result[0] += "⦧" + stepAnn.value(); + } + return result; + } + return null; + } + + public static Collection getFlags(Command command, Method method) { + Parameter[] params = method.getParameters(); + List flags = new ArrayList<>(); + for (Parameter param : params) { + ArgFlag flagAnn = param.getAnnotation(ArgFlag.class); + if (flagAnn != null) flags.add(flagAnn); + } + return flags; + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/TaskManager.java b/worldedit-core/src/main/java/com/boydti/fawe/util/TaskManager.java index 2a9f3e2f2..0e5ca516c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/TaskManager.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/TaskManager.java @@ -1,6 +1,7 @@ package com.boydti.fawe.util; import com.boydti.fawe.Fawe; +import com.boydti.fawe.beta.implementation.QueueHandler; import com.boydti.fawe.config.Settings; import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.object.RunnableVal; @@ -10,7 +11,9 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.Collection; import java.util.Iterator; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Supplier; @@ -138,7 +141,8 @@ public abstract class TaskManager { * @param queue * @param run */ - public void runUnsafe(IQueueExtent queue, Runnable run) { + public void runUnsafe(Runnable run) { + QueueHandler queue = Fawe.get().getQueueHandler(); queue.startSet(true); try { run.run(); @@ -254,23 +258,6 @@ public abstract class TaskManager { }); } - /** - * Quickly run a task on the main thread, and wait for execution to finish:
- * - Useful if you need to access something from the Bukkit API from another thread
- * - Usualy wait time is around 25ms
- * - * @param function - * @param - * @return - */ - public T sync(final RunnableVal function) { - return sync(function, Integer.MAX_VALUE); - } - - public T sync(final Supplier function) { - return sync(function, Integer.MAX_VALUE); - } - public void wait(AtomicBoolean running, int timout) { try { long start = System.currentTimeMillis(); @@ -295,15 +282,11 @@ public abstract class TaskManager { } } - public T syncWhenFree(@NotNull final RunnableVal function) { - return syncWhenFree(function, Integer.MAX_VALUE); - } - public void taskWhenFree(@NotNull Runnable run) { if (Fawe.isMainThread()) { run.run(); } else { - SetQueue.IMP.addTask(run); + Fawe.get().getQueueHandler().sync(run); } } @@ -317,43 +300,16 @@ public abstract class TaskManager { * @param * @return */ - public T syncWhenFree(@NotNull final RunnableVal function, int timeout) { + public T syncWhenFree(@NotNull final RunnableVal function) { if (Fawe.isMainThread()) { function.run(); return function.value; } - final AtomicBoolean running = new AtomicBoolean(true); - RunnableVal run = new RunnableVal() { - @Override - public void run(RuntimeException value) { - try { - function.run(); - } catch (RuntimeException e) { - this.value = e; - } catch (Throwable neverHappens) { - neverHappens.printStackTrace(); - } finally { - running.set(false); - } - synchronized (function) { - function.notifyAll(); - } - } - }; - SetQueue.IMP.addTask(run); try { - synchronized (function) { - while (running.get()) { - function.wait(timeout); - } - } - } catch (InterruptedException e) { - e.printStackTrace(); + return Fawe.get().getQueueHandler().sync((Supplier) function).get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); } - if (run.value != null) { - throw run.value; - } - return function.value; } /** @@ -366,45 +322,27 @@ public abstract class TaskManager { * @param * @return */ - public T sync(@NotNull final RunnableVal function, int timeout) { - return sync((Supplier) function, timeout); + public T sync(@NotNull final RunnableVal function) { + return sync((Supplier) function); } - public T sync(final Supplier function, int timeout) { + /** + * Quickly run a task on the main thread, and wait for execution to finish:
+ * - Useful if you need to access something from the Bukkit API from another thread
+ * - Usually wait time is around 25ms
+ * + * @param function + * @param + * @return + */ + public T sync(final Supplier function) { if (Fawe.isMainThread()) { return function.get(); } - final AtomicBoolean running = new AtomicBoolean(true); - RunnableVal run = new RunnableVal() { - @Override - public void run(Object value) { - try { - this.value = function.get(); - } catch (RuntimeException e) { - this.value = e; - } catch (Throwable neverHappens) { - neverHappens.printStackTrace(); - } finally { - running.set(false); - synchronized (function) { - function.notifyAll(); - } - } - } - }; - SetQueue.IMP.addTask(run); try { - synchronized (function) { - while (running.get()) { - function.wait(timeout); - } - } - } catch (InterruptedException e) { - e.printStackTrace(); + return Fawe.get().getQueueHandler().sync(function).get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); } - if (run.value instanceof RuntimeException) { - throw (RuntimeException) run.value; - } - return (T) run.value; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/chat/UsageMessage.java b/worldedit-core/src/main/java/com/boydti/fawe/util/chat/UsageMessage.java deleted file mode 100644 index 3ad417fab..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/chat/UsageMessage.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.boydti.fawe.util.chat; - -import com.boydti.fawe.config.BBC; -import com.boydti.fawe.config.Commands; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.StringMan; -import com.sk89q.minecraft.util.commands.CommandLocals; -import com.sk89q.minecraft.util.commands.Link; -import com.sk89q.worldedit.extension.platform.PlatformCommandManager; -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.Parameter; -import com.sk89q.worldedit.util.command.PrimaryAliasComparator; -import com.sk89q.worldedit.internal.annotation.Range; -import com.sk89q.worldedit.util.command.parametric.ParameterData; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.List; -import javax.annotation.Nullable; - - -import static com.google.common.base.Preconditions.checkNotNull; - -public class UsageMessage extends Message { - /** - * Create a new usage box. - * - * @param command the command to describe - * @param commandString the command that was used, such as "/we" or "/brush sphere" - */ - public UsageMessage(CommandCallable command, String commandString) { - this(command, 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 locals list of locals to use - */ - public UsageMessage(CommandCallable command, String commandString, @Nullable CommandLocals locals) { - checkNotNull(command); - checkNotNull(commandString); - if (command instanceof Dispatcher) { - attachDispatcherUsage((Dispatcher) command, commandString, locals); - } else { - attachCommandUsage(command.getDescription(), commandString); - } - } - - private void attachDispatcherUsage(Dispatcher dispatcher, String commandString, @Nullable CommandLocals locals) { - prefix(); - text(BBC.HELP_HEADER_SUBCOMMANDS.f()); - String prefix = !commandString.isEmpty() ? commandString + " " : ""; - - List list = new ArrayList<>(dispatcher.getCommands()); - list.sort(new PrimaryAliasComparator(PlatformCommandManager.COMMAND_CLEAN_PATTERN)); - - for (CommandMapping mapping : list) { - boolean perm = locals == null || mapping.getCallable().testPermission(locals); - newline(); - String cmd = prefix + mapping.getPrimaryAlias(); - text((perm ? BBC.HELP_ITEM_ALLOWED : BBC.HELP_ITEM_DENIED).format(cmd, mapping.getDescription().getDescription())); - command(cmd); - } - } - - protected String separateArg(String arg) { - return " " + arg; - } - - private void attachCommandUsage(Description description, String commandString) { - List params = description.getParameters(); - String[] usage; - if (description.getUsage() != null) { - usage = description.getUsage().split(" ", params.size()); - } else { - usage = new String[params.size()]; - for (int i = 0; i < usage.length; i++) { - Parameter param = params.get(i); - boolean optional = param.isValueFlag() || param.isOptional(); - String arg; - if (param.getFlag() != null) { - arg = "-" + param.getFlag(); - if (param.isValueFlag()) - arg += param.getName(); - } else { - arg = param.getName(); - if (param.getDefaultValue() != null && param.getDefaultValue().length > 0) - arg += "=" + StringMan.join(param.getDefaultValue(), ","); - } - usage[i] = optional ? ("[" + arg + "]") : ("<" + arg + ">"); - } - } - - prefix(); - text("&cUsage: "); - text("&7" + commandString); - suggestTip(commandString + " "); - for (int i = 0; i < usage.length; i++) { - String argStr = usage[i]; - text(separateArg(argStr.replaceAll("[\\[|\\]|<|>]", "&0$0&7"))); - - if (params.isEmpty()) continue; - Parameter param = params.get(i); - - StringBuilder tooltip = new StringBuilder(); - String command = null; - - tooltip.append("Name: " + param.getName()); - if (param instanceof ParameterData) { - ParameterData pd = (ParameterData) param; - Type type = pd.getType(); - if (type instanceof Class) { - tooltip.append("\nType: " + ((Class) type).getSimpleName()); - } - - Range range = MainUtil.getOf(pd.getModifiers(), Range.class); - if (range != null) { - String min = range.min() == Double.MIN_VALUE ? "(-∞" : ("[" + range.min()); - String max = range.max() == Double.MAX_VALUE ? "∞)" : (range.max() + "]"); - tooltip.append("\nRange: " + min + "," + max); - } - if (type instanceof Class) { - Link link = (Link) ((Class) type).getAnnotation(Link.class); - if (link != null) { - command = Commands.getAlias(link.clazz(), link.value()); - } - } - } - tooltip.append("\nOptional: " + (param.isOptional() || param.isValueFlag())); - if (param.getDefaultValue() != null) { - tooltip.append("\nDefault: " + param.getDefaultValue()[0]); - } else if (argStr.contains("=")) { - tooltip.append("\nDefault: " + argStr.split("[=|\\]|>]")[1]); - } - if (command != null) { - tooltip.append("\nClick for more info"); - } - tooltip(tooltip.toString()); - if (command != null) command(command); - } - - newline(); - if (description.getHelp() != null) { - text("&cHelp: &7" + description.getHelp()); - } else if (description.getDescription() != null) { - text("&cDescription: &7" + description.getDescription()); - } else { - text("No further help is available."); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/task/TaskBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/util/task/TaskBuilder.java index 5887f1d4c..45c3ebeae 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/task/TaskBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/task/TaskBuilder.java @@ -2,9 +2,9 @@ package com.boydti.fawe.util.task; import com.boydti.fawe.Fawe; import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.implementation.QueueHandler; import com.boydti.fawe.object.Metadatable; import com.boydti.fawe.object.RunnableVal; -import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import java.util.ArrayDeque; import java.util.ArrayList; @@ -430,7 +430,7 @@ public class TaskBuilder extends Metadatable { public static abstract class SplitTask extends RunnableTask { private final long allocation; - private final IQueueExtent queue; + private final QueueHandler queue; private long last; private long start; private Object asyncWaitLock = new Object(); @@ -447,7 +447,7 @@ public class TaskBuilder extends Metadatable { public SplitTask(long allocation) { super(TaskType.SYNC_WHEN_FREE); this.allocation = allocation; - this.queue = SetQueue.IMP.getNewQueue((String) null, true, false); + this.queue = Fawe.get().getQueueHandler(); } public Object execSplit(final Object previous) { 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 cd1a3c985..e5153a1b2 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 @@ -489,7 +489,7 @@ public abstract class CommandsManager { newFlags.add(flags[i]); } - InjectedValueAccess context = new InjectedValueAccess(newArgs, valueFlags); + CommandContext context = new CommandContext(newArgs, valueFlags); if (context.argsLength() < cmd.min()) { throw new CommandUsageException("Too few arguments.", getUsage(args, level, cmd)); 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 cf437a194..485ed1623 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/WorldEdit.java @@ -80,6 +80,8 @@ import java.util.Locale; import java.util.Map; import javax.annotation.Nullable; import javax.script.ScriptException; + +import org.mozilla.javascript.NativeJavaObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -633,14 +635,14 @@ public final class WorldEdit { * @param args arguments for the script * @throws WorldEditException */ - public void runScript(Player player, File f, String[] args) throws WorldEditException { + public Object runScript(Player player, File f, String[] args) throws WorldEditException { String filename = f.getPath(); int index = filename.lastIndexOf('.'); String ext = filename.substring(index + 1); if (!ext.equalsIgnoreCase("js")) { player.printError("Only .js scripts are currently supported"); - return; + return null; } String script; @@ -653,7 +655,7 @@ public final class WorldEdit { if (file == null) { player.printError("Script does not exist: " + filename); - return; + return null; } } else { file = new FileInputStream(f); @@ -666,7 +668,7 @@ public final class WorldEdit { script = new String(data, 0, data.length, StandardCharsets.UTF_8); } catch (IOException e) { player.printError("Script read error: " + e.getMessage()); - return; + return null; } LocalSession session = getSessionManager().get(player); @@ -680,7 +682,7 @@ public final class WorldEdit { } catch (NoClassDefFoundError ignored) { player.printError("Failed to find an installed script engine."); player.printError("Please see https://worldedit.readthedocs.io/en/latest/usage/other/craftscripts/"); - return; + return null; } engine.setTimeLimit(getConfiguration().scriptTimeout); @@ -691,7 +693,11 @@ public final class WorldEdit { vars.put("player", player); try { - engine.evaluate(script, filename, vars); + Object result = engine.evaluate(script, filename, vars); + if (result instanceof NativeJavaObject) { + result = ((NativeJavaObject) result).unwrap(); + } + return result; } catch (ScriptException e) { player.printError("Failed to execute:"); player.printRaw(e.getMessage()); @@ -708,6 +714,7 @@ public final class WorldEdit { session.remember(editSession); } } + return null; } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java index 8ee310c4a..2a9790448 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java @@ -30,7 +30,6 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.internal.annotation.Range; -import com.sk89q.worldedit.util.command.parametric.Optional; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Switch; @@ -48,7 +47,7 @@ import java.util.zip.GZIPInputStream; * Tool commands. */ -@Command(aliases = {"brush", "br", "/b"}, desc = "Tool commands") +//@Command(aliases = {"brush", "br", "/b"}, desc = "Tool commands") public class BrushOptionsCommands extends MethodCommands { public BrushOptionsCommands(WorldEdit we) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java index 5448f4746..9784747b2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java @@ -35,24 +35,26 @@ import java.util.Collections; import java.util.List; import java.util.Set; -@Command(aliases = {"patterns"}, - desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)", - descFooter = "Patterns determine what blocks are placed\n" + - " - Use [brackets] for arguments\n" + - " - Use , to OR multiple\n" + - "e.g. #surfacespread[10][#existing],andesite\n" + - "More Info: https://git.io/vSPmA" -) +//@Command(aliases = {"patterns"}, +// desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)", +// descFooter = "Patterns determine what blocks are placed\n" + +// " - Use [brackets] for arguments\n" + +// " - Use , to OR multiple\n" + +// "e.g. #surfacespread[10][#existing],andesite\n" + +// "More Info: https://git.io/vSPmA" +//) public class PatternCommands extends MethodCommands { + private final WorldEdit worldEdit; + public PatternCommands(WorldEdit worldEdit) { - super(worldEdit); + this.worldEdit = worldEdit; } @Command( name = "#existing", aliases = {"#*", "*", ".*"}, desc = "Use the block that is already there", - usage = "[properties]" + descFooter = "[properties]" ) public Pattern existing(Extent extent, @Arg(name = "properties", desc = "String", def = "") String properties) { // TODO FIXME , @Arg(name = "properties", desc = "String", def = "") String properties if (properties == null) return new ExistingPattern(extent); @@ -73,7 +75,7 @@ public class PatternCommands extends MethodCommands { name = "#simplex", desc = "Use simplex noise to randomize blocks. Tutorial: https://imgur.com/a/rwVAE" ) - public Pattern simplex(@Arg() double scale, Pattern other) { + public Pattern simplex(@Arg(desc = "scale factor") double scale, Pattern other) { if (other instanceof RandomPattern) { scale = (1d / Math.max(1, scale)); RandomCollection collection = ((RandomPattern) other).getCollection(); @@ -282,8 +284,7 @@ public class PatternCommands extends MethodCommands { desc = "Apply a pattern depending on a mask" ) public Pattern mask(Actor actor, LocalSession session, Mask mask, Pattern pass, Pattern fail) { - PatternExtent extent = new PatternExtent(pass); - return new MaskedPattern(mask, extent, fail); + return new MaskedPattern(mask, pass, fail); } @Command( 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 ab322e2da..050d241e3 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 @@ -81,111 +81,20 @@ public class ScriptingCommands { ) @CommandPermissions("fawe.setupdispatcher") public void setupdispatcher(Player player, LocalSession session, final InjectedValueAccess args) throws WorldEditException { - PlatformCommandManager.getInstance().setupDispatcher(); - } - - public static T runScript(Player player, File f, String[] args) throws WorldEditException { - return runScript(player, f, args, null); - } - - public static T runScript(Actor actor, File f, String[] args, @Nullable Function processor) throws WorldEditException { - String filename = f.getPath(); - int index = filename.lastIndexOf("."); - String ext = filename.substring(index + 1, filename.length()); - - if (!ext.equalsIgnoreCase("js")) { - actor.printError("Only .js scripts are currently supported"); - return null; - } - - String script; - - try { - InputStream file; - - if (!f.exists()) { - file = WorldEdit.class.getResourceAsStream("craftscripts/" + filename); - - if (file == null) { - actor.printError("Script does not exist: " + filename); - return null; - } - } else { - file = new FileInputStream(f); - } - - DataInputStream in = new DataInputStream(file); - byte[] data = new byte[in.available()]; - in.readFully(data); - in.close(); - script = new String(data, 0, data.length, StandardCharsets.UTF_8); - } catch (IOException e) { - actor.printError("Script read error: " + e.getMessage()); - return null; - } - - if (processor != null) { - script = processor.apply(script); - } - - WorldEdit worldEdit = WorldEdit.getInstance(); - LocalSession session = worldEdit.getSessionManager().get(actor); - - CraftScriptEngine engine = null; - - Object result = null; - try { - - engine = new RhinoCraftScriptEngine(); - } catch (NoClassDefFoundError e) { - actor.printError("Failed to find an installed script engine."); - actor.printError("Download: https://github.com/downloads/mozilla/rhino/rhino1_7R4.zip"); - actor.printError("Extract: `js.jar` to `plugins` or `mods` directory`"); - actor.printError("More info: https://github.com/boy0001/CraftScripts/"); - return null; - } - - engine.setTimeLimit(worldEdit.getConfiguration().scriptTimeout); - - Player player = actor instanceof Player ? (Player) actor : null; - CraftScriptContext scriptContext = new CraftScriptContext(worldEdit, WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.USER_COMMANDS), - WorldEdit.getInstance().getConfiguration(), session, player, args); - - Map vars = new HashMap<>(); - vars.put("argv", args); - vars.put("context", scriptContext); - vars.put("actor", actor); - vars.put("player", player); - - try { - result = engine.evaluate(script, filename, vars); - } catch (ScriptException e) { - e.printStackTrace(); - actor.printError("Failed to execute:"); - actor.printRaw(e.getMessage()); - } catch (NumberFormatException | WorldEditException e) { - throw e; - } catch (Throwable e) { - actor.printError("Failed to execute (see console):"); - actor.printRaw(e.getClass().getCanonicalName()); - e.printStackTrace(); - } - if (result instanceof NativeJavaObject) { - return (T) ((NativeJavaObject) result).unwrap(); - } - return (T) result; + PlatformCommandManager.getInstance().registerAllCommands(); } @Command( - name = "cs", - desc = "Execute a CraftScript" + name = "cs", + desc = "Execute a CraftScript" ) @CommandPermissions("worldedit.scripting.execute") @Logging(ALL) - public void execute(Player player, LocalSession session, InjectedValueAccess args) throws WorldEditException { - final String[] scriptArgs = args.getSlice(1); - final String filename = args.getString(0); - + 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)) { BBC.SCRIPTING_NO_PERM.send(player); return; @@ -195,27 +104,20 @@ public class ScriptingCommands { File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir); File f = worldEdit.getSafeOpenFile(player, dir, filename, "js", "js"); - try { - new RhinoCraftScriptEngine(); - } catch (NoClassDefFoundError e) { - player.printError("Failed to find an installed script engine."); - player.printError("Download: https://github.com/downloads/mozilla/rhino/rhino1_7R4.zip"); - player.printError("Extract: `js.jar` to `plugins` or `mods` directory`"); - player.printError("More info: https://github.com/boy0001/CraftScripts/"); - return; - } - runScript(LocationMaskedPlayerWrapper.unwrap(player), f, scriptArgs); + + worldEdit.runScript(player, f, Stream.concat(Stream.of(filename), args.stream()) + .toArray(String[]::new)); } @Command( - name = ".s", - desc = "Execute last CraftScript" + name = ".s", + desc = "Execute last CraftScript" ) @CommandPermissions("worldedit.scripting.execute") @Logging(ALL) public void executeLast(Player player, LocalSession session, @Arg(desc = "Arguments to the CraftScript", def = "", variable = true) - List args) throws WorldEditException { + List args) throws WorldEditException { String lastScript = session.getLastScript(); @@ -233,6 +135,6 @@ public class ScriptingCommands { File f = worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js"); worldEdit.runScript(player, f, Stream.concat(Stream.of(lastScript), args.stream()) - .toArray(String[]::new)); + .toArray(String[]::new)); } } 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 09d80779d..268044386 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 @@ -46,7 +46,7 @@ import java.util.List; * Snapshot commands. */ @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) -@Command(aliases = {"snapshot", "snap"}, desc = "List, load and view information related to snapshots") +//@Command(aliases = {"snapshot", "snap"}, desc = "List, load and view information related to snapshots") public class SnapshotCommands { private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); @@ -205,7 +205,7 @@ public class SnapshotCommands { if (snapshot == null) { player.printError("Couldn't find a snapshot before " - + dateFormat.withZone(session.getTimeZone().toZoneId()).format(date) + "."); + + dateFormat.withZone(session.getTimeZone()).format(date) + "."); } else { session.setSnapshot(snapshot); BBC.SNAPSHOT_SET.send(player, snapshot.getName()); @@ -235,7 +235,7 @@ public class SnapshotCommands { Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName()); if (snapshot == null) { player.printError("Couldn't find a snapshot after " - + dateFormat.withZone(session.getTimeZone().toZoneId()).format(date) + "."); + + dateFormat.withZone(session.getTimeZone()).format(date) + "."); } else { session.setSnapshot(snapshot); BBC.SNAPSHOT_SET.send(player, snapshot.getName()); 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 856be7418..cd7319c81 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 @@ -21,6 +21,7 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.config.BBC; import org.enginehub.piston.annotation.Command; +import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.inject.InjectedValueAccess; import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.LocalConfiguration; @@ -32,7 +33,7 @@ import com.sk89q.worldedit.command.tool.RecursivePickaxe; import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.entity.Player; -@Command(aliases = {"superpickaxe", "pickaxe", "sp"}, desc = "Super-pickaxe commands: [More Info](https://goo.gl/aBtGHo)") +//@Command(aliases = {"superpickaxe", "pickaxe", "sp"}, desc = "Super-pickaxe commands: [More Info](https://goo.gl/aBtGHo)") public class SuperPickaxeCommands { private final WorldEdit we; @@ -56,10 +57,11 @@ public class SuperPickaxeCommands { desc = "Enable the area super pickaxe pickaxe mode" ) @CommandPermissions("worldedit.superpickaxe.area") - public void area(Player player, LocalSession session, InjectedValueAccess 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) { BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); @@ -77,10 +79,11 @@ public class SuperPickaxeCommands { desc = "Enable the recursive super pickaxe pickaxe mode" ) @CommandPermissions("worldedit.superpickaxe.recursive") - public void recursive(Player player, LocalSession session, InjectedValueAccess 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) { BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); 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 7040ba4a5..0f545b1d7 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 @@ -22,55 +22,29 @@ package com.sk89q.worldedit.extension.platform; import static com.google.common.base.Preconditions.checkNotNull; import com.boydti.fawe.Fawe; -import com.boydti.fawe.command.AnvilCommands; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.task.ThrowableSupplier; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper; -import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.reflect.TypeToken; -import com.sk89q.minecraft.util.commands.CommandLocals; 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; -import com.sk89q.worldedit.command.ApplyBrushCommands; -import com.sk89q.worldedit.command.BiomeCommands; //import com.sk89q.worldedit.command.BiomeCommandsRegistration; -import com.sk89q.worldedit.command.BrushCommands; -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.ExpandCommands; -import com.sk89q.worldedit.command.GeneralCommands; //import com.sk89q.worldedit.command.GeneralCommandsRegistration; -import com.sk89q.worldedit.command.GenerationCommands; -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.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.SnapshotCommandsRegistration; -import com.sk89q.worldedit.command.SnapshotUtilCommands; -import com.sk89q.worldedit.command.SuperPickaxeCommands; //import com.sk89q.worldedit.command.SuperPickaxeCommandsRegistration; -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.WorldEditCommandsRegistration; import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.BooleanConverter; @@ -84,9 +58,7 @@ 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.tool.brush.Brush; import com.sk89q.worldedit.command.util.CommandPermissions; -import com.sk89q.worldedit.command.util.CommandQueued; import com.sk89q.worldedit.command.util.CommandQueuedCondition; import com.sk89q.worldedit.command.util.PermissionCondition; import com.sk89q.worldedit.command.util.SubCommandPermissionCondition; @@ -94,15 +66,17 @@ 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.extension.platform.binding.AnnotatedBindings; +import com.sk89q.worldedit.extension.platform.binding.CommandBindings; +import com.sk89q.worldedit.extension.platform.binding.ConsumeBindings; +import com.sk89q.worldedit.extension.platform.binding.ProvideBindings; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.command.CommandArgParser; import com.sk89q.worldedit.internal.command.CommandLoggingHandler; import com.sk89q.worldedit.internal.command.CommandRegistrationHandler; import com.sk89q.worldedit.internal.command.exception.ExceptionConverter; import com.sk89q.worldedit.internal.command.exception.WorldEditExceptionConverter; import com.sk89q.worldedit.internal.util.Substring; -import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.scripting.CommandScriptLoader; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.auth.AuthorizationException; @@ -152,7 +126,6 @@ import org.enginehub.piston.part.SubCommandPart; import org.enginehub.piston.suggestion.Suggestion; import org.enginehub.piston.util.HelpGenerator; import org.enginehub.piston.util.ValueProvider; -import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -246,32 +219,16 @@ public final class PlatformCommandManager { } private void registerAlwaysInjectedValues() { - globalInjectedValues.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."); - } - }); - }); - globalInjectedValues.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; - }); - }); globalInjectedValues.injectValue(Key.of(InjectedValueAccess.class), context -> Optional.of(context)); + register(new AnnotatedBindings(worldEdit)); + register(new CommandBindings(worldEdit)); + register(new ConsumeBindings(worldEdit)); + register(new ProvideBindings(worldEdit)); + register(new ProvideBindings(worldEdit)); + } + + public void register(Object classWithMethods) { + // TODO NOT IMPLEMENTED - register the following using a custom processor / annotations } private void registerSubCommands(String name, List aliases, String desc, @@ -306,7 +263,7 @@ public final class PlatformCommandManager { }); } - private void registerAllCommands() { + public void registerAllCommands() { if (Settings.IMP.ENABLED_COMPONENTS.COMMANDS) { // TODO NOT IMPLEMENTED dunno why these have issues generating // registerSubCommands( diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/AnnotatedBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/AnnotatedBindings.java new file mode 100644 index 000000000..54cdbef74 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/AnnotatedBindings.java @@ -0,0 +1,49 @@ +package com.sk89q.worldedit.extension.platform.binding; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.internal.annotation.Validate; + +import java.lang.annotation.Annotation; + +public class AnnotatedBindings extends Bindings { + + private final WorldEdit worldEdit; + + public AnnotatedBindings(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + + @Validate() + public String getText(String argument, Validate modifier) { + return validate(argument, modifier); + } + + /** + * Validate a string value using relevant modifiers. + * + * @param string the string + * @param modifiers the list of modifiers to scan + * @throws InputParseException on a validation error + */ + private static String validate(String string, Annotation... modifiers) + { + if (string != null) { + for (Annotation modifier : modifiers) { + if (modifier instanceof Validate) { + Validate validate = (Validate) modifier; + + if (!validate.value().isEmpty()) { + if (!string.matches(validate.value())) { + throw new InputParseException( + String.format( + "The given text doesn't match the right format (technically speaking, the 'format' is %s)", + validate.value())); + } + } + } + } + } + return string; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java new file mode 100644 index 000000000..14a4dce71 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java @@ -0,0 +1,4 @@ +package com.sk89q.worldedit.extension.platform.binding; + +public class Bindings { +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/CommandBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/CommandBindings.java new file mode 100644 index 000000000..351d7754b --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/CommandBindings.java @@ -0,0 +1,11 @@ +package com.sk89q.worldedit.extension.platform.binding; + +import com.sk89q.worldedit.WorldEdit; + +public class CommandBindings extends Bindings { + private final WorldEdit worldEdit; + + public CommandBindings(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/ConsumeBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/ConsumeBindings.java new file mode 100644 index 000000000..57d034bca --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/ConsumeBindings.java @@ -0,0 +1,13 @@ +package com.sk89q.worldedit.extension.platform.binding; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.internal.annotation.Validate; + +public class ConsumeBindings extends Bindings { + private final WorldEdit worldEdit; + + public ConsumeBindings(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/PrimitiveBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/PrimitiveBindings.java new file mode 100644 index 000000000..1061ed155 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/PrimitiveBindings.java @@ -0,0 +1,394 @@ +package com.sk89q.worldedit.extension.platform.binding; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.object.extent.NullExtent; +import com.boydti.fawe.object.extent.ResettableExtent; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extension.factory.DefaultTransformParser; +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.internal.annotation.Range; +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.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.Vector2; +import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.world.World; + +import javax.annotation.Nullable; +import java.lang.annotation.Annotation; +import java.util.Locale; + +public class PrimitiveBindings extends Bindings { + + /* + Parsers + */ + public Expression getExpression(String argument) throws ExpressionException { + try { + return new Expression(Double.parseDouble(argument)); + } catch (NumberFormatException e1) { + try { + Expression expression = Expression.compile(argument); + expression.optimize(); + return expression; + } catch (EvaluationException e) { + throw new InputParseException(String.format( + "Expected '%s' to be a valid number (or a valid mathematical expression)", argument)); + } catch (ExpressionException e) { + throw new InputParseException(String.format( + "Expected '%s' to be a number or valid math expression (error: %s)", argument, e.getMessage())); + } + } + } + + /** + * Gets an {@link com.sk89q.worldedit.extent.Extent} from a {@link ArgumentStack}. + * + * @param context the context + * @return an extent + * @throws InputParseException on other error + */ + public ResettableExtent getResettableExtent(Actor actor, String argument) throws InputParseException { + if (argument.equalsIgnoreCase("#null")) { + return new NullExtent(); + } + DefaultTransformParser parser = Fawe.get().getTransformParser(); + ParserContext parserContext = new ParserContext(); + if (actor instanceof Entity) { + Extent extent = ((Entity) actor).getExtent(); + if (extent instanceof World) { + parserContext.setWorld((World) extent); + } + } + parserContext.setSession(WorldEdit.getInstance().getSessionManager().get(actor)); + return parser.parseFromInput(argument, parserContext); + } + + /** + * Gets a type from a {@link ArgumentStack}. + * + * @param context the context + * @return the requested type + * @throws InputParseException on error + */ + public Boolean getBoolean(String argument) { + switch (argument.toLowerCase(Locale.ROOT)) { + case "": + return null; + case "true": + case "yes": + case "on": + case "y": + case "1": + case "t": + return true; + case "false": + case "no": + case "off": + case "f": + case "n": + case "0": + return false; + default: + throw new InputParseException("Invalid boolean " + argument); + } + } + + /** + * Gets a type from a {@link ArgumentStack}. + * + * @param context the context + * @return the requested type + * @throws InputParseException on error + */ + public Vector3 getVector3(String argument) { + String radiusString = argument; + String[] radii = radiusString.split(","); + final double radiusX, radiusY, radiusZ; + switch (radii.length) { + case 1: + radiusX = radiusY = radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + break; + + case 3: + radiusX = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + radiusY = Math.max(1, PrimitiveBindings.parseNumericInput(radii[1])); + radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[2])); + break; + + default: + throw new InputParseException("You must either specify 1 or 3 radius values."); + } + return Vector3.at(radiusX, radiusY, radiusZ); + } + + + /** + * Gets a type from a {@link ArgumentStack}. + * + * @param context the context + * @return the requested type + * @throws InputParseException on error + */ + public Vector2 getVector2(String argument) { + String radiusString = argument; + String[] radii = radiusString.split(","); + final double radiusX, radiusZ; + switch (radii.length) { + case 1: + radiusX = radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + break; + + case 2: + radiusX = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[1])); + break; + + default: + throw new InputParseException("You must either specify 1 or 2 radius values."); + } + return Vector2.at(radiusX, radiusZ); + } + + /** + * Gets a type from a {@link ArgumentStack}. + * + * @param context the context + * @return the requested type + * @throws InputParseException on error + */ + public BlockVector3 getBlockVector3(String argument) { + String radiusString = argument; + String[] radii = radiusString.split(","); + final double radiusX, radiusY, radiusZ; + switch (radii.length) { + case 1: + radiusX = radiusY = radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + break; + + case 3: + radiusX = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + radiusY = Math.max(1, PrimitiveBindings.parseNumericInput(radii[1])); + radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[2])); + break; + + default: + throw new InputParseException("You must either specify 1 or 3 radius values."); + } + return BlockVector3.at(radiusX, radiusY, radiusZ); + } + + + /** + * Gets a type from a {@link ArgumentStack}. + * + * @param context the context + * @return the requested type + * @throws InputParseException on error + */ + public BlockVector2 getBlockVector2(String argument) { + String radiusString = argument; + String[] radii = radiusString.split(","); + final double radiusX, radiusZ; + switch (radii.length) { + case 1: + radiusX = radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + break; + + case 2: + radiusX = Math.max(1, PrimitiveBindings.parseNumericInput(radii[0])); + radiusZ = Math.max(1, PrimitiveBindings.parseNumericInput(radii[1])); + break; + + default: + throw new InputParseException("You must either specify 1 or 2 radius values."); + } + return BlockVector2.at(radiusX, radiusZ); + } + + /* + + */ + + public Long getLong(String argument, Annotation... modifiers) { + try { + Long v = Long.parseLong(argument); + validate(v, modifiers); + return v; + + } catch (NumberFormatException ignore) { + return null; + } + } + + private static void validate(long number, Annotation... modifiers) { + for (Annotation modifier : modifiers) { + if (modifier instanceof Range) { + Range range = (Range) modifier; + if (number < range.min()) { + throw new InputParseException( + 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 InputParseException( + String.format( + "A valid value is less than or equal to %s " + + "(you entered %s)", range.max(), number)); + } + } + } + } + + /** + * Try to parse numeric input as either a number or a mathematical expression. + * + * @param input input + * @return a number + * @throws InputParseException thrown on parse error + */ + public static + @Nullable + Double parseNumericInput(@Nullable String input) { + 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 InputParseException(String.format( + "Expected '%s' to be a valid number (or a valid mathematical expression)", input)); + } catch (ExpressionException e) { + throw new InputParseException(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 InputParseException on error + */ + public Integer getInteger(String argument, Annotation[] modifiers) { + Double v = parseNumericInput(argument); + 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 InputParseException on error + */ + public Short getShort(String argument, Annotation[] modifiers) { + Integer v = getInteger(argument, 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 InputParseException on error + */ + public Double getDouble(String argument, Annotation[] modifiers) { + Double v = parseNumericInput(argument); + 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 InputParseException on error + */ + public Float getFloat(String argument, Annotation[] modifiers) { + Double v = getDouble(argument, 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 InputParseException on a validation error + */ + private static void validate(double number, Annotation[] modifiers) + { + for (Annotation modifier : modifiers) { + if (modifier instanceof Range) { + Range range = (Range) modifier; + if (number < range.min()) { + throw new InputParseException( + 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 InputParseException( + 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 InputParseException on a validation error + */ + private static void validate(int number, Annotation[] modifiers) + { + for (Annotation modifier : modifiers) { + if (modifier instanceof Range) { + Range range = (Range) modifier; + if (number < range.min()) { + throw new InputParseException( + 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 InputParseException( + String.format( + "A valid value is less than or equal to %s (you entered %s)", range.max(), number)); + } + } + } + } +} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/ProvideBindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/ProvideBindings.java new file mode 100644 index 000000000..2a1412cce --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/ProvideBindings.java @@ -0,0 +1,231 @@ +package com.sk89q.worldedit.extension.platform.binding; + +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.TextureUtil; +import com.boydti.fawe.util.image.ImageUtil; +import com.sk89q.worldedit.EditSession; +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.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.extension.platform.Capability; +import com.sk89q.worldedit.extent.Extent; +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.session.request.Request; +import com.sk89q.worldedit.util.TreeGenerator; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.biome.BiomeTypes; +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.block.BlockType; +import com.sk89q.worldedit.world.registry.BiomeRegistry; +import org.enginehub.piston.inject.InjectedValueAccess; +import org.enginehub.piston.inject.InjectedValueStore; +import org.enginehub.piston.inject.Key; +import org.enginehub.piston.util.ValueProvider; + +import java.awt.image.BufferedImage; +import java.lang.annotation.Annotation; +import java.net.URI; +import java.util.Collection; +import java.util.Optional; + +public class ProvideBindings extends Bindings { + private final WorldEdit worldEdit; + + public ProvideBindings(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + + /* + Provided + */ + + public Player getPlayer(Actor actor) { + if (actor.isPlayer()) { + return (Player) actor; + } + throw new InputParseException("This command must be used with a player."); + } + + public LocalSession getLocalSession(Player player) { + return worldEdit.getSessionManager().get(player); + } + + public EditSession editSession(LocalSession localSession, Player player) { + EditSession editSession = localSession.createEditSession(player); + editSession.enableStandardMode(); + return editSession; + } + + @Selection + public Region selection(LocalSession localSession, Player player) { + return localSession.getSelection(player.getWorld()); + } + + public TextureUtil getTexture(LocalSession session) { + return session.getTextureUtil(); + } + + public class ImageUri { + public final URI uri; + private BufferedImage image; + + ImageUri(URI uri) { + this.uri = uri; + } + + public BufferedImage load() { + if (image != null) { + return image; + } + return image = ImageUtil.load(uri); + } + } + + public Extent getExtent(Actor actor, InjectedValueAccess access, InjectedValueStore store) { + Optional editSessionOpt = access.injectedValue(Key.of(EditSession.class)); + if (editSessionOpt.isPresent()) { + return editSessionOpt.get(); + } + Extent extent = Request.request().getExtent(); + if (extent != null) { + return extent; + } + LocalSession session = WorldEdit.getInstance().getSessionManager().get(actor); + Player plr = getPlayer(actor); + EditSession editSession = editSession(getLocalSession(plr), plr); + store.injectValue(Key.of(EditSession.class), ValueProvider.constant(editSession)); + return editSession; + } + + /** + * Gets an {@link com.boydti.fawe.object.FawePlayer} from a {@link ArgumentStack}. + * + * @param context the context + * @return a FawePlayer + * @throws ParameterException on other error + */ + public FawePlayer getFawePlayer(Actor actor) throws InputParseException { + return FawePlayer.wrap(actor); + } + + /* + Parsed + */ + public ImageUri getImage(String argument) { + return new ImageUri(ImageUtil.getImageURI(argument)); + } + + public BlockType blockType(Actor actor, String argument) { + return blockState(actor, argument).getBlockType(); + } + + public BlockStateHolder blockStateHolder(Actor actor, String argument) { + return blockState(actor, argument); + } + + public BlockState blockState(Actor actor, String argument) { + return baseBlock(actor, argument).toBlockState(); + } + + public BaseBlock baseBlock(Actor actor, String argument) { + 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 worldEdit.getBlockFactory().parseFromInput(argument, parserContext); + } catch (NoMatchException e) { + throw new InputParseException(e.getMessage()); + } + } + + /** + * 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 + */ + @Direction + public BlockVector3 getDirection(Player player, Direction direction, String argument) throws UnknownDirectionException { + if (direction.includeDiagonals()) { + return worldEdit.getDiagonalDirection(player, argument); + } else { + return worldEdit.getDirection(player, argument); + } + } + + /** + * Gets an {@link TreeType} from a {@link ArgumentStack}. + * + * @param context the context + * @return a pattern + * @throws ParameterException on error + * @throws WorldEditException on error + */ + public TreeGenerator.TreeType getTreeType(String argument) throws WorldEditException { + if (argument != null) { + TreeGenerator.TreeType type = TreeGenerator.lookup(argument); + if (type != null) { + return type; + } else { + throw new InputParseException( + String.format("Can't recognize tree type '%s' -- choose from: %s", argument, + TreeGenerator.TreeType.getPrimaryAliases())); + } + } else { + return TreeGenerator.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 + */ + public BiomeType getBiomeType(String argument) throws WorldEditException { + if (argument != null) { + + if (MathMan.isInteger(argument)) return BiomeTypes.getLegacy(Integer.parseInt(argument)); + BiomeRegistry biomeRegistry = WorldEdit.getInstance().getPlatformManager() + .queryCapability(Capability.GAME_HOOKS).getRegistries().getBiomeRegistry(); + Collection knownBiomes = BiomeType.REGISTRY.values(); + BiomeType biome = Biomes.findBiomeByName(knownBiomes, argument, biomeRegistry); + if (biome != null) { + return biome; + } else { + throw new InputParseException( + String.format("Can't recognize biome type '%s' -- use /biomelist to list available types", argument)); + } + } else { + throw new InputParseException( + "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/internal/annotation/Direction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Direction.java index bd2b55b4f..cc3c72dba 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 @@ -31,7 +31,7 @@ import java.lang.annotation.Target; * Annotates a {@link BlockVector3} parameter to inject a direction. */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) +@Target({ElementType.PARAMETER, ElementType.METHOD}) @InjectAnnotation public @interface Direction { 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 1886f43f7..0099e1f43 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 @@ -30,7 +30,7 @@ import java.lang.annotation.Target; * Indicates that this value should come from the current selection. */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) +@Target({ElementType.PARAMETER, ElementType.METHOD}) @InjectAnnotation public @interface Selection { } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Validate.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Validate.java index e47282deb..fa1e43039 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Validate.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/annotation/Validate.java @@ -31,7 +31,7 @@ import java.util.regex.Pattern; * @see PrimitiveBindings where this validation is used */ @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.PARAMETER) +@Target({ElementType.PARAMETER, ElementType.METHOD}) public @interface Validate { /** @@ -40,6 +40,6 @@ public @interface Validate { * @see Pattern regular expression class * @return the pattern */ - String regex() default ""; + String value() default ""; } 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 2656039ce..000000000 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/command/WorldEditBinding.java +++ /dev/null @@ -1,379 +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.boydti.fawe.util.MathMan; - -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.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.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.BiomeTypes; -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.block.BlockType; -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 { - - 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 - * @return a selection - * @throws IncompleteRegionException if no selection is available - * @throws ParameterException on other error - */ - @BindingMatch( - type = Region.class, - behavior = BindingBehavior.PROVIDES) - public Object getSelection(ArgumentStack context) 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 = BlockStateHolder.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BlockStateHolder getBlockStateHolder(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); - } - } - - @BindingMatch(type = BlockState.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BlockState getBlockState(ArgumentStack context) throws ParameterException, WorldEditException { - BlockStateHolder result = getBlockStateHolder(context); - return result instanceof BlockState ? (BlockState) result : result.toImmutableState(); - } - - @BindingMatch(type = {BaseBlock.class, BlockState.class, BlockStateHolder.class}, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BaseBlock getBaseBlock(ArgumentStack context) throws ParameterException, WorldEditException { - return getBlockState(context).toBaseBlock(); - } - - /** - * Gets an {@link BaseBlock} from a {@link ArgumentStack}. - * - * @param context the context - * @return a block type - * @throws ParameterException on error - * @throws WorldEditException on error - */ - @BindingMatch(type = BlockType.class, - behavior = BindingBehavior.CONSUMES, - consumedCount = 1) - public BlockType getBlockType(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).getBlockType(); - } 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) { - - if (MathMan.isInteger(input)) return BiomeTypes.get(Integer.parseInt(input)); - - 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/internal/util/DocumentationPrinter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/DocumentationPrinter.java index fcb8dfbee..7be6b4be3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/DocumentationPrinter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/util/DocumentationPrinter.java @@ -146,12 +146,6 @@ public final class DocumentationPrinter { stream.print(" || "); - if (cmd.flags() != null && !cmd.flags().isEmpty()) { - stream.print(cmd.flags()); - } - - stream.print(" || "); - if (cmd.desc() != null && !cmd.desc().isEmpty()) { stream.print(cmd.desc()); }