From ffc2092d932ac661ae434da8b72b449b854806f5 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Sun, 30 Jun 2019 14:56:32 -0400 Subject: [PATCH] toggles and timeouts --- .../com/boydti/fawe/bukkit/BukkitPlayer.java | 2 +- .../worldedit/bukkit/BukkitCommandSender.java | 11 +- .../sk89q/worldedit/bukkit/BukkitPlayer.java | 29 ++++ .../com/boydti/fawe/object/FawePlayer.java | 19 --- .../boydti/fawe/wrappers/PlayerWrapper.java | 90 +++++----- .../java/com/sk89q/worldedit/EditSession.java | 158 +++++++++++++----- .../worldedit/command/OptionsCommands.java | 24 ++- .../worldedit/command/RegionCommands.java | 34 ++-- .../extension/platform/PlayerProxy.java | 12 +- .../worldedit/function/factory/Deform.java | 9 +- .../function/generator/FloraGenerator.java | 13 +- .../function/mask/BlockTypeMask.java | 5 - .../function/mask/ExpressionMask.java | 1 - .../function/mask/ExpressionMask2D.java | 1 - .../function/mask/SolidBlockMask.java | 16 +- .../function/pattern/WaterloggedRemover.java | 9 +- .../function/visitor/BreadthFirstSearch.java | 1 + .../internal/expression/Expression.java | 1 + .../sk89q/worldedit/util/auth/Subject.java | 9 + 19 files changed, 272 insertions(+), 172 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java index 17fe87fa7..02ff18c46 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java @@ -45,7 +45,7 @@ public class BukkitPlayer extends FawePlayer { * Permissions are used to managing WorldEdit region restrictions * - The `/wea` command will give/remove the required bypass permission */ - if (Fawe. imp().getVault() == null || Fawe. imp().getVault().permission == null) { + if (Fawe.imp().getVault() == null || Fawe. imp().getVault().permission == null) { this.parent.addAttachment(Fawe. imp().getPlugin()).setPermission(perm, flag); } else if (flag) { if (!Fawe. imp().getVault().permission.playerAdd(this.parent, perm)) { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java index 55929af02..4059bf080 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitCommandSender.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.bukkit; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; - import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.internal.cui.CUIEvent; import com.sk89q.worldedit.session.SessionKey; @@ -29,11 +28,10 @@ import com.sk89q.worldedit.util.auth.AuthorizationException; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import javax.annotation.Nullable; import java.io.File; import java.util.UUID; -import javax.annotation.Nullable; - public class BukkitCommandSender implements Actor { /** @@ -106,6 +104,13 @@ public class BukkitCommandSender implements Actor { return true; } + @Override public boolean togglePermission(String permission) { + return false; + } + + @Override public void setPermission(String permission, boolean value) { + } + @Override public void checkPermission(String permission) throws AuthorizationException { } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 9b25740c6..8f1ddc153 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.bukkit; +import com.boydti.fawe.Fawe; +import com.boydti.fawe.bukkit.FaweBukkit; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.TaskManager; @@ -200,6 +202,33 @@ public class BukkitPlayer extends AbstractPlayerActor { player.getWorld().getName(), player, perm); } + @Override public boolean togglePermission(String permission) { + if (this.hasPermission(permission)) { + player.addAttachment(plugin).setPermission(permission, false); + return false; + } else { + player.addAttachment(plugin).setPermission(permission, true); + return true; + } + } + + @Override + public void setPermission(String permission, boolean value) { + /* + * Permissions are used to managing WorldEdit region restrictions + * - The `/wea` command will give/remove the required bypass permission + */ + if (Fawe.imp().getVault() == null || Fawe. imp().getVault().permission == null) { + player.addAttachment(Fawe. imp().getPlugin()).setPermission(permission, value); + } else if (value) { + if (!Fawe. imp().getVault().permission.playerAdd(player, permission)) { + player.addAttachment(Fawe. imp().getPlugin()).setPermission(permission, value); + } + } else if (!Fawe.imp().getVault().permission.playerRemove(player, permission)) { + player.addAttachment(Fawe.imp().getPlugin()).setPermission(permission, value); + } + } + @Override public World getWorld() { return BukkitAdapter.adapt(player.getWorld()); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/FawePlayer.java b/worldedit-core/src/main/java/com/boydti/fawe/object/FawePlayer.java index a758c866b..5b1bf1583 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object; import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweAPI; import com.boydti.fawe.command.CFICommands; import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; @@ -249,16 +248,6 @@ public abstract class FawePlayer extends Metadatable { } } - public boolean toggle(String perm) { - if (this.hasPermission(perm)) { - this.setPermission(perm, false); - return false; - } else { - this.setPermission(perm, true); - return true; - } - } - /** * Queue an action to run async * @param run @@ -457,14 +446,6 @@ public abstract class FawePlayer extends Metadatable { */ public abstract boolean hasPermission(final String perm); - /** - * Set a permission (requires Vault) - * - * @param perm - * @param flag - */ - public abstract void setPermission(final String perm, final boolean flag); - /** * Send a message to the player * diff --git a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java index 4ff97afc3..92e7b0f94 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/wrappers/PlayerWrapper.java @@ -5,9 +5,10 @@ import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.*; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Player; @@ -22,16 +23,14 @@ import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.HandSide; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TargetBlock; -import com.sk89q.worldedit.util.auth.AuthorizationException; import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.gamemode.GameMode; import javax.annotation.Nullable; import java.io.File; import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.function.Supplier; public class PlayerWrapper extends AbstractPlayerActor { private final Player parent; @@ -131,6 +130,14 @@ public class PlayerWrapper extends AbstractPlayerActor { return parent.hasPermission(perm); } + @Override public boolean togglePermission(String permission) { + return parent.togglePermission(permission); + } + + @Override public void setPermission(String permission, boolean value) { + parent.setPermission(permission, value); + } + @Override public void dispatchCUIEvent(CUIEvent event) { parent.dispatchCUIEvent(event); @@ -336,50 +343,47 @@ public class PlayerWrapper extends AbstractPlayerActor { @Override public boolean passThroughForwardWall(final int range) { - return TaskManager.IMP.sync(new Supplier() { - @Override - public Boolean get() { - int searchDist = 0; - TargetBlock hitBlox = new TargetBlock(PlayerWrapper.this, range, 0.2); - Extent world = getLocation().getExtent(); - Location block; - boolean firstBlock = true; - int freeToFind = 2; - boolean inFree = false; + return TaskManager.IMP.sync(() -> { + int searchDist = 0; + TargetBlock hitBlox = new TargetBlock(PlayerWrapper.this, range, 0.2); + Extent world = getLocation().getExtent(); + Location block; + boolean firstBlock = true; + int freeToFind = 2; + boolean inFree = false; - while ((block = hitBlox.getNextBlock()) != null) { - boolean free = !world.getBlock(BlockVector3.at(block.getBlockX(), block.getBlockY(), block.getBlockZ())).getBlockType().getMaterial().isMovementBlocker(); + while ((block = hitBlox.getNextBlock()) != null) { + boolean free = !world.getBlock(BlockVector3.at(block.getBlockX(), block.getBlockY(), block.getBlockZ())).getBlockType().getMaterial().isMovementBlocker(); - if (firstBlock) { - firstBlock = false; + if (firstBlock) { + firstBlock = false; - if (!free) { - --freeToFind; - continue; - } + if (!free) { + --freeToFind; + continue; } - - ++searchDist; - if (searchDist > 20) { - return false; - } - - if (inFree != free) { - if (free) { - --freeToFind; - } - } - - if (freeToFind == 0) { - setOnGround(block); - return true; - } - - inFree = free; } - return false; + ++searchDist; + if (searchDist > 20) { + return false; + } + + if (inFree != free) { + if (free) { + --freeToFind; + } + } + + if (freeToFind == 0) { + setOnGround(block); + return true; + } + + inFree = free; } + + return false; }); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 9cdfe5543..a49f1ddf2 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -377,7 +377,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } else { this.extent = new ProcessedWEExtent(this.extent, this.limit); if (allowedRegions.length == 1) { - Region region = allowedRegions[0]; this.extent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]); } else { this.extent = new MultiRegionExtent(this.extent, this.limit, allowedRegions); @@ -1155,11 +1154,11 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, this.changes++; switch (stage) { case BEFORE_HISTORY: - return this.extent.setBlock(position, block); + return extent.setBlock(position, block); case BEFORE_CHANGE: - return this.bypassHistory.setBlock(position, block); + return bypassHistory.setBlock(position, block); case BEFORE_REORDER: - return this.bypassAll.setBlock(position, block); + return bypassAll.setBlock(position, block); } throw new RuntimeException("New enum entry added that is unhandled here"); @@ -1175,7 +1174,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public > boolean rawSetBlock(BlockVector3 position, B block) { this.changes++; try { - return this.bypassAll.setBlock(position, block); + return bypassAll.setBlock(position, block); } catch (WorldEditException e) { throw new RuntimeException("Unexpected exception", e); } @@ -1201,7 +1200,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public > boolean setBlock(BlockVector3 position, B block) throws MaxChangedBlocksException { this.changes++; try { - return this.extent.setBlock(position, block); + return extent.setBlock(position, block); } catch (MaxChangedBlocksException e) { throw e; } catch (WorldEditException e) { @@ -1209,6 +1208,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } } + public > boolean setBlock(int x, int y, int z, B block) { this.changes++; try { @@ -1218,6 +1218,16 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } } + /** + * Sets the block at the given coordiantes, subject to both history and block re-ordering. + * + * @param x the x coordinate + * @param y the y coordinate + * @param z the z coordinate + * @param pattern a pattern to use + * @return Whether the block changed -- not entirely dependable + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ public boolean setBlock(int x, int y, int z, Pattern pattern) { this.changes++; try { @@ -1228,8 +1238,15 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } } - @SuppressWarnings("deprecation") - public boolean setBlock(final BlockVector3 position, final Pattern pattern) { + /** + * Sets the block at a position, subject to both history and block re-ordering. + * + * @param position the position + * @param pattern a pattern to use + * @return Whether the block changed -- not entirely dependable + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + public boolean setBlock(BlockVector3 position, Pattern pattern) throws MaxChangedBlocksException { this.changes++; try { return pattern.apply(this.extent, position, position); @@ -1238,8 +1255,16 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } } - @SuppressWarnings("deprecation") - public int setBlocks(final Set vset, final Pattern pattern) { + /** + * Set blocks that are in a set of positions and return the number of times + * that the block set calls returned true. + * + * @param vset a set of positions + * @param pattern the pattern + * @return the number of changed blocks + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + public int setBlocks(Set vset, Pattern pattern) throws MaxChangedBlocksException { RegionVisitor visitor = new RegionVisitor(vset, new BlockReplace(extent, pattern), this); Operations.completeBlindly(visitor); changes += visitor.getAffected(); @@ -1492,7 +1517,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @param searchBlocks the list of blocks to search * @return the number of blocks that matched the pattern */ - public int countBlocks(Region region, Set searchBlocks) { + public int countBlocks(Region region, Set searchBlocks) { Mask mask = new BlockMaskBuilder().addBlocks(searchBlocks).build(extent); RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() { @Override @@ -1585,7 +1610,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @throws MaxChangedBlocksException thrown if too many blocks are changed */ public > int fillXZ(BlockVector3 origin, B block, double radius, int depth, boolean recursive) throws MaxChangedBlocksException { - return fillXZ(origin, (block), radius, depth, recursive); + return fillXZ(origin, block, radius, depth, recursive); } /** @@ -1650,7 +1675,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, getWorld(), // Causes clamping of Y range position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, height - 1, apothem - 1)); - Pattern pattern = (BlockTypes.AIR.getDefaultState()); + Pattern pattern = BlockTypes.AIR.getDefaultState(); return setBlocks(region, pattern); } @@ -1672,7 +1697,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, getWorld(), // Causes clamping of Y range position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, -height + 1, apothem - 1)); - Pattern pattern = (BlockTypes.AIR.getDefaultState()); + Pattern pattern = BlockTypes.AIR.getDefaultState(); return setBlocks(region, pattern); } @@ -1685,7 +1710,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @return number of blocks affected * @throws MaxChangedBlocksException thrown if too many blocks are changed */ - public int removeNear(final BlockVector3 position, Mask mask, final int apothem) { + public int removeNear(BlockVector3 position, Mask mask, int apothem) throws MaxChangedBlocksException { checkNotNull(position); checkArgument(apothem >= 1, "apothem >= 1"); @@ -1796,6 +1821,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { checkNotNull(region); checkNotNull(pattern); + if (pattern instanceof BlockPattern) { return setBlocks(region, ((BlockPattern) pattern).getBlock()); } @@ -2005,7 +2031,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public > int overlayCuboidBlocks(Region region, B block) throws MaxChangedBlocksException { checkNotNull(block); - return overlayCuboidBlocks(region, (block)); + return overlayCuboidBlocks(region, block); } /** @@ -2997,7 +3023,27 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @throws MaxChangedBlocksException */ public int makeShape(final Region region, final Vector3 zero, final Vector3 unit, - final Pattern pattern, final String expressionString, final boolean hollow) + final Pattern pattern, final String expressionString, final boolean hollow) + throws ExpressionException, MaxChangedBlocksException { + return makeShape(region, zero, unit, pattern, expressionString, hollow, WorldEdit.getInstance().getConfiguration().calculationTimeout); + } + + /** + * Generate a shape for the given expression. + * + * @param region the region to generate the shape in + * @param zero the coordinate origin for x/y/z variables + * @param unit the scale of the x/y/z/ variables + * @param pattern the default material to make the shape from + * @param expressionString the expression defining the shape + * @param hollow whether the shape should be hollow + * @param timeout the time, in milliseconds, to wait for each expression evaluation before halting it. -1 to disable + * @return number of blocks changed + * @throws ExpressionException + * @throws MaxChangedBlocksException + */ + public int makeShape(final Region region, final Vector3 zero, final Vector3 unit, + final Pattern pattern, final String expressionString, final boolean hollow, final int timeout) throws ExpressionException, MaxChangedBlocksException { final Expression expression = Expression.compile(expressionString, "x", "y", "z", "type", "data"); expression.optimize(); @@ -3011,21 +3057,21 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, final int[] timedOut = {0}; final ArbitraryShape shape = new ArbitraryShape(region) { @Override - public BaseBlock getMaterial(final int x, final int y, final int z, final BaseBlock defaultMaterial) { - //TODO Optimize - avoid vector creation (math) -// final Vector3 current = mutablev.setComponents(x, y, z); -// protected BlockStateHolder getMaterial(int x, int y, int z, BlockStateHolder defaultMaterial) { + protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) { final Vector3 current = Vector3.at(x, y, z); environment.setCurrentBlock(current); final Vector3 scaled = current.subtract(zero).divide(unit); try { - if (expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ(), defaultMaterial.getBlockType().getInternalId(), defaultMaterial.getInternalPropertiesId()) <= 0) { + if (expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ(), defaultMaterial.getBlockType().getInternalId(), defaultMaterial.getInternalPropertiesId()}, timeout) <= 0) { // TODO data return null; } return BlockTypes.get((int) typeVariable.getValue()).withPropertyId((int) dataVariable.getValue()).toBaseBlock(); + } catch (ExpressionTimeoutException e) { + timedOut[0] = timedOut[0] + 1; + return null; } catch (Exception e) { log.warn("Failed to create shape", e); return null; @@ -3043,6 +3089,11 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString) throws ExpressionException, MaxChangedBlocksException { + return deformRegion(region, zero, unit, expressionString, WorldEdit.getInstance().getConfiguration().calculationTimeout); + } + + public int deformRegion(final Region region, final Vector3 zero, final Vector3 unit, final String expressionString, + final int timeout) throws ExpressionException, MaxChangedBlocksException { final Expression expression = Expression.compile(expressionString, "x", "y", "z"); expression.optimize(); @@ -3060,15 +3111,15 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public boolean apply(BlockVector3 position) throws WorldEditException { try { // offset, scale - double sx = (position.getX() - zero.getX()) / unit.getX(); - double sy = (position.getY() - zero.getY()) / unit.getY(); - double sz = (position.getZ() - zero.getZ()) / unit.getZ(); + final Vector3 scaled = position.toVector3().subtract(zero).divide(unit); + // transform - expression.evaluate(sx, sy, sz); + expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ()}, timeout); int xv = (int) (x.getValue() * unit.getX() + zero2.getX()); int yv = (int) (y.getValue() * unit.getY() + zero2.getY()); int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ()); - // read/write block from world + + // read block from world return setBlock(position, getBlock(xv, yv, zv)); } catch (EvaluationException e) { throw new RuntimeException(e); @@ -3159,7 +3210,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, return changes; } - public int drawLine(final Pattern pattern, final BlockVector3 pos1, final BlockVector3 pos2, final double radius, final boolean filled) { + public int drawLine(final Pattern pattern, final BlockVector3 pos1, final BlockVector3 pos2, final double radius, final boolean filled) throws MaxChangedBlocksException { return drawLine(pattern, pos1, pos2, radius, filled, false); } @@ -3175,7 +3226,8 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, * @return number of blocks affected * @throws MaxChangedBlocksException thrown if too many blocks are changed */ - public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, double radius, boolean filled, boolean flat) { + public int drawLine(Pattern pattern, BlockVector3 pos1, BlockVector3 pos2, double radius, boolean filled, boolean flat) + throws MaxChangedBlocksException { LocalBlockVectorSet vset = new LocalBlockVectorSet(); boolean notdrawn = true; @@ -3336,11 +3388,12 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, final LocalBlockVectorSet returnset = new LocalBlockVectorSet(); final LocalBlockVectorSet newset = new LocalBlockVectorSet(); newset.addAll(vset); - for (final BlockVector3 v : newset) { + for (BlockVector3 v : newset) { final int x = v.getX(), y = v.getY(), z = v.getZ(); - if (!(newset.contains(x + 1, y, z) - && newset.contains(x - 1, y, z) - && newset.contains(x, y, z + 1) && newset.contains(x, y, z - 1))) { + if (!(newset.contains(x + 1, y, z) && + newset.contains(x - 1, y, z) && + newset.contains(x, y, z + 1) && + newset.contains(x, y, z - 1))) { returnset.add(v); } } @@ -3348,16 +3401,17 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } public Set getHollowed(final Set vset) { - final Set returnset = new LocalBlockVectorSet(); + final Set returnset = new LocalBlockVectorSet(); final LocalBlockVectorSet newset = new LocalBlockVectorSet(); newset.addAll(vset); - for (final BlockVector3 v : newset) { + for (BlockVector3 v : newset) { final int x = v.getX(), y = v.getY(), z = v.getZ(); - if (!(newset.contains(x + 1, y, z) - && newset.contains(x - 1, y, z) - && newset.contains(x, y + 1, z) - && newset.contains(x, y - 1, z) - && newset.contains(x, y, z + 1) && newset.contains(x, y, z - 1))) { + if (!(newset.contains(x + 1, y, z) && + newset.contains(x - 1, y, z) && + newset.contains(x, y + 1, z) && + newset.contains(x, y - 1, z) && + newset.contains(x, y, z + 1) && + newset.contains(x, y, z - 1))) { returnset.add(v); } } @@ -3368,7 +3422,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, final LocalBlockVectorSet queue = new LocalBlockVectorSet(); queue.add(origin); while (!queue.isEmpty()) { - BlockVector3 current = queue.getIndex(0); + final BlockVector3 current = queue.getIndex(0); queue.remove(current); final BlockState block = getBlock(current); if (block.getBlockType().getMaterial().isMovementBlocker()) { @@ -3392,6 +3446,12 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType, final String expressionString, final boolean hollow) throws ExpressionException, MaxChangedBlocksException { + return makeBiomeShape(region, zero, unit, biomeType, expressionString, hollow, WorldEdit.getInstance().getConfiguration().calculationTimeout); + } + + public int makeBiomeShape(final Region region, final Vector3 zero, final Vector3 unit, final BiomeType biomeType, + final String expressionString, final boolean hollow, final int timeout) + throws ExpressionException, MaxChangedBlocksException { final Vector2 zero2D = zero.toVector2(); final Vector2 unit2D = unit.toVector2(); @@ -3402,20 +3462,24 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(editSession, unit, zero); expression.setEnvironment(environment); + final int[] timedOut = {0}; final ArbitraryBiomeShape shape = new ArbitraryBiomeShape(region) { @Override - protected BiomeType getBiome(final int x, final int z, final BiomeType defaultBiomeType) { + protected BiomeType getBiome(int x, int z, BiomeType defaultBiomeType) { environment.setCurrentBlock(x, 0, z); double scaledX = (x - zero2D.getX()) / unit2D.getX(); double scaledZ = (z - zero2D.getZ()) / unit2D.getZ(); try { - if (expression.evaluate(scaledX, scaledZ) <= 0) { + if (expression.evaluate(new double[]{scaledX, scaledZ}, timeout) <= 0) { return null; } // TODO: Allow biome setting via a script variable (needs BiomeType<->int mapping) return defaultBiomeType; + } catch (ExpressionTimeoutException e) { + timedOut[0] = timedOut[0] + 1; + return null; } catch (Exception e) { log.warn("Failed to create shape", e); return null; @@ -3423,6 +3487,11 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } }; int changed = shape.generate(this, biomeType, hollow); + if (timedOut[0] > 0) { + throw new ExpressionTimeoutException( + String.format("%d blocks changed. %d blocks took too long to evaluate (increase time with //timeout)", + changed, timedOut[0])); + } return changed; } @@ -3529,7 +3598,6 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, boolean containsAny = false; if (cuboid && containsBot1 && containsBot2 && containsTop1 && containsTop2 && conNextX && conNextZ) { containsAny = true; - BlockVector3 mbv = mutable; if (fcs != null) { for (int x = 0; x < 16; x++) { int xx = x + bx; @@ -3537,7 +3605,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, int zz = z + bz; for (int y = 0; y < maxY + 1; y++) { BaseBlock block = getFullBlock(mutable.setComponents(xx, y, zz)); - fcs.add(mbv, block, BlockTypes.AIR.getDefaultState().toBaseBlock()); + fcs.add(mutable, block, BlockTypes.AIR.getDefaultState().toBaseBlock()); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java index edb5a0dfd..8572c984c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java @@ -4,31 +4,37 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.extent.ResettableExtent; -import com.boydti.fawe.util.*; +import com.boydti.fawe.util.CachedTextureUtil; +import com.boydti.fawe.util.CleanTextureUtil; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.RandomTextureUtil; +import com.boydti.fawe.util.TextureUtil; + +import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.collect.Sets; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; -import com.sk89q.worldedit.*; -import com.sk89q.worldedit.extension.input.DisallowedUsageException; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.DisallowedUsageException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.ParameterException; +import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemTypes; import java.io.FileNotFoundException; import java.util.HashSet; - -import static com.google.common.base.Preconditions.checkNotNull; - /** * General WorldEdit commands. */ @@ -54,7 +60,7 @@ public class OptionsCommands { @CommandPermissions("fawe.tips") public void tips(Player player, LocalSession session) throws WorldEditException { FawePlayer fp = FawePlayer.wrap(player); - if (fp.toggle("fawe.tips")) { + if (player.togglePermission("fawe.tips")) { BBC.WORLDEDIT_TOGGLE_TIPS_ON.send(player); } else { BBC.WORLDEDIT_TOGGLE_TIPS_OFF.send(player); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index c1cc532f0..bd96cd32d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -28,12 +28,16 @@ import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.visitor.Fast2DIterator; import com.boydti.fawe.util.MathMan; + +import static com.google.common.base.Preconditions.checkNotNull; import com.sk89q.jnbt.CompoundTag; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.Logging; - +import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL; +import static com.sk89q.minecraft.util.commands.Logging.LogMode.ORIENTATION_REGION; +import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; @@ -58,7 +62,14 @@ import com.sk89q.worldedit.math.convolution.GaussianKernel; import com.sk89q.worldedit.math.convolution.HeightMap; import com.sk89q.worldedit.math.convolution.HeightMapFilter; import com.sk89q.worldedit.math.noise.RandomNoise; -import com.sk89q.worldedit.regions.*; +import com.sk89q.worldedit.regions.ConvexPolyhedralRegion; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionOperationException; +import com.sk89q.worldedit.regions.Regions; +import static com.sk89q.worldedit.regions.Regions.asFlatRegion; +import static com.sk89q.worldedit.regions.Regions.maximumBlockY; +import static com.sk89q.worldedit.regions.Regions.minimumBlockY; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TreeGenerator.TreeType; import com.sk89q.worldedit.util.command.binding.Range; @@ -76,15 +87,6 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.ORIENTATION_REGION; -import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; -import static com.sk89q.worldedit.regions.Regions.asFlatRegion; -import static com.sk89q.worldedit.regions.Regions.maximumBlockY; -import static com.sk89q.worldedit.regions.Regions.minimumBlockY; - /** * Commands that operate on regions. */ @@ -486,11 +488,10 @@ public class RegionCommands extends MethodCommands { ) @CommandPermissions("fawe.admin") public void wea(Player player) throws WorldEditException { - FawePlayer fp = FawePlayer.wrap(player); - if (fp.toggle("fawe.bypass")) { - BBC.WORLDEDIT_BYPASSED.send(fp); + if (player.togglePermission("fawe.bypass")) { + BBC.WORLDEDIT_BYPASSED.send(player); } else { - BBC.WORLDEDIT_RESTRICTED.send(fp); + BBC.WORLDEDIT_RESTRICTED.send(player); } } @@ -500,8 +501,7 @@ public class RegionCommands extends MethodCommands { help = "Select your current allowed region" ) @CommandPermissions("fawe.worldeditregion") - public void wer(Player player) throws WorldEditException { - FawePlayer fp = FawePlayer.wrap(player); + public void wer(FawePlayer fp) throws WorldEditException { final Region region = fp.getLargestRegion(); if (region == null) { BBC.NO_REGION.send(fp); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index c1ef08d98..8d4523d01 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.extension.platform; import static com.google.common.base.Preconditions.checkNotNull; - import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.entity.BaseEntity; @@ -37,9 +36,8 @@ import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.gamemode.GameMode; -import java.util.UUID; - import javax.annotation.Nullable; +import java.util.UUID; public class PlayerProxy extends AbstractPlayerActor { @@ -155,6 +153,14 @@ public class PlayerProxy extends AbstractPlayerActor { return permActor.hasPermission(perm); } + @Override public boolean togglePermission(String permission) { + return permActor.hasPermission(permission); + } + + @Override public void setPermission(String permission, boolean value) { + permActor.setPermission(permission, value); + } + @Override public void dispatchCUIEvent(CUIEvent event) { cuiActor.dispatchCUIEvent(event); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java index 6a32edb23..0098d455a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/factory/Deform.java @@ -150,7 +150,8 @@ public class Deform implements Contextual { } LocalSession session = context.getSession(); - return new DeformOperation(context.getDestination(), region, zero, unit, expression); + return new DeformOperation(context.getDestination(), region, zero, unit, expression, + session == null ? WorldEdit.getInstance().getConfiguration().calculationTimeout : session.getTimeout()); } private static final class DeformOperation implements Operation { @@ -159,20 +160,22 @@ public class Deform implements Contextual { private final Vector3 zero; private final Vector3 unit; private final String expression; + private final int timeout; - private DeformOperation(Extent destination, Region region, Vector3 zero, Vector3 unit, String expression) { + private DeformOperation(Extent destination, Region region, Vector3 zero, Vector3 unit, String expression, int timeout) { this.destination = destination; this.region = region; this.zero = zero; this.unit = unit; this.expression = expression; + this.timeout = timeout; } @Override public Operation resume(RunContext run) throws WorldEditException { try { // TODO: Move deformation code - ((EditSession) destination).deformRegion(region, zero, unit, expression); + ((EditSession) destination).deformRegion(region, zero, unit, expression, timeout); return null; } catch (ExpressionException e) { throw new RuntimeException("Failed to execute expression", e); // TODO: Better exception to throw here? diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java index d453ab448..d133993cc 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/generator/FloraGenerator.java @@ -22,7 +22,6 @@ package com.sk89q.worldedit.function.generator; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.math.BlockVector3; @@ -83,9 +82,9 @@ public class FloraGenerator implements RegionFunction { */ public static Pattern getDesertPattern() { RandomPattern pattern = new RandomPattern(); - pattern.add((BlockTypes.DEAD_BUSH.getDefaultState()), 30); - pattern.add((BlockTypes.CACTUS.getDefaultState()), 20); - pattern.add((BlockTypes.AIR.getDefaultState()), 300); + pattern.add(BlockTypes.DEAD_BUSH.getDefaultState(), 30); + pattern.add(BlockTypes.CACTUS.getDefaultState(), 20); + pattern.add(BlockTypes.AIR.getDefaultState(), 300); return pattern; } @@ -96,9 +95,9 @@ public class FloraGenerator implements RegionFunction { */ public static Pattern getTemperatePattern() { RandomPattern pattern = new RandomPattern(); - pattern.add((BlockTypes.GRASS.getDefaultState()), 300); - pattern.add((BlockTypes.POPPY.getDefaultState()), 5); - pattern.add((BlockTypes.DANDELION.getDefaultState()), 5); + pattern.add(BlockTypes.GRASS.getDefaultState(), 300); + pattern.add(BlockTypes.POPPY.getDefaultState(), 5); + pattern.add(BlockTypes.DANDELION.getDefaultState(), 5); return pattern; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java index c27e82481..2a6279469 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java @@ -20,14 +20,12 @@ package com.sk89q.worldedit.function.mask; import static com.google.common.base.Preconditions.checkNotNull; - import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import javax.annotation.Nullable; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -113,9 +111,6 @@ public class BlockTypeMask extends AbstractExtentMask { public boolean test(BlockVector3 vector) { return types[getExtent().getBlockType(vector).getInternalId()]; } -// public boolean test(BlockVector3 vector) { -// return blocks.contains(getExtent().getBlock(vector).getBlockType()); -// } @Nullable @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java index d8ddcc704..eba02d0a7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.function.mask; import static com.google.common.base.Preconditions.checkNotNull; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java index 0f4d9b198..a50c5e375 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/ExpressionMask2D.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.function.mask; import static com.google.common.base.Preconditions.checkNotNull; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SolidBlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SolidBlockMask.java index b73bbb32b..2192d8f35 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SolidBlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SolidBlockMask.java @@ -29,14 +29,6 @@ import javax.annotation.Nullable; public class SolidBlockMask extends BlockTypeMask { - public static boolean[] getTypes() { - boolean[] types = new boolean[BlockTypes.size()]; - for (BlockType type : BlockTypes.values) { - types[type.getInternalId()] = type.getMaterial().isSolid(); - } - return types; - } - public SolidBlockMask(Extent extent) { super(extent, getTypes()); } @@ -48,6 +40,14 @@ public class SolidBlockMask extends BlockTypeMask { return block.getBlockType().getMaterial().isMovementBlocker(); } + public static boolean[] getTypes() { + boolean[] types = new boolean[BlockTypes.size()]; + for (BlockType type : BlockTypes.values) { + types[type.getInternalId()] = type.getMaterial().isSolid(); + } + return types; + } + @Nullable @Override public Mask2D toMask2D() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java index e05e2d229..4d5e4fcf1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/WaterloggedRemover.java @@ -20,9 +20,7 @@ package com.sk89q.worldedit.function.pattern; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.BlockMaskBuilder; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.PropertyKey; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -30,9 +28,6 @@ import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockTypes; import java.lang.ref.SoftReference; -import java.util.Map; -import java.util.function.BiPredicate; -import java.util.function.Predicate; /** * Removes the waterlogged state from blocks if possible. If not possible, returns air. @@ -42,9 +37,9 @@ public class WaterloggedRemover extends AbstractExtentPattern { private static SoftReference cache = new SoftReference<>(null); private synchronized BlockState[] getRemap() { - BlockState[] remap = this.cache.get(); + BlockState[] remap = cache.get(); if (remap != null) return remap; - this.cache = new SoftReference<>(remap = new BlockState[BlockTypes.states.length]); + cache = new SoftReference<>(remap = new BlockState[BlockTypes.states.length]); // init for (int i = 0; i < remap.length; i++) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java index e7b678d27..8dcdbc558 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java @@ -318,4 +318,5 @@ public abstract class BreadthFirstSearch implements Operation { visited.clear(); affected = 0; } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java index 6e7b41a19..e35ba22d5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/expression/Expression.java @@ -105,6 +105,7 @@ public class Expression { private Expression(List tokens, String... variableNames) throws ExpressionException { this.variableNames = variableNames; + variables.put("e", new Constant(-1, Math.E)); variables.put("pi", new Constant(-1, Math.PI)); variables.put("true", new Constant(-1, 1)); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/auth/Subject.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/auth/Subject.java index 166ad22b5..09f577cca 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/auth/Subject.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/auth/Subject.java @@ -48,4 +48,13 @@ public interface Subject { */ boolean hasPermission(String permission); + /** + * Add and remove permissions from a subject to show and hide certain messages. + * + * @param permission the permission + * @return false if the permission was removed, true if this subject has permission + */ + boolean togglePermission(String permission); + + void setPermission(String permission, boolean value); }