From 14d5275e0528e5c07e55967e9b716aa0c8d2080d Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Fri, 12 Jul 2019 02:10:32 +1000 Subject: [PATCH] wip chunk based bitset --- .../implementation/MultiThreadedQueue.java | 17 ++- .../com/boydti/fawe/object/FawePlayer.java | 35 ------ .../fawe/object/collection/ChunkBVecSet.java | 109 ++++++++++++++++ .../fawe/object/collection/ChunkBitSet.java | 31 +++++ .../java/com/sk89q/worldedit/EditSession.java | 5 +- .../com/sk89q/worldedit/extent/Extent.java | 6 + .../function/visitor/RegionVisitor.java | 119 +----------------- 7 files changed, 166 insertions(+), 156 deletions(-) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBVecSet.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 3795c4dcf..badabc0d2 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 @@ -17,6 +17,7 @@ import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.visitor.RegionVisitor; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.world.World; @@ -103,6 +104,10 @@ public class MultiThreadedQueue extends AbstractDelegateExtent implements IQueue return filter; } + public int getChanges() { + return -1; + } + @Override public int countBlocks(final Region region, final Mask searchMask) { return @@ -116,19 +121,25 @@ public class MultiThreadedQueue extends AbstractDelegateExtent implements IQueue @Override public > int setBlocks(Region region, B block) throws MaxChangedBlocksException { apply(region, block); - return 0; + return getChanges(); } @Override public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException { apply(region, pattern); - return 0; + return getChanges(); + } + + @Override + public int setBlocks(Set vset, Pattern pattern) { + TODO + return getChanges(); } @Override public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { apply(region, mask.toFilter(pattern)); - return 0; + return getChanges(); } @Override 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 73dfccd85..86c27f3e3 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 @@ -686,39 +686,4 @@ public abstract class FawePlayer extends Metadatable { } return proxy; } - - - /** - * Get the tracked EditSession(s) for this player
- * - Queued or autoqueued EditSessions are considered tracked - * - * @param requiredStage - * @return - */ - public Map getTrackedSessions(SetQueue.QueueStage requiredStage) { - Map map = new ConcurrentHashMap<>(8, 0.9f, 1); - if (requiredStage == null || requiredStage == SetQueue.QueueStage.ACTIVE) { - for (FaweQueue queue : SetQueue.IMP.getActiveQueues()) { - Collection sessions = queue.getEditSessions(); - for (EditSession session : sessions) { - FawePlayer currentPlayer = session.getPlayer(); - if (currentPlayer == this) { - map.put(session, SetQueue.QueueStage.ACTIVE); - } - } - } - } - if (requiredStage == null || requiredStage == SetQueue.QueueStage.INACTIVE) { - for (FaweQueue queue : SetQueue.IMP.getInactiveQueues()) { - Collection sessions = queue.getEditSessions(); - for (EditSession session : sessions) { - FawePlayer currentPlayer = session.getPlayer(); - if (currentPlayer == this) { - map.put(session, SetQueue.QueueStage.INACTIVE); - } - } - } - } - return map; - } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBVecSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBVecSet.java new file mode 100644 index 000000000..0dddf8bdc --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBVecSet.java @@ -0,0 +1,109 @@ +package com.boydti.fawe.object.collection; + +import com.sk89q.worldedit.math.BlockVector3; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +public class ChunkBVecSet implements Set { + private final int offsetX, offsetZ; + private final ChunkBitSet set; + private int size = 0; + + public ChunkBVecSet(int size) { + this(Integer.MAX_VALUE, Integer.MAX_VALUE, new ChunkBitSet(size)); + } + + public ChunkBVecSet(ChunkBitSet set, int offsetX, int offsetZ) { + this.offsetX = offsetX; + this.offsetZ = offsetZ; + this.set = set; + } + + public ChunkBitSet getBitSet() { + return set; + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public boolean contains(Object o) { + try { + return contain((BlockVector3) o); + } catch (ClassCastException e) { + e.printStackTrace(); + return false; + } + } + + public boolean contain(BlockVector3 obj) { + return contain(obj.getX(), obj.getY(), obj.getZ()); + } + + public boolean contain(int x, int y, int z) { + return set.get(x - offsetX, y, z - offsetZ); + } + + @NotNull + @Override + public Iterator iterator() { + return null; + } + + @NotNull + @Override + public Object[] toArray() { + return new Object[0]; + } + + @NotNull + @Override + public T[] toArray(@NotNull T[] a) { + return null; + } + + @Override + public boolean add(BlockVector3 blockVector3) { + return false; + } + + @Override + public boolean remove(Object o) { + return false; + } + + @Override + public boolean containsAll(@NotNull Collection c) { + return false; + } + + @Override + public boolean addAll(@NotNull Collection c) { + return false; + } + + @Override + public boolean retainAll(@NotNull Collection c) { + return false; + } + + @Override + public boolean removeAll(@NotNull Collection c) { + return false; + } + + @Override + public void clear() { + + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBitSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBitSet.java index 33e3988ab..eac383c64 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBitSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/ChunkBitSet.java @@ -26,6 +26,10 @@ public class ChunkBitSet { return rows[x >> 4].get(this.rows, x, y, z); } + public void add(int x, int y, int z) { + rows[x >> 4].add(this.rows, x, y, z); + } + public void set(int x, int y, int z) { rows[x >> 4].set(this.rows, x, y, z); } @@ -37,6 +41,10 @@ public class ChunkBitSet { private interface IRow { default boolean get(IRow[] rows, int x, int y, int z) { return false; } void set(IRow[] rows, int x, int y, int z); + default boolean add(IRow[] rows, int x, int y, int z) { + set(rows, x, y, z); + return true; + } default void clear(IRow[] rows, int x, int y, int z) { return; } } @@ -85,6 +93,11 @@ public class ChunkBitSet { this.rows[z >> 4].set(this.rows, x, y, z); } + @Override + public boolean add(IRow[] parent, int x, int y, int z) { + return this.rows[z >> 4].add(this.rows, x, y, z); + } + @Override public void clear(IRow[] parent, int x, int y, int z) { this.rows[z >> 4].clear(this.rows, x, y, z); @@ -109,6 +122,11 @@ public class ChunkBitSet { this.rows[y >> 4].set(this.rows, x, y, z); } + @Override + public boolean add(IRow[] parent, int x, int y, int z) { + return this.rows[y >> 4].add(this.rows, x, y, z); + } + @Override public void clear(IRow[] parent, int x, int y, int z) { this.rows[y >> 4].set(this.rows, x, y, z); @@ -134,6 +152,19 @@ public class ChunkBitSet { bits[i >> 6] |= (1L << (i & 0x3F)); } + @Override + public boolean add(IRow[] parent, int x, int y, int z) { + int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15); + int offset = i >> 6; + long value = bits[offset]; + long mask = (1L << (i & 0x3F)); + if ((value & mask) != 0) { + bits[offset] = value | mask; + return true; + } + return false; + } + @Override public void clear(IRow[] parent, int x, int y, int z) { int i = ((y & 15) << 8) | ((z & 15) << 4) | (x & 15); 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 ce92e7e65..2ecc31871 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -24,8 +24,6 @@ import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.HasFaweQueue; import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal; @@ -45,7 +43,6 @@ import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.ExtentTraverser; import com.boydti.fawe.util.MaskTraverser; import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.TaskManager; import com.google.common.base.Supplier; import com.sk89q.jnbt.CompoundTag; @@ -944,7 +941,7 @@ public class EditSession extends AbstractDelegateExtent implements HasFaweQueue, } public int setBlocks(final Set vset, final Pattern pattern) { - RegionVisitor visitor = new RegionVisitor(vset, new BlockReplace(getExtent(), pattern), this); + RegionVisitor visitor = new RegionVisitor(vset, new BlockReplace(getExtent(), pattern)); Operations.completeBlindly(visitor); changes += visitor.getAffected(); return changes; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index a76be6020..08f75d223 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -581,4 +581,10 @@ public interface Extent extends InputExtent, OutputExtent { return setBlocks(centerRegion, pattern); } + default int setBlocks(final Set vset, final Pattern pattern) { + RegionVisitor visitor = new RegionVisitor(vset, new BlockReplace(getExtent(), pattern)); + Operations.completeBlindly(visitor); + return 0; + } + } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java index 9694e79a3..a8e46d9dd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java @@ -20,13 +20,6 @@ package com.sk89q.worldedit.function.visitor; import com.boydti.fawe.config.BBC; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.example.MappedFaweQueue; -import com.boydti.fawe.object.FaweQueue; -import com.boydti.fawe.object.HasFaweQueue; -import com.boydti.fawe.object.exception.FaweException; - -import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.operation.Operation; @@ -34,7 +27,6 @@ import com.sk89q.worldedit.function.operation.RunContext; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; -import java.util.Iterator; import java.util.List; /** @@ -46,7 +38,6 @@ public class RegionVisitor implements Operation { public final RegionFunction function; public int affected = 0; public final Iterable iterable; - private final MappedFaweQueue queue; /** * Deprecated in favor of the other constructors which will preload chunks during iteration @@ -56,22 +47,14 @@ public class RegionVisitor implements Operation { */ @Deprecated public RegionVisitor(Region region, RegionFunction function) { - this(region, function, (FaweQueue) null); + this((Iterable) region, function); } - public RegionVisitor(Region region, RegionFunction function, EditSession editSession) { - this(region, function, editSession != null ? editSession.getQueue() : null); - } - - public RegionVisitor(Region region, RegionFunction function, FaweQueue queue) { - this((Iterable) region, function, queue); - } - - public RegionVisitor(Iterable iterable, RegionFunction function, HasFaweQueue hasQueue) { + @Deprecated + public RegionVisitor(Iterable iterable, RegionFunction function) { this.region = iterable instanceof Region ? (Region) iterable : null; this.function = function; this.iterable = iterable; - this.queue = hasQueue != null && hasQueue.getQueue() instanceof MappedFaweQueue ? (MappedFaweQueue) hasQueue.getQueue() : null; } /** @@ -85,100 +68,8 @@ public class RegionVisitor implements Operation { @Override public Operation resume(RunContext run) throws WorldEditException { - if (queue != null && Settings.IMP.QUEUE.PRELOAD_CHUNKS > 1) { - /* - * The following is done to reduce iteration cost - * - Preload chunks just in time - * - Only check every 16th block for potential chunk loads - * - Stop iteration on exception instead of hasNext - * - Do not calculate the stacktrace as it is expensive - */ - Iterator trailIter = iterable.iterator(); - Iterator leadIter = iterable.iterator(); - int lastTrailChunkX = Integer.MIN_VALUE; - int lastTrailChunkZ = Integer.MIN_VALUE; - int lastLeadChunkX = Integer.MIN_VALUE; - int lastLeadChunkZ = Integer.MIN_VALUE; - int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS; - try { - for (; ; ) { - BlockVector3 pt = trailIter.next(); - apply(pt); - int cx = pt.getBlockX() >> 4; - int cz = pt.getBlockZ() >> 4; - if (cx != lastTrailChunkX || cz != lastTrailChunkZ) { - lastTrailChunkX = cx; - lastTrailChunkZ = cz; - int amount; - if (lastLeadChunkX == Integer.MIN_VALUE) { - lastLeadChunkX = cx; - lastLeadChunkZ = cz; - amount = loadingTarget; - } else { - amount = 1; - } - for (int count = 0; count < amount; ) { - BlockVector3 v = leadIter.next(); - int vcx = v.getBlockX() >> 4; - int vcz = v.getBlockZ() >> 4; - if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) { - lastLeadChunkX = vcx; - lastLeadChunkZ = vcz; - queue.queueChunkLoad(vcx, vcz); - count++; - } - // Skip the next 15 blocks - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - leadIter.next(); - } - } - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - apply(trailIter.next()); - } - } catch (FaweException e) { - throw new RuntimeException(e); - } catch (Throwable ignore) { - ignore.printStackTrace(); - } - try { - while (true) { - apply(trailIter.next()); - apply(trailIter.next()); - } - } catch (FaweException e) { - throw new RuntimeException(e); - } catch (Throwable ignore) { - } - } else { - for (BlockVector3 pt : iterable) { - apply(pt); - } + for (BlockVector3 pt : iterable) { + apply(pt); } return null; }