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) {
Location target = null;
int range = this.range > -1 ? getRange() : MAX_RANGE;
int range = this.range > -1 ? getRange() : DEFAULT_RANGE;
if (adjacent) {
Location face = player.getBlockTraceFace(range, true);
return face.add(face.getDirection());

View File

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

View File

@ -154,4 +154,9 @@ public class FuzzyRegionSelector extends AbstractDelegateExtent implements Regio
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();
}
}
}

View File

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

View File

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

View File

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

View File

@ -281,7 +281,7 @@ public class BrushOptionsCommands extends MethodCommands {
parserContext.setSession(session);
parserContext.setExtent(editSession);
Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
tool.setTargetMask(mask);
tool.setTraceMask(mask);
BBC.BRUSH_TARGET_MASK_SET.send(player, context.getJoinedStrings(0));
}

View File

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

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.WorldEdit;
@ -31,6 +32,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
@ -39,6 +41,7 @@ import org.enginehub.piston.annotation.param.Switch;
/**
* Commands for moving the player around.
*/
@Command(aliases = {}, desc = "Commands for moving the player around: [More Info](https://goo.gl/uQTUiT)")
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class NavigationCommands {
@ -159,11 +162,12 @@ public class NavigationCommands {
desc = "Teleport to a location"
)
@CommandPermissions("worldedit.navigation.jumpto.command")
public void jumpTo(Player player) throws WorldEditException {
Location pos = player.getSolidBlockTrace(300);
public void jumpTo(Player player, @Arg(desc = "Location to jump to", def = "") Location pos, @Switch(name='f', desc = "force teleport") boolean force) throws WorldEditException {
if (pos == null) {
pos = player.getSolidBlockTrace(300);
}
if (pos != null) {
player.findFreePosition(pos);
if(force) player.setPosition(pos); else player.findFreePosition(pos);
BBC.POOF.send(player);
} else {
BBC.NO_BLOCK.send(player);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -61,7 +61,7 @@ public class ToolCommands {
)
public void none(Player player, LocalSession session) throws WorldEditException {
session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null);
session.setTool(player, null);
player.print("Tool unbound from your current item.");
}
@ -72,9 +72,8 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.setwand")
public void selwand(Player player, LocalSession session) throws WorldEditException {
final ItemType itemType = player.getItemInHand(HandSide.MAIN_HAND).getType();
session.setTool(itemType, new SelectionWand());
session.setTool(player, new SelectionWand());
player.print("Selection wand bound to " + itemType.getName() + ".");
}
@ -87,7 +86,7 @@ public class ToolCommands {
public void navwand(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new NavigationWand());
session.setTool(player, new NavigationWand());
player.print("Navigation wand bound to " + itemStack.getType().getName() + ".");
}
@ -99,7 +98,7 @@ public class ToolCommands {
public void info(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new QueryTool());
session.setTool(player, new QueryTool());
BBC.TOOL_INFO.send(player, itemStack.getType().getName());
}
@ -112,7 +111,7 @@ public class ToolCommands {
@Arg(desc = "The radius of the brush", def = "1")
double radius) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new InspectBrush());
session.setTool(player, new InspectBrush());
BBC.TOOL_INSPECT.send(player, itemStack.getType().getName());
}
@ -126,7 +125,7 @@ public class ToolCommands {
TreeGenerator.TreeType type) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new TreePlanter(type));
session.setTool(player, new TreePlanter(type));
BBC.TOOL_TREE.send(player, itemStack.getType().getName());
}
@ -140,7 +139,7 @@ public class ToolCommands {
Pattern pattern) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new BlockReplacer(pattern));
session.setTool(player, new BlockReplacer(pattern));
BBC.TOOL_REPL.send(player, itemStack.getType().getName());
}
@ -152,7 +151,7 @@ public class ToolCommands {
public void cycler(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new BlockDataCyler());
session.setTool(player, new BlockDataCyler());
BBC.TOOL_CYCLER.send(player, itemStack.getType().getName());
}
@ -176,7 +175,7 @@ public class ToolCommands {
}
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new FloodFillTool(range, pattern));
session.setTool(player, new FloodFillTool(range, pattern));
BBC.TOOL_FLOOD_FILL.send(player, itemStack.getType().getName());
}
@ -188,7 +187,7 @@ public class ToolCommands {
public void deltree(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new FloatingTreeRemover());
session.setTool(player, new FloatingTreeRemover());
BBC.TOOL_DELTREE.send(player, itemStack.getType().getName());
}
@ -200,7 +199,7 @@ public class ToolCommands {
public void farwand(Player player, LocalSession session) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new DistanceWand());
session.setTool(player, new DistanceWand());
BBC.TOOL_FARWAND.send(player, itemStack.getType().getName());
}
@ -217,7 +216,7 @@ public class ToolCommands {
Pattern secondary) throws WorldEditException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), new LongRangeBuildTool(primary, secondary));
session.setTool(player, new LongRangeBuildTool(primary, secondary));
BBC.TOOL_LRBUILD_BOUND.send(player, itemStack.getType().getName());
BBC.TOOL_LRBUILD_INFO.send(player, secondary, primary);
}

View File

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

View File

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

View File

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

View File

@ -93,10 +93,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
}
protected static int MAX_RANGE = 500;
protected static int DEFAULT_RANGE = 240;
protected int range = -1;
private VisualMode visualMode = VisualMode.NONE;
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private Mask targetMask = null;
private Mask traceMask;
private int targetOffset;
private transient BrushSettings primary = new BrushSettings();
@ -179,7 +180,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
if (targetMode != TargetMode.TARGET_BLOCK_RANGE) {
map.put("target", targetMode);
}
if (range != -1 && range != 240) {
if (range != -1 && range != DEFAULT_RANGE) {
map.put("range", range);
}
if (targetOffset != 0) {
@ -307,6 +308,25 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
update();
}
/**
* Get the mask used for identifying where to stop traces.
*
* @return the mask used to stop block traces
*/
public @Nullable Mask getTraceMask() {
return traceMask;
}
/**
* Set the block mask used for identifying where to stop traces.
*
* @param traceMask the mask used to stop block traces
*/
public void setTraceMask(@Nullable Mask traceMask) {
this.traceMask = traceMask;
update();
}
/**
* Set the block filter used for identifying blocks to replace.
*
@ -329,7 +349,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
current.setBrush(brush);
current.addPermission(permission);
update();
update();
}
/**
@ -392,7 +411,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
* @return the range of the brush in blocks
*/
public int getRange() {
return (range < 0) ? MAX_RANGE : Math.min(range, MAX_RANGE);
return (range < 0) ? DEFAULT_RANGE : Math.min(range, MAX_RANGE);
}
/**
@ -401,7 +420,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
* @param range the range of the brush in blocks
*/
public void setRange(int range) {
this.range = range;
if (range == DEFAULT_RANGE) {
range = -1;
} else {
this.range = range;
}
}
@Override
@ -449,7 +472,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
}
private Vector3 trace(EditSession editSession, Player player, int range, boolean useLastBlock) {
Mask mask = targetMask == null ? new SolidBlockMask(editSession) : targetMask;
Mask mask = traceMask == null ? new SolidBlockMask(editSession) : traceMask;
new MaskTraverser(mask).reset(editSession);
MaskedTargetBlock tb = new MaskedTargetBlock(mask, player, range, 0.2);
return TaskManager.IMP.sync(new RunnableVal<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) {
if (action == BrushAction.PRIMARY) {
setContext(primary);
} else if (action == BrushAction.SECONDARY) {
setContext(secondary);
switch (action) {
case PRIMARY:
setContext(primary);
break;
case SECONDARY:
setContext(secondary);
break;
}
BrushSettings current = getContext();
Brush brush = current.getBrush();
if (brush == null) return false;
BlockBag bag = session.getBlockBag(player);
if (current.setWorld(player.getWorld().getName()) && !current.canUse(player)) {
BBC.NO_PERM.send(player, StringMan.join(current.getPermissions(), ","));
return false;
}
try (EditSession editSession = session.createEditSession(player)) {
if (current.setWorld(editSession.getWorld().getName()) && !current.canUse(player)) {
BBC.NO_PERM.send(player, StringMan.join(current.getPermissions(), ","));
return false;
}
BlockVector3 target = getPosition(editSession, player);
if (target == null) {
@ -485,6 +508,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
BBC.NO_BLOCK.send(player);
return true;
}
BlockBag bag = editSession.getBlockBag();
Request.request().setEditSession(editSession);
Mask mask = current.getMask();
@ -519,11 +543,11 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
player.printError("Max blocks change limit reached.");
} finally {
session.remember(editSession);
if (bag != null) {
bag.flushChanges();
}
}
} finally {
if (bag != null) {
bag.flushChanges();
}
Request.reset();
}
@ -552,11 +576,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
update();
}
public void setTargetMask(Mask mask) {
this.targetMask = mask;
update();
}
public void setVisualMode(Player player, VisualMode visualMode) {
if (visualMode == null) visualMode = VisualMode.NONE;
if (this.visualMode != visualMode) {
@ -583,10 +602,6 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
return targetOffset;
}
public Mask getTargetMask() {
return targetMask;
}
public VisualMode getVisualMode() {
return visualMode;
}

View File

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

View File

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

View File

@ -88,37 +88,4 @@ public class RecursivePickaxe implements BlockTool {
return true;
}
private static void recurse(Platform server, EditSession editSession, World world, BlockVector3 pos,
BlockVector3 origin, double size, BlockType initialType, Set<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.usingOrigin = usingOrigin;
this.pasteBiomes = false;
this.pasteEntities = false;
this.pasteEntities = true;
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.BlockStateMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.BlocksMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.DefaultMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.ExistingMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.ExpressionMaskParser;
import com.sk89q.worldedit.extension.factory.parser.mask.LazyRegionMaskParser;
@ -58,20 +59,19 @@ public final class MaskFactory extends AbstractFactory<Mask> {
* @param worldEdit the WorldEdit instance
*/
public MaskFactory(WorldEdit worldEdit) {
super(worldEdit, new BlocksMaskParser(worldEdit));
super(worldEdit, new DefaultMaskParser(worldEdit));
register(new ExistingMaskParser(worldEdit));
register(new SolidMaskParser(worldEdit));
register(new LazyRegionMaskParser(worldEdit));
register(new RegionMaskParser(worldEdit));
register(new OffsetMaskParser(worldEdit));
register(new NoiseMaskParser(worldEdit));
register(new BlockStateMaskParser(worldEdit));
register(new NegateMaskParser(worldEdit));
register(new ExpressionMaskParser(worldEdit));
register(new BlockCategoryMaskParser(worldEdit));
register(new BiomeMaskParser(worldEdit));
// register(new ExistingMaskParser(worldEdit));
// register(new SolidMaskParser(worldEdit));
// register(new LazyRegionMaskParser(worldEdit));
// register(new RegionMaskParser(worldEdit));
// register(new OffsetMaskParser(worldEdit));
// register(new NoiseMaskParser(worldEdit));
// register(new BlockStateMaskParser(worldEdit));
// register(new NegateMaskParser(worldEdit));
// register(new ExpressionMaskParser(worldEdit));
register(new BlockCategoryMaskParser(worldEdit)); // TODO implement in DefaultMaskParser
// register(new BiomeMaskParser(worldEdit));
}
@Override
@ -96,7 +96,7 @@ public final class MaskFactory extends AbstractFactory<Mask> {
case 0:
throw new NoMatchException("No match for '" + input + "'");
case 1:
return masks.get(0);
return masks.get(0).optimize();
default:
return new MaskIntersection(masks).optimize();
}

View File

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

View File

@ -19,18 +19,23 @@
package com.sk89q.worldedit.extension.factory.parser;
import com.boydti.fawe.command.SuggestInputParseException;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.jnbt.JSON2NBT;
import com.boydti.fawe.jnbt.NBTException;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.StringMan;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.NotABlockException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.MobSpawnerBlock;
import com.sk89q.worldedit.blocks.SignBlock;
import com.sk89q.worldedit.blocks.SkullBlock;
import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.blocks.metadata.MobType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
import com.sk89q.worldedit.extension.input.InputParseException;
@ -38,6 +43,8 @@ import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.SlottableBlockBag;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property;
@ -45,19 +52,16 @@ import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockCategory;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.FuzzyBlockState;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import java.util.HashMap;
import java.util.Arrays;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
@ -107,8 +111,6 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
}
private static String[] EMPTY_STRING_ARRAY = {};
/**
* 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 {
BlockType blockType = null;
Map<Property<?>, Object> blockStates = new HashMap<>();
String[] blockAndExtraData = input.trim().split("\\|");
String[] blockAndExtraData = input.trim().split("\\|", 2);
blockAndExtraData[0] = woolMapper(blockAndExtraData[0]);
BlockState state = null;
@ -236,21 +171,31 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
// Legacy matcher
if (context.isTryingLegacy()) {
try {
String[] split = blockAndExtraData[0].split(":", 2);
if (split.length == 0) {
throw new InputParseException("Invalid colon.");
} else if (split.length == 1) {
String[] split = blockAndExtraData[0].split(":");
if (split.length == 1) {
state = LegacyMapper.getInstance().getBlockFromLegacy(Integer.parseInt(split[0]));
} else if (MathMan.isInteger(split[0])) {
int id = Integer.parseInt(split[0]);
int data = Integer.parseInt(split[1]);
if (data < 0 || data >= 16) {
throw new InputParseException("Invalid data " + data);
}
state = LegacyMapper.getInstance().getBlockFromLegacy(id, data);
} else {
state = LegacyMapper.getInstance().getBlockFromLegacy(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
BlockType type = BlockTypes.get(split[0].toLowerCase(Locale.ROOT));
if (type != null) {
int data = Integer.parseInt(split[1]);
if (data < 0 || data >= 16) {
throw new InputParseException("Invalid data " + data);
}
state = LegacyMapper.getInstance().getBlockFromLegacy(type.getLegacyCombinedId() >> 4, data);
}
}
if (state != null) {
blockType = state.getBlockType();
}
} catch (NumberFormatException ignored) {
} catch (NumberFormatException e) {
}
}
CompoundTag nbt = null;
if (state == null) {
String typeString;
String stateString = null;
@ -259,101 +204,98 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
typeString = blockAndExtraData[0];
} else {
typeString = blockAndExtraData[0].substring(0, stateStart);
if (stateStart + 1 >= blockAndExtraData[0].length()) {
throw new InputParseException("Invalid format. Hanging bracket @ " + stateStart + ".");
}
int stateEnd = blockAndExtraData[0].lastIndexOf(']');
if (stateEnd < 0) {
throw new InputParseException("Invalid format. Unclosed property.");
}
stateString = blockAndExtraData[0].substring(stateStart + 1, blockAndExtraData[0].length() - 1);
}
if (typeString.isEmpty()) {
throw new InputParseException("Invalid format");
}
String[] stateProperties = EMPTY_STRING_ARRAY;
if (stateString != null) {
stateProperties = stateString.split(",");
}
if ("hand".equalsIgnoreCase(typeString)) {
// Get the block type from the item in the user's hand.
final BaseBlock blockInHand = getBlockInHand(context.requireActor(), HandSide.MAIN_HAND).toBaseBlock();
if (blockInHand.getClass() != BaseBlock.class) {
return blockInHand;
}
blockType = blockInHand.getBlockType();
blockStates.putAll(blockInHand.getStates());
} else if ("offhand".equalsIgnoreCase(typeString)) {
// Get the block type from the item in the user's off hand.
final BaseBlock blockInHand = getBlockInHand(context.requireActor(), HandSide.OFF_HAND).toBaseBlock();
if (blockInHand.getClass() != BaseBlock.class) {
return blockInHand;
}
blockType = blockInHand.getBlockType();
blockStates.putAll(blockInHand.getStates());
} else if ("pos1".equalsIgnoreCase(typeString)) {
// PosX
if (typeString.matches("pos[0-9]+")) {
int index = Integer.parseInt(typeString.replaceAll("[a-z]+", ""));
// Get the block type from the "primary position"
final World world = context.requireWorld();
final BlockVector3 primaryPosition;
try {
primaryPosition = context.requireSession().getRegionSelector(world).getPrimaryPosition();
primaryPosition = context.requireSession().getRegionSelector(world).getVerticies().get(index - 1);
} catch (IncompleteRegionException e) {
throw new InputParseException("Your selection is not complete.");
}
final BlockState blockInHand = world.getBlock(primaryPosition);
blockType = blockInHand.getBlockType();
blockStates.putAll(blockInHand.getStates());
state = world.getBlock(primaryPosition);
} else {
// Attempt to lookup a block from ID or name.
blockType = BlockTypes.get(typeString.toLowerCase(Locale.ROOT));
}
if ("hand".equalsIgnoreCase(typeString)) {
// Get the block type from the item in the user's hand.
state = getBlockInHand(context.requireActor(), HandSide.MAIN_HAND);
} else if ("offhand".equalsIgnoreCase(typeString)) {
// Get the block type from the item in the user's off hand.
state = getBlockInHand(context.requireActor(), HandSide.OFF_HAND);
} else if (typeString.matches("slot[0-9]+")) {
int slot = Integer.parseInt(typeString.substring(4)) - 1;
Actor actor = context.requireActor();
if (!(actor instanceof Player)) {
throw new InputParseException("The user is not a player!");
}
Player player = (Player) actor;
BlockBag bag = player.getInventoryBlockBag();
if (bag == null || !(bag instanceof SlottableBlockBag)) {
throw new InputParseException("Unsupported!");
}
SlottableBlockBag slottable = (SlottableBlockBag) bag;
BaseItem item = slottable.getItem(slot);
if (blockType == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
}
if (!item.getType().hasBlockType()) {
throw new InputParseException("You're not holding a block!");
}
state = item.getType().getBlockType().getDefaultState();
nbt = item.getNbtData();
} else {
BlockType type = BlockTypes.parse(typeString.toLowerCase(Locale.ROOT));
blockStates.putAll(parseProperties(blockType, stateProperties, context));
if (context.isPreferringWildcard()) {
FuzzyBlockState.Builder fuzzyBuilder = FuzzyBlockState.builder();
fuzzyBuilder.type(blockType);
for (Map.Entry<Property<?>, Object> blockState : blockStates.entrySet()) {
@SuppressWarnings("unchecked")
Property<Object> objProp = (Property<Object>) blockState.getKey();
fuzzyBuilder.withProperty(objProp, blockState.getValue());
if (type != null) {
state = type.getDefaultState();
}
if (state == null) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
}
}
state = fuzzyBuilder.build();
} else {
// No wildcards allowed => eliminate them. (Start with default state)
state = blockType.getDefaultState();
for (Map.Entry<Property<?>, Object> blockState : blockStates.entrySet()) {
@SuppressWarnings("unchecked")
Property<Object> objProp = (Property<Object>) blockState.getKey();
state = state.with(objProp, blockState.getValue());
}
if (nbt == null) nbt = state.getNbtData();
if (stateString != null) {
state = BlockState.get(state.getBlockType(), "[" + stateString + "]", state);
if (context.isPreferringWildcard()) {
if (stateString.isEmpty()) {
state = new FuzzyBlockState(state);
} else {
BlockType type = state.getBlockType();
FuzzyBlockState.Builder fuzzyBuilder = FuzzyBlockState.builder();
fuzzyBuilder.type(type);
String[] entries = stateString.split(",");
for (String entry : entries) {
String[] split = entry.split("=");
String key = split[0];
String val = split[1];
Property<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) {
throw new NoMatchException("Does not match a valid block type: '" + input + "'");
if (blockAndExtraData.length > 1 && blockAndExtraData[1].startsWith("{")) {
String joined = StringMan.join(Arrays.copyOfRange(blockAndExtraData, 1, blockAndExtraData.length), "|");
try {
nbt = JSON2NBT.getTagFromJson(joined);
} catch (NBTException e) {
throw new NoMatchException(e.getMessage());
}
}
// Check if the item is allowed
if (context.isRestricted()) {
Actor actor = context.requireActor();
if (actor != null && !actor.hasPermission("worldedit.anyblock")
&& worldEdit.getConfiguration().disallowedBlocks.contains(blockType.getId())) {
throw new DisallowedUsageException("You are not allowed to use '" + input + "'");
}
}
BlockType blockType = state.getBlockType();
if (!context.isTryingLegacy()) {
return state.toBaseBlock();
}
if (nbt != null) return validate(context, state.toBaseBlock(nbt));
if (blockType == BlockTypes.SIGN || blockType == BlockTypes.WALL_SIGN
|| BlockCategories.SIGNS.contains(blockType)) {
@ -363,35 +305,39 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
text[1] = blockAndExtraData.length > 2 ? blockAndExtraData[2] : "";
text[2] = blockAndExtraData.length > 3 ? blockAndExtraData[3] : "";
text[3] = blockAndExtraData.length > 4 ? blockAndExtraData[4] : "";
return new SignBlock(state, text);
return validate(context, new SignBlock(state, text));
} else if (blockType == BlockTypes.SPAWNER) {
// Allow setting mob spawn type
if (blockAndExtraData.length > 1) {
String mobName = blockAndExtraData[1];
EntityType ent = EntityTypes.get(mobName.toLowerCase(Locale.ROOT));
if (ent == null) {
throw new NoMatchException("Unknown entity type '" + mobName + "'");
for (MobType mobType : MobType.values()) {
if (mobType.getName().toLowerCase().equals(mobName.toLowerCase(Locale.ROOT))) {
mobName = mobType.getName();
break;
}
}
mobName = ent.getId();
if (!worldEdit.getPlatformManager().queryCapability(Capability.USER_COMMANDS).isValidMobType(mobName)) {
throw new NoMatchException("Unknown mob type '" + mobName + "'");
String finalMobName = mobName.toLowerCase(Locale.ROOT);
throw new SuggestInputParseException("Unknown mob type '" + mobName + "'", mobName, () -> Stream.of(MobType.values())
.map(m -> m.getName().toLowerCase(Locale.ROOT))
.filter(s -> s.startsWith(finalMobName))
.collect(Collectors.toList()));
}
return new MobSpawnerBlock(state, mobName);
return validate(context, new MobSpawnerBlock(state, mobName));
} else {
//noinspection ConstantConditions
return new MobSpawnerBlock(state, EntityTypes.PIG.getId());
return validate(context, new MobSpawnerBlock(state, MobType.PIG.getName()));
}
} else if (blockType == BlockTypes.PLAYER_HEAD || blockType == BlockTypes.PLAYER_WALL_HEAD) {
// allow setting type/player/rotation
if (blockAndExtraData.length <= 1) {
return new SkullBlock(state);
return validate(context, new SkullBlock(state));
}
String type = blockAndExtraData[1];
return new SkullBlock(state, type.replace(" ", "_")); // valid MC usernames
return validate(context, new SkullBlock(state, type.replace(" ", "_"))); // valid MC usernames
} else {
return state.toBaseBlock();
return validate(context, state.toBaseBlock());
}
}
@ -410,4 +356,4 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
return holder;
}
}
}

View File

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

View File

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

View File

@ -26,6 +26,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
import com.sk89q.worldedit.world.World;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
@ -156,4 +157,12 @@ public interface RegionSelector {
*/
List<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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
@ -300,4 +301,8 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
return "cuboid";
}
@Override
public List<BlockVector3> getVerticies() {
return Arrays.asList(position1, position2);
}
}

View File

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