From 3303434d52ca01be5f80a5611d165654d5146838 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 29 Jul 2019 05:03:17 +1000 Subject: [PATCH 1/4] listchunks doesn't need to be a list Nor does it need to be a string. As long as we can iterate, it should be fine. This somewhat mitigates OOM from listchunks. --- .../worldedit/command/ChunkCommands.java | 3 +- .../formatting/component/PaginationBox.java | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java index 36d288eb4..4a170883c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ChunkCommands.java @@ -94,8 +94,7 @@ public class ChunkCommands { @ArgFlag(name = 'p', desc = "Page number.", def = "1") int page) throws WorldEditException { Set chunks = session.getSelection(player.getWorld()).getChunks(); - PaginationBox paginationBox = PaginationBox.fromStrings("Selected Chunks", "/listchunks -p %page%", - chunks.stream().map(BlockVector2::toString).collect(Collectors.toList())); + PaginationBox paginationBox = PaginationBox.fromStrings("Selected Chunks", "/listchunks -p %page%", chunks); player.print(paginationBox.create(page)); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java index 3f9b95267..6125643ed 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/formatting/component/PaginationBox.java @@ -26,6 +26,9 @@ import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; public abstract class PaginationBox extends MessageBox { @@ -128,21 +131,44 @@ public abstract class PaginationBox extends MessageBox { throw new IllegalStateException("Pagination components must be created with a page"); } + public static PaginationBox fromStrings(String header, @Nullable String pageCommand, Collection lines) { + return new ListPaginationBox(header, pageCommand, lines); + } + public static PaginationBox fromStrings(String header, @Nullable String pageCommand, List lines) { return new ListPaginationBox(header, pageCommand, lines); } private static class ListPaginationBox extends PaginationBox { - private final List lines; + private final Collection lines; + private int iterIndex; + private Iterator iterator; ListPaginationBox(String header, String pageCommand, List lines) { + this(header, pageCommand, (Collection) lines); + } + + ListPaginationBox(String header, String pageCommand, Collection lines) { super(header, pageCommand); this.lines = lines; } @Override public Component getComponent(int number) { - return TextComponent.of(lines.get(number)); + Object obj; + if (lines instanceof List) { + obj = ((List) lines).get(number); + } else { + if (iterator == null || iterIndex > number) { + iterator = lines.iterator(); + iterIndex = 0; + } + do { + obj = iterator.next(); + iterIndex++; + } while (iterIndex < number); + } + return TextComponent.of(obj.toString()); } @Override From da858f2131b17c5db43ff4243e6ac65848132e27 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 29 Jul 2019 05:07:46 +1000 Subject: [PATCH 2/4] Check isEmpty for sign color --- .../java/com/boydti/fawe/bukkit/wrapper/state/AsyncSign.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncSign.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncSign.java index 74b4927e4..3e7b72fd3 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncSign.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/state/AsyncSign.java @@ -80,7 +80,7 @@ public class AsyncSign extends AsyncBlockState implements Sign { CompoundTag nbt = getNbtData(); if (nbt != null) { String color = nbt.getString("Color").toUpperCase(); - return DyeColor.valueOf(color); + if (!color.isEmpty()) return DyeColor.valueOf(color); } return DyeColor.BLACK; } From 1c256c1f5a9df16a32327aee73500f49048c0188 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 29 Jul 2019 05:26:44 +1000 Subject: [PATCH 3/4] add Range annotation --- .../worldedit/command/GeneralCommands.java | 2 +- .../worldedit/command/GenerationCommands.java | 4 +- .../worldedit/command/HistoryCommands.java | 5 +- .../worldedit/command/RegionCommands.java | 7 +- .../worldedit/command/UtilityCommands.java | 71 +++++++++---------- 5 files changed, 44 insertions(+), 45 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java index a5cf25550..7f659eb52 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java @@ -324,7 +324,7 @@ public class GeneralCommands { checkRandomization = false; } else { if (argLower.equals("#copy") || argLower.equals("#clipboard")) { - Clipboard clipboard = worldEdit.getSessionManager().get(player).getClipboard().getClipboard(); + Clipboard clipboard = session.getClipboard().getClipboard(); util = TextureUtil.fromClipboard(clipboard); } else if (argLower.equals("*") || argLower.equals("true")) { util = Fawe.get().getTextureUtil(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 273a602f4..cd546794c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -20,9 +20,11 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.command.MethodCommands.getArguments; import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT; import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; +import static com.sk89q.worldedit.internal.command.CommandUtil.checkCommandArgument; import com.boydti.fawe.Fawe; import com.boydti.fawe.config.BBC; @@ -274,7 +276,7 @@ public class GenerationCommands { int size, @Arg(desc = "The type of forest", def = "tree") TreeType type, - @Arg(desc = "The density of the forest, between 0 and 100", def = "5") + @Range(min = 0, max = 100) @Arg(desc = "The density of the forest, between 0 and 100", def = "5") double density) throws WorldEditException { checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100"); density /= 100; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index 2942671a9..ef90d74a9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.command.MethodCommands.getArguments; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweAPI; @@ -219,7 +220,7 @@ public class HistoryCommands { ) @CommandPermissions({"worldedit.history.undo", "worldedit.history.undo.self"}) public void undo(Player player, LocalSession session, - @Arg(desc = "Number of undoes to perform", def = "1") + @Range(min = 1) @Arg(desc = "Number of undoes to perform", def = "1") int times, @Arg(name = "player", desc = "Undo this player's operations", def = "") String playerName, @@ -266,7 +267,7 @@ public class HistoryCommands { ) @CommandPermissions({"worldedit.history.redo", "worldedit.history.redo.self"}) public void redo(Player player, LocalSession session, - @Arg(desc = "Number of redoes to perform", def = "1") + @Range(min = 1) @Arg(desc = "Number of redoes to perform", def = "1") int times, @Arg(name = "player", desc = "Redo this player's operations", def = "") String playerName) throws WorldEditException { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index ff8badd69..f9627ca03 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -20,6 +20,7 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; +import static com.sk89q.worldedit.command.MethodCommands.getArguments; import static com.sk89q.worldedit.command.util.Logging.LogMode.ALL; import static com.sk89q.worldedit.command.util.Logging.LogMode.ORIENTATION_REGION; import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION; @@ -216,7 +217,7 @@ public class RegionCommands { @Selection Region region, @Arg(desc = "The pattern of blocks to place") Pattern pattern, - @Arg(desc = "The thickness of the line", def = "0") + @Range(min = 1) @Arg(desc = "The thickness of the line", def = "0") int thickness, @Switch(name = 'h', desc = "Generate only a shell") boolean shell) throws WorldEditException { @@ -546,7 +547,7 @@ public class RegionCommands { boolean skipEntities, @Switch(name = 'a', desc = "Ignore air blocks") boolean ignoreAirBlocks, - @Switch(name = 'm', desc = "TODO") + @Switch(name = 'm', desc = "Source mask") Mask sourceMask, InjectedValueAccess context) throws WorldEditException { player.checkConfirmationStack(() -> { @@ -672,7 +673,7 @@ public class RegionCommands { @Logging(REGION) public void hollow(FawePlayer player, EditSession editSession, @Selection Region region, - @Arg(desc = "Thickness of the shell to leave", def = "0") + @Range(min = 0) @Arg(desc = "Thickness of the shell to leave", def = "0") int thickness, @Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air") Pattern pattern, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 53dcfd15a..33126194a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -91,13 +91,13 @@ import java.util.UUID; import java.util.function.Consumer; import java.util.function.Supplier; import javax.imageio.ImageIO; -import org.checkerframework.checker.nullness.qual.NonNull; + import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.Switch; -import org.enginehub.piston.inject.InjectedValueAccess; +import org.jetbrains.annotations.NotNull; /** * Utility commands. @@ -190,9 +190,9 @@ public class UtilityCommands { public int fill(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The blocks to fill with") Pattern pattern, - @Arg(desc = "The radius to fill in") + @Range(min=1) @Arg(desc = "The radius to fill in") double radius, - @Arg(desc = "The depth to fill", def = "1") + @Range(min=1) @Arg(desc = "The depth to fill", def = "1") int depth, @Arg(desc = "Direction to fill", def = "down") BlockVector3 direction) throws WorldEditException { radius = Math.max(1, radius); @@ -285,7 +285,7 @@ public class UtilityCommands { public int fillr(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The blocks to fill with") Pattern pattern, - @Arg(desc = "The radius to fill in") + @Range(min=1) @Arg(desc = "The radius to fill in") double radius, @Arg(desc = "The depth to fill", def = "") Integer depth) throws WorldEditException { @@ -307,7 +307,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.drain") @Logging(PLACEMENT) public int drain(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius to drain") + @Range(min=0) @Arg(desc = "The radius to drain") double radius, @Switch(name = 'w', desc = "Also un-waterlog blocks") boolean waterlogged) throws WorldEditException { @@ -327,7 +327,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.fixlava") @Logging(PLACEMENT) public int fixLava(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius to fix in") + @Range(min=0) @Arg(desc = "The radius to fix in") double radius) throws WorldEditException { radius = Math.max(0, radius); we.checkMaxRadius(radius); @@ -344,7 +344,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.fixwater") @Logging(PLACEMENT) public int fixWater(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius to fix in") + @Range(min=0) @Arg(desc = "The radius to fix in") double radius) throws WorldEditException { radius = Math.max(0, radius); we.checkMaxRadius(radius); @@ -361,7 +361,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.removeabove") @Logging(PLACEMENT) public int removeAbove(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The apothem of the square to remove from", def = "1") + @Range(min=1) @Arg(desc = "The apothem of the square to remove from", def = "1") int size, @Arg(desc = "The maximum height above you to remove from", def = "") Integer height) throws WorldEditException { @@ -406,7 +406,7 @@ public class UtilityCommands { public int removeNear(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The mask of blocks to remove") Mask mask, - @Arg(desc = "The radius of the square to remove from", def = "50") + @Range(min=1) @Arg(desc = "The radius of the square to remove from", def = "50") int radius) throws WorldEditException { radius = Math.max(1, radius); we.checkMaxRadius(radius); @@ -424,7 +424,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.replacenear") @Logging(PLACEMENT) public int replaceNear(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius of the square to remove in") + @Range(min=1) @Arg(desc = "The radius of the square to remove in") int radius, @Arg(desc = "The mask matching blocks to remove", def = "") Mask from, @@ -455,7 +455,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.snow") @Logging(PLACEMENT) public int snow(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius of the circle to snow in", def = "10") + @Range(min=1) @Arg(desc = "The radius of the circle to snow in", def = "10") double size) throws WorldEditException { size = Math.max(1, size); we.checkMaxRadius(size); @@ -473,7 +473,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.thaw") @Logging(PLACEMENT) public int thaw(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius of the circle to thaw in", def = "10") + @Range(min=1) @Arg(desc = "The radius of the circle to thaw in", def = "10") double size) throws WorldEditException { size = Math.max(1, size); we.checkMaxRadius(size); @@ -491,7 +491,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.green") @Logging(PLACEMENT) public int green(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius of the circle to convert in", def = "10") + @Range(min=1) @Arg(desc = "The radius of the circle to convert in", def = "10") double size, @Switch(name = 'f', desc = "Also convert coarse dirt") boolean convertCoarse) throws WorldEditException { @@ -512,7 +512,7 @@ public class UtilityCommands { @CommandPermissions("worldedit.extinguish") @Logging(PLACEMENT) public void extinguish(Player player, LocalSession session, EditSession editSession, - @Arg(desc = "The radius of the square to remove in", def = "") + @Range(min=1) @Arg(desc = "The radius of the square to remove in", def = "") Integer radius) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); @@ -595,7 +595,7 @@ public class UtilityCommands { public int remove(Actor actor, @Arg(desc = "The type of entity to remove") EntityRemover remover, - @Arg(desc = "The radius of the cuboid to remove from") + @Range(min=-1) @Arg(desc = "The radius of the cuboid to remove from") int radius) throws WorldEditException { Player player = actor instanceof Player ? (Player) actor : null; @@ -707,8 +707,8 @@ public class UtilityCommands { PrintCommandHelp.help(command, page, listSubCommands, we, actor); } - public static void list(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) { - list(dir, actor, args, page, -1, formatName, playerFolder, new RunnableVal3() { + public static void list(File dir, Actor actor, List args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) { + list(dir, actor, args, page, -1, formatName, playerFolder, false, false, new RunnableVal3() { @Override public void run(Builder m, URI uri, String fileName) { m.append(BBC.SCHEMATIC_LIST_ELEM.format(fileName, "")); @@ -719,7 +719,7 @@ public class UtilityCommands { }); } - public static void list(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, RunnableVal3 eachMsg) { + public static void list(File dir, Actor actor, List args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, boolean oldFirst, boolean newFirst, RunnableVal3 eachMsg) { List fileList = new ArrayList<>(); if (perPage == -1) perPage = actor instanceof Player ? 12 : 20; // More pages for console page = getFiles(dir, actor, args, page, perPage, formatName, playerFolder, fileList::add); @@ -739,7 +739,7 @@ public class UtilityCommands { return; } - final int sortType = 0; //args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0; + final int sortType = oldFirst ? -1 : newFirst ? 1 : 0; // cleanup file list fileList.sort((f1, f2) -> { boolean dir1 = f1.isDirectory(); @@ -766,12 +766,12 @@ public class UtilityCommands { int limit = Math.min(offset + perPage, fileList.size()); - String fullArgs = (String) args.getLocals().get("arguments"); - String baseCmd = null; - if (fullArgs != null) { - baseCmd = fullArgs.endsWith(" " + page) ? fullArgs.substring(0, fullArgs.length() - (" " + page).length()) : fullArgs; - } - @NonNull Builder m = TextComponent.builder(BBC.SCHEMATIC_LIST.format(page, pageCount)); +// String fullArgs = (String) args.getLocals().get("arguments"); +// String baseCmd = null; +// if (fullArgs != null) { +// baseCmd = fullArgs.endsWith(" " + page) ? fullArgs.substring(0, fullArgs.length() - (" " + page).length()) : fullArgs; +// } + @NotNull Builder m = TextComponent.builder(BBC.SCHEMATIC_LIST.format(page, pageCount)); UUID uuid = playerFolder ? actor.getUniqueId() : null; for (int i = offset; i < limit; i++) { @@ -779,22 +779,17 @@ public class UtilityCommands { File file = fileList.get(i); eachMsg.run(m, file.toURI(), getPath(dir, file, uuid)); } - if (baseCmd != null) { - //TODO m.newline().paginate(baseCmd, page, pageCount); - } +// if (baseCmd != null) { +// //TODO m.newline().paginate(baseCmd, page, pageCount); +// } actor.print(m.build()); } - public static int getFiles(File root, Actor actor, InjectedValueAccess args, int page, int perPage, String formatName, boolean playerFolder, Consumer forEachFile, ListFilters... filters) { - // TODO NOT IMPLEMENTED replace getFiles - return page; - } - - public static int getFiles(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, Consumer forEachFile) { + public static int getFiles(File dir, Actor actor, List args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, Consumer forEachFile) { Consumer rootFunction = forEachFile; //schem list all - int len = args.argsLength(); + int len = args.size(); List filters = new ArrayList<>(); String dirFilter = File.separator; @@ -803,8 +798,8 @@ public class UtilityCommands { boolean listGlobal = !Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS; if (len > 0) { int max = len; - if (MathMan.isInteger(args.getString(len - 1))) { - page = args.getInteger(--len); + if (MathMan.isInteger(args.get(len - 1))) { + page = Integer.parseInt(args.get(--len)); } for (int i = 0; i < len; i++) { String arg = ""; From 02d5f3e8d582c4ffb740e0798f22bcf993c0e3f0 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 29 Jul 2019 05:27:50 +1000 Subject: [PATCH 4/4] Update PlatformManager.java --- .../com/sk89q/worldedit/extension/platform/PlatformManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 04cea7ece..b438f4ba3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -333,7 +333,7 @@ public class PlatformManager { case HIT: { // superpickaxe is special because its primary interaction is a left click, not a right click // in addition, it is implicitly bound to all pickaxe items, not just a single tool item - if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) { + if (session.hasSuperPickAxe()) { final BlockTool superPickaxe = session.getSuperPickaxe(); if (superPickaxe != null && superPickaxe.canUse(player) && player.isHoldingPickAxe()) { FawePlayer fp = FawePlayer.wrap(player);