This commit is contained in:
Jesse Boyd 2019-07-18 02:31:13 +10:00
parent 68ea3d6e99
commit 905fbf5a0b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
34 changed files with 402 additions and 489 deletions

View File

@ -50,7 +50,7 @@ public class InspectBrush extends BrushTool implements DoubleActionTraceTool {
public Vector3 getTarget(Player player, boolean adjacent) { public Vector3 getTarget(Player player, boolean adjacent) {
Location target = null; Location target = null;
int range = this.range > -1 ? getRange() : MAX_RANGE; int range = this.range > -1 ? getRange() : DEFAULT_RANGE;
if (adjacent) { if (adjacent) {
Location face = player.getBlockTraceFace(range, true); Location face = player.getBlockTraceFace(range, true);
return face.add(face.getDirection()); return face.add(face.getDirection());

View File

@ -503,7 +503,11 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
} }
public int getSize() { public int getSize() {
return Arrays.stream(blocks).sum(); int count = 0;
for (int block : blocks) {
count += block;
}
return count;
} }
} }

View File

@ -154,4 +154,9 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
return lines; return lines;
} }
@Override
public List<BlockVector3> getVerticies() {
return positions;
}
} }

View File

@ -229,4 +229,8 @@ public class PolyhedralRegionSelector implements RegionSelector, CUIRegion {
} }
} }
@Override
public List<BlockVector3> getVerticies() {
return new ArrayList<>(region.getVertices());
}
} }

View File

@ -861,5 +861,4 @@ public class MainUtil {
e.printStackTrace(); e.printStackTrace();
} }
} }
} }

View File

@ -2317,6 +2317,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusX = (int) Math.ceil(radiusX);
final int ceilRadiusZ = (int) Math.ceil(radiusZ); final int ceilRadiusZ = (int) Math.ceil(radiusZ);
double xSqr, zSqr;
double distanceSq; double distanceSq;
double nextXn = 0; double nextXn = 0;
@ -2331,12 +2332,14 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
nextMinXn = (x + 1) * minInvRadiusX; nextMinXn = (x + 1) * minInvRadiusX;
double nextZn = 0; double nextZn = 0;
double nextMinZn = 0; double nextMinZn = 0;
xSqr = xn * xn;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn; final double zn = nextZn;
double dz2 = nextMinZn * nextMinZn; double dz2 = nextMinZn * nextMinZn;
nextZn = (z + 1) * invRadiusZ; nextZn = (z + 1) * invRadiusZ;
nextMinZn = (z + 1) * minInvRadiusZ; nextMinZn = (z + 1) * minInvRadiusZ;
distanceSq = lengthSq(xn, zn); zSqr = zn * zn;
distanceSq = xSqr + zSqr;
if (distanceSq > 1) { if (distanceSq > 1) {
if (z == 0) { if (z == 0) {
break forX; break forX;
@ -2360,13 +2363,13 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
forX: for (int x = 0; x <= ceilRadiusX; ++x) { forX: for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn; final double xn = nextXn;
nextXn = (x + 1) * invRadiusX; nextXn = (x + 1) * invRadiusX;
double dx = xn * xn;
double nextZn = 0; double nextZn = 0;
xSqr = xn * xn;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn; final double zn = nextZn;
nextZn = (z + 1) * invRadiusZ; nextZn = (z + 1) * invRadiusZ;
double dz = zn * zn; zSqr = zn * zn;
distanceSq = lengthSq(xn,zn); distanceSq = xSqr + zSqr;
if (distanceSq > 1) { if (distanceSq > 1) {
if (z == 0) { if (z == 0) {
break forX; break forX;
@ -2375,7 +2378,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
} }
if (!filled) { if (!filled) {
if ((dz + nextXn * nextXn <= 1) && (nextZn * nextZn + dx <= 1)) { if ((zSqr + nextXn * nextXn <= 1) && (nextZn * nextZn + xSqr <= 1)) {
continue; continue;
} }
} }
@ -2528,18 +2531,20 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
double nextXn = invRadiusX; double nextXn = invRadiusX;
forX: for (int x = 0; x <= ceilRadiusX; ++x) { forX: for (int x = 0; x <= ceilRadiusX; ++x) {
final double xn = nextXn; final double xn = nextXn;
double dx = xn * xn;
nextXn = (x + 1) * invRadiusX; nextXn = (x + 1) * invRadiusX;
double nextZn = invRadiusZ; double nextZn = invRadiusZ;
double dx = xn * xn;
forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { forZ: for (int z = 0; z <= ceilRadiusZ; ++z) {
final double zn = nextZn; final double zn = nextZn;
double dz = zn * zn; double dz = zn * zn;
double dxz = dx + dz;
nextZn = (z + 1) * invRadiusZ; nextZn = (z + 1) * invRadiusZ;
double nextYn = invRadiusY; double nextYn = invRadiusY;
forY: for (int y = 0; y <= ceilRadiusY; ++y) { forY: for (int y = 0; y <= ceilRadiusY; ++y) {
final double yn = nextYn; final double yn = nextYn;
double dxyz = lengthSq(zn, yn, zn); double dy = yn * yn;
double dxyz = dxz + dy;
nextYn = (y + 1) * invRadiusY; nextYn = (y + 1) * invRadiusY;
if (dxyz > 1) { if (dxyz > 1) {
@ -2553,8 +2558,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
} }
if (!filled) { if (!filled) {
double dy = yn * yn; if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1) {
if (lengthSq(nextXn, yn, zn) <= 1 && lengthSq(xn, nextYn, zn) <= 1 && lengthSq(xn, yn, nextZn) <= 1) {
continue; continue;
} }
} }
@ -2762,19 +2766,21 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
if (dx2 + dz2 > radiusSq) { if (dx2 + dz2 > radiusSq) {
continue; continue;
} }
loop:
for (int y = maxY; y >= 1; --y) { for (int y = maxY; y >= 1; --y) {
final BlockState block = getBlock(x, y, z); final BlockType block = getBlockType(x, y, z);
switch (block.getInternalId()) {
if (block.getBlockType() == BlockTypes.DIRT || case BlockID.COARSE_DIRT:
(!onlyNormalDirt && block.getBlockType() == BlockTypes.COARSE_DIRT)) { if (onlyNormalDirt) break loop;
this.setBlock(x, y, z, grass); case BlockID.DIRT:
this.setBlock(x, y, z, grass);
break; break loop;
} else if (block.getBlockType() == BlockTypes.WATER || block.getBlockType() == BlockTypes.LAVA) { case BlockID.WATER:
break; case BlockID.LAVA:
} else if (block.getBlockType().getMaterial().isMovementBlocker()) { default:
break; 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) { for (double loop = 0; loop <= 1; loop += 1D / splinelength / quality) {
BlockVector3 tipv = interpol.getPosition(loop).toBlockPoint(); BlockVector3 tipv = interpol.getPosition(loop).toBlockPoint();
if (radius == 0) { if (radius == 0) {
try { pattern.apply(this, tipv, tipv);
pattern.apply(this, tipv, tipv);
} catch (WorldEditException e) {
e.printStackTrace();
}
} else { } else {
vset.add(tipv); vset.add(tipv);
} }
@ -3485,14 +3487,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue,
Direction.DOWN.toBlockVector(), 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 @Override
public String getName() { public String getName() {

View File

@ -932,18 +932,22 @@ public class LocalSession implements TextureHolder {
* @return the tool, which may be {@code null} * @return the tool, which may be {@code null}
*/ */
@Nullable @Nullable
@Deprecated
public Tool getTool(ItemType item) { public Tool getTool(ItemType item) {
return tools[item.getInternalId()]; return tools[item.getInternalId()];
} }
@Nullable @Nullable
public Tool getTool(Player player) { public Tool getTool(Player player) {
if (!Settings.IMP.EXPERIMENTAL.PERSISTENT_BRUSHES && !hasTool) {
return null;
}
BaseItem item = player.getItemInHand(HandSide.MAIN_HAND); BaseItem item = player.getItemInHand(HandSide.MAIN_HAND);
return getTool(item, player); return getTool(item, player);
} }
public Tool getTool(BaseItem item, Player 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); BrushTool tool = BrushCache.getTool(player, this, item);
if (tool != null) return tool; 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 * or the tool is not assigned, the slot will be replaced with the
* brush tool. * brush tool.
* *
* @deprecated FAWE binds to the item, not the type - this allows brushes to persist
* @param item the item type * @param item the item type
* @return the tool, or {@code null} * @return the tool, or {@code null}
* @throws InvalidToolBindException if the item can't be bound to that item * @throws InvalidToolBindException if the item can't be bound to that item
*/ */
@Deprecated
public BrushTool getBrushTool(ItemType item) throws InvalidToolBindException { 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 { 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 { 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); 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 { public BrushTool getBrushTool(BaseItem item, Player player, boolean create) throws InvalidToolBindException {
Tool tool = getTool(item.getDefaultState(), player); Tool tool = getTool(item, player);
if (!(tool instanceof BrushTool)) { if (!(tool instanceof BrushTool)) {
if (create) { if (create) {
tool = new BrushTool(); tool = new BrushTool();
setTool(item.getDefaultState(), tool, player); setTool(item, tool, player);
} else { } else {
return null; return null;
} }
@ -1022,7 +1025,7 @@ public class LocalSession implements TextureHolder {
throw new InvalidToolBindException(type, "Already used for the navigation wand"); throw new InvalidToolBindException(type, "Already used for the navigation wand");
} }
Tool previous; 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); previous = BrushCache.getCachedTool(item);
BrushCache.setTool(item, (BrushTool) tool); BrushCache.setTool(item, (BrushTool) tool);
if (tool != null) { if (tool != null) {
@ -1330,13 +1333,15 @@ public class LocalSession implements TextureHolder {
BlockBag blockBag = getBlockBag(player); BlockBag blockBag = getBlockBag(player);
// Create an edit session World world = player.getWorld();
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory() boolean isPlayer = player.isPlayer();
.getEditSession(player.isPlayer() ? player.getWorld() : null, EditSessionBuilder builder = new EditSessionBuilder(world);
getBlockChangeLimit(), blockBag, player); if (player.isPlayer()) builder.player(FawePlayer.wrap(player));
Request.request().setEditSession(editSession); builder.blockBag(blockBag);
builder.fastmode(fastMode);
EditSession editSession = builder.build();
editSession.setFastMode(fastMode);
if (mask != null) { if (mask != null) {
editSession.setMask(mask); editSession.setMask(mask);
} }

View File

@ -1216,8 +1216,8 @@ public class BrushCommands {
boolean ignoreAir, boolean ignoreAir,
@Switch(name = 'o', desc = "Paste starting at the target location, instead of centering on it") @Switch(name = 'o', desc = "Paste starting at the target location, instead of centering on it")
boolean usingOrigin, boolean usingOrigin,
@Switch(name = 'e', desc = "Paste entities if available") @Switch(name = 'e', desc = "Skip paste entities if available")
boolean pasteEntities, boolean skipEntities,
@Switch(name = 'b', desc = "Paste biomes if available") @Switch(name = 'b', desc = "Paste biomes if available")
boolean pasteBiomes, boolean pasteBiomes,
@ArgFlag(name = 'm', desc = "Skip blocks matching this mask in the clipboard", def = "") @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.getBlockX());
worldEdit.checkMaxBrushRadius(size.getBlockY()); worldEdit.checkMaxBrushRadius(size.getBlockY());
worldEdit.checkMaxBrushRadius(size.getBlockZ()); 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(); CommandLocals locals = context.getLocals();
BrushSettings bs = new BrushSettings(); BrushSettings bs = new BrushSettings();
@ -1645,7 +1645,7 @@ public class BrushCommands {
flags.or(CreatureButcher.Flags.TAGGED , killWithName, "worldedit.butcher.tagged"); flags.or(CreatureButcher.Flags.TAGGED , killWithName, "worldedit.butcher.tagged");
flags.or(CreatureButcher.Flags.ARMOR_STAND , killArmorStands, "worldedit.butcher.armorstands"); 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); tool.setSize(radius);
ButcherBrush brush = new ButcherBrush(flags); ButcherBrush brush = new ButcherBrush(flags);
tool.setBrush(brush, "worldedit.brush.butcher"); tool.setBrush(brush, "worldedit.brush.butcher");

View File

@ -281,7 +281,7 @@ public class BrushOptionsCommands extends MethodCommands {
parserContext.setSession(session); parserContext.setSession(session);
parserContext.setExtent(editSession); parserContext.setExtent(editSession);
Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); 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)); BBC.BRUSH_TARGET_MASK_SET.send(player, context.getJoinedStrings(0));
} }

View File

@ -225,25 +225,25 @@ public class HistoryCommands extends MethodCommands {
BBC.COMMAND_UNDO_DISABLED.send(player); BBC.COMMAND_UNDO_DISABLED.send(player);
return; 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); times = Math.max(1, times);
LocalSession undoSession = session;
int finalTimes = times; int finalTimes = times;
FawePlayer.wrap(player).checkConfirmation(() -> { FawePlayer.wrap(player).checkConfirmation(() -> {
player.checkPermission("worldedit.history.undo.other");
EditSession undone = null; EditSession undone = null;
int i = 0; int i = 0;
for (; i < finalTimes; ++i) { for (; i < finalTimes; ++i) {
if (context.argsLength() < 2) { undone = undoSession.undo(undoSession.getBlockBag(player), player);
undone = undoSession.undo(undoSession.getBlockBag(player), player); if (undone == null) break;
} 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;
}
} }
if (undone == null) i--; if (undone == null) i--;
if (i > 0) { if (i > 0) {
@ -273,7 +273,7 @@ public class HistoryCommands extends MethodCommands {
player.checkPermission("worldedit.history.redo.other"); player.checkPermission("worldedit.history.redo.other");
redoSession = worldEdit.getSessionManager().findByName(playerName); redoSession = worldEdit.getSessionManager().findByName(playerName);
if (redoSession == null) { if (redoSession == null) {
player.printError("Unable to find session for " + playerName); BBC.COMMAND_HISTORY_OTHER_ERROR.send(player, playerName);
return; return;
} }
} }
@ -288,7 +288,7 @@ public class HistoryCommands extends MethodCommands {
} }
} }
if (timesRedone > 0) { if (timesRedone > 0) {
player.print("Redid " + timesRedone + " available edits."); BBC.COMMAND_REDO_SUCCESS.send(player, timesRedone == 1 ? "" : " x" + timesRedone);
} else { } else {
BBC.COMMAND_REDO_ERROR.send(player); BBC.COMMAND_REDO_ERROR.send(player);
} }

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION; import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.WorldEdit; 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.command.util.Logging;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Arg;
@ -39,6 +41,7 @@ import org.enginehub.piston.annotation.param.Switch;
/** /**
* Commands for moving the player around. * 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) @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class NavigationCommands { public class NavigationCommands {
@ -159,11 +162,12 @@ public class NavigationCommands {
desc = "Teleport to a location" desc = "Teleport to a location"
) )
@CommandPermissions("worldedit.navigation.jumpto.command") @CommandPermissions("worldedit.navigation.jumpto.command")
public void jumpTo(Player player) throws WorldEditException { 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) {
Location pos = player.getSolidBlockTrace(300); pos = player.getSolidBlockTrace(300);
}
if (pos != null) { if (pos != null) {
player.findFreePosition(pos); if(force) player.setPosition(pos); else player.findFreePosition(pos);
BBC.POOF.send(player); BBC.POOF.send(player);
} else { } else {
BBC.NO_BLOCK.send(player); BBC.NO_BLOCK.send(player);

View File

@ -74,6 +74,7 @@ import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.regions.Regions;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType; 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.util.command.parametric.Optional;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.BiomeTypes;
@ -92,6 +93,7 @@ import org.enginehub.piston.annotation.param.Switch;
/** /**
* Commands that operate on regions. * 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) @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class RegionCommands { public class RegionCommands {
@ -222,7 +224,7 @@ public class RegionCommands {
@Selection Region region, @Selection Region region,
@Arg(desc = "The pattern of blocks to place") @Arg(desc = "The pattern of blocks to place")
Pattern pattern, 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, int thickness,
@Switch(name = 'h', desc = "Generate only a shell") @Switch(name = 'h', desc = "Generate only a shell")
boolean shell) throws WorldEditException { boolean shell) throws WorldEditException {
@ -230,8 +232,6 @@ public class RegionCommands {
player.printError("//line only works with cuboid selections"); player.printError("//line only works with cuboid selections");
return 0; return 0;
} }
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
CuboidRegion cuboidregion = (CuboidRegion) region; CuboidRegion cuboidregion = (CuboidRegion) region;
BlockVector3 pos1 = cuboidregion.getPos1(); BlockVector3 pos1 = cuboidregion.getPos1();
BlockVector3 pos2 = cuboidregion.getPos2(); BlockVector3 pos2 = cuboidregion.getPos2();
@ -252,7 +252,7 @@ public class RegionCommands {
@Selection Region region, @Selection Region region,
@Arg(desc = "The pattern of blocks to place") @Arg(desc = "The pattern of blocks to place")
Pattern pattern, 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, int thickness,
@Switch(name = 'h', desc = "Generate only a shell") @Switch(name = 'h', desc = "Generate only a shell")
boolean shell, boolean shell,
@ -261,7 +261,6 @@ public class RegionCommands {
player.printError("//curve only works with convex polyhedral selections"); player.printError("//curve only works with convex polyhedral selections");
return; return;
} }
checkCommandArgument(thickness >= 0, "Thickness must be >= 0");
player.checkConfirmationRegion(() -> { player.checkConfirmationRegion(() -> {
ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region; ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region;

View File

@ -324,7 +324,9 @@ public class SchematicCommands {
return; return;
} }
boolean other = false;
if (filename.contains("../")) { if (filename.contains("../")) {
other = true;
if (!player.hasPermission("worldedit.schematic.save.other")) { if (!player.hasPermission("worldedit.schematic.save.other")) {
BBC.NO_PERM.send(player, "worldedit.schematic.save.other"); BBC.NO_PERM.send(player, "worldedit.schematic.save.other");
return; return;
@ -342,6 +344,12 @@ public class SchematicCommands {
if (!player.hasPermission("worldedit.schematic.delete")) { if (!player.hasPermission("worldedit.schematic.delete")) {
throw new StopExecutionException(TextComponent.of("That schematic already exists!")); 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) { if (!allowOverwrite) {
player.printError("That schematic already exists. Use the -f flag to overwrite it."); player.printError("That schematic already exists. Use the -f flag to overwrite it.");
return; return;
@ -373,9 +381,8 @@ public class SchematicCommands {
BBC.SCHEMATIC_MOVE_EXISTS.send(player, f.getName()); BBC.SCHEMATIC_MOVE_EXISTS.send(player, f.getName());
} }
ClipboardHolder holder = session.getClipboard();
try (FileOutputStream fos = new FileOutputStream(f)) { try (FileOutputStream fos = new FileOutputStream(f)) {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard(); Clipboard clipboard = holder.getClipboard();
Transform transform = holder.getTransform(); Transform transform = holder.getTransform();
Clipboard target; Clipboard target;
@ -502,7 +509,7 @@ public class SchematicCommands {
BBC.NO_PERM.send(actor, "worldedit.schematic.delete.other"); BBC.NO_PERM.send(actor, "worldedit.schematic.delete.other");
continue; continue;
} }
if (!f.delete()) { if (!delete(f)) {
actor.printError("Deletion of " + filename + " failed! Maybe it is read-only."); actor.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
continue; continue;
} }
@ -814,4 +821,12 @@ public class SchematicCommands {
} }
return fileList; return fileList;
} }
private boolean delete(File file) {
if (file.delete()) {
new File(file.getParentFile(), "." + file.getName() + ".cached").delete();
return true;
}
return false;
}
} }

View File

@ -408,7 +408,6 @@ public class SelectionCommands {
Region region; Region region;
if (clipboardInfo) { if (clipboardInfo) {
ClipboardHolder root = session.getClipboard(); ClipboardHolder root = session.getClipboard();
// Clipboard clipboard = holder.getClipboard();
int index = 0; int index = 0;
for (ClipboardHolder holder : root.getHolders()) { for (ClipboardHolder holder : root.getHolders()) {
Clipboard clipboard = holder.getClipboard(); Clipboard clipboard = holder.getClipboard();
@ -471,7 +470,7 @@ public class SelectionCommands {
@Arg(desc = "The mask of blocks to match") @Arg(desc = "The mask of blocks to match")
Mask mask) throws WorldEditException { Mask mask) throws WorldEditException {
int count = editSession.countBlock(session.getSelection(player.getWorld()), mask); int count = editSession.countBlock(session.getSelection(player.getWorld()), mask);
player.print("Counted: " + count); BBC.SELECTION_COUNT.send(player, count);
} }
@Command( @Command(
@ -527,6 +526,7 @@ public class SelectionCommands {
public void select(Player player, LocalSession session, EditSession editSession, public void select(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "Selector to switch to", def = "") @Arg(desc = "Selector to switch to", def = "")
SelectorChoice selector, SelectorChoice selector,
@Arg(desc = "Selector mask", def = "") Mask mask,
@Switch(name = 'd', desc = "Set default selector") @Switch(name = 'd', desc = "Set default selector")
boolean setDefaultSelector) throws WorldEditException { boolean setDefaultSelector) throws WorldEditException {
final World world = player.getWorld(); final World world = player.getWorld();
@ -537,7 +537,6 @@ public class SelectionCommands {
return; return;
} }
final String typeName = args.getString(0);
final RegionSelector oldSelector = session.getRegionSelector(world); final RegionSelector oldSelector = session.getRegionSelector(world);
final RegionSelector newSelector; final RegionSelector newSelector;
@ -587,15 +586,7 @@ public class SelectionCommands {
break; break;
case FUZZY: case FUZZY:
case MAGIC: case MAGIC:
Mask mask; if (mask == null) {
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 {
mask = new IdMask(world); mask = new IdMask(world);
} }
newSelector = new FuzzyRegionSelector(player, editSession, mask); newSelector = new FuzzyRegionSelector(player, editSession, mask);

View File

@ -46,6 +46,7 @@ import java.util.List;
* Snapshot commands. * Snapshot commands.
*/ */
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
@Command(aliases = {"snapshot", "snap"}, desc = "List, load and view information related to snapshots")
public class SnapshotCommands { public class SnapshotCommands {
private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); private static final DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");

View File

@ -127,12 +127,12 @@ public class SnapshotUtilCommands {
if (restore.hadTotalFailure()) { if (restore.hadTotalFailure()) {
String error = restore.getLastErrorMessage(); String error = restore.getLastErrorMessage();
if (!restore.getMissingChunks().isEmpty()) { if (!restore.getMissingChunks().isEmpty()) {
player.printError("Chunks were not present in snapshot."); BBC.SNAPSHOT_ERROR_RESTORE.send(player);
} else if (error != null) { } else if (error != null) {
player.printError("Errors prevented any blocks from being restored."); player.printError("Errors prevented any blocks from being restored.");
player.printError("Last error: " + error); player.printError("Last error: " + error);
} else { } else {
player.printError("No chunks could be loaded. (Bad archive?)"); BBC.SNAPSHOT_ERROR_RESTORE_CHUNKS.send(player);
} }
} else { } else {
player.print(String.format("Restored; %d " player.print(String.format("Restored; %d "

View File

@ -61,7 +61,7 @@ public class ToolCommands {
) )
public void none(Player player, LocalSession session) throws WorldEditException { 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."); player.print("Tool unbound from your current item.");
} }
@ -72,9 +72,8 @@ public class ToolCommands {
) )
@CommandPermissions("worldedit.setwand") @CommandPermissions("worldedit.setwand")
public void selwand(Player player, LocalSession session) throws WorldEditException { public void selwand(Player player, LocalSession session) throws WorldEditException {
final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType(); 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() + "."); player.print("Selection wand bound to " + itemType.getName() + ".");
} }
@ -87,7 +86,7 @@ public class ToolCommands {
public void navwand(Player player, LocalSession session) throws WorldEditException { public void navwand(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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() + "."); 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 { public void info(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_INFO.send(player, itemStack.getType().getName());
} }
@ -112,7 +111,7 @@ public class ToolCommands {
@Arg(desc = "The radius of the brush", def = "1") @Arg(desc = "The radius of the brush", def = "1")
double radius) throws WorldEditException { double radius) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_INSPECT.send(player, itemStack.getType().getName());
} }
@ -126,7 +125,7 @@ public class ToolCommands {
TreeGenerator.TreeType type) throws WorldEditException { TreeGenerator.TreeType type) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_TREE.send(player, itemStack.getType().getName());
} }
@ -140,7 +139,7 @@ public class ToolCommands {
Pattern pattern) throws WorldEditException { Pattern pattern) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_REPL.send(player, itemStack.getType().getName());
} }
@ -152,7 +151,7 @@ public class ToolCommands {
public void cycler(Player player, LocalSession session) throws WorldEditException { public void cycler(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_CYCLER.send(player, itemStack.getType().getName());
} }
@ -176,7 +175,7 @@ public class ToolCommands {
} }
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); 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 { public void deltree(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_DELTREE.send(player, itemStack.getType().getName());
} }
@ -200,7 +199,7 @@ public class ToolCommands {
public void farwand(Player player, LocalSession session) throws WorldEditException { public void farwand(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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()); BBC.TOOL_FARWAND.send(player, itemStack.getType().getName());
} }
@ -217,7 +216,7 @@ public class ToolCommands {
Pattern secondary) throws WorldEditException { Pattern secondary) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); 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_BOUND.send(player, itemStack.getType().getName());
BBC.TOOL_LRBUILD_INFO.send(player, secondary, primary); BBC.TOOL_LRBUILD_INFO.send(player, secondary, primary);
} }

View File

@ -75,7 +75,7 @@ public class ToolUtilCommands {
public void mask(Player player, LocalSession session, public void mask(Player player, LocalSession session,
@Arg(desc = "The mask to set", def = "") @Arg(desc = "The mask to set", def = "")
Mask mask) throws WorldEditException { Mask mask) throws WorldEditException {
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setMask(mask); session.getBrushTool(player).setMask(mask);
if (mask == null) { if (mask == null) {
player.print("Brush mask disabled."); player.print("Brush mask disabled.");
} else { } else {
@ -92,7 +92,7 @@ public class ToolUtilCommands {
public void material(Player player, LocalSession session, public void material(Player player, LocalSession session,
@Arg(desc = "The pattern of blocks to use") @Arg(desc = "The pattern of blocks to use")
Pattern pattern) throws WorldEditException { Pattern pattern) throws WorldEditException {
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setFill(pattern); session.getBrushTool(player).setFill(pattern);
player.print("Brush material set."); player.print("Brush material set.");
} }
@ -104,7 +104,7 @@ public class ToolUtilCommands {
public void range(Player player, LocalSession session, public void range(Player player, LocalSession session,
@Arg(desc = "The range of the brush") @Arg(desc = "The range of the brush")
int range) throws WorldEditException { int range) throws WorldEditException {
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setRange(range); session.getBrushTool(player).setRange(range);
player.print("Brush range set."); player.print("Brush range set.");
} }
@ -118,7 +118,7 @@ public class ToolUtilCommands {
int size) throws WorldEditException { int size) throws WorldEditException {
we.checkMaxBrushRadius(size); we.checkMaxBrushRadius(size);
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setSize(size); session.getBrushTool(player).setSize(size);
player.print("Brush size set."); player.print("Brush size set.");
} }
@ -130,8 +130,7 @@ public class ToolUtilCommands {
public void traceMask(Player player, LocalSession session, public void traceMask(Player player, LocalSession session,
@Arg(desc = "The trace mask to set", def = "") @Arg(desc = "The trace mask to set", def = "")
Mask mask) throws WorldEditException { Mask mask) throws WorldEditException {
//TODO TraceMask session.getBrushTool(player).setTraceMask(mask);
//session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setTraceMask(mask);
if (mask == null) { if (mask == null) {
player.print("Trace mask disabled."); player.print("Trace mask disabled.");
} else { } else {

View File

@ -101,6 +101,7 @@ import org.enginehub.piston.annotation.param.Switch;
* Utility commands. * Utility commands.
*/ */
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
@Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)")
public class UtilityCommands { public class UtilityCommands {
private final WorldEdit we; private final WorldEdit we;
@ -189,13 +190,11 @@ public class UtilityCommands {
@Arg(desc = "The blocks to fill with") @Arg(desc = "The blocks to fill with")
Pattern pattern, Pattern pattern,
@Arg(desc = "The radius to fill in") @Arg(desc = "The radius to fill in")
double radius, @Range(min=1) double radius,
@Arg(desc = "The depth to fill", def = "1") @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 { @Arg(desc = "Direction to fill", def = "down") BlockVector3 direction) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
depth = Math.max(1, depth);
BlockVector3 pos = session.getPlacementPosition(player); BlockVector3 pos = session.getPlacementPosition(player);
int affected = editSession.fillDirection(pos, pattern, radius, depth, direction); int affected = editSession.fillDirection(pos, pattern, radius, depth, direction);
@ -284,10 +283,9 @@ public class UtilityCommands {
@Arg(desc = "The blocks to fill with") @Arg(desc = "The blocks to fill with")
Pattern pattern, Pattern pattern,
@Arg(desc = "The radius to fill in") @Arg(desc = "The radius to fill in")
double radius, @Range(min=1) double radius,
@Arg(desc = "The depth to fill", def = "") @Arg(desc = "The depth to fill", def = "")
Integer depth) throws WorldEditException { @Range(min=1) Integer depth) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth); depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
@ -306,10 +304,9 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int drain(Player player, LocalSession session, EditSession editSession, public int drain(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius to drain") @Arg(desc = "The radius to drain")
double radius, @Range(min=0) double radius,
@Switch(name = 'w', desc = "Also un-waterlog blocks") @Switch(name = 'w', desc = "Also un-waterlog blocks")
boolean waterlogged) throws WorldEditException { boolean waterlogged) throws WorldEditException {
radius = Math.max(0, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
int affected = editSession.drainArea( int affected = editSession.drainArea(
session.getPlacementPosition(player), radius, waterlogged); session.getPlacementPosition(player), radius, waterlogged);
@ -326,8 +323,7 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int fixLava(Player player, LocalSession session, EditSession editSession, public int fixLava(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius to fix in") @Arg(desc = "The radius to fix in")
double radius) throws WorldEditException { @Range(min=0) double radius) throws WorldEditException {
radius = Math.max(0, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.LAVA); int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.LAVA);
player.print(affected + " block(s) have been changed."); player.print(affected + " block(s) have been changed.");
@ -343,8 +339,7 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int fixWater(Player player, LocalSession session, EditSession editSession, public int fixWater(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius to fix in") @Arg(desc = "The radius to fix in")
double radius) throws WorldEditException { @Range(min=0) double radius) throws WorldEditException {
radius = Math.max(0, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.WATER); int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.WATER);
BBC.VISITOR_BLOCK.send(player, affected); BBC.VISITOR_BLOCK.send(player, affected);
@ -360,10 +355,9 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int removeAbove(Player player, LocalSession session, EditSession editSession, public int removeAbove(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The apothem of the square to remove from", def = "1") @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 = "") @Arg(desc = "The maximum height above you to remove from", def = "")
Integer height) throws WorldEditException { Integer height) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size); we.checkMaxRadius(size);
int affected = editSession.removeAbove(session.getPlacementPosition(player), size, height); int affected = editSession.removeAbove(session.getPlacementPosition(player), size, height);
BBC.VISITOR_BLOCK.send(player, affected); BBC.VISITOR_BLOCK.send(player, affected);
@ -379,10 +373,9 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int removeBelow(Player player, LocalSession session, EditSession editSession, public int removeBelow(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The apothem of the square to remove from", def = "1") @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 = "") @Arg(desc = "The maximum height below you to remove from", def = "")
Integer height) throws WorldEditException { Integer height) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size); we.checkMaxRadius(size);
World world = player.getWorld(); World world = player.getWorld();
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1); 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") @Arg(desc = "The mask of blocks to remove")
Mask mask, Mask mask,
@Arg(desc = "The radius of the square to remove from", def = "50") @Arg(desc = "The radius of the square to remove from", def = "50")
int radius) throws WorldEditException { @Range(min=1) int radius) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
int affected = editSession.removeNear(session.getPlacementPosition(player), mask, radius); int affected = editSession.removeNear(session.getPlacementPosition(player), mask, radius);
@ -421,12 +413,11 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int replaceNear(Player player, LocalSession session, EditSession editSession, public int replaceNear(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the square to remove in") @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 = "") @Arg(desc = "The mask matching blocks to remove", def = "")
Mask from, Mask from,
@Arg(desc = "The pattern of blocks to replace with") @Arg(desc = "The pattern of blocks to replace with")
Pattern to) throws WorldEditException { Pattern to) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius); we.checkMaxRadius(radius);
BlockVector3 base = session.getPlacementPosition(player); BlockVector3 base = session.getPlacementPosition(player);
@ -452,8 +443,7 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int snow(Player player, LocalSession session, EditSession editSession, public int snow(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the circle to snow in", def = "10") @Arg(desc = "The radius of the circle to snow in", def = "10")
double size) throws WorldEditException { @Range(min=1) double size) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size); we.checkMaxRadius(size);
int affected = editSession.simulateSnow(session.getPlacementPosition(player), size); int affected = editSession.simulateSnow(session.getPlacementPosition(player), size);
@ -470,8 +460,7 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int thaw(Player player, LocalSession session, EditSession editSession, public int thaw(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the circle to thaw in", def = "10") @Arg(desc = "The radius of the circle to thaw in", def = "10")
double size) throws WorldEditException { @Range(min=1) double size) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size); we.checkMaxRadius(size);
int affected = editSession.thaw(session.getPlacementPosition(player), size); int affected = editSession.thaw(session.getPlacementPosition(player), size);
@ -488,10 +477,9 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public int green(Player player, LocalSession session, EditSession editSession, public int green(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the circle to convert in", def = "10") @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") @Switch(name = 'f', desc = "Also convert coarse dirt")
boolean convertCoarse) throws WorldEditException { boolean convertCoarse) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size); we.checkMaxRadius(size);
final boolean onlyNormalDirt = !convertCoarse; final boolean onlyNormalDirt = !convertCoarse;
@ -509,12 +497,12 @@ public class UtilityCommands {
@Logging(PLACEMENT) @Logging(PLACEMENT)
public void extinguish(Player player, LocalSession session, EditSession editSession, public void extinguish(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the square to remove in", def = "") @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(); LocalConfiguration config = we.getConfiguration();
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40; 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); we.checkMaxRadius(size);
Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE); Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE);

View File

@ -118,6 +118,7 @@ public class WorldEditCommands {
name = "report", name = "report",
aliases = { "debugpaste" }, aliases = { "debugpaste" },
desc = "Writes a report of latest.log, config.yml, message.yml and your commands.yml to https://athion.net/ISPaster/paste" 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"}) @CommandPermissions({"worldedit.report", "worldedit.debugpaste"})
public void report(Actor actor) throws WorldEditException, IOException { public void report(Actor actor) throws WorldEditException, IOException {

View File

@ -93,10 +93,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
} }
protected static int MAX_RANGE = 500; protected static int MAX_RANGE = 500;
protected static int DEFAULT_RANGE = 240;
protected int range = -1; protected int range = -1;
private VisualMode visualMode = VisualMode.NONE; private VisualMode visualMode = VisualMode.NONE;
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE; private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private Mask targetMask = null; private Mask traceMask;
private int targetOffset; private int targetOffset;
private transient BrushSettings primary = new BrushSettings(); private transient BrushSettings primary = new BrushSettings();
@ -179,7 +180,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
if (targetMode != TargetMode.TARGET_BLOCK_RANGE) { if (targetMode != TargetMode.TARGET_BLOCK_RANGE) {
map.put("target", targetMode); map.put("target", targetMode);
} }
if (range != -1 && range != 240) { if (range != -1 && range != DEFAULT_RANGE) {
map.put("range", range); map.put("range", range);
} }
if (targetOffset != 0) { if (targetOffset != 0) {
@ -307,6 +308,25 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
update(); 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. * 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.setBrush(brush);
current.addPermission(permission); current.addPermission(permission);
update(); update();
update();
} }
/** /**
@ -392,7 +411,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
* @return the range of the brush in blocks * @return the range of the brush in blocks
*/ */
public int getRange() { 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 * @param range the range of the brush in blocks
*/ */
public void setRange(int range) { public void setRange(int range) {
this.range = range; if (range == DEFAULT_RANGE) {
range = -1;
} else {
this.range = range;
}
} }
@Override @Override
@ -449,7 +472,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
} }
private Vector3 trace(EditSession editSession, Player player, int range, boolean useLastBlock) { 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); new MaskTraverser(mask).reset(editSession);
MaskedTargetBlock tb = new MaskedTargetBlock(mask, player, range, 0.2); MaskedTargetBlock tb = new MaskedTargetBlock(mask, player, range, 0.2);
return TaskManager.IMP.sync(new RunnableVal<Vector3>() { return TaskManager.IMP.sync(new RunnableVal<Vector3>() {
@ -461,23 +484,23 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
} }
public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) { public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) {
if (action == BrushAction.PRIMARY) { switch (action) {
setContext(primary); case PRIMARY:
} else if (action == BrushAction.SECONDARY) { setContext(primary);
setContext(secondary); break;
case SECONDARY:
setContext(secondary);
break;
} }
BrushSettings current = getContext(); BrushSettings current = getContext();
Brush brush = current.getBrush(); Brush brush = current.getBrush();
if (brush == null) return false; 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)) { 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); BlockVector3 target = getPosition(editSession, player);
if (target == null) { if (target == null) {
@ -485,6 +508,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
BBC.NO_BLOCK.send(player); BBC.NO_BLOCK.send(player);
return true; return true;
} }
BlockBag bag = editSession.getBlockBag();
Request.request().setEditSession(editSession); Request.request().setEditSession(editSession);
Mask mask = current.getMask(); Mask mask = current.getMask();
@ -519,11 +543,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
player.printError("Max blocks change limit reached."); player.printError("Max blocks change limit reached.");
} finally { } finally {
session.remember(editSession); session.remember(editSession);
if (bag != null) {
bag.flushChanges();
}
} }
} finally { } finally {
if (bag != null) {
bag.flushChanges();
}
Request.reset(); Request.reset();
} }
@ -552,11 +576,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
update(); update();
} }
public void setTargetMask(Mask mask) {
this.targetMask = mask;
update();
}
public void setVisualMode(Player player, VisualMode visualMode) { public void setVisualMode(Player player, VisualMode visualMode) {
if (visualMode == null) visualMode = VisualMode.NONE; if (visualMode == null) visualMode = VisualMode.NONE;
if (this.visualMode != visualMode) { if (this.visualMode != visualMode) {
@ -583,10 +602,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
return targetOffset; return targetOffset;
} }
public Mask getTargetMask() {
return targetMask;
}
public VisualMode getVisualMode() { public VisualMode getVisualMode() {
return visualMode; return visualMode;
} }

View File

@ -75,7 +75,7 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
if (this.range > -1) { if (this.range > -1) {
target = player.getBlockTrace(getRange(), true); target = player.getBlockTrace(getRange(), true);
} else { } else {
target = player.getBlockTrace(MAX_RANGE); target = player.getBlockTrace(DEFAULT_RANGE);
} }
if (target == null) { if (target == null) {

View File

@ -92,12 +92,7 @@ public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTo
private Location getTargetFace(Player player) { private Location getTargetFace(Player player) {
Location target = player.getBlockTraceFace(getRange(), true); Location target = player.getBlockTraceFace(getRange(), true);
if (this.range > -1) { target = player.getBlockTrace(getRange(), true);
target = player.getBlockTrace(getRange(), true);
} else {
target = player.getBlockTrace(MAX_RANGE, false);
}
if (target == null) { if (target == null) {
BBC.NO_BLOCK.send(player); BBC.NO_BLOCK.send(player);
return null; return null;

View File

@ -88,37 +88,4 @@ public class RecursivePickaxe implements BlockTool {
return true; return true;
} }
private static void recurse(Platform server, EditSession editSession, World world, BlockVector3 pos,
BlockVector3 origin, double size, BlockType initialType, Set<BlockVector3> 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);
}
} }

View File

@ -44,7 +44,7 @@ public class ClipboardBrush implements Brush {
this.ignoreAirBlocks = ignoreAirBlocks; this.ignoreAirBlocks = ignoreAirBlocks;
this.usingOrigin = usingOrigin; this.usingOrigin = usingOrigin;
this.pasteBiomes = false; this.pasteBiomes = false;
this.pasteEntities = false; this.pasteEntities = true;
this.sourceMask = null; this.sourceMask = null;
} }

View File

@ -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.BlockCategoryMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.BlockStateMaskParser; 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.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.ExistingMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser; import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser;
@ -58,20 +59,19 @@ public final class MaskFactory extends AbstractFactory<Mask> {
* @param worldEdit the WorldEdit instance * @param worldEdit the WorldEdit instance
*/ */
public MaskFactory(WorldEdit worldEdit) { public MaskFactory(WorldEdit worldEdit) {
super(worldEdit, new BlocksMaskParser(worldEdit)); super(worldEdit, new DefaultMaskParser(worldEdit));
register(new ExistingMaskParser(worldEdit)); // register(new ExistingMaskParser(worldEdit));
register(new SolidMaskParser(worldEdit)); // register(new SolidMaskParser(worldEdit));
register(new LazyRegionMaskParser(worldEdit)); // register(new LazyRegionMaskParser(worldEdit));
register(new RegionMaskParser(worldEdit)); // register(new RegionMaskParser(worldEdit));
register(new OffsetMaskParser(worldEdit)); // register(new OffsetMaskParser(worldEdit));
register(new NoiseMaskParser(worldEdit)); // register(new NoiseMaskParser(worldEdit));
register(new BlockStateMaskParser(worldEdit)); // register(new BlockStateMaskParser(worldEdit));
register(new NegateMaskParser(worldEdit)); // register(new NegateMaskParser(worldEdit));
register(new ExpressionMaskParser(worldEdit)); // register(new ExpressionMaskParser(worldEdit));
register(new BlockCategoryMaskParser(worldEdit)); // TODO implement in DefaultMaskParser
register(new BlockCategoryMaskParser(worldEdit)); // register(new BiomeMaskParser(worldEdit));
register(new BiomeMaskParser(worldEdit));
} }
@Override @Override
@ -96,7 +96,7 @@ public final class MaskFactory extends AbstractFactory<Mask> {
case 0: case 0:
throw new NoMatchException("No match for '" + input + "'"); throw new NoMatchException("No match for '" + input + "'");
case 1: case 1:
return masks.get(0); return masks.get(0).optimize();
default: default:
return new MaskIntersection(masks).optimize(); return new MaskIntersection(masks).optimize();
} }

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extension.factory;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser; 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.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.RandomPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser;
@ -44,16 +45,16 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
* @param worldEdit the WorldEdit instance * @param worldEdit the WorldEdit instance
*/ */
public PatternFactory(WorldEdit worldEdit) { public PatternFactory(WorldEdit worldEdit) {
super(worldEdit, new SingleBlockPatternParser(worldEdit)); super(worldEdit, new DefaultPatternParser(worldEdit));
// split and parse each sub-pattern // split and parse each sub-pattern
register(new RandomPatternParser(worldEdit)); // register(new RandomPatternParser(worldEdit));
// individual patterns // individual patterns
register(new ClipboardPatternParser(worldEdit)); // register(new ClipboardPatternParser(worldEdit));
register(new TypeOrStateApplyingPatternParser(worldEdit)); // register(new TypeOrStateApplyingPatternParser(worldEdit));
register(new RandomStatePatternParser(worldEdit)); // register(new RandomStatePatternParser(worldEdit));
register(new BlockCategoryPatternParser(worldEdit)); register(new BlockCategoryPatternParser(worldEdit)); // TODO implement in pattern parser
} }
} }

View File

@ -19,18 +19,23 @@
package com.sk89q.worldedit.extension.factory.parser; package com.sk89q.worldedit.extension.factory.parser;
import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.config.BBC; 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.jnbt.CompoundTag;
import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.NotABlockException; import com.sk89q.worldedit.NotABlockException;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.MobSpawnerBlock; import com.sk89q.worldedit.blocks.MobSpawnerBlock;
import com.sk89q.worldedit.blocks.SignBlock; import com.sk89q.worldedit.blocks.SignBlock;
import com.sk89q.worldedit.blocks.SkullBlock; 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.entity.Player;
import com.sk89q.worldedit.extension.input.DisallowedUsageException; import com.sk89q.worldedit.extension.input.DisallowedUsageException;
import com.sk89q.worldedit.extension.input.InputParseException; 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.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; 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.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property; 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.World;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories; 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.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.FuzzyBlockState; 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 com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.HashMap; import java.util.Arrays;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
@ -107,8 +111,6 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
} }
} }
private static String[] EMPTY_STRING_ARRAY = {};
/** /**
* Backwards compatibility for wool colours in block syntax. * Backwards compatibility for wool colours in block syntax.
* *
@ -160,75 +162,8 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
} }
} }
private static Map<Property<?>, Object> parseProperties(BlockType type, String[] stateProperties, ParserContext context) throws NoMatchException {
Map<Property<?>, 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<Object> propertyKey = (Property<Object>) 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<String> 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 { private BaseBlock parseLogic(String input, ParserContext context) throws InputParseException {
BlockType blockType = null; String[] blockAndExtraData = input.trim().split("\\|", 2);
Map<Property<?>, Object> blockStates = new HashMap<>();
String[] blockAndExtraData = input.trim().split("\\|");
blockAndExtraData[0] = woolMapper(blockAndExtraData[0]); blockAndExtraData[0] = woolMapper(blockAndExtraData[0]);
BlockState state = null; BlockState state = null;
@ -236,21 +171,31 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
// Legacy matcher // Legacy matcher
if (context.isTryingLegacy()) { if (context.isTryingLegacy()) {
try { try {
String[] split = blockAndExtraData[0].split(":", 2); String[] split = blockAndExtraData[0].split(":");
if (split.length == 0) { if (split.length == 1) {
throw new InputParseException("Invalid colon.");
} else if (split.length == 1) {
state = LegacyMapper.getInstance().getBlockFromLegacy(Integer.parseInt(split[0])); 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 { } 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) { } catch (NumberFormatException e) {
blockType = state.getBlockType();
}
} catch (NumberFormatException ignored) {
} }
} }
CompoundTag nbt = null;
if (state == null) { if (state == null) {
String typeString; String typeString;
String stateString = null; String stateString = null;
@ -259,101 +204,98 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
typeString = blockAndExtraData[0]; typeString = blockAndExtraData[0];
} else { } else {
typeString = blockAndExtraData[0].substring(0, stateStart); 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); stateString = blockAndExtraData[0].substring(stateStart + 1, blockAndExtraData[0].length() - 1);
} }
if (typeString.isEmpty()) { if (typeString.isEmpty()) {
throw new InputParseException("Invalid format"); throw new InputParseException("Invalid format");
} }
String[] stateProperties = EMPTY_STRING_ARRAY; // PosX
if (stateString != null) { if (typeString.matches("pos[0-9]+")) {
stateProperties = stateString.split(","); int index = Integer.parseInt(typeString.replaceAll("[a-z]+", ""));
}
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)) {
// Get the block type from the "primary position" // Get the block type from the "primary position"
final World world = context.requireWorld(); final World world = context.requireWorld();
final BlockVector3 primaryPosition; final BlockVector3 primaryPosition;
try { try {
primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition(); primaryPosition = context.requireSession().getRegionSelector(world).getVerticies().get(index - 1);
} catch (IncompleteRegionException e) { } catch (IncompleteRegionException e) {
throw new InputParseException("Your selection is not complete."); throw new InputParseException("Your selection is not complete.");
} }
final BlockState blockInHand = world.getBlock(primaryPosition); state = world.getBlock(primaryPosition);
blockType = blockInHand.getBlockType();
blockStates.putAll(blockInHand.getStates());
} else { } else {
// Attempt to lookup a block from ID or name. if ("hand".equalsIgnoreCase(typeString)) {
blockType = BlockTypes.get(typeString.toLowerCase(Locale.ROOT)); // 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) { if (!item.getType().hasBlockType()) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'"); 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 (type != null) {
state = type.getDefaultState();
if (context.isPreferringWildcard()) { }
FuzzyBlockState.Builder fuzzyBuilder = FuzzyBlockState.builder(); if (state == null) {
fuzzyBuilder.type(blockType); throw new NoMatchException("Does not match a valid block type: '" + input + "'");
for (Map.Entry<Property<?>, Object> blockState : blockStates.entrySet()) { }
@SuppressWarnings("unchecked")
Property<Object> objProp = (Property<Object>) blockState.getKey();
fuzzyBuilder.withProperty(objProp, blockState.getValue());
} }
state = fuzzyBuilder.build(); }
} else { if (nbt == null) nbt = state.getNbtData();
// No wildcards allowed => eliminate them. (Start with default state)
state = blockType.getDefaultState(); if (stateString != null) {
for (Map.Entry<Property<?>, Object> blockState : blockStates.entrySet()) { state = BlockState.get(state.getBlockType(), "[" + stateString + "]", state);
@SuppressWarnings("unchecked") if (context.isPreferringWildcard()) {
Property<Object> objProp = (Property<Object>) blockState.getKey(); if (stateString.isEmpty()) {
state = state.with(objProp, blockState.getValue()); 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<Object> 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) { if (blockAndExtraData.length > 1 && blockAndExtraData[1].startsWith("{")) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'"); 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 // Check if the item is allowed
if (context.isRestricted()) { BlockType blockType = state.getBlockType();
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 + "'");
}
}
if (!context.isTryingLegacy()) { if (nbt != null) return validate(context, state.toBaseBlock(nbt));
return state.toBaseBlock();
}
if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN
|| BlockCategories.SIGNS.contains(blockType)) { || BlockCategories.SIGNS.contains(blockType)) {
@ -363,35 +305,39 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
text[1] = blockAndExtraData.length > 2 ? blockAndExtraData[2] : ""; text[1] = blockAndExtraData.length > 2 ? blockAndExtraData[2] : "";
text[2] = blockAndExtraData.length > 3 ? blockAndExtraData[3] : ""; text[2] = blockAndExtraData.length > 3 ? blockAndExtraData[3] : "";
text[3] = blockAndExtraData.length > 4 ? blockAndExtraData[4] : ""; text[3] = blockAndExtraData.length > 4 ? blockAndExtraData[4] : "";
return new SignBlock(state, text); return validate(context, new SignBlock(state, text));
} else if (blockType == BlockTypes.SPAWNER) { } else if (blockType == BlockTypes.SPAWNER) {
// Allow setting mob spawn type // Allow setting mob spawn type
if (blockAndExtraData.length > 1) { if (blockAndExtraData.length > 1) {
String mobName = blockAndExtraData[1]; String mobName = blockAndExtraData[1];
EntityType ent = EntityTypes.get(mobName.toLowerCase(Locale.ROOT)); for (MobType mobType : MobType.values()) {
if (ent == null) { if (mobType.getName().toLowerCase().equals(mobName.toLowerCase(Locale.ROOT))) {
throw new NoMatchException("Unknown entity type '" + mobName + "'"); mobName = mobType.getName();
break;
}
} }
mobName = ent.getId();
if (!worldEdit.getPlatformManager().queryCapability(Capability.USER_COMMANDS).isValidMobType(mobName)) { 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 { } else {
//noinspection ConstantConditions return validate(context, new MobSpawnerBlock(state, MobType.PIG.getName()));
return new MobSpawnerBlock(state, EntityTypes.PIG.getId());
} }
} else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) { } else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) {
// allow setting type/player/rotation // allow setting type/player/rotation
if (blockAndExtraData.length <= 1) { if (blockAndExtraData.length <= 1) {
return new SkullBlock(state); return validate(context, new SkullBlock(state));
} }
String type = blockAndExtraData[1]; 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 { } else {
return state.toBaseBlock(); return validate(context, state.toBaseBlock());
} }
} }
@ -410,4 +356,4 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
} }
return holder; return holder;
} }
} }

View File

@ -120,7 +120,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
if (free == 2) { if (free == 2) {
final BlockVector3 pos = mutablePos.setComponents(x, y - 2, z); final BlockVector3 pos = mutablePos.setComponents(x, y - 2, z);
final BlockStateHolder state = world.getBlock(pos); 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; return;
} }
@ -139,7 +139,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
final BlockVector3 pos = BlockVector3.at(x, y, z); final BlockVector3 pos = BlockVector3.at(x, y, z);
final BlockState id = world.getBlock(pos); final BlockState id = world.getBlock(pos);
if (id.getBlockType().getMaterial().isMovementBlocker()) { 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; return;
} }
@ -412,7 +412,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
if (typeId.hasBlockType()) { if (typeId.hasBlockType()) {
return typeId.getBlockType().getDefaultState().toBaseBlock(); return typeId.getBlockType().getDefaultState().toBaseBlock();
} else { } else {
throw new NotABlockException(); return BlockTypes.AIR.getDefaultState().toBaseBlock();
} }
} }

View File

@ -331,89 +331,48 @@ public class PlatformManager {
if (event.isCancelled()) return; if (event.isCancelled()) return;
} }
if (event.getType() == Interaction.HIT) { switch (event.getType()) {
// superpickaxe is special because its primary interaction is a left click, not a right click case HIT: {
// in addition, it is implicitly bound to all pickaxe items, not just a single tool item // superpickaxe is special because its primary interaction is a left click, not a right click
if (player.getItemInHand(HandSide.MAIN_HAND).getType().getId().equals(getConfiguration().wandItem)) { // in addition, it is implicitly bound to all pickaxe items, not just a single tool item
if (!actor.hasPermission("worldedit.selection.pos")) { if (session.hasSuperPickAxe()) {
return; final BlockTool superPickaxe = session.getSuperPickaxe();
} if (superPickaxe != null && superPickaxe.canUse(player) && player.isHoldingPickAxe()) {
FawePlayer<?> fp = FawePlayer.wrap(player); FawePlayer<?> fp = FawePlayer.wrap(player);
RegionSelector selector = session.getRegionSelector(player.getWorld()); final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation());
final Player maskedPlayerWrapper = fp.runAction(() -> reset(superPickaxe).actPrimary(queryCapability(Capability.WORLD_EDITING), getConfiguration(), maskedPlayerWrapper, session, location), false, true);
new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), event.setCancelled(true);
((Player) actor).getLocation()); return;
BlockVector3 blockPoint = vector.toBlockPoint();
fp.runAction(() -> {
if (selector.selectPrimary(blockPoint,
ActorSelectorLimits.forActor(maskedPlayerWrapper))) {
selector
.explainPrimarySelection(actor, session, blockPoint);
} }
}, false, true); }
event.setCancelled(true); Tool tool = session.getTool(player);
return; if (tool instanceof DoubleActionBlockTool && tool.canUse(player)) {
}
if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) {
final BlockTool superPickaxe = session.getSuperPickaxe();
if (superPickaxe != null && superPickaxe.canUse(player)) {
FawePlayer<?> fp = FawePlayer.wrap(player); FawePlayer<?> fp = FawePlayer.wrap(player);
final Player maskedPlayerWrapper = new LocationMaskedPlayerWrapper(PlayerWrapper.wrap((Player) actor), ((Player) actor).getLocation()); 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); fp.runAction(() -> reset(((DoubleActionBlockTool) tool)).actSecondary(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);
event.setCancelled(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) { } catch (Throwable e) {

View File

@ -26,6 +26,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits; import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -156,4 +157,12 @@ public interface RegionSelector {
*/ */
List<String> getInformationLines(); List<String> getInformationLines();
/**
* Get the verticies
* @return
* @throws IncompleteRegionException
*/
default List<BlockVector3> getVerticies() throws IncompleteRegionException {
return Collections.singletonList(getPrimaryPosition());
}
} }

View File

@ -277,4 +277,8 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion
} }
} }
@Override
public List<BlockVector3> getVerticies() {
return new ArrayList<>(region.getVertices());
}
} }

View File

@ -36,6 +36,7 @@ import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -300,4 +301,8 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
return "cuboid"; return "cuboid";
} }
@Override
public List<BlockVector3> getVerticies() {
return Arrays.asList(position1, position2);
}
} }

View File

@ -39,7 +39,11 @@ public class FuzzyBlockState extends BlockState {
private final Map<PropertyKey, Object> props; private final Map<PropertyKey, Object> props;
FuzzyBlockState(BlockType blockType) { FuzzyBlockState(BlockType blockType) {
super(blockType); this(blockType.getDefaultState(), null);
}
public FuzzyBlockState(BlockState state) {
this(state, null);
} }
private FuzzyBlockState(BlockState state, Map<Property<?>, Object> values) { private FuzzyBlockState(BlockState state, Map<Property<?>, Object> values) {