From 9f0602f2ecb0eceb5fd47484901f06b955950435 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 2 May 2016 12:04:28 +1000 Subject: [PATCH] Various Fixes #89 brush fixes optimizations restructure etc --- .../fawe/bukkit/logging/BlocksHubHook.java | 9 +- .../fawe/bukkit/logging/LoggingChangeSet.java | 86 ++++++ .../bukkit/v0/BukkitEditSessionWrapper_0.java | 6 +- .../boydti/fawe/bukkit/v0/BukkitQueue_0.java | 2 +- .../fawe/bukkit/v1_9/BukkitChunk_1_9.java | 13 +- .../fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java | 26 +- core/src/main/java/com/boydti/fawe/Fawe.java | 3 + .../java/com/boydti/fawe/command/Cancel.java | 19 +- .../java/com/boydti/fawe/config/Settings.java | 6 +- .../com/boydti/fawe/object/HistoryExtent.java | 53 ++-- .../boydti/fawe/object/brush/HeightBrush.java | 58 +++- .../object/changeset/DiskStorageHistory.java | 1 + .../object/extent/FastWorldEditExtent.java | 8 +- ...{FaweExtent.java => FaweRegionExtent.java} | 5 +- ...Wrapper.java => MemoryCheckingExtent.java} | 4 +- .../boydti/fawe/object/extent/NullExtent.java | 27 +- .../fawe/object/extent/ProcessedWEExtent.java | 255 ++---------------- .../java/com/boydti/fawe/util/FaweQueue.java | 10 + .../java/com/boydti/fawe/util/SetQueue.java | 44 +-- .../java/com/boydti/fawe/util/WEManager.java | 18 +- .../boydti/fawe/wrappers/WorldWrapper.java | 4 +- .../java/com/sk89q/worldedit/EditSession.java | 113 +++++--- .../worldedit/command/BrushCommands.java | 15 +- .../worldedit/command/ClipboardCommands.java | 3 +- .../command/tool/brush/GravityBrush.java | 18 +- 25 files changed, 400 insertions(+), 406 deletions(-) create mode 100644 bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingChangeSet.java rename core/src/main/java/com/boydti/fawe/object/extent/{FaweExtent.java => FaweRegionExtent.java} (73%) rename core/src/main/java/com/boydti/fawe/object/extent/{SafeExtentWrapper.java => MemoryCheckingExtent.java} (89%) diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java index f6797ceb..f0819945 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/BlocksHubHook.java @@ -1,8 +1,11 @@ package com.boydti.fawe.bukkit.logging; +import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.boydti.fawe.util.FaweQueue; +import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.history.changeset.ChangeSet; import org.PrimeSoft.blocksHub.BlocksHub; import org.PrimeSoft.blocksHub.IBlocksHubApi; import org.bukkit.Bukkit; @@ -17,7 +20,7 @@ public class BlocksHubHook { this.api = this.hub.getApi(); } - public Extent getLoggingExtent(final Extent parent, final ChangeSet set, final FawePlayer player) { - return new LoggingExtent(parent, set, (FawePlayer) player, this.api); + public FaweChangeSet getLoggingChangeSet(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer player) { + return new LoggingChangeSet((FawePlayer) player, set, api); } } diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingChangeSet.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingChangeSet.java new file mode 100644 index 00000000..dccbf37b --- /dev/null +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/logging/LoggingChangeSet.java @@ -0,0 +1,86 @@ +package com.boydti.fawe.bukkit.logging; + +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.changeset.FaweChangeSet; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.history.change.Change; +import java.util.Iterator; +import org.PrimeSoft.blocksHub.IBlocksHubApi; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +public class LoggingChangeSet implements FaweChangeSet { + + private final FaweChangeSet parent; + private final IBlocksHubApi api; + private final World world; + private final Location loc; + private final String name; + + public LoggingChangeSet(FawePlayer player, FaweChangeSet parent, IBlocksHubApi api) { + this.parent = parent; + this.name = player.getName(); + this.api = api; + this.world = player.parent.getWorld(); + this.loc = new Location(world, 0, 0, 0); + } + + @Override + public boolean flush() { + return parent.flush(); + } + + @Override + public int getCompressedSize() { + return parent.getCompressedSize(); + } + + @Override + public void add(Vector location, BaseBlock from, BaseBlock to) { + loc.setX(location.getX()); + loc.setY(location.getY()); + loc.setZ(location.getZ()); + api.logBlock(name, world, loc, from.getId(), (byte) from.getData(), to.getId(), (byte) to.getData()); + parent.add(location, from, to); + } + + @Override + public void add(int x, int y, int z, int combinedId4DataFrom, BaseBlock to) { + loc.setX(x); + loc.setY(y); + loc.setZ(z); + api.logBlock(name, world, loc, combinedId4DataFrom >> 4, (byte) (combinedId4DataFrom & 0xF), to.getId(), (byte) to.getData()); + parent.add(x, y, z, combinedId4DataFrom, to); + } + + @Override + public void add(int x, int y, int z, int combinedId4DataFrom, int combinedId4DataTo) { + loc.setX(x); + loc.setY(y); + loc.setZ(z); + api.logBlock(name, world, loc, combinedId4DataFrom >> 4, (byte) (combinedId4DataFrom & 0xF), combinedId4DataTo >> 4, (byte) (combinedId4DataTo & 0xF)); + parent.add(x, y, z, combinedId4DataFrom, combinedId4DataTo); + } + + @Override + public void add(Change change) { + parent.add(change); + } + + @Override + public Iterator backwardIterator() { + return parent.backwardIterator(); + } + + @Override + public Iterator forwardIterator() { + return parent.forwardIterator(); + } + + @Override + public int size() { + return parent.size(); + } +} diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java index d3d31093..7b4e638d 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitEditSessionWrapper_0.java @@ -24,10 +24,10 @@ public class BukkitEditSessionWrapper_0 extends EditSessionWrapper { @Override public Extent getHistoryExtent(EditSession session, FaweLimit limit, Extent parent, FaweChangeSet set, FaweQueue queue, FawePlayer player) { if (this.hook != null) { - // If we are doing logging, return a custom logging extent - return this.hook.getLoggingExtent(parent, set, player); + // If we are doing logging, use a custom logging ChangeSet + set = hook.getLoggingChangeSet(session, limit, parent, set, queue, player); } - // Otherwise return the normal history extent + // Now return the normal history extent return super.getHistoryExtent(session, limit, parent, set, queue, player); } } diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java index 366d76da..5288b7a9 100644 --- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java @@ -79,7 +79,7 @@ public abstract class BukkitQueue_0 extends NMSMa ChunkListener.physicsFreeze = false; if (parallel) { try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled); - } catch (Throwable ignore) {ignore.printStackTrace();} + } catch (Throwable ignore) {} try { Class.forName("org.spigotmc.AsyncCatcher").getField("enabled").set(null, true); } catch (Throwable ignore) {} } } diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java index cb94f1eb..ff158f2d 100644 --- a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitChunk_1_9.java @@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.v1_9; import com.boydti.fawe.FaweCache; import com.boydti.fawe.example.CharFaweChunk; import com.boydti.fawe.util.FaweQueue; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import net.minecraft.server.v1_9_R1.Block; import net.minecraft.server.v1_9_R1.DataBits; @@ -96,7 +97,17 @@ public class BukkitChunk_1_9 extends CharFaweChunk { if (sectionPalettes == null) { sectionPalettes = new DataPaletteBlock[16]; } - DataPaletteBlock palette = sectionPalettes[layer] = new DataPaletteBlock(); + DataPaletteBlock palette; + try { + palette = sectionPalettes[layer] = new DataPaletteBlock(); + } catch (Throwable e) { + try { + Constructor constructor = DataPaletteBlock.class.getDeclaredConstructor(IBlockData[].class); + palette = sectionPalettes[layer] = constructor.newInstance(null); + } catch (Throwable e2) { + throw new RuntimeException(e2); + } + } char[] blocks = getIdArray(layer); for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { diff --git a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java index 0eb1de5a..404e0681 100644 --- a/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java +++ b/bukkit19/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java @@ -10,6 +10,7 @@ import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.util.MemUtil; import com.sk89q.worldedit.LocalSession; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayDeque; @@ -224,6 +225,28 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0 constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, IBlockData[].class); + return constructor.newInstance(y2, flag, null); + } else { + Constructor constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, char[].class, IBlockData[].class); + return constructor.newInstance(y2, flag, array, null); + } + } catch (Throwable e2) { + throw new RuntimeException(e2); + } + } + } + @Override public boolean setComponents(final FaweChunk pc) { final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc; @@ -268,9 +291,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0()); options.put("extent.debug", EXTENT_DEBUG); options.put("metrics", METRICS); @@ -140,7 +140,7 @@ public class Settings { QUEUE_SIZE = config.getInt("queue.target-size"); QUEUE_MAX_WAIT = config.getInt("queue.max-wait-ms"); UNSAFE_PARALLEL_THREADS = config.getInt("queue.parallel-threads"); - QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms"); + QUEUE_DISCARD_AFTER = config.getInt("queue.discard-after-ms", QUEUE_DISCARD_AFTER); ALLOWED_3RDPARTY_EXTENTS = config.getStringList("extent.allowed-plugins"); EXTENT_DEBUG = config.getBoolean("extent.debug"); STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk"); diff --git a/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java index 2371336b..874b9253 100644 --- a/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/HistoryExtent.java @@ -50,37 +50,34 @@ public class HistoryExtent extends AbstractDelegateExtent { @Override public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { - if (super.setBlock(location, block)) { - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - int combined = queue.getCombinedId4DataDebug(x, y, z, 0, session); - int id = (combined >> 4); - if (id == block.getId()) { - if (!FaweCache.hasData(id)) { - return false; - } - int data = id & 0xF; - if (data == block.getData()) { - return false; - } + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + int combined = queue.getCombinedId4DataDebug(x, y, z, 0, session); + int id = (combined >> 4); + if (id == block.getId()) { + if (!FaweCache.hasData(id)) { + return false; } - if (!FaweCache.hasNBT(id)) { - if (FaweCache.hasNBT(block.getId())) { - this.changeSet.add(x, y, z, combined, block); - } else { - this.changeSet.add(x, y, z, combined, (block.getId() << 4) + block.getData()); - } - } else { - try { - this.changeSet.add(location, getBlock(location), block); - } catch (Throwable e) { - this.changeSet.add(x, y, z, combined, block); - } + int data = id & 0xF; + if (data == block.getData()) { + return false; } - return true; } - return false; + if (!FaweCache.hasNBT(id)) { + if (FaweCache.hasNBT(block.getId())) { + this.changeSet.add(x, y, z, combined, block); + } else { + this.changeSet.add(x, y, z, combined, (block.getId() << 4) + block.getData()); + } + } else { + try { + this.changeSet.add(location, getBlock(location), block); + } catch (Throwable e) { + this.changeSet.add(x, y, z, combined, block); + } + } + return super.setBlock(location, block); } @Nullable diff --git a/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java index efaf378a..e24ddba5 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java @@ -8,8 +8,12 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.brush.Brush; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.regions.CuboidRegion; import java.awt.image.BufferedImage; import java.awt.image.Raster; import java.io.File; @@ -21,12 +25,33 @@ public class HeightBrush implements Brush { public final HeightMap heightMap; private final int rotation; double yscale = 1; + private final BrushTool tool; - public HeightBrush(File file, int rotation, double yscale) { + public HeightBrush(File file, int rotation, double yscale, BrushTool tool, EditSession session, CuboidRegion selection) { + this.tool = tool; this.rotation = (rotation / 90) % 4; this.yscale = yscale; if (file == null || !file.exists()) { - heightMap = new HeightMap(); + if (file.getName().equalsIgnoreCase("#selection.png") && selection != null) { + byte[][] heightArray = new byte[selection.getWidth()][selection.getLength()]; + int minX = selection.getMinimumPoint().getBlockX(); + int minZ = selection.getMinimumPoint().getBlockZ(); + int minY = selection.getMinimumY() - 1; + int maxY = selection.getMaximumY() + 1; + int selHeight = selection.getHeight(); + for (Vector pos : selection) { + int xx = pos.getBlockX(); + int zz = pos.getBlockZ(); + int worldPointHeight = session.getHighestTerrainBlock(xx, zz, minY, maxY); + int pointHeight = (256 * (worldPointHeight - minY)) / selHeight; + int x = xx - minX; + int z = zz - minZ; + heightArray[x][z] = (byte) pointHeight; + } + heightMap = new ArrayHeightMap(heightArray); + } else { + heightMap = new HeightMap(); + } } else { try { BufferedImage heightFile = ImageIO.read(file); @@ -53,10 +78,12 @@ public class HeightBrush implements Brush { @Override public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { - + Mask mask = tool.getMask(); + if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { + mask = null; + } int size = (int) sizeDouble; heightMap.setSize(size); - int size2 = size * size; int startY = position.getBlockY() + size; int endY = position.getBlockY() - size; @@ -65,6 +92,7 @@ public class HeightBrush implements Brush { Vector mutablePos = new Vector(0, 0, 0); for (int x = -size; x <= size; x++) { int xx = cx + x; + mutablePos.x = xx; for (int z = -size; z <= size; z++) { int zz = cz + z; int raise; @@ -86,11 +114,18 @@ public class HeightBrush implements Brush { if (raise == 0) { continue; } + mutablePos.z = zz; int foundHeight = Integer.MAX_VALUE; BaseBlock block = null; for (int y = startY; y >= endY; y--) { block = editSession.getLazyBlock(xx, y, zz); if (block != EditSession.nullBlock) { + if (mask != null) { + mutablePos.y = y; + if (!mask.test(mutablePos)) { + continue; + } + } foundHeight = y; break; } @@ -98,10 +133,17 @@ public class HeightBrush implements Brush { if (foundHeight == Integer.MAX_VALUE) { continue; } - for (int y = foundHeight + 1; y <= foundHeight + raise; y++) { - mutablePos.x = xx; - mutablePos.y = y; - mutablePos.z = zz; + if (raise > 0) { + for (int y = foundHeight + 1; y <= foundHeight + raise; y++) { + mutablePos.y = y; + editSession.setBlock(mutablePos, block); + } + } else { + for (int y = foundHeight; y > foundHeight + raise; y--) { + mutablePos.y = y; + editSession.setBlock(mutablePos, EditSession.nullBlock); + } + mutablePos.y = foundHeight + raise; editSession.setBlock(mutablePos, block); } } diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java index 6ba3355d..a22be982 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java @@ -152,6 +152,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet { EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory(); EditSession edit = factory.getEditSession(world, -1, null, player); edit.setChangeSet(this); + edit.dequeue(); return edit; } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java index 77acb5cf..12775637 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/FastWorldEditExtent.java @@ -12,13 +12,14 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.List; -public class FastWorldEditExtent extends FaweExtent { +public class FastWorldEditExtent extends AbstractDelegateExtent { private final FaweQueue queue; @@ -228,9 +229,4 @@ public class FastWorldEditExtent extends FaweExtent { } } } - - @Override - public boolean contains(int x, int y, int z) { - return true; - } } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/FaweExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/FaweRegionExtent.java similarity index 73% rename from core/src/main/java/com/boydti/fawe/object/extent/FaweExtent.java rename to core/src/main/java/com/boydti/fawe/object/extent/FaweRegionExtent.java index 3a5f704a..fb680751 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/FaweExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/FaweRegionExtent.java @@ -3,14 +3,13 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -public abstract class FaweExtent extends AbstractDelegateExtent { - +public abstract class FaweRegionExtent extends AbstractDelegateExtent { /** * Create a new instance. * * @param extent the extent */ - protected FaweExtent(Extent extent) { + public FaweRegionExtent(Extent extent) { super(extent); } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java b/core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java similarity index 89% rename from core/src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java rename to core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java index 3d120e50..866a3ef5 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/SafeExtentWrapper.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java @@ -11,10 +11,10 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -public class SafeExtentWrapper extends AbstractDelegateExtent { +public class MemoryCheckingExtent extends AbstractDelegateExtent { private final FawePlayer player; - public SafeExtentWrapper(final FawePlayer player, final Extent extent) { + public MemoryCheckingExtent(final FawePlayer player, final Extent extent) { super(extent); this.player = player; } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/NullExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/NullExtent.java index 5d4b9ea9..c49415c9 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/NullExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/NullExtent.java @@ -15,18 +15,16 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; -public class NullExtent extends FaweExtent { +public class NullExtent implements Extent { private final BBC reason; /** * Create a new instance. - * - * @param extent the extent */ - public NullExtent(Extent extent, BBC failReason) { - super(extent); + public NullExtent(BBC failReason) { this.reason = failReason; } @@ -50,6 +48,12 @@ public class NullExtent extends FaweExtent { throw new FaweException(reason); } + @Nullable + @Override + public Operation commit() { + return null; + } + @Override public boolean setBlock(final Vector arg0, final BaseBlock arg1) throws WorldEditException { throw new FaweException(reason); @@ -79,17 +83,4 @@ public class NullExtent extends FaweExtent { public Vector getMinimumPoint() { return new Vector(0, 0, 0); } - - @Override - public boolean contains(int x, int y, int z) { return false; } - - @Override - protected Operation commitBefore() { - return null; - } - - @Override - public Extent getExtent() { - return this; - } } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java index 6a3e3934..5d6191c7 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/ProcessedWEExtent.java @@ -3,14 +3,9 @@ package com.boydti.fawe.object.extent; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.FaweLimit; -import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.RegionWrapper; -import com.boydti.fawe.util.FaweQueue; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.WEManager; import com.sk89q.worldedit.BlockVector; -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.WorldEditException; @@ -20,52 +15,30 @@ import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.HashSet; import java.util.List; -public class ProcessedWEExtent extends FaweExtent { - private final FaweQueue queue; +public class ProcessedWEExtent extends FaweRegionExtent { private final FaweLimit limit; - private Extent parent; + private final RegionWrapper[] mask; - private final FawePlayer user; - private final HashSet mask; - - public ProcessedWEExtent(final World world, final FawePlayer player, final HashSet mask, FaweLimit limit, FaweQueue queue) { - super(world); - this.user = player; - this.queue = queue; - this.mask = mask; + public ProcessedWEExtent(final Extent parent, final HashSet mask, FaweLimit limit) { + super(parent); + this.mask = mask.toArray(new RegionWrapper[mask.size()]); this.limit = limit; } - public void setParent(final Extent parent) { - this.parent = parent; - } - @Override public Entity createEntity(final Location location, final BaseEntity entity) { if (limit.MAX_ENTITIES-- < 0 || entity == null) { return null; } - if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) { - TaskManager.IMP.task(new Runnable() { - @Override - public void run() { - ProcessedWEExtent.super.createEntity(location, entity); - } - }); - } - return null; + return super.createEntity(location, entity); } @Override public BaseBiome getBiome(final Vector2D position) { - if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) { - return EditSession.nullBiome; - } return super.getBiome(position); } @@ -74,21 +47,6 @@ public class ProcessedWEExtent extends FaweExtent { @Override public BaseBlock getLazyBlock(final Vector position) { -// TODO get fast! -// TODO caches base blocks - - if ((this.lastBlock != null) && this.lastVector.equals(position.toBlockVector())) { - return this.lastBlock; - } - if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) { - try { - this.lastVector = position.toBlockVector(); - return this.lastBlock = super.getBlock(position); - } catch (final Throwable e) { - return EditSession.nullBlock; - } - } - this.lastVector = position.toBlockVector(); return super.getLazyBlock(position); } @@ -109,200 +67,27 @@ public class ProcessedWEExtent extends FaweExtent { @Override public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { - final short id = (short) block.getType(); - boolean nbt = true; - switch (id) { - case 63: - case 68: - if (block.hasNbtData() && !MainUtil.isValidSign(block.getNbtData())) { - nbt = false; - } - case 54: - case 130: - case 142: - case 27: - case 137: - case 52: - case 154: - case 84: - case 25: - case 144: - case 138: - case 176: - case 177: - case 119: - case 323: - case 117: - case 116: - case 28: - case 66: - case 157: - case 61: - case 62: - case 140: - case 146: - case 149: - case 150: - case 158: - case 23: - case 123: - case 124: - case 29: - case 33: - case 151: - case 178: { - if (limit.MAX_BLOCKSTATES-- < 0) { - if (this.parent != null) { - WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES); - this.parent = null; - } - return false; - } - final int x = location.getBlockX(); - final int z = location.getBlockZ(); - if (WEManager.IMP.maskContains(this.mask, x, z)) { - if (limit.MAX_CHANGES-- < 0) { - if (this.parent != null) { - WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES); - this.parent = null; - } - return false; - } - if (block.hasNbtData() && nbt) { - final Vector loc = new Vector(location.x, location.y, location.z); - queue.addTask(x >> 4, z >> 4, new Runnable() { - @Override - public void run() { - try { - ProcessedWEExtent.super.setBlock(loc, block); - } catch (WorldEditException e) { - e.printStackTrace(); - } - } - }); - return true; - } - queue.setBlock(x, location.getBlockY(), z, id, FaweCache.hasData(id) ? (byte) block.getData() : 0); - return true; - } else if (limit.MAX_FAILS-- < 0) { - if (this.parent != null) { - WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); - this.parent = null; - } - } - return false; - } - default: { - final int x = location.getBlockX(); - final int y = location.getBlockY(); - final int z = location.getBlockZ(); - if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) { - if (limit.MAX_CHANGES -- <0) { - WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES); - this.parent = null; - return false; - } - switch (id) { - case 0: - case 2: - case 4: - case 13: - case 14: - case 15: - case 20: - case 21: - case 22: - case 25: - case 30: - case 32: - case 37: - case 39: - case 40: - case 41: - case 42: - case 45: - case 46: - case 47: - case 48: - case 49: - case 51: - case 52: - case 56: - case 57: - case 58: - case 60: - case 7: - case 8: - case 9: - case 10: - case 11: - case 73: - case 74: - case 78: - case 79: - case 80: - case 81: - case 82: - case 83: - case 84: - case 85: - case 87: - case 88: - case 101: - case 102: - case 103: - case 110: - case 112: - case 113: - case 117: - case 121: - case 122: - case 123: - case 124: - case 129: - case 133: - case 138: - case 137: - case 140: - case 165: - case 166: - case 169: - case 170: - case 172: - case 173: - case 174: - case 181: - case 182: - case 188: - case 189: - case 190: - case 191: - case 192: { - queue.setBlock(x, y, z, id, (byte) 0); - return true; - } - default: { - queue.setBlock(x, y, z, id, (byte) block.getData()); - return true; - } - } - } else if (limit.MAX_FAILS-- < 0) { - if (this.parent != null) { - WEManager.IMP.cancelEdit(this.parent, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); - this.parent = null; - } - } + if (block.hasNbtData() && FaweCache.hasNBT(block.getType())) { + if (limit.MAX_BLOCKSTATES-- < 0) { + WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES); return false; } } + if (WEManager.IMP.maskContains(this.mask, (int) location.x, (int) location.z)) { + if (limit.MAX_CHANGES-- < 0) { + WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES); + return false; + } + return super.setBlock(location, block); + } else if (limit.MAX_FAILS-- < 0) { + WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES); + } + return false; } @Override public boolean setBiome(final Vector2D position, final BaseBiome biome) { - if (WEManager.IMP.maskContains(this.mask, position.getBlockX(), position.getBlockZ())) { - queue.setBiome(position.getBlockX(), position.getBlockZ(), biome); - } - return false; + return super.setBiome(position, biome); } @Override diff --git a/core/src/main/java/com/boydti/fawe/util/FaweQueue.java b/core/src/main/java/com/boydti/fawe/util/FaweQueue.java index 844045ab..75e30e70 100644 --- a/core/src/main/java/com/boydti/fawe/util/FaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/FaweQueue.java @@ -54,6 +54,16 @@ public abstract class FaweQueue { public void endSet(boolean parallel) {} + public int cancel() { + int count = 0; + for (EditSession session : sessions) { + if (session.cancel()) { + count++; + } + } + return count; + } + /** * Gets the FaweChunk and sets the requested blocks * @return diff --git a/core/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java index d0d78563..5ee4f6c4 100644 --- a/core/src/main/java/com/boydti/fawe/util/SetQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/SetQueue.java @@ -79,26 +79,34 @@ public class SetQueue { if (SET_TASK.value2 == null) { return; } - if (Settings.UNSAFE_PARALLEL_THREADS <= 1) { - SET_TASK.value2.startSet(false); - SET_TASK.run(); - SET_TASK.value2.endSet(false); - } else { - SET_TASK.value2.startSet(true); - ArrayList threads = new ArrayList(); - for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) { - threads.add(new Thread(SET_TASK)); - } - for (Thread thread : threads) { - thread.start(); - } - for (Thread thread : threads) { - try { - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); + if (Thread.currentThread() != Fawe.get().getMainThread()) { + throw new IllegalStateException("This shouldn't be possible for placement to occur off the main thread"); + } + // Disable the async catcher as it can't discern async vs parallel + SET_TASK.value2.startSet(true); + try { + if (Settings.UNSAFE_PARALLEL_THREADS <= 1) { + SET_TASK.run(); + } else { + ArrayList threads = new ArrayList(); + for (int i = 0; i < Settings.UNSAFE_PARALLEL_THREADS; i++) { + threads.add(new Thread(SET_TASK)); + } + for (Thread thread : threads) { + thread.start(); + } + for (Thread thread : threads) { + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } + } catch (Throwable e) { + e.printStackTrace(); + } finally { + // Enable it again (note that we are still on the main thread) SET_TASK.value2.endSet(true); } } diff --git a/core/src/main/java/com/boydti/fawe/util/WEManager.java b/core/src/main/java/com/boydti/fawe/util/WEManager.java index 6879c480..c41d9c9d 100644 --- a/core/src/main/java/com/boydti/fawe/util/WEManager.java +++ b/core/src/main/java/com/boydti/fawe/util/WEManager.java @@ -26,7 +26,7 @@ public class WEManager { try { final Field field = AbstractDelegateExtent.class.getDeclaredField("extent"); field.setAccessible(true); - field.set(parent, new NullExtent((Extent) field.get(parent), reason)); + field.set(parent, new NullExtent(reason)); } catch (final Exception e) { e.printStackTrace(); } @@ -42,6 +42,22 @@ public class WEManager { return false; } + public boolean maskContains(RegionWrapper[] mask, final int x, final int z) { + switch (mask.length) { + case 0: + return false; + case 1: + return mask[0].isIn(x, z); + default: + for (final RegionWrapper region : mask) { + if (region.isIn(x, z)) { + return true; + } + } + return false; + } + } + public HashSet getMask(final FawePlayer player) { final HashSet regions = new HashSet<>(); if (player.hasPermission("fawe.bypass") || !Settings.REGION_RESTRICTIONS) { diff --git a/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java b/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java index ea0dec4a..9260f850 100644 --- a/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java +++ b/core/src/main/java/com/boydti/fawe/wrappers/WorldWrapper.java @@ -3,7 +3,7 @@ package com.boydti.fawe.wrappers; import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.changeset.FaweChangeSet; -import com.boydti.fawe.object.extent.FaweExtent; +import com.boydti.fawe.object.extent.FaweRegionExtent; import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.BlockVector2D; @@ -230,7 +230,7 @@ public class WorldWrapper extends AbstractWorld { public boolean regenerate(final Region region, final EditSession session) { final FaweQueue queue = session.getQueue(); final FaweChangeSet fcs = (FaweChangeSet) session.getChangeSet(); - final FaweExtent fe = session.getFaweExtent(); + final FaweRegionExtent fe = session.getRegionExtent(); session.setChangeSet(fcs); final boolean cuboid = region instanceof CuboidRegion; Set chunks = region.getChunks(); diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index d1cd3cb0..c8ac217e 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -34,11 +34,10 @@ import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.changeset.MemoryOptimizedHistory; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.extent.FastWorldEditExtent; -import com.boydti.fawe.object.extent.FaweExtent; +import com.boydti.fawe.object.extent.FaweRegionExtent; +import com.boydti.fawe.object.extent.MemoryCheckingExtent; import com.boydti.fawe.object.extent.NullExtent; import com.boydti.fawe.object.extent.ProcessedWEExtent; -import com.boydti.fawe.object.extent.SafeExtentWrapper; -import com.boydti.fawe.util.ExtentWrapper; import com.boydti.fawe.util.FaweQueue; import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.Perm; @@ -118,7 +117,6 @@ import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; -import java.lang.reflect.Field; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; @@ -164,8 +162,9 @@ public class EditSession implements Extent { public Actor actor; public FaweChangeSet changeSet; public EditSessionWrapper wrapper; - public FaweExtent faweExtent; public MaskingExtent maskingExtent; + public FaweRegionExtent regionExtent; + public Extent primaryExtent; public Extent bypassReorderHistory; public Extent bypassHistory; public Extent bypassNone; @@ -204,7 +203,6 @@ public class EditSession implements Extent { } private int changes = 0; - private int maxBlocks; private BlockBag blockBag; /** @@ -220,13 +218,14 @@ public class EditSession implements Extent { checkNotNull(eventBus); checkArgument(maxBlocks >= -1, "maxBlocks >= -1 required"); checkNotNull(event); + this.actor = event.getActor(); - // Wrap world + // TODO block bag this.blockBag = blockBag; - this.maxBlocks = maxBlocks; - // Invalid; return null extent + + // Invalid world: return null extent if (world == null) { - FaweExtent extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); + NullExtent extent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); this.bypassReorderHistory = extent; this.bypassHistory = extent; this.bypassNone = extent; @@ -234,26 +233,18 @@ public class EditSession implements Extent { this.wrapper = Fawe.imp().getEditSessionWrapper(this); return; } - // Set the world of the event to the actual world (workaround for CoreProtect) - try { - Class eventClass = event.getClass(); - Field fieldWorld = eventClass.getDeclaredField("world"); - fieldWorld.setAccessible(true); - if (world instanceof WorldWrapper) { - fieldWorld.set(event, ((WorldWrapper) world).getParent()); - } else { - fieldWorld.set(event, world); - } - } catch (Throwable e) { - e.printStackTrace(); - } + + // Wrap the world this.world = (world = new WorldWrapper((AbstractWorld) world)); + + // Delegate some methods to an implementation specific class this.wrapper = Fawe.imp().getEditSessionWrapper(this); + // Not a player; bypass history if ((actor == null) || !actor.isPlayer()) { this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true); queue.addEditSession(this); - Extent extent = (this.faweExtent = new FastWorldEditExtent(world, queue)); + Extent extent = primaryExtent = new FastWorldEditExtent(world, queue); // Everything bypasses extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER); @@ -264,8 +255,9 @@ public class EditSession implements Extent { this.changeSet = new NullChangeSet(); return; } - this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor); + Extent extent; + HashSet mask; final FawePlayer fp = FawePlayer.wrap(actor); final LocalSession session = fp.getSession(); this.fastmode = session.hasFastMode(); @@ -273,7 +265,7 @@ public class EditSession implements Extent { this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true); queue.addEditSession(this); // Bypass skips processing and area restrictions - extent = (this.faweExtent = new FastWorldEditExtent(world, queue)); + extent = primaryExtent = new FastWorldEditExtent(world, queue); if (this.hasFastMode()) { // Fastmode skips history and memory checks extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); @@ -284,30 +276,28 @@ public class EditSession implements Extent { this.bypassNone = extent; return; } + mask = null; } else { this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true); queue.addEditSession(this); this.limit = fp.getLimit(); - final HashSet mask = WEManager.IMP.getMask(fp); + mask = WEManager.IMP.getMask(fp); if (mask.size() == 0) { // No allowed area; return null extent - extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); + extent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); this.bypassReorderHistory = extent; this.bypassHistory = extent; this.bypassNone = extent; return; } - // Process the WorldEdit action - ProcessedWEExtent processed = (ProcessedWEExtent) (this.faweExtent = new ProcessedWEExtent(world, fp, mask, limit, queue)); - extent = processed; + extent = primaryExtent = new FastWorldEditExtent(world, queue); if (this.hasFastMode()) { // Fastmode skips history, masking, and memory checks extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER); + // Restrictions + extent = new ProcessedWEExtent(extent, mask, limit); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY); - extent = new ExtentWrapper(extent); - // Set the parent. This allows efficient cancelling - processed.setParent(extent); this.bypassReorderHistory = extent; this.bypassHistory = extent; this.bypassNone = extent; @@ -318,9 +308,8 @@ public class EditSession implements Extent { if (Perm.hasPermission(fp, "worldedit.fast")) { BBC.WORLDEDIT_OOM_ADMIN.send(fp); } - // Memory limit reached; return null extent - extent = faweExtent = new NullExtent(world, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); + extent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); this.bypassReorderHistory = extent; this.bypassHistory = extent; this.bypassNone = extent; @@ -328,14 +317,24 @@ public class EditSession implements Extent { } } // Perform memory checks after reorder - extent = new SafeExtentWrapper(fp, extent); - processed.setParent(extent); + extent = new MemoryCheckingExtent(fp, extent); } // Include history, masking and memory checking. Extent wrapped; + // First two events extent = wrapped = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_CHANGE); extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_REORDER); + + // History + this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor); extent = this.wrapper.getHistoryExtent(this, limit, extent, this.changeSet, queue, fp); + + // Region restrictions if mask is not null + if (mask != null) { + extent = this.regionExtent = new ProcessedWEExtent(extent, mask, limit); + } + + // Masking final Player skp = (Player) actor; final int item = skp.getItemInHand(); boolean hasMask = session.getMask() != null; @@ -351,14 +350,44 @@ public class EditSession implements Extent { extent = this.maskingExtent = new MaskingExtent(extent, Masks.alwaysTrue()); } + // Before history event extent = this.wrapExtent(extent, eventBus, event, Stage.BEFORE_HISTORY); - extent = new SafeExtentWrapper(fp, extent); + this.bypassReorderHistory = wrapped; this.bypassHistory = wrapped; this.bypassNone = extent; return; } + public FaweRegionExtent getRegionExtent() { + return regionExtent; + } + + public boolean cancel() { + // Cancel this + if (primaryExtent != null && queue != null) { + try { + WEManager.IMP.cancelEdit(primaryExtent, BBC.WORLDEDIT_CANCEL_REASON_MANUAL); + } catch (Throwable ignore) {} + NullExtent nullExtent = new NullExtent(BBC.WORLDEDIT_CANCEL_REASON_MANUAL); + primaryExtent = nullExtent; + dequeue(); + queue.clear(); + return true; + } + return false; + } + + public void dequeue() { + if (queue != null) { + SetQueue.IMP.dequeue(queue); + } + } + + public FastWorldEditExtent getPrimaryExtent() { + return (FastWorldEditExtent) primaryExtent; + } + public void debug(BBC message, Object... args) { message.send(actor, args); } @@ -427,7 +456,7 @@ public class EditSession implements Extent { * @return the limit (>= 0) or -1 for no limit */ public int getBlockChangeLimit() { - return this.maxBlocks; + return -1; } /** @@ -489,10 +518,6 @@ public class EditSession implements Extent { } } - public FaweExtent getFaweExtent() { - return this.faweExtent; - } - /** * Set the mask. * diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java index 699dc84d..83b8acf4 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -29,6 +29,7 @@ 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.EditSession; +import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.Vector; @@ -51,6 +52,7 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; @@ -226,13 +228,13 @@ public class BrushCommands { BrushTool tool = session.getBrushTool(player.getItemInHand()); tool.setSize(radius); - tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity"); + tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity"); BBC.BRUSH_GRAVITY.send(player, radius); } @Command( - aliases = { "height", "high" }, - usage = "[radius] [file] [rotation] [yscale]", + aliases = { "height", "heightmap" }, + usage = "[radius] [file|#selection|null] [rotation] [yscale]", flags = "h", desc = "Height brush", help = @@ -246,7 +248,12 @@ public class BrushCommands { File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + (filename.endsWith(".png") ? filename : filename + ".png")); BrushTool tool = session.getBrushTool(player.getItemInHand()); tool.setSize(radius); - tool.setBrush(new HeightBrush(file, rotation, yscale), "worldedit.brush.height"); + try { + tool.setBrush(new HeightBrush(file, rotation, yscale, tool, editSession, (CuboidRegion) session.getSelection(player.getWorld())), "worldedit.brush.height"); + } catch (IncompleteRegionException ignore) { + ignore.printStackTrace(); + tool.setBrush(new HeightBrush(file, rotation, yscale, tool, editSession, null), "worldedit.brush.height"); + } BBC.BRUSH_HEIGHT.send(player, radius); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index a22f1819..1308bd32 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -47,6 +47,7 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.math.transform.AffineTransform; +import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; @@ -278,7 +279,7 @@ public class ClipboardCommands { final Vector origin = clipboard.getOrigin(); final Vector to = atOrigin ? origin : session.getPlacementPosition(player); // Optimize for BlockArrayClipboard - if (clipboard instanceof BlockArrayClipboard) { + if (clipboard instanceof BlockArrayClipboard && region instanceof CuboidRegion) { // To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min) final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX(); final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY(); diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java b/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java index 3fad1d53..777a05ce 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java @@ -23,18 +23,27 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.pattern.Pattern; public class GravityBrush implements Brush { private final boolean fullHeight; + private final BrushTool tool; - public GravityBrush(boolean fullHeight) { + public GravityBrush(boolean fullHeight, BrushTool tool) { this.fullHeight = fullHeight; + this.tool = tool; } @Override public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { + Mask mask = tool.getMask(); + if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { + mask = null; + } int size = (int) sizeDouble; int endY = position.getBlockY() + size; int startPerformY = Math.max(0, position.getBlockY() - size); @@ -51,11 +60,12 @@ public class GravityBrush implements Brush { continue; } BaseBlock block = editSession.getLazyBlock(x, y, z); - if (block != EditSession.nullBlock) { + mutablePos.x = x; + mutablePos.y = y; + mutablePos.z = z; + if (block != EditSession.nullBlock && (mask == null || mask.test(mutablePos))) { if (freeSpot != y) { - mutablePos.x = x; mutablePos.y = freeSpot; - mutablePos.z = z; editSession.setBlock(mutablePos, block); mutablePos.y = y; editSession.setBlock(mutablePos, EditSession.nullBlock);