From 905fbf5a0b5af8cc51bc671bfc5676c13687fca5 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Thu, 18 Jul 2019 02:31:13 +1000 Subject: [PATCH] 8108d0a9 --- .../fawe/object/brush/InspectBrush.java | 2 +- .../object/changeset/DiskStorageHistory.java | 6 +- .../regions/selector/FuzzyRegionSelector.java | 5 + .../selector/PolyhedralRegionSelector.java | 4 + .../java/com/boydti/fawe/util/MainUtil.java | 1 - .../java/com/sk89q/worldedit/EditSession.java | 62 ++-- .../com/sk89q/worldedit/LocalSession.java | 37 ++- .../worldedit/command/BrushCommands.java | 8 +- .../command/BrushOptionsCommands.java | 2 +- .../worldedit/command/HistoryCommands.java | 30 +- .../worldedit/command/NavigationCommands.java | 12 +- .../worldedit/command/RegionCommands.java | 9 +- .../worldedit/command/SchematicCommands.java | 21 +- .../worldedit/command/SelectionCommands.java | 15 +- .../worldedit/command/SnapshotCommands.java | 1 + .../command/SnapshotUtilCommands.java | 4 +- .../sk89q/worldedit/command/ToolCommands.java | 25 +- .../worldedit/command/ToolUtilCommands.java | 11 +- .../worldedit/command/UtilityCommands.java | 46 ++- .../worldedit/command/WorldEditCommands.java | 1 + .../worldedit/command/tool/BrushTool.java | 73 +++-- .../worldedit/command/tool/DistanceWand.java | 2 +- .../command/tool/LongRangeBuildTool.java | 7 +- .../command/tool/RecursivePickaxe.java | 33 -- .../command/tool/brush/ClipboardBrush.java | 2 +- .../extension/factory/MaskFactory.java | 28 +- .../extension/factory/PatternFactory.java | 13 +- .../factory/parser/DefaultBlockParser.java | 288 +++++++----------- .../platform/AbstractPlayerActor.java | 6 +- .../extension/platform/PlatformManager.java | 113 +++---- .../worldedit/regions/RegionSelector.java | 9 + .../ConvexPolyhedralRegionSelector.java | 4 + .../selector/CuboidRegionSelector.java | 5 + .../world/block/FuzzyBlockState.java | 6 +- 34 files changed, 402 insertions(+), 489 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java index 785ab43af..7e7c96c24 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/InspectBrush.java @@ -50,7 +50,7 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool { public Vector3 getTarget(Player player, boolean adjacent) { Location target = null; - int range = this.range > -1 ? getRange() : MAX_RANGE; + int range = this.range > -1 ? getRange() : DEFAULT_RANGE; if (adjacent) { Location face = player.getBlockTraceFace(range, true); return face.add(face.getDirection()); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java index e09546f04..46cd651da 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java @@ -503,7 +503,11 @@ public class DiskStorageHistory extends FaweStreamChangeSet { } public int getSize() { - return Arrays.stream(blocks).sum(); + int count = 0; + for (int block : blocks) { + count += block; + } + return count; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java index 3478d6129..561b106a5 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java @@ -154,4 +154,9 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio return lines; } + @Override + public List getVerticies() { + return positions; + } + } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/PolyhedralRegionSelector.java b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/PolyhedralRegionSelector.java index 29094ed38..c028caa26 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/PolyhedralRegionSelector.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/PolyhedralRegionSelector.java @@ -229,4 +229,8 @@ public class PolyhedralRegionSelector implements RegionSelector, CUIRegion { } } + @Override + public List getVerticies() { + return new ArrayList<>(region.getVertices()); + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/MainUtil.java b/worldedit-core/src/main/java/com/boydti/fawe/util/MainUtil.java index 6bf1fdd8f..ede7f89be 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/MainUtil.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/MainUtil.java @@ -861,5 +861,4 @@ public class MainUtil { e.printStackTrace(); } } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 1c90a82ff..b9a4c30b9 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -2317,6 +2317,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusZ = (int) Math.ceil(radiusZ); + double xSqr, zSqr; double distanceSq; double nextXn = 0; @@ -2331,12 +2332,14 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, nextMinXn = (x + 1) * minInvRadiusX; double nextZn = 0; double nextMinZn = 0; + xSqr = xn * xn; forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { final double zn = nextZn; double dz2 = nextMinZn * nextMinZn; nextZn = (z + 1) * invRadiusZ; nextMinZn = (z + 1) * minInvRadiusZ; - distanceSq = lengthSq(xn, zn); + zSqr = zn * zn; + distanceSq = xSqr + zSqr; if (distanceSq > 1) { if (z == 0) { break forX; @@ -2360,13 +2363,13 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, forX: for (int x = 0; x <= ceilRadiusX; ++x) { final double xn = nextXn; nextXn = (x + 1) * invRadiusX; - double dx = xn * xn; double nextZn = 0; + xSqr = xn * xn; forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { final double zn = nextZn; nextZn = (z + 1) * invRadiusZ; - double dz = zn * zn; - distanceSq = lengthSq(xn,zn); + zSqr = zn * zn; + distanceSq = xSqr + zSqr; if (distanceSq > 1) { if (z == 0) { break forX; @@ -2375,7 +2378,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } if (!filled) { - if ((dz + nextXn * nextXn <= 1) && (nextZn * nextZn + dx <= 1)) { + if ((zSqr + nextXn * nextXn <= 1) && (nextZn * nextZn + xSqr <= 1)) { continue; } } @@ -2528,18 +2531,20 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, double nextXn = invRadiusX; forX: for (int x = 0; x <= ceilRadiusX; ++x) { final double xn = nextXn; + double dx = xn * xn; nextXn = (x + 1) * invRadiusX; double nextZn = invRadiusZ; - double dx = xn * xn; forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { final double zn = nextZn; double dz = zn * zn; + double dxz = dx + dz; nextZn = (z + 1) * invRadiusZ; double nextYn = invRadiusY; forY: for (int y = 0; y <= ceilRadiusY; ++y) { final double yn = nextYn; - double dxyz = lengthSq(zn, yn, zn); + double dy = yn * yn; + double dxyz = dxz + dy; nextYn = (y + 1) * invRadiusY; if (dxyz > 1) { @@ -2553,8 +2558,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } if (!filled) { - double dy = yn * yn; - if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) { + if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1) { continue; } } @@ -2762,19 +2766,21 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, if (dx2 + dz2 > radiusSq) { continue; } - + loop: for (int y = maxY; y >= 1; --y) { - final BlockState block = getBlock(x, y, z); - - if (block.getBlockType() == BlockTypes.DIRT || - (!onlyNormalDirt && block.getBlockType() == BlockTypes.COARSE_DIRT)) { - this.setBlock(x, y, z, grass); - - break; - } else if (block.getBlockType() == BlockTypes.WATER || block.getBlockType() == BlockTypes.LAVA) { - break; - } else if (block.getBlockType().getMaterial().isMovementBlocker()) { - break; + final BlockType block = getBlockType(x, y, z); + switch (block.getInternalId()) { + case BlockID.COARSE_DIRT: + if (onlyNormalDirt) break loop; + case BlockID.DIRT: + this.setBlock(x, y, z, grass); + break loop; + case BlockID.WATER: + case BlockID.LAVA: + default: + if (block.getMaterial().isMovementBlocker()) { + break loop; + } } } } @@ -3302,11 +3308,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) { BlockVector3 tipv = interpol.getPosition(loop).toBlockPoint(); if (radius == 0) { - try { - pattern.apply(this, tipv, tipv); - } catch (WorldEditException e) { - e.printStackTrace(); - } + pattern.apply(this, tipv, tipv); } else { vset.add(tipv); } @@ -3485,14 +3487,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, Direction.DOWN.toBlockVector(), }; - private static double lengthSq(double x, double y, double z) { - return (x * x) + (y * y) + (z * z); - } - - private static double lengthSq(double x, double z) { - return (x * x) + (z * z); - } - @Override public String getName() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 633b60ee9..4f28e1483 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -932,18 +932,22 @@ public class LocalSession implements TextureHolder { * @return the tool, which may be {@code null} */ @Nullable + @Deprecated public Tool getTool(ItemType item) { return tools[item.getInternalId()]; } @Nullable public Tool getTool(Player player) { + if (!Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && !hasTool) { + return null; + } BaseItem item = player.getItemInHand(HandSide.MAIN_HAND); return getTool(item, player); } public Tool getTool(BaseItem item, Player player) { - if (item.getNativeItem() != null) { + if (Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && item.getNativeItem() != null) { BrushTool tool = BrushCache.getTool(player, this, item); if (tool != null) return tool; } @@ -955,12 +959,14 @@ public class LocalSession implements TextureHolder { * or the tool is not assigned, the slot will be replaced with the * brush tool. * + * @deprecated FAWE binds to the item, not the type - this allows brushes to persist * @param item the item type * @return the tool, or {@code null} * @throws InvalidToolBindException if the item can't be bound to that item */ + @Deprecated public BrushTool getBrushTool(ItemType item) throws InvalidToolBindException { - return getBrushTool(item, null, true); + return getBrushTool(item.getDefaultState(), null, true); } public BrushTool getBrushTool(Player player) throws InvalidToolBindException { @@ -968,19 +974,16 @@ public class LocalSession implements TextureHolder { } public BrushTool getBrushTool(Player player, boolean create) throws InvalidToolBindException { - ItemType item = player.getItemInHand(HandSide.MAIN_HAND).getType(); + BaseItem item = player.getItemInHand(HandSide.MAIN_HAND); return getBrushTool(item, player, create); } - public BrushTool getBrushTool(ItemType item, boolean create) throws InvalidToolBindException { - return getBrushTool(item, null, create); - } - public BrushTool getBrushTool(ItemType item, Player player, boolean create) throws InvalidToolBindException { - Tool tool = getTool(item.getDefaultState(), player); + public BrushTool getBrushTool(BaseItem item, Player player, boolean create) throws InvalidToolBindException { + Tool tool = getTool(item, player); if (!(tool instanceof BrushTool)) { if (create) { tool = new BrushTool(); - setTool(item.getDefaultState(), tool, player); + setTool(item, tool, player); } else { return null; } @@ -1022,7 +1025,7 @@ public class LocalSession implements TextureHolder { throw new InvalidToolBindException(type, "Already used for the navigation wand"); } Tool previous; - if (player != null && (tool instanceof BrushTool || tool == null) && item.getNativeItem() != null) { + if (player != null && (tool instanceof BrushTool || tool == null) && Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && item.getNativeItem() != null) { previous = BrushCache.getCachedTool(item); BrushCache.setTool(item, (BrushTool) tool); if (tool != null) { @@ -1330,13 +1333,15 @@ public class LocalSession implements TextureHolder { BlockBag blockBag = getBlockBag(player); - // Create an edit session - EditSession editSession = WorldEdit.getInstance().getEditSessionFactory() - .getEditSession(player.isPlayer() ? player.getWorld() : null, - getBlockChangeLimit(), blockBag, player); - Request.request().setEditSession(editSession); + World world = player.getWorld(); + boolean isPlayer = player.isPlayer(); + EditSessionBuilder builder = new EditSessionBuilder(world); + if (player.isPlayer()) builder.player(FawePlayer.wrap(player)); + builder.blockBag(blockBag); + builder.fastmode(fastMode); + + EditSession editSession = builder.build(); - editSession.setFastMode(fastMode); if (mask != null) { editSession.setMask(mask); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 39aeb1760..5f383103f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -1216,8 +1216,8 @@ public class BrushCommands { boolean ignoreAir, @Switch(name = 'o', desc = "Paste starting at the target location, instead of centering on it") boolean usingOrigin, - @Switch(name = 'e', desc = "Paste entities if available") - boolean pasteEntities, + @Switch(name = 'e', desc = "Skip paste entities if available") + boolean skipEntities, @Switch(name = 'b', desc = "Paste biomes if available") boolean pasteBiomes, @ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "") @@ -1231,7 +1231,7 @@ public class BrushCommands { worldEdit.checkMaxBrushRadius(size.getBlockX()); worldEdit.checkMaxBrushRadius(size.getBlockY()); worldEdit.checkMaxBrushRadius(size.getBlockZ()); - Brush brush = new ClipboardBrush(holder, ignoreAir, usingOrigin); + Brush brush = new ClipboardBrush(holder, ignoreAir, usingOrigin, !skipEntities, pasteBiomes, sourceMask); CommandLocals locals = context.getLocals(); BrushSettings bs = new BrushSettings(); @@ -1645,7 +1645,7 @@ public class BrushCommands { flags.or(CreatureButcher.Flags.TAGGED , killWithName, "worldedit.butcher.tagged"); flags.or(CreatureButcher.Flags.ARMOR_STAND , killArmorStands, "worldedit.butcher.armorstands"); - BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); + BrushTool tool = session.getBrushTool(player); tool.setSize(radius); ButcherBrush brush = new ButcherBrush(flags); tool.setBrush(brush, "worldedit.brush.butcher"); 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 8361b4c39..72fd6dd05 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 @@ -281,7 +281,7 @@ public class BrushOptionsCommands extends MethodCommands { parserContext.setSession(session); parserContext.setExtent(editSession); Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); - tool.setTargetMask(mask); + tool.setTraceMask(mask); BBC.BRUSH_TARGET_MASK_SET.send(player, context.getJoinedStrings(0)); } 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 41f5b475d..bb26d654c 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 @@ -225,25 +225,25 @@ public class HistoryCommands extends MethodCommands { BBC.COMMAND_UNDO_DISABLED.send(player); return; } + LocalSession undoSession; + if (context.argsLength() == 2) { + player.checkPermission("worldedit.history.undo.other"); + undoSession = worldEdit.getSessionManager().findByName(playerName); + if (undoSession == null) { + BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName); + return; + } + } else { + undoSession = session; + } times = Math.max(1, times); - LocalSession undoSession = session; int finalTimes = times; FawePlayer.wrap(player).checkConfirmation(() -> { - player.checkPermission("worldedit.history.undo.other"); EditSession undone = null; int i = 0; for (; i < finalTimes; ++i) { - if (context.argsLength() < 2) { - undone = undoSession.undo(undoSession.getBlockBag(player), player); - } else { - LocalSession sess = worldEdit.getSessionManager().findByName(playerName); - if (sess == null) { - BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName); - break; - } - undone = sess.undo(session.getBlockBag(player), player); - if (undone == null) break; - } + undone = undoSession.undo(undoSession.getBlockBag(player), player); + if (undone == null) break; } if (undone == null) i--; if (i > 0) { @@ -273,7 +273,7 @@ public class HistoryCommands extends MethodCommands { player.checkPermission("worldedit.history.redo.other"); redoSession = worldEdit.getSessionManager().findByName(playerName); if (redoSession == null) { - player.printError("Unable to find session for " + playerName); + BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName); return; } } @@ -288,7 +288,7 @@ public class HistoryCommands extends MethodCommands { } } if (timesRedone > 0) { - player.print("Redid " + timesRedone + " available edits."); + BBC.COMMAND_REDO_SUCCESS.send(player, timesRedone == 1 ? "" : " x" + timesRedone); } else { BBC.COMMAND_REDO_ERROR.send(player); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java index 8f36b0114..c1b52da1b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/NavigationCommands.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.command; import static com.google.common.base.Preconditions.checkNotNull; import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; +import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.WorldEdit; @@ -31,6 +32,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.param.Arg; @@ -39,6 +41,7 @@ import org.enginehub.piston.annotation.param.Switch; /** * Commands for moving the player around. */ +@Command(aliases = {}, desc = "Commands for moving the player around: [More Info](https://goo.gl/uQTUiT)") @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class NavigationCommands { @@ -159,11 +162,12 @@ public class NavigationCommands { desc = "Teleport to a location" ) @CommandPermissions("worldedit.navigation.jumpto.command") - public void jumpTo(Player player) throws WorldEditException { - - Location pos = player.getSolidBlockTrace(300); + public void jumpTo(Player player, @Arg(desc = "Location to jump to", def = "") Location pos, @Switch(name='f', desc = "force teleport") boolean force) throws WorldEditException { + if (pos == null) { + pos = player.getSolidBlockTrace(300); + } if (pos != null) { - player.findFreePosition(pos); + if(force) player.setPosition(pos); else player.findFreePosition(pos); BBC.POOF.send(player); } else { BBC.NO_BLOCK.send(player); 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 1e42dbd20..f961fb9e7 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 @@ -74,6 +74,7 @@ import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator.TreeType; +import com.sk89q.worldedit.util.command.binding.Range; import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; @@ -92,6 +93,7 @@ import org.enginehub.piston.annotation.param.Switch; /** * Commands that operate on regions. */ +@Command(aliases = {}, desc = "Commands that operate on regions: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Region_operations)") @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) public class RegionCommands { @@ -222,7 +224,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 = 0) @Arg(desc = "The thickness of the line", def = "0") int thickness, @Switch(name = 'h', desc = "Generate only a shell") boolean shell) throws WorldEditException { @@ -230,8 +232,6 @@ public class RegionCommands { player.printError("//line only works with cuboid selections"); return 0; } - checkCommandArgument(thickness >= 0, "Thickness must be >= 0"); - CuboidRegion cuboidregion = (CuboidRegion) region; BlockVector3 pos1 = cuboidregion.getPos1(); BlockVector3 pos2 = cuboidregion.getPos2(); @@ -252,7 +252,7 @@ public class RegionCommands { @Selection Region region, @Arg(desc = "The pattern of blocks to place") Pattern pattern, - @Arg(desc = "The thickness of the curve", def = "0") + @Range(min = 0) @Arg(desc = "The thickness of the curve", def = "0") int thickness, @Switch(name = 'h', desc = "Generate only a shell") boolean shell, @@ -261,7 +261,6 @@ public class RegionCommands { player.printError("//curve only works with convex polyhedral selections"); return; } - checkCommandArgument(thickness >= 0, "Thickness must be >= 0"); player.checkConfirmationRegion(() -> { ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index d496ce801..021b0c3ae 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -324,7 +324,9 @@ public class SchematicCommands { return; } + boolean other = false; if (filename.contains("../")) { + other = true; if (!player.hasPermission("worldedit.schematic.save.other")) { BBC.NO_PERM.send(player, "worldedit.schematic.save.other"); return; @@ -342,6 +344,12 @@ public class SchematicCommands { if (!player.hasPermission("worldedit.schematic.delete")) { throw new StopExecutionException(TextComponent.of("That schematic already exists!")); } + if (other) { + if (!player.hasPermission("worldedit.schematic.delete.other")) { + BBC.NO_PERM.send(player, "worldedit.schematic.delete.other"); + return; + } + } if (!allowOverwrite) { player.printError("That schematic already exists. Use the -f flag to overwrite it."); return; @@ -373,9 +381,8 @@ public class SchematicCommands { BBC.SCHEMATIC_MOVE_EXISTS.send(player, f.getName()); } - ClipboardHolder holder = session.getClipboard(); - try (FileOutputStream fos = new FileOutputStream(f)) { + ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); Transform transform = holder.getTransform(); Clipboard target; @@ -502,7 +509,7 @@ public class SchematicCommands { BBC.NO_PERM.send(actor, "worldedit.schematic.delete.other"); continue; } - if (!f.delete()) { + if (!delete(f)) { actor.printError("Deletion of " + filename + " failed! Maybe it is read-only."); continue; } @@ -814,4 +821,12 @@ public class SchematicCommands { } return fileList; } + + private boolean delete(File file) { + if (file.delete()) { + new File(file.getParentFile(), "." + file.getName() + ".cached").delete(); + return true; + } + return false; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index 6893ca7f6..676dda1b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -408,7 +408,6 @@ public class SelectionCommands { Region region; if (clipboardInfo) { ClipboardHolder root = session.getClipboard(); -// Clipboard clipboard = holder.getClipboard(); int index = 0; for (ClipboardHolder holder : root.getHolders()) { Clipboard clipboard = holder.getClipboard(); @@ -471,7 +470,7 @@ public class SelectionCommands { @Arg(desc = "The mask of blocks to match") Mask mask) throws WorldEditException { int count = editSession.countBlock(session.getSelection(player.getWorld()), mask); - player.print("Counted: " + count); + BBC.SELECTION_COUNT.send(player, count); } @Command( @@ -527,6 +526,7 @@ public class SelectionCommands { public void select(Player player, LocalSession session, EditSession editSession, @Arg(desc = "Selector to switch to", def = "") SelectorChoice selector, + @Arg(desc = "Selector mask", def = "") Mask mask, @Switch(name = 'd', desc = "Set default selector") boolean setDefaultSelector) throws WorldEditException { final World world = player.getWorld(); @@ -537,7 +537,6 @@ public class SelectionCommands { return; } - final String typeName = args.getString(0); final RegionSelector oldSelector = session.getRegionSelector(world); final RegionSelector newSelector; @@ -587,15 +586,7 @@ public class SelectionCommands { break; case FUZZY: case MAGIC: - Mask mask; - if (typeName.length() > 6) { - ParserContext parserContext = new ParserContext(); - parserContext.setActor(player); - parserContext.setWorld(player.getWorld()); - parserContext.setSession(session); - parserContext.setExtent(editSession); - mask = we.getMaskFactory().parseFromInput(typeName.substring(6), parserContext); - } else { + if (mask == null) { mask = new IdMask(world); } newSelector = new FuzzyRegionSelector(player, editSession, mask); 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 a1677bd03..09d80779d 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,6 +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") public class SnapshotCommands { private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java index 0d916a0c8..aa6fda420 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SnapshotUtilCommands.java @@ -127,12 +127,12 @@ public class SnapshotUtilCommands { if (restore.hadTotalFailure()) { String error = restore.getLastErrorMessage(); if (!restore.getMissingChunks().isEmpty()) { - player.printError("Chunks were not present in snapshot."); + BBC.SNAPSHOT_ERROR_RESTORE.send(player); } else if (error != null) { player.printError("Errors prevented any blocks from being restored."); player.printError("Last error: " + error); } else { - player.printError("No chunks could be loaded. (Bad archive?)"); + BBC.SNAPSHOT_ERROR_RESTORE_CHUNKS.send(player); } } else { player.print(String.format("Restored; %d " diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 4da8518a9..46eaadc41 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -61,7 +61,7 @@ public class ToolCommands { ) public void none(Player player, LocalSession session) throws WorldEditException { - session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null); + session.setTool(player, null); player.print("Tool unbound from your current item."); } @@ -72,9 +72,8 @@ public class ToolCommands { ) @CommandPermissions("worldedit.setwand") public void selwand(Player player, LocalSession session) throws WorldEditException { - final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); - session.setTool(itemType, new SelectionWand()); + session.setTool(player, new SelectionWand()); player.print("Selection wand bound to " + itemType.getName() + "."); } @@ -87,7 +86,7 @@ public class ToolCommands { public void navwand(Player player, LocalSession session) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new NavigationWand()); + session.setTool(player, new NavigationWand()); player.print("Navigation wand bound to " + itemStack.getType().getName() + "."); } @@ -99,7 +98,7 @@ public class ToolCommands { public void info(Player player, LocalSession session) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new QueryTool()); + session.setTool(player, new QueryTool()); BBC.TOOL_INFO.send(player, itemStack.getType().getName()); } @@ -112,7 +111,7 @@ public class ToolCommands { @Arg(desc = "The radius of the brush", def = "1") double radius) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new InspectBrush()); + session.setTool(player, new InspectBrush()); BBC.TOOL_INSPECT.send(player, itemStack.getType().getName()); } @@ -126,7 +125,7 @@ public class ToolCommands { TreeGenerator.TreeType type) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new TreePlanter(type)); + session.setTool(player, new TreePlanter(type)); BBC.TOOL_TREE.send(player, itemStack.getType().getName()); } @@ -140,7 +139,7 @@ public class ToolCommands { Pattern pattern) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new BlockReplacer(pattern)); + session.setTool(player, new BlockReplacer(pattern)); BBC.TOOL_REPL.send(player, itemStack.getType().getName()); } @@ -152,7 +151,7 @@ public class ToolCommands { public void cycler(Player player, LocalSession session) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new BlockDataCyler()); + session.setTool(player, new BlockDataCyler()); BBC.TOOL_CYCLER.send(player, itemStack.getType().getName()); } @@ -176,7 +175,7 @@ public class ToolCommands { } BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new FloodFillTool(range, pattern)); + session.setTool(player, new FloodFillTool(range, pattern)); BBC.TOOL_FLOOD_FILL.send(player, itemStack.getType().getName()); } @@ -188,7 +187,7 @@ public class ToolCommands { public void deltree(Player player, LocalSession session) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new FloatingTreeRemover()); + session.setTool(player, new FloatingTreeRemover()); BBC.TOOL_DELTREE.send(player, itemStack.getType().getName()); } @@ -200,7 +199,7 @@ public class ToolCommands { public void farwand(Player player, LocalSession session) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new DistanceWand()); + session.setTool(player, new DistanceWand()); BBC.TOOL_FARWAND.send(player, itemStack.getType().getName()); } @@ -217,7 +216,7 @@ public class ToolCommands { Pattern secondary) throws WorldEditException { BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); - session.setTool(itemStack.getType(), new LongRangeBuildTool(primary, secondary)); + session.setTool(player, new LongRangeBuildTool(primary, secondary)); BBC.TOOL_LRBUILD_BOUND.send(player, itemStack.getType().getName()); BBC.TOOL_LRBUILD_INFO.send(player, secondary, primary); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java index 004353be5..3368eb3d1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java @@ -75,7 +75,7 @@ public class ToolUtilCommands { public void mask(Player player, LocalSession session, @Arg(desc = "The mask to set", def = "") Mask mask) throws WorldEditException { - session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setMask(mask); + session.getBrushTool(player).setMask(mask); if (mask == null) { player.print("Brush mask disabled."); } else { @@ -92,7 +92,7 @@ public class ToolUtilCommands { public void material(Player player, LocalSession session, @Arg(desc = "The pattern of blocks to use") Pattern pattern) throws WorldEditException { - session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setFill(pattern); + session.getBrushTool(player).setFill(pattern); player.print("Brush material set."); } @@ -104,7 +104,7 @@ public class ToolUtilCommands { public void range(Player player, LocalSession session, @Arg(desc = "The range of the brush") int range) throws WorldEditException { - session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setRange(range); + session.getBrushTool(player).setRange(range); player.print("Brush range set."); } @@ -118,7 +118,7 @@ public class ToolUtilCommands { int size) throws WorldEditException { we.checkMaxBrushRadius(size); - session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setSize(size); + session.getBrushTool(player).setSize(size); player.print("Brush size set."); } @@ -130,8 +130,7 @@ public class ToolUtilCommands { public void traceMask(Player player, LocalSession session, @Arg(desc = "The trace mask to set", def = "") Mask mask) throws WorldEditException { - //TODO TraceMask - //session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setTraceMask(mask); + session.getBrushTool(player).setTraceMask(mask); if (mask == null) { player.print("Trace mask disabled."); } else { 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 7b320a1e3..86c28e49a 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 @@ -101,6 +101,7 @@ import org.enginehub.piston.annotation.param.Switch; * Utility commands. */ @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) +@Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)") public class UtilityCommands { private final WorldEdit we; @@ -189,13 +190,11 @@ public class UtilityCommands { @Arg(desc = "The blocks to fill with") Pattern pattern, @Arg(desc = "The radius to fill in") - double radius, + @Range(min=1) double radius, @Arg(desc = "The depth to fill", def = "1") - int depth, + @Range(min=1) int depth, @Arg(desc = "Direction to fill", def = "down") BlockVector3 direction) throws WorldEditException { - radius = Math.max(1, radius); we.checkMaxRadius(radius); - depth = Math.max(1, depth); BlockVector3 pos = session.getPlacementPosition(player); int affected = editSession.fillDirection(pos, pattern, radius, depth, direction); @@ -284,10 +283,9 @@ public class UtilityCommands { @Arg(desc = "The blocks to fill with") Pattern pattern, @Arg(desc = "The radius to fill in") - double radius, + @Range(min=1) double radius, @Arg(desc = "The depth to fill", def = "") - Integer depth) throws WorldEditException { - radius = Math.max(1, radius); + @Range(min=1) Integer depth) throws WorldEditException { we.checkMaxRadius(radius); depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth); we.checkMaxRadius(radius); @@ -306,10 +304,9 @@ public class UtilityCommands { @Logging(PLACEMENT) public int drain(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius to drain") - double radius, + @Range(min=0) double radius, @Switch(name = 'w', desc = "Also un-waterlog blocks") boolean waterlogged) throws WorldEditException { - radius = Math.max(0, radius); we.checkMaxRadius(radius); int affected = editSession.drainArea( session.getPlacementPosition(player), radius, waterlogged); @@ -326,8 +323,7 @@ public class UtilityCommands { @Logging(PLACEMENT) public int fixLava(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius to fix in") - double radius) throws WorldEditException { - radius = Math.max(0, radius); + @Range(min=0) double radius) throws WorldEditException { we.checkMaxRadius(radius); int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.LAVA); player.print(affected + " block(s) have been changed."); @@ -343,8 +339,7 @@ public class UtilityCommands { @Logging(PLACEMENT) public int fixWater(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius to fix in") - double radius) throws WorldEditException { - radius = Math.max(0, radius); + @Range(min=0) double radius) throws WorldEditException { we.checkMaxRadius(radius); int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.WATER); BBC.VISITOR_BLOCK.send(player, affected); @@ -360,10 +355,9 @@ public class UtilityCommands { @Logging(PLACEMENT) public int removeAbove(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The apothem of the square to remove from", def = "1") - int size, + @Range(min=1) int size, @Arg(desc = "The maximum height above you to remove from", def = "") Integer height) throws WorldEditException { - size = Math.max(1, size); we.checkMaxRadius(size); int affected = editSession.removeAbove(session.getPlacementPosition(player), size, height); BBC.VISITOR_BLOCK.send(player, affected); @@ -379,10 +373,9 @@ public class UtilityCommands { @Logging(PLACEMENT) public int removeBelow(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The apothem of the square to remove from", def = "1") - int size, + @Range(min=1) int size, @Arg(desc = "The maximum height below you to remove from", def = "") Integer height) throws WorldEditException { - size = Math.max(1, size); we.checkMaxRadius(size); World world = player.getWorld(); height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1); @@ -403,8 +396,7 @@ public class UtilityCommands { @Arg(desc = "The mask of blocks to remove") Mask mask, @Arg(desc = "The radius of the square to remove from", def = "50") - int radius) throws WorldEditException { - radius = Math.max(1, radius); + @Range(min=1) int radius) throws WorldEditException { we.checkMaxRadius(radius); int affected = editSession.removeNear(session.getPlacementPosition(player), mask, radius); @@ -421,12 +413,11 @@ public class UtilityCommands { @Logging(PLACEMENT) public int replaceNear(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the square to remove in") - int radius, + @Range(min=1) int radius, @Arg(desc = "The mask matching blocks to remove", def = "") Mask from, @Arg(desc = "The pattern of blocks to replace with") Pattern to) throws WorldEditException { - radius = Math.max(1, radius); we.checkMaxRadius(radius); BlockVector3 base = session.getPlacementPosition(player); @@ -452,8 +443,7 @@ public class UtilityCommands { @Logging(PLACEMENT) public int snow(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the circle to snow in", def = "10") - double size) throws WorldEditException { - size = Math.max(1, size); + @Range(min=1) double size) throws WorldEditException { we.checkMaxRadius(size); int affected = editSession.simulateSnow(session.getPlacementPosition(player), size); @@ -470,8 +460,7 @@ public class UtilityCommands { @Logging(PLACEMENT) public int thaw(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the circle to thaw in", def = "10") - double size) throws WorldEditException { - size = Math.max(1, size); + @Range(min=1) double size) throws WorldEditException { we.checkMaxRadius(size); int affected = editSession.thaw(session.getPlacementPosition(player), size); @@ -488,10 +477,9 @@ public class UtilityCommands { @Logging(PLACEMENT) public int green(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the circle to convert in", def = "10") - double size, + @Range(min=1) double size, @Switch(name = 'f', desc = "Also convert coarse dirt") boolean convertCoarse) throws WorldEditException { - size = Math.max(1, size); we.checkMaxRadius(size); final boolean onlyNormalDirt = !convertCoarse; @@ -509,12 +497,12 @@ public class UtilityCommands { @Logging(PLACEMENT) public void extinguish(Player player, LocalSession session, EditSession editSession, @Arg(desc = "The radius of the square to remove in", def = "") - Integer radius) throws WorldEditException { + @Range(min=1) Integer radius) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40; - int size = radius != null ? Math.max(1, radius) : defaultRadius; + int size = radius != null ? radius : defaultRadius; we.checkMaxRadius(size); Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java index dd9f3c553..3043bae7c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/WorldEditCommands.java @@ -118,6 +118,7 @@ public class WorldEditCommands { name = "report", aliases = { "debugpaste" }, desc = "Writes a report of latest.log, config.yml, message.yml and your commands.yml to https://athion.net/ISPaster/paste" +// queued = false ) @CommandPermissions({"worldedit.report", "worldedit.debugpaste"}) public void report(Actor actor) throws WorldEditException, IOException { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index 533a130a2..87c69438c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -93,10 +93,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool } protected static int MAX_RANGE = 500; + protected static int DEFAULT_RANGE = 240; protected int range = -1; private VisualMode visualMode = VisualMode.NONE; private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE; - private Mask targetMask = null; + private Mask traceMask; private int targetOffset; private transient BrushSettings primary = new BrushSettings(); @@ -179,7 +180,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool if (targetMode != TargetMode.TARGET_BLOCK_RANGE) { map.put("target", targetMode); } - if (range != -1 && range != 240) { + if (range != -1 && range != DEFAULT_RANGE) { map.put("range", range); } if (targetOffset != 0) { @@ -307,6 +308,25 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool update(); } + /** + * Get the mask used for identifying where to stop traces. + * + * @return the mask used to stop block traces + */ + public @Nullable Mask getTraceMask() { + return traceMask; + } + + /** + * Set the block mask used for identifying where to stop traces. + * + * @param traceMask the mask used to stop block traces + */ + public void setTraceMask(@Nullable Mask traceMask) { + this.traceMask = traceMask; + update(); + } + /** * Set the block filter used for identifying blocks to replace. * @@ -329,7 +349,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool current.setBrush(brush); current.addPermission(permission); update(); - update(); } /** @@ -392,7 +411,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @return the range of the brush in blocks */ public int getRange() { - return (range < 0) ? MAX_RANGE : Math.min(range, MAX_RANGE); + return (range < 0) ? DEFAULT_RANGE : Math.min(range, MAX_RANGE); } /** @@ -401,7 +420,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @param range the range of the brush in blocks */ public void setRange(int range) { - this.range = range; + if (range == DEFAULT_RANGE) { + range = -1; + } else { + this.range = range; + } } @Override @@ -449,7 +472,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool } private Vector3 trace(EditSession editSession, Player player, int range, boolean useLastBlock) { - Mask mask = targetMask == null ? new SolidBlockMask(editSession) : targetMask; + Mask mask = traceMask == null ? new SolidBlockMask(editSession) : traceMask; new MaskTraverser(mask).reset(editSession); MaskedTargetBlock tb = new MaskedTargetBlock(mask, player, range, 0.2); return TaskManager.IMP.sync(new RunnableVal() { @@ -461,23 +484,23 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool } public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) { - if (action == BrushAction.PRIMARY) { - setContext(primary); - } else if (action == BrushAction.SECONDARY) { - setContext(secondary); + switch (action) { + case PRIMARY: + setContext(primary); + break; + case SECONDARY: + setContext(secondary); + break; } BrushSettings current = getContext(); Brush brush = current.getBrush(); if (brush == null) return false; - BlockBag bag = session.getBlockBag(player); - + if (current.setWorld(player.getWorld().getName()) && !current.canUse(player)) { + BBC.NO_PERM.send(player, StringMan.join(current.getPermissions(), ",")); + return false; + } try (EditSession editSession = session.createEditSession(player)) { - if (current.setWorld(editSession.getWorld().getName()) && !current.canUse(player)) { - BBC.NO_PERM.send(player, StringMan.join(current.getPermissions(), ",")); - return false; - } - BlockVector3 target = getPosition(editSession, player); if (target == null) { @@ -485,6 +508,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool BBC.NO_BLOCK.send(player); return true; } + BlockBag bag = editSession.getBlockBag(); Request.request().setEditSession(editSession); Mask mask = current.getMask(); @@ -519,11 +543,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool player.printError("Max blocks change limit reached."); } finally { session.remember(editSession); + if (bag != null) { + bag.flushChanges(); + } } } finally { - if (bag != null) { - bag.flushChanges(); - } Request.reset(); } @@ -552,11 +576,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool update(); } - public void setTargetMask(Mask mask) { - this.targetMask = mask; - update(); - } - public void setVisualMode(Player player, VisualMode visualMode) { if (visualMode == null) visualMode = VisualMode.NONE; if (this.visualMode != visualMode) { @@ -583,10 +602,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool return targetOffset; } - public Mask getTargetMask() { - return targetMask; - } - public VisualMode getVisualMode() { return visualMode; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java index d48ab016f..a854ed122 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/DistanceWand.java @@ -75,7 +75,7 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool { if (this.range > -1) { target = player.getBlockTrace(getRange(), true); } else { - target = player.getBlockTrace(MAX_RANGE); + target = player.getBlockTrace(DEFAULT_RANGE); } if (target == null) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java index 72008347c..19d43291b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/LongRangeBuildTool.java @@ -92,12 +92,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo private Location getTargetFace(Player player) { Location target = player.getBlockTraceFace(getRange(), true); - if (this.range > -1) { - target = player.getBlockTrace(getRange(), true); - } else { - target = player.getBlockTrace(MAX_RANGE, false); - } - + target = player.getBlockTrace(getRange(), true); if (target == null) { BBC.NO_BLOCK.send(player); return null; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java index 5119dfe33..335110f64 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/RecursivePickaxe.java @@ -88,37 +88,4 @@ public class RecursivePickaxe implements BlockTool { return true; } - - private static void recurse(Platform server, EditSession editSession, World world, BlockVector3 pos, - BlockVector3 origin, double size, BlockType initialType, Set visited) throws MaxChangedBlocksException { - - final double distanceSq = origin.distanceSq(pos); - if (distanceSq > size*size || visited.contains(pos)) { - return; - } - - visited.add(pos); - - if (editSession.getBlock(pos).getBlockType() != initialType) { - return; - } - - editSession.setBlock(pos, BlockTypes.AIR.getDefaultState()); - - world.queueBlockBreakEffect(server, pos, initialType, distanceSq); - - recurse(server, editSession, world, pos.add(1, 0, 0), - origin, size, initialType, visited); - recurse(server, editSession, world, pos.add(-1, 0, 0), - origin, size, initialType, visited); - recurse(server, editSession, world, pos.add(0, 0, 1), - origin, size, initialType, visited); - recurse(server, editSession, world, pos.add(0, 0, -1), - origin, size, initialType, visited); - recurse(server, editSession, world, pos.add(0, 1, 0), - origin, size, initialType, visited); - recurse(server, editSession, world, pos.add(0, -1, 0), - origin, size, initialType, visited); - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java index bbb489242..1e783df55 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/brush/ClipboardBrush.java @@ -44,7 +44,7 @@ public class ClipboardBrush implements Brush { this.ignoreAirBlocks = ignoreAirBlocks; this.usingOrigin = usingOrigin; this.pasteBiomes = false; - this.pasteEntities = false; + this.pasteEntities = true; this.sourceMask = null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java index cdb62a3ea..736d0663d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/MaskFactory.java @@ -24,6 +24,7 @@ import com.sk89q.worldedit.extension.factory.parser.mask.BiomeMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.BlockCategoryMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.BlockStateMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.BlocksMaskParser; +import com.sk89q.worldedit.extension.factory.parser.mask.DefaultMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.ExistingMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser; @@ -58,20 +59,19 @@ public final class MaskFactory extends AbstractFactory { * @param worldEdit the WorldEdit instance */ public MaskFactory(WorldEdit worldEdit) { - super(worldEdit, new BlocksMaskParser(worldEdit)); + super(worldEdit, new DefaultMaskParser(worldEdit)); - register(new ExistingMaskParser(worldEdit)); - register(new SolidMaskParser(worldEdit)); - register(new LazyRegionMaskParser(worldEdit)); - register(new RegionMaskParser(worldEdit)); - register(new OffsetMaskParser(worldEdit)); - register(new NoiseMaskParser(worldEdit)); - register(new BlockStateMaskParser(worldEdit)); - register(new NegateMaskParser(worldEdit)); - register(new ExpressionMaskParser(worldEdit)); - - register(new BlockCategoryMaskParser(worldEdit)); - register(new BiomeMaskParser(worldEdit)); +// register(new ExistingMaskParser(worldEdit)); +// register(new SolidMaskParser(worldEdit)); +// register(new LazyRegionMaskParser(worldEdit)); +// register(new RegionMaskParser(worldEdit)); +// register(new OffsetMaskParser(worldEdit)); +// register(new NoiseMaskParser(worldEdit)); +// register(new BlockStateMaskParser(worldEdit)); +// register(new NegateMaskParser(worldEdit)); +// register(new ExpressionMaskParser(worldEdit)); + register(new BlockCategoryMaskParser(worldEdit)); // TODO implement in DefaultMaskParser +// register(new BiomeMaskParser(worldEdit)); } @Override @@ -96,7 +96,7 @@ public final class MaskFactory extends AbstractFactory { case 0: throw new NoMatchException("No match for '" + input + "'"); case 1: - return masks.get(0); + return masks.get(0).optimize(); default: return new MaskIntersection(masks).optimize(); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java index 014229a3e..d00d1136f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/PatternFactory.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.extension.factory; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser; +import com.sk89q.worldedit.extension.factory.parser.pattern.DefaultPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser; @@ -44,16 +45,16 @@ public final class PatternFactory extends AbstractFactory { * @param worldEdit the WorldEdit instance */ public PatternFactory(WorldEdit worldEdit) { - super(worldEdit, new SingleBlockPatternParser(worldEdit)); + super(worldEdit, new DefaultPatternParser(worldEdit)); // split and parse each sub-pattern - register(new RandomPatternParser(worldEdit)); +// register(new RandomPatternParser(worldEdit)); // individual patterns - register(new ClipboardPatternParser(worldEdit)); - register(new TypeOrStateApplyingPatternParser(worldEdit)); - register(new RandomStatePatternParser(worldEdit)); - register(new BlockCategoryPatternParser(worldEdit)); +// register(new ClipboardPatternParser(worldEdit)); +// register(new TypeOrStateApplyingPatternParser(worldEdit)); +// register(new RandomStatePatternParser(worldEdit)); + register(new BlockCategoryPatternParser(worldEdit)); // TODO implement in pattern parser } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java index b5b678e27..d1c61edff 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java @@ -19,18 +19,23 @@ package com.sk89q.worldedit.extension.factory.parser; +import com.boydti.fawe.command.SuggestInputParseException; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.jnbt.JSON2NBT; +import com.boydti.fawe.jnbt.NBTException; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.StringMan; -import com.google.common.collect.Maps; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.NotABlockException; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.MobSpawnerBlock; import com.sk89q.worldedit.blocks.SignBlock; import com.sk89q.worldedit.blocks.SkullBlock; -import com.sk89q.worldedit.command.util.SuggestionHelper; +import com.sk89q.worldedit.blocks.metadata.MobType; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.input.DisallowedUsageException; import com.sk89q.worldedit.extension.input.InputParseException; @@ -38,6 +43,8 @@ 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.inventory.BlockBag; +import com.sk89q.worldedit.extent.inventory.SlottableBlockBag; import com.sk89q.worldedit.internal.registry.InputParser; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; @@ -45,19 +52,16 @@ import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockCategories; -import com.sk89q.worldedit.world.block.BlockCategory; 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 com.sk89q.worldedit.world.block.FuzzyBlockState; -import com.sk89q.worldedit.world.entity.EntityType; -import com.sk89q.worldedit.world.entity.EntityTypes; import com.sk89q.worldedit.world.registry.LegacyMapper; -import java.util.HashMap; +import java.util.Arrays; import java.util.Locale; -import java.util.Map; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -107,8 +111,6 @@ public class DefaultBlockParser extends InputParser { } } - private static String[] EMPTY_STRING_ARRAY = {}; - /** * Backwards compatibility for wool colours in block syntax. * @@ -160,75 +162,8 @@ public class DefaultBlockParser extends InputParser { } } - private static Map, Object> parseProperties(BlockType type, String[] stateProperties, ParserContext context) throws NoMatchException { - Map, Object> blockStates = new HashMap<>(); - - if (stateProperties.length > 0) { // Block data not yet detected - // Parse the block data (optional) - for (String parseableData : stateProperties) { - try { - String[] parts = parseableData.split("="); - if (parts.length != 2) { - throw new NoMatchException("Bad state format in " + parseableData); - } - - @SuppressWarnings("unchecked") - Property propertyKey = (Property) type.getPropertyMap().get(parts[0]); - if (propertyKey == null) { - if (context.getActor() != null) { - throw new NoMatchException("Unknown property " + parts[0] + " for block " + type.getId()); - } else { - WorldEdit.logger.warn("Unknown property " + parts[0] + " for block " + type.getId()); - } - return Maps.newHashMap(); - } - if (blockStates.containsKey(propertyKey)) { - throw new NoMatchException("Duplicate property " + parts[0]); - } - Object value; - try { - value = propertyKey.getValueFor(parts[1]); - } catch (IllegalArgumentException e) { - throw new NoMatchException("Unknown value " + parts[1] + " for state " + parts[0]); - } - - blockStates.put(propertyKey, value); - } catch (NoMatchException e) { - throw e; // Pass-through - } catch (Exception e) { - WorldEdit.logger.warn("Unknown state '" + parseableData + "'", e); - throw new NoMatchException("Unknown state '" + parseableData + "'"); - } - } - } - - return blockStates; - } - - @Override - public Stream getSuggestions(String input) { - final int idx = input.lastIndexOf('['); - if (idx < 0) { - return SuggestionHelper.getNamespacedRegistrySuggestions(BlockType.REGISTRY, input); - } - String blockType = input.substring(0, idx); - BlockType type = BlockTypes.get(blockType.toLowerCase(Locale.ROOT)); - if (type == null) { - return Stream.empty(); - } - - String props = input.substring(idx + 1); - if (props.isEmpty()) { - return type.getProperties().stream().map(p -> input + p.getName() + "="); - } - - return SuggestionHelper.getBlockPropertySuggestions(blockType, props); - } - private BaseBlock parseLogic(String input, ParserContext context) throws InputParseException { - BlockType blockType = null; - Map, Object> blockStates = new HashMap<>(); - String[] blockAndExtraData = input.trim().split("\\|"); + String[] blockAndExtraData = input.trim().split("\\|", 2); blockAndExtraData[0] = woolMapper(blockAndExtraData[0]); BlockState state = null; @@ -236,21 +171,31 @@ public class DefaultBlockParser extends InputParser { // Legacy matcher if (context.isTryingLegacy()) { try { - String[] split = blockAndExtraData[0].split(":", 2); - if (split.length == 0) { - throw new InputParseException("Invalid colon."); - } else if (split.length == 1) { + String[] split = blockAndExtraData[0].split(":"); + if (split.length == 1) { state = LegacyMapper.getInstance().getBlockFromLegacy(Integer.parseInt(split[0])); + } else if (MathMan.isInteger(split[0])) { + int id = Integer.parseInt(split[0]); + int data = Integer.parseInt(split[1]); + if (data < 0 || data >= 16) { + throw new InputParseException("Invalid data " + data); + } + state = LegacyMapper.getInstance().getBlockFromLegacy(id, data); } else { - state = LegacyMapper.getInstance().getBlockFromLegacy(Integer.parseInt(split[0]), Integer.parseInt(split[1])); + BlockType type = BlockTypes.get(split[0].toLowerCase(Locale.ROOT)); + if (type != null) { + int data = Integer.parseInt(split[1]); + if (data < 0 || data >= 16) { + throw new InputParseException("Invalid data " + data); + } + state = LegacyMapper.getInstance().getBlockFromLegacy(type.getLegacyCombinedId() >> 4, data); + } } - if (state != null) { - blockType = state.getBlockType(); - } - } catch (NumberFormatException ignored) { + } catch (NumberFormatException e) { } } + CompoundTag nbt = null; if (state == null) { String typeString; String stateString = null; @@ -259,101 +204,98 @@ public class DefaultBlockParser extends InputParser { typeString = blockAndExtraData[0]; } else { typeString = blockAndExtraData[0].substring(0, stateStart); - if (stateStart + 1 >= blockAndExtraData[0].length()) { - throw new InputParseException("Invalid format. Hanging bracket @ " + stateStart + "."); - } - int stateEnd = blockAndExtraData[0].lastIndexOf(']'); - if (stateEnd < 0) { - throw new InputParseException("Invalid format. Unclosed property."); - } stateString = blockAndExtraData[0].substring(stateStart + 1, blockAndExtraData[0].length() - 1); } if (typeString.isEmpty()) { throw new InputParseException("Invalid format"); } - String[] stateProperties = EMPTY_STRING_ARRAY; - if (stateString != null) { - stateProperties = stateString.split(","); - } - - if ("hand".equalsIgnoreCase(typeString)) { - // Get the block type from the item in the user's hand. - final BaseBlock blockInHand = getBlockInHand(context.requireActor(), HandSide.MAIN_HAND).toBaseBlock(); - if (blockInHand.getClass() != BaseBlock.class) { - return blockInHand; - } - - blockType = blockInHand.getBlockType(); - blockStates.putAll(blockInHand.getStates()); - } else if ("offhand".equalsIgnoreCase(typeString)) { - // Get the block type from the item in the user's off hand. - final BaseBlock blockInHand = getBlockInHand(context.requireActor(), HandSide.OFF_HAND).toBaseBlock(); - if (blockInHand.getClass() != BaseBlock.class) { - return blockInHand; - } - - blockType = blockInHand.getBlockType(); - blockStates.putAll(blockInHand.getStates()); - } else if ("pos1".equalsIgnoreCase(typeString)) { + // PosX + if (typeString.matches("pos[0-9]+")) { + int index = Integer.parseInt(typeString.replaceAll("[a-z]+", "")); // Get the block type from the "primary position" final World world = context.requireWorld(); final BlockVector3 primaryPosition; try { - primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition(); + primaryPosition = context.requireSession().getRegionSelector(world).getVerticies().get(index - 1); } catch (IncompleteRegionException e) { throw new InputParseException("Your selection is not complete."); } - final BlockState blockInHand = world.getBlock(primaryPosition); - - blockType = blockInHand.getBlockType(); - blockStates.putAll(blockInHand.getStates()); + state = world.getBlock(primaryPosition); } else { - // Attempt to lookup a block from ID or name. - blockType = BlockTypes.get(typeString.toLowerCase(Locale.ROOT)); - } + if ("hand".equalsIgnoreCase(typeString)) { + // Get the block type from the item in the user's hand. + state = getBlockInHand(context.requireActor(), HandSide.MAIN_HAND); + } else if ("offhand".equalsIgnoreCase(typeString)) { + // Get the block type from the item in the user's off hand. + state = getBlockInHand(context.requireActor(), HandSide.OFF_HAND); + } else if (typeString.matches("slot[0-9]+")) { + int slot = Integer.parseInt(typeString.substring(4)) - 1; + Actor actor = context.requireActor(); + if (!(actor instanceof Player)) { + throw new InputParseException("The user is not a player!"); + } + Player player = (Player) actor; + BlockBag bag = player.getInventoryBlockBag(); + if (bag == null || !(bag instanceof SlottableBlockBag)) { + throw new InputParseException("Unsupported!"); + } + SlottableBlockBag slottable = (SlottableBlockBag) bag; + BaseItem item = slottable.getItem(slot); - if (blockType == null) { - throw new NoMatchException("Does not match a valid block type: '" + input + "'"); - } + if (!item.getType().hasBlockType()) { + throw new InputParseException("You're not holding a block!"); + } + state = item.getType().getBlockType().getDefaultState(); + nbt = item.getNbtData(); + } else { + BlockType type = BlockTypes.parse(typeString.toLowerCase(Locale.ROOT)); - blockStates.putAll(parseProperties(blockType, stateProperties, context)); - - if (context.isPreferringWildcard()) { - FuzzyBlockState.Builder fuzzyBuilder = FuzzyBlockState.builder(); - fuzzyBuilder.type(blockType); - for (Map.Entry, Object> blockState : blockStates.entrySet()) { - @SuppressWarnings("unchecked") - Property objProp = (Property) blockState.getKey(); - fuzzyBuilder.withProperty(objProp, blockState.getValue()); + if (type != null) { + state = type.getDefaultState(); + } + if (state == null) { + throw new NoMatchException("Does not match a valid block type: '" + input + "'"); + } } - state = fuzzyBuilder.build(); - } else { - // No wildcards allowed => eliminate them. (Start with default state) - state = blockType.getDefaultState(); - for (Map.Entry, Object> blockState : blockStates.entrySet()) { - @SuppressWarnings("unchecked") - Property objProp = (Property) blockState.getKey(); - state = state.with(objProp, blockState.getValue()); + } + if (nbt == null) nbt = state.getNbtData(); + + if (stateString != null) { + state = BlockState.get(state.getBlockType(), "[" + stateString + "]", state); + if (context.isPreferringWildcard()) { + if (stateString.isEmpty()) { + state = new FuzzyBlockState(state); + } else { + BlockType type = state.getBlockType(); + FuzzyBlockState.Builder fuzzyBuilder = FuzzyBlockState.builder(); + fuzzyBuilder.type(type); + String[] entries = stateString.split(","); + for (String entry : entries) { + String[] split = entry.split("="); + String key = split[0]; + String val = split[1]; + Property prop = type.getProperty(key); + fuzzyBuilder.withProperty(prop, prop.getValueFor(val)); + } + state = fuzzyBuilder.build(); + } } } } - // this should be impossible but IntelliJ isn't that smart - if (blockType == null) { - throw new NoMatchException("Does not match a valid block type: '" + input + "'"); + + if (blockAndExtraData.length > 1 && blockAndExtraData[1].startsWith("{")) { + String joined = StringMan.join(Arrays.copyOfRange(blockAndExtraData, 1, blockAndExtraData.length), "|"); + try { + nbt = JSON2NBT.getTagFromJson(joined); + } catch (NBTException e) { + throw new NoMatchException(e.getMessage()); + } } // Check if the item is allowed - if (context.isRestricted()) { - Actor actor = context.requireActor(); - if (actor != null && !actor.hasPermission("worldedit.anyblock") - && worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId())) { - throw new DisallowedUsageException("You are not allowed to use '" + input + "'"); - } - } + BlockType blockType = state.getBlockType(); - if (!context.isTryingLegacy()) { - return state.toBaseBlock(); - } + if (nbt != null) return validate(context, state.toBaseBlock(nbt)); if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN || BlockCategories.SIGNS.contains(blockType)) { @@ -363,35 +305,39 @@ public class DefaultBlockParser extends InputParser { text[1] = blockAndExtraData.length > 2 ? blockAndExtraData[2] : ""; text[2] = blockAndExtraData.length > 3 ? blockAndExtraData[3] : ""; text[3] = blockAndExtraData.length > 4 ? blockAndExtraData[4] : ""; - return new SignBlock(state, text); + return validate(context, new SignBlock(state, text)); } else if (blockType == BlockTypes.SPAWNER) { // Allow setting mob spawn type if (blockAndExtraData.length > 1) { String mobName = blockAndExtraData[1]; - EntityType ent = EntityTypes.get(mobName.toLowerCase(Locale.ROOT)); - if (ent == null) { - throw new NoMatchException("Unknown entity type '" + mobName + "'"); + for (MobType mobType : MobType.values()) { + if (mobType.getName().toLowerCase().equals(mobName.toLowerCase(Locale.ROOT))) { + mobName = mobType.getName(); + break; + } } - mobName = ent.getId(); if (!worldEdit.getPlatformManager().queryCapability(Capability.USER_COMMANDS).isValidMobType(mobName)) { - throw new NoMatchException("Unknown mob type '" + mobName + "'"); + String finalMobName = mobName.toLowerCase(Locale.ROOT); + throw new SuggestInputParseException("Unknown mob type '" + mobName + "'", mobName, () -> Stream.of(MobType.values()) + .map(m -> m.getName().toLowerCase(Locale.ROOT)) + .filter(s -> s.startsWith(finalMobName)) + .collect(Collectors.toList())); } - return new MobSpawnerBlock(state, mobName); + return validate(context, new MobSpawnerBlock(state, mobName)); } else { - //noinspection ConstantConditions - return new MobSpawnerBlock(state, EntityTypes.PIG.getId()); + return validate(context, new MobSpawnerBlock(state, MobType.PIG.getName())); } } else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) { // allow setting type/player/rotation if (blockAndExtraData.length <= 1) { - return new SkullBlock(state); + return validate(context, new SkullBlock(state)); } String type = blockAndExtraData[1]; - return new SkullBlock(state, type.replace(" ", "_")); // valid MC usernames + return validate(context, new SkullBlock(state, type.replace(" ", "_"))); // valid MC usernames } else { - return state.toBaseBlock(); + return validate(context, state.toBaseBlock()); } } @@ -410,4 +356,4 @@ public class DefaultBlockParser extends InputParser { } return holder; } -} +} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index 7fe98e233..b21744f97 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -120,7 +120,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { if (free == 2) { final BlockVector3 pos = mutablePos.setComponents(x, y - 2, z); final BlockStateHolder state = world.getBlock(pos); - setPosition(Vector3.at(x + 0.5, y - 2 + BlockTypeUtil.centralTopLimit(state), z + 0.5)); + setPosition(new Location(world, Vector3.at(x + 0.5, y - 2 + BlockTypeUtil.centralTopLimit(state), z + 0.5))); return; } @@ -139,7 +139,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { final BlockVector3 pos = BlockVector3.at(x, y, z); final BlockState id = world.getBlock(pos); if (id.getBlockType().getMaterial().isMovementBlocker()) { - setPosition(Vector3.at(x + 0.5, y + + BlockTypeUtil.centralTopLimit(id), z + 0.5)); + setPosition(new Location(world, Vector3.at(x + 0.5, y + + BlockTypeUtil.centralTopLimit(id), z + 0.5))); return; } @@ -412,7 +412,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { if (typeId.hasBlockType()) { return typeId.getBlockType().getDefaultState().toBaseBlock(); } else { - throw new NotABlockException(); + return BlockTypes.AIR.getDefaultState().toBaseBlock(); } } 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 6773f0604..c2abe3036 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 @@ -331,89 +331,48 @@ public class PlatformManager { if (event.isCancelled()) return; } - if (event.getType() == Interaction.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 (player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { - if (!actor.hasPermission("worldedit.selection.pos")) { - return; - } - FawePlayer fp = FawePlayer.wrap(player); - RegionSelector selector = session.getRegionSelector(player.getWorld()); - final Player maskedPlayerWrapper = - new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), - ((Player) actor).getLocation()); - BlockVector3 blockPoint = vector.toBlockPoint(); - fp.runAction(() -> { - if (selector.selectPrimary(blockPoint, - ActorSelectorLimits.forActor(maskedPlayerWrapper))) { - selector - .explainPrimarySelection(actor, session, blockPoint); + switch (event.getType()) { + 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()) { + final BlockTool superPickaxe = session.getSuperPickaxe(); + if (superPickaxe != null && superPickaxe.canUse(player) && player.isHoldingPickAxe()) { + FawePlayer fp = FawePlayer.wrap(player); + final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); + fp.runAction(() -> reset(superPickaxe).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location), false, true); + event.setCancelled(true); + return; } - }, false, true); + } - event.setCancelled(true); - return; - } - - if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) { - final BlockTool superPickaxe = session.getSuperPickaxe(); - if (superPickaxe != null && superPickaxe.canUse(player)) { + Tool tool = session.getTool(player); + if (tool instanceof DoubleActionBlockTool && tool.canUse(player)) { FawePlayer fp = FawePlayer.wrap(player); final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(() -> reset(superPickaxe).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location), false, true); - event.setCancelled(true); - return; - } - } - - Tool tool = session.getTool(player.getItemInHand(HandSide.MAIN_HAND).getType()); - if (tool instanceof DoubleActionBlockTool && tool.canUse(player)) { - FawePlayer fp = FawePlayer.wrap(player); - final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(() -> reset(((DoubleActionBlockTool) tool)).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location), false, true); - event.setCancelled(true); - } - - } else if (event.getType() == Interaction.OPEN) { - if (player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { - if (!actor.hasPermission("worldedit.selection.pos")) { - return; - } - FawePlayer fp = FawePlayer.wrap(player); - if (fp.checkAction()) { - RegionSelector selector = session.getRegionSelector(player.getWorld()); - Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper( - PlayerWrapper.wrap((Player) actor), - ((Player) actor).getLocation()); - BlockVector3 blockPoint = vector.toBlockPoint(); - fp.runAction(() -> { - if (selector.selectSecondary(blockPoint, - ActorSelectorLimits.forActor(maskedPlayerWrapper))) { - selector.explainSecondarySelection(actor, session, - blockPoint); - } - }, false, true); - } - - event.setCancelled(true); - return; - } - - Tool tool = session.getTool(player); - if (tool instanceof BlockTool && tool.canUse(player)) { - FawePlayer fp = FawePlayer.wrap(player); - if (fp.checkAction()) { - final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); - fp.runAction(() -> { - if (tool instanceof BrushTool) { - ((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); - } else { - reset((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); - } - }, false, true); + fp.runAction(() -> reset(((DoubleActionBlockTool) tool)).actSecondary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location), false, true); event.setCancelled(true); } + break; + } + + case OPEN: { + Tool tool = session.getTool(player); + if (tool instanceof BlockTool && tool.canUse(player)) { + FawePlayer fp = FawePlayer.wrap(player); + if (fp.checkAction()) { + final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); + fp.runAction(() -> { + if (tool instanceof BrushTool) { + ((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); + } else { + reset((BlockTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location); + } + }, false, true); + event.setCancelled(true); + } + } + break; } } } catch (Throwable e) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionSelector.java index 22c8cda2f..bfad407c1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/RegionSelector.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.selector.limit.SelectorLimits; import com.sk89q.worldedit.world.World; +import java.util.Collections; import java.util.List; import javax.annotation.Nullable; @@ -156,4 +157,12 @@ public interface RegionSelector { */ List getInformationLines(); + /** + * Get the verticies + * @return + * @throws IncompleteRegionException + */ + default List getVerticies() throws IncompleteRegionException { + return Collections.singletonList(getPrimaryPosition()); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java index 0eaddea57..439d7f3d4 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/ConvexPolyhedralRegionSelector.java @@ -277,4 +277,8 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion } } + @Override + public List getVerticies() { + return new ArrayList<>(region.getVertices()); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java index 7656bc546..f03716e43 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CuboidRegionSelector.java @@ -36,6 +36,7 @@ import com.sk89q.worldedit.world.World; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -300,4 +301,8 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion { return "cuboid"; } + @Override + public List getVerticies() { + return Arrays.asList(position1, position2); + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java index cf7f1fa08..e28d86ea5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/FuzzyBlockState.java @@ -39,7 +39,11 @@ public class FuzzyBlockState extends BlockState { private final Map props; FuzzyBlockState(BlockType blockType) { - super(blockType); + this(blockType.getDefaultState(), null); + } + + public FuzzyBlockState(BlockState state) { + this(state, null); } private FuzzyBlockState(BlockState state, Map, Object> values) {