From 3c626ef25a662d0897a0bbb69bd915ca54bd9676 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Wed, 7 Aug 2019 06:38:25 +1000 Subject: [PATCH] Differentiate passthrough / abstract delegate AbstractDelegateExtent allows overriding just the basic set/get to change behavior - at performance cost Passthrough passes all operation, so each must be individually overrided. --- .../implementation/MultiThreadedQueue.java | 3 +- .../java/com/boydti/fawe/config/Settings.java | 2 +- .../brush/visualization/VisualExtent.java | 1 + .../object/extent/BlockTranslateExtent.java | 1 + .../object/extent/ExtentHeightCacher.java | 9 +- .../object/extent/MemoryCheckingExtent.java | 23 +- .../boydti/fawe/object/extent/SlowExtent.java | 32 +- .../fawe/object/extent/TemporalExtent.java | 3 +- .../regions/selector/FuzzyRegionSelector.java | 3 +- .../java/com/sk89q/worldedit/EditSession.java | 3 +- .../worldedit/extent/PassthroughExtent.java | 291 ++++++++++++++++++ 11 files changed, 338 insertions(+), 33 deletions(-) create mode 100644 worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java index 5b64ed33c..f47d3a732 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/MultiThreadedQueue.java @@ -9,6 +9,7 @@ import com.boydti.fawe.beta.filters.DistrFilter; import com.boydti.fawe.config.Settings; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.extent.AbstractDelegateExtent; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; @@ -25,7 +26,7 @@ import java.util.Set; import java.util.concurrent.ForkJoinTask; import java.util.stream.IntStream; -public class MultiThreadedQueue extends AbstractDelegateExtent implements IQueueWrapper { +public class MultiThreadedQueue extends PassthroughExtent implements IQueueWrapper { private final World world; private final QueueHandler handler; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index 5e234d644..82229b7bd 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -142,7 +142,7 @@ public class Settings extends Config { public int MAX_EXPRESSION_MS = 50; @Comment({ "Cinematic block placement:", - " - Adds a delay to block placement (ms/block)", + " - Adds a delay to block placement (nanoseconds/block)", " - Having an artificial delay will use more CPU/Memory", }) public int SPEED_REDUCTION = 0; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java index 4419b2218..6c58fca9a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java @@ -7,6 +7,7 @@ import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java index 4000aa826..c88416df8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java @@ -1,6 +1,7 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.extent.AbstractDelegateExtent; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ExtentHeightCacher.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ExtentHeightCacher.java index 4230773f0..9368c5856 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ExtentHeightCacher.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/ExtentHeightCacher.java @@ -2,9 +2,11 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.PassthroughExtent; + import java.util.Arrays; -public class ExtentHeightCacher extends AbstractDelegateExtent { +public class ExtentHeightCacher extends PassthroughExtent { public ExtentHeightCacher(Extent extent) { super(extent); @@ -18,15 +20,10 @@ public class ExtentHeightCacher extends AbstractDelegateExtent { } } - private transient int cacheCenX; - private transient int cacheCenZ; private transient int cacheBotX = Integer.MIN_VALUE; private transient int cacheBotZ = Integer.MIN_VALUE; - private transient int cacheCenterZ; private transient byte[] cacheHeights; private transient int lastY; - private transient boolean foundY; - private transient boolean lastValue; @Override public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java index d9b428f96..4d79f6ad7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/MemoryCheckingExtent.java @@ -9,10 +9,11 @@ import com.boydti.fawe.util.WEManager; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockStateHolder; -public class MemoryCheckingExtent extends AbstractDelegateExtent { +public class MemoryCheckingExtent extends PassthroughExtent { private final FawePlayer player; public MemoryCheckingExtent(final FawePlayer player, final Extent extent) { @@ -21,20 +22,16 @@ public class MemoryCheckingExtent extends AbstractDelegateExtent { } @Override - public > boolean setBlock(final BlockVector3 location, final B block) throws WorldEditException { - if (super.setBlock(location, block)) { - if (MemUtil.isMemoryLimited()) { - if (this.player != null) { - player.sendMessage(BBC.WORLDEDIT_CANCEL_REASON.format(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY.s())); - if (Permission.hasPermission(this.player.toWorldEditPlayer(), "worldedit.fast")) { - BBC.WORLDEDIT_OOM_ADMIN.send(this.player); - } + public Extent getExtent() { + if (MemUtil.isMemoryLimited()) { + if (this.player != null) { + player.sendMessage(BBC.WORLDEDIT_CANCEL_REASON.format(BBC.WORLDEDIT_CANCEL_REASON_LOW_MEMORY.s())); + if (Permission.hasPermission(this.player.toWorldEditPlayer(), "worldedit.fast")) { + BBC.WORLDEDIT_OOM_ADMIN.send(this.player); } - WEManager.IMP.cancelEdit(this, FaweException.LOW_MEMORY); - return false; } - return true; + WEManager.IMP.cancelEdit(this, FaweException.LOW_MEMORY); } - return false; + return super.getExtent(); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SlowExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SlowExtent.java index 05679c565..8defb4884 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SlowExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/SlowExtent.java @@ -3,6 +3,7 @@ package com.boydti.fawe.object.extent; import com.boydti.fawe.Fawe; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; @@ -10,20 +11,33 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockStateHolder; public class SlowExtent extends AbstractDelegateExtent { - private final long sleep; + private long THRESHOLD = 50 * 1000000; // 1 tick + private final long nanos; + private long increment; - public SlowExtent(Extent extent, long sleep) { + public SlowExtent(Extent extent, long nanos) { super(extent); - this.sleep = sleep; + this.nanos = nanos; } @Override - public > boolean setBlock(BlockVector3 location, B block) throws WorldEditException { - if (!Fawe.isMainThread()) try { - Thread.sleep(sleep); - } catch (InterruptedException e) { - e.printStackTrace(); + public > boolean setBlock(int x, int y, int z, T block) throws WorldEditException { + delay(); + return super.setBlock(x, y, z, block); + } + + public void delay() { + increment += nanos; + if (increment >= THRESHOLD) { + long wait = increment / 1000000; + if (!Fawe.isMainThread()) { + try { + Thread.sleep(wait); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + increment -= wait * 1000000; } - return super.setBlock(location, block); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TemporalExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TemporalExtent.java index 01192bd6b..252d4428c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TemporalExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/TemporalExtent.java @@ -1,5 +1,6 @@ package com.boydti.fawe.object.extent; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.extent.AbstractDelegateExtent; @@ -10,7 +11,7 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; -public class TemporalExtent extends AbstractDelegateExtent { +public class TemporalExtent extends PassthroughExtent { private int x, y, z = Integer.MAX_VALUE; private BlockStateHolder block = BlockTypes.AIR.getDefaultState(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java index c07421d0f..c373441b4 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/regions/selector/FuzzyRegionSelector.java @@ -12,6 +12,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.AbstractDelegateExtent; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -24,7 +25,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.annotation.Nullable; -public class FuzzyRegionSelector extends AbstractDelegateExtent implements RegionSelector { +public class FuzzyRegionSelector extends PassthroughExtent implements RegionSelector { private final Player player; private FuzzyRegion region; 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 c6b654357..033c629cf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -59,6 +59,7 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.ChangeSetExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.MaskingExtent; +import com.sk89q.worldedit.extent.PassthroughExtent; import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBagExtent; import com.sk89q.worldedit.extent.world.SurvivalModeExtent; @@ -163,7 +164,7 @@ import org.slf4j.LoggerFactory; * using the {@link ChangeSetExtent}.

*/ @SuppressWarnings({"FieldCanBeLocal"}) -public class EditSession extends AbstractDelegateExtent implements SimpleWorld, AutoCloseable { +public class EditSession extends PassthroughExtent implements SimpleWorld, AutoCloseable { private static final Logger log = LoggerFactory.getLogger(EditSession.class); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java new file mode 100644 index 000000000..7f4523005 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/PassthroughExtent.java @@ -0,0 +1,291 @@ +package com.sk89q.worldedit.extent; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.function.generator.GenBase; +import com.sk89q.worldedit.function.generator.Resource; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.util.Countable; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BaseBlock; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockType; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class PassthroughExtent extends AbstractDelegateExtent { + /** + * Create a new instance. + * + * @param extent the extent + */ + public PassthroughExtent(Extent extent) { + super(extent); + } + + public BlockVector3 getMinimumPoint() { + return getExtent().getMinimumPoint(); + } + + public BlockVector3 getMaximumPoint() { + return getExtent().getMaximumPoint(); + } + + @Override + public List getEntities(Region region) { + return getExtent().getEntities(region); + } + + @Override + public List getEntities() { + return getExtent().getEntities(); + } + + @Override + @Nullable + public Entity createEntity(Location location, BaseEntity entity) { + return getExtent().createEntity(location, entity); + } + + @Override + @Nullable + public void removeEntity(int x, int y, int z, UUID uuid) { + getExtent().removeEntity(x, y, z, uuid); + } + + public boolean isQueueEnabled() { + return getExtent().isQueueEnabled(); + } + + public void enableQueue() { + getExtent().enableQueue(); + } + + public void disableQueue() { + getExtent().disableQueue(); + } + + @Override + public boolean isWorld() { + return getExtent().isWorld(); + } + + @Override + public boolean regenerateChunk(int x, int z, @Nullable BiomeType type, @Nullable Long seed) { + return getExtent().regenerateChunk(x, z, type, seed); + } + + @Override + public int getHighestTerrainBlock(int x, int z, int minY, int maxY) { + return getExtent().getHighestTerrainBlock(x, z, minY, maxY); + } + + @Override + public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) { + return getExtent().getHighestTerrainBlock(x, z, minY, maxY, filter); + } + + @Override + public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) { + return getExtent().getNearestSurfaceLayer(x, z, y, minY, maxY); + } + + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) { + return getExtent().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir); + } + + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { + return getExtent().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); + } + + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { + return getExtent().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); + } + + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) { + return getExtent().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask); + } + + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, boolean ignoreAir) { + return getExtent().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir); + } + + @Override + public void addCaves(Region region) throws WorldEditException { + getExtent().addCaves(region); + } + + @Override + public void generate(Region region, GenBase gen) throws WorldEditException { + getExtent().generate(region, gen); + } + + @Override + public void addSchems(Region region, Mask mask, List clipboards, int rarity, boolean rotate) throws WorldEditException { + getExtent().addSchems(region, mask, clipboards, rarity, rotate); + } + + @Override + public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException { + getExtent().spawnResource(region, gen, rarity, frequency); + } + + @Override + public boolean contains(BlockVector3 pt) { + return getExtent().contains(pt); + } + + @Override + public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException { + getExtent().addOre(region, mask, material, size, frequency, rarity, minY, maxY); + } + + @Override + public void addOres(Region region, Mask mask) throws WorldEditException { + getExtent().addOres(region, mask); + } + + @Override + public List> getBlockDistribution(Region region) { + return getExtent().getBlockDistribution(region); + } + + @Override + public List> getBlockDistributionWithData(Region region) { + return getExtent().getBlockDistributionWithData(region); + } + + @Nullable + public Operation commit() { + return getExtent().commit(); + } + + @Override + public boolean cancel() { + return getExtent().cancel(); + } + + public int getMaxY() { + return getExtent().getMaxY(); + } + + @Override + public BlockArrayClipboard lazyCopy(Region region) { + return getExtent().lazyCopy(region); + } + + @Override + public int countBlocks(Region region, Set searchBlocks) { + return getExtent().countBlocks(region, searchBlocks); + } + + @Override + public int countBlocks(Region region, Mask searchMask) { + return getExtent().countBlocks(region, searchMask); + } + + @Override + public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { + return getExtent().setBlocks(region, block); + } + + @Override + public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { + return getExtent().setBlocks(region, pattern); + } + + @Override + public > int replaceBlocks(Region region, Set filter, B replacement) throws MaxChangedBlocksException { + return getExtent().replaceBlocks(region, filter, replacement); + } + + @Override + public int replaceBlocks(Region region, Set filter, Pattern pattern) throws MaxChangedBlocksException { + return getExtent().replaceBlocks(region, filter, pattern); + } + + @Override + public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { + return getExtent().replaceBlocks(region, mask, pattern); + } + + @Override + public int center(Region region, Pattern pattern) throws MaxChangedBlocksException { + return getExtent().center(region, pattern); + } + + @Override + public int setBlocks(Set vset, Pattern pattern) { + return getExtent().setBlocks(vset, pattern); + } + + public BlockState getBlock(BlockVector3 position) { + return getExtent().getBlock(position); + } + + public BlockState getBlock(int x, int y, int z) { + return getExtent().getBlock(x, y, z); + } + + @Override + public BaseBlock getFullBlock(BlockVector3 position) { + return getExtent().getFullBlock(position); + } + + public BaseBlock getFullBlock(int x, int y, int z) { + return getExtent().getFullBlock(x, y, z); + } + + @Override + public BiomeType getBiome(BlockVector2 position) { + return getExtent().getBiome(position); + } + + public BiomeType getBiomeType(int x, int z) { + return getExtent().getBiomeType(x, z); + } + + @Override + @Deprecated + public > boolean setBlock(BlockVector3 position, T block) throws WorldEditException { + return getExtent().setBlock(position, block); + } + + public > boolean setBlock(int x, int y, int z, T block) throws WorldEditException { + return getExtent().setBlock(x, y, z, block); + } + + @Override + public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { + return getExtent().setTile(x, y, z, tile); + } + + @Override + public boolean setBiome(BlockVector2 position, BiomeType biome) { + return getExtent().setBiome(position, biome); + } + + public boolean setBiome(int x, int y, int z, BiomeType biome) { + return getExtent().setBiome(x, y, z, biome); + } +}