diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java index 0eec7fbf7..7abe76c21 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java @@ -2,16 +2,14 @@ package com.boydti.fawe.bukkit.beta; import com.boydti.fawe.Fawe; import com.boydti.fawe.beta.Filter; -import com.boydti.fawe.beta.IChunk; import com.boydti.fawe.beta.IGetBlocks; import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.ISetBlocks; import com.boydti.fawe.beta.implementation.QueueHandler; -import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; import com.boydti.fawe.beta.implementation.holder.ChunkHolder; import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13; import com.boydti.fawe.util.ReflectionUtils; -import com.google.common.util.concurrent.Futures; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.LongTag; @@ -20,8 +18,6 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockTypes; -import net.jpountz.util.UnsafeUtils; import net.minecraft.server.v1_13_R2.BiomeBase; import net.minecraft.server.v1_13_R2.BlockPosition; import net.minecraft.server.v1_13_R2.Chunk; @@ -37,18 +33,14 @@ import org.bukkit.block.Biome; import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock; import org.bukkit.event.entity.CreatureSpawnEvent; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicReferenceArray; public class BukkitChunkHolder> extends ChunkHolder { @Override @@ -86,7 +78,7 @@ public class BukkitChunkHolder> extends ChunkHolder { int Z = getZ(); BukkitQueue extent = (BukkitQueue) getExtent(); BukkitGetBlocks get = (BukkitGetBlocks) getOrCreateGet(); - CharSetBlocks set = (CharSetBlocks) getOrCreateSet(); + ISetBlocks set = getOrCreateSet(); Chunk nmsChunk = extent.ensureLoaded(X, Z); @@ -102,12 +94,10 @@ public class BukkitChunkHolder> extends ChunkHolder { final int ly = pos.getY(); final int lz = pos.getZ() & 15; final int layer = ly >> 4; - final char[] array = set.blocks[layer]; - if (array == null) { + if (!set.hasSection(layer)) { continue; } - final int index = (((ly & 0xF) << 8) | (lz << 4) | lx); - if (array[index] != 0) { + if (set.getBlock(lx, ly, lz).getOrdinal() != 0) { TileEntity tile = entry.getValue(); tile.z(); tile.invalidateBlockCache(); @@ -116,7 +106,6 @@ public class BukkitChunkHolder> extends ChunkHolder { } } - int bitMask = 0; synchronized (nmsChunk) { ChunkSection[] sections = nmsChunk.getSections(); @@ -128,7 +117,7 @@ public class BukkitChunkHolder> extends ChunkHolder { bitMask |= 1 << layer; - char[] setArr = set.blocks[layer]; + char[] setArr = set.getArray(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; if (existingSection == null) { @@ -182,11 +171,12 @@ public class BukkitChunkHolder> extends ChunkHolder { } // Biomes - if (set.biomes != null) { + BiomeType[] biomes = set.getBiomes(); + if (biomes != null) { // set biomes final BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex(); - for (int i = 0; i < set.biomes.length; i++) { - final BiomeType biome = set.biomes[i]; + for (int i = 0; i < biomes.length; i++) { + final BiomeType biome = biomes[i]; if (biome != null) { final Biome craftBiome = BukkitAdapter.adapt(biome); currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome); @@ -200,11 +190,10 @@ public class BukkitChunkHolder> extends ChunkHolder { int bx = X << 4; int bz = Z << 4; - if (set.entityRemoves != null && !set.entityRemoves.isEmpty()) { + Set entityRemoves = set.getEntityRemoves(); + if (entityRemoves != null && !entityRemoves.isEmpty()) { if (syncTasks == null) syncTasks = new Runnable[3]; - HashSet entsToRemove = set.entityRemoves; - syncTasks[2] = new Runnable() { @Override public void run() { @@ -216,7 +205,7 @@ public class BukkitChunkHolder> extends ChunkHolder { final Iterator iter = ents.iterator(); while (iter.hasNext()) { final Entity entity = iter.next(); - if (entsToRemove.contains(entity.getUniqueID())) { + if (entityRemoves.contains(entity.getUniqueID())) { iter.remove(); entity.b(false); entity.die(); @@ -229,15 +218,14 @@ public class BukkitChunkHolder> extends ChunkHolder { }; } - if (set.entities != null && !set.entities.isEmpty()) { + Set entities = set.getEntities(); + if (entities != null && !entities.isEmpty()) { if (syncTasks == null) syncTasks = new Runnable[2]; - HashSet entitiesToSpawn = set.entities; - syncTasks[1] = new Runnable() { @Override public void run() { - for (final CompoundTag nativeTag : entitiesToSpawn) { + for (final CompoundTag nativeTag : entities) { final Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); final StringTag idTag = (StringTag) entityTagMap.get("Id"); final ListTag posTag = (ListTag) entityTagMap.get("Pos"); @@ -274,10 +262,10 @@ public class BukkitChunkHolder> extends ChunkHolder { } // set tiles - if (set.tiles != null && !set.tiles.isEmpty()) { + Map tiles = set.getTiles(); + if (tiles != null && !tiles.isEmpty()) { if (syncTasks == null) syncTasks = new Runnable[1]; - HashMap tiles = set.tiles; syncTasks[0] = new Runnable() { @Override public void run() { @@ -307,19 +295,22 @@ public class BukkitChunkHolder> extends ChunkHolder { }; } - int finalMask = bitMask; - Runnable callback = () -> { - if (finalMask != 0) { + Runnable callback; + if (bitMask == 0) { + callback = null; + } else { + int finalMask = bitMask; + callback = () -> { // Set Modified nmsChunk.f(true); nmsChunk.mustSave = true; nmsChunk.markDirty(); // send to player extent.sendChunk(X, Z, finalMask); - } - extent.returnToPool(BukkitChunkHolder.this); - }; + extent.returnToPool(BukkitChunkHolder.this); + }; + } if (syncTasks != null) { QueueHandler queueHandler = Fawe.get().getQueueHandler(); Runnable[] finalSyncTasks = syncTasks; @@ -335,12 +326,21 @@ public class BukkitChunkHolder> extends ChunkHolder { task.run(); } } - return queueHandler.async(callback, null); + if (callback == null) { + extent.returnToPool(BukkitChunkHolder.this); + return null; + } else { + return queueHandler.async(callback, null); + } } }; return (T) (Future) queueHandler.sync(chain); } else { - callback.run(); + if (callback == null) { + extent.returnToPool(BukkitChunkHolder.this); + } else { + callback.run(); + } } } return null; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java index 6db6b7c7d..8d767b49e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/CharFilterBlock.java @@ -1,7 +1,6 @@ package com.boydti.fawe.beta; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; -import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -14,7 +13,8 @@ import static com.sk89q.worldedit.world.block.BlockTypes.states; public class CharFilterBlock implements FilterBlock { private IQueueExtent queue; private CharGetBlocks get; - private CharSetBlocks set; + + private ISetBlocks set; private char[] getArr; private @Nullable char[] setArr; @@ -39,28 +39,26 @@ public class CharFilterBlock implements FilterBlock { return this; } - public final void filter(final IGetBlocks iget, final ISetBlocks iset, final Filter filter) { - final CharSetBlocks set = (CharSetBlocks) iset; + @Override + public final void filter(final IGetBlocks iget, final ISetBlocks iset, final int layer, final Filter filter) { + this.layer = layer; final CharGetBlocks get = (CharGetBlocks) iget; - for (int layer = 0; layer < 16; layer++) { - if (!get.hasSection(layer)) continue; - this.set = set; - getArr = get.sections[layer].get(get, layer); - if (set.hasSection(layer)) { - setArr = set.blocks[layer]; - delegate = FULL; - } else { - delegate = NULL; - setArr = null; - } - this.layer = layer; - this.yy = layer << 4; + if (!get.hasSection(layer)) return; + this.set = iset; + getArr = get.sections[layer].get(get, layer); + if (set.hasSection(layer)) { + setArr = set.getArray(layer); + delegate = FULL; + } else { + delegate = NULL; + setArr = null; + } + this.yy = layer << 4; - for (y = 0, index = 0; y < 16; y++) { - for (z = 0; z < 16; z++) { - for (x = 0; x < 16; x++, index++) { - filter.applyBlock(this); - } + for (y = 0, index = 0; y < 16; y++) { + for (z = 0; z < 16; z++) { + for (x = 0; x < 16; x++, index++) { + filter.applyBlock(this); } } } @@ -305,7 +303,7 @@ public class CharFilterBlock implements FilterBlock { Set delegate */ private SetDelegate initSet() { - setArr = set.sections[layer].get(set, layer); + setArr = set.getArray(layer); return delegate = FULL; } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java index 01a49bdc7..9bcdf29c8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java @@ -57,7 +57,7 @@ public interface Filter { return this; } - default void join(final Filter parent) { + default void join() { } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java index ac6cd3312..e305dc43c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/FilterBlock.java @@ -1,7 +1,5 @@ package com.boydti.fawe.beta; -import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; -import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; @@ -11,7 +9,7 @@ public interface FilterBlock { FilterBlock init(int X, int Z, IGetBlocks chunk); - void filter(IGetBlocks get, ISetBlocks set, Filter filter); + void filter(IGetBlocks get, ISetBlocks set, int layer, Filter filter); void setOrdinal(int ordinal); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java index eb6afbd84..827bc8c7a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java @@ -27,8 +27,6 @@ public interface IChunk> extends Trimable, Callable { int getZ(); - - /** * If the chunk is a delegate, returns it's paren'ts root * @return root IChunk @@ -42,14 +40,6 @@ public interface IChunk> extends Trimable, Callable { */ boolean isEmpty(); - /** - * Spend time optimizing for apply
- * default behavior: do nothing - */ - default void optimize() { - - } - /** * Apply the queued changes to the world
* The future returned may return another future
diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java index 51fcd9dc9..dda0dfd5a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java @@ -2,9 +2,13 @@ package com.boydti.fawe.beta; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.UUID; /** @@ -26,4 +30,19 @@ public interface ISetBlocks extends IBlocks { default void optimize() { } + + BlockState getBlock(int x, int y, int z); + + char[] getArray(int layer); + + BiomeType[] getBiomes(); + + Map getTiles(); + + Set getEntities(); + + Set getEntityRemoves(); + + @Override + void reset(); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java index 052519cd7..988b60161 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/CountFilter.java @@ -1,6 +1,5 @@ package com.boydti.fawe.beta.filters; -import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.FilterBlock; import com.boydti.fawe.config.BBC; import com.sk89q.worldedit.extension.platform.Actor; @@ -12,11 +11,35 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class CountFilter implements Filter { +public class CountFilter extends ForkedFilter { private final int[] counter = new int[BlockTypes.states.length]; + public CountFilter() { + super(null); + } + + private CountFilter(CountFilter root) { + super(root); + } + @Override - public void applyBlock(final FilterBlock block) { + public CountFilter init() { + return new CountFilter(this); + } + + @Override + public void join(CountFilter filter) { + for (int i = 0; i < filter.counter.length; i++) { + this.counter[i] += filter.counter[i]; + } + } + + /* + Implementation + */ + + @Override + public final void applyBlock(final FilterBlock block) { counter[block.getOrdinal()]++; } @@ -42,17 +65,4 @@ public class CountFilter implements Filter { actor.print(BBC.getPrefix() + str); } } - - @Override - public Filter fork() { - return new CountFilter(); - } - - @Override - public void join(final Filter parent) { - final CountFilter other = (CountFilter) parent; - for (int i = 0; i < counter.length; i++) { - other.counter[i] += this.counter[i]; - } - } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/ForkedFilter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/ForkedFilter.java new file mode 100644 index 000000000..6118c4dea --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/filters/ForkedFilter.java @@ -0,0 +1,48 @@ +package com.boydti.fawe.beta.filters; + +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.FilterBlock; +import com.boydti.fawe.config.BBC; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.Countable; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypes; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class ForkedFilter> implements Filter { + protected final Map children; + + public ForkedFilter(T root) { + if (root != null) { + children = root.children; + } else { + children = new ConcurrentHashMap<>(); + children.put(Thread.currentThread(), (T) this); + } + } + + @Override + public final Filter fork() { + return children.computeIfAbsent(Thread.currentThread(), thread -> init()); + } + + public abstract T init(); + + @Override + public void join() { + for (Map.Entry entry : children.entrySet()) { + T filter = entry.getValue(); + if (filter != this) { + join(filter); + } + } + children.clear(); + } + + public abstract void join(T filter); +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java index 4cfe41121..b7965f2a3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java @@ -12,7 +12,6 @@ import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.WorldWrapper; -import com.google.common.util.concurrent.Futures; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.world.World; @@ -24,7 +23,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.Future; @@ -163,40 +161,30 @@ public abstract class QueueHandler implements Trimable, Runnable { synchronized (queue) { FilterBlock block = null; - try { - while (true) { - // Get the next chunk pos - final int X, Z; - synchronized (chunksIter) { - if (!chunksIter.hasNext()) break; - final BlockVector2 pos = chunksIter.next(); - X = pos.getX(); - Z = pos.getZ(); - } - IChunk chunk = queue.getCachedChunk(X, Z); - // Initialize - chunk.init(queue, X, Z); - - if (!newFilter.appliesChunk(X, Z)) { - continue; - } - chunk = newFilter.applyChunk(chunk); - - if (chunk == null) continue; - - if (block == null) block = queue.initFilterBlock(); - chunk.filter(newFilter, block); - - newFilter.finishChunk(chunk); - - queue.submit(chunk); + while (true) { + // Get the next chunk pos + final int X, Z; + synchronized (chunksIter) { + if (!chunksIter.hasNext()) break; + final BlockVector2 pos = chunksIter.next(); + X = pos.getX(); + Z = pos.getZ(); } - } finally { - if (filter != newFilter) { - synchronized (filter) { - newFilter.join(filter); - } + IChunk chunk = queue.getCachedChunk(X, Z); + // Initialize + chunk.init(queue, X, Z); + + if (!newFilter.appliesChunk(X, Z)) { + continue; } + chunk = newFilter.applyChunk(chunk); + + if (chunk == null) continue; + + if (block == null) block = queue.initFilterBlock(); + chunk.filter(newFilter, block); + + queue.submit(chunk); } queue.flush(); } @@ -210,5 +198,6 @@ public abstract class QueueHandler implements Trimable, Runnable { task.quietlyJoin(); } } + filter.join(); } } \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java index 3fc218961..f132fe2da 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java @@ -4,10 +4,14 @@ import com.boydti.fawe.beta.ISetBlocks; import com.boydti.fawe.util.MathMan; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; +import com.sk89q.worldedit.world.block.BlockTypes; import java.util.HashMap; import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.UUID; public class CharSetBlocks extends CharBlocks implements ISetBlocks { @@ -16,6 +20,31 @@ public class CharSetBlocks extends CharBlocks implements ISetBlocks { public HashSet entities; public HashSet entityRemoves; + @Override + public char[] getArray(int layer) { + return sections[layer].get(this, layer); + } + + @Override + public BiomeType[] getBiomes() { + return biomes; + } + + @Override + public Map getTiles() { + return tiles; + } + + @Override + public Set getEntities() { + return entities; + } + + @Override + public Set getEntityRemoves() { + return entityRemoves; + } + @Override public boolean setBiome(final int x, final int y, final int z, final BiomeType biome) { if (biomes == null) { @@ -25,6 +54,11 @@ public class CharSetBlocks extends CharBlocks implements ISetBlocks { return true; } + @Override + public BlockState getBlock(int x, int y, int z) { + return BlockTypes.states[get(x, y, z)]; + } + @Override public boolean setBlock(final int x, final int y, final int z, final BlockStateHolder holder) { set(x, y, z, holder.getOrdinalChar()); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FullCharBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FullCharBlocks.java deleted file mode 100644 index bbe4bfec2..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FullCharBlocks.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.boydti.fawe.beta.implementation.blocks; - -import com.boydti.fawe.beta.IBlocks; - -// TODO implement -public class FullCharBlocks implements IBlocks { - public final boolean[] hasSections = new boolean[16]; - public final char[] blocks = new char[65536]; - - @Override - public boolean hasSection(final int layer) { - return false; - } - - @Override - public void reset() { - - } - - @Override - public boolean trim(final boolean aggressive) { - return false; - } -} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java index 153e162bd..46c491cfa 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java @@ -40,7 +40,11 @@ public abstract class ChunkHolder implements IChunk, Supplier { final IGetBlocks get = getOrCreateGet(); final ISetBlocks set = getOrCreateSet(); block = block.init(X, Z, get); - block.filter(get, set, filter); + for (int layer = 0; layer < 16; layer++) { + if (!get.hasSection(layer)) continue; + block.filter(get, set, layer, filter); + } + filter.finishChunk(this); } @Override @@ -94,12 +98,12 @@ public abstract class ChunkHolder implements IChunk, Supplier { return get(); } - @Override - public void optimize() { - if (set != null) { - set.optimize(); - } - } +// @Override +// public void optimize() { +// if (set != null) { +// set.optimize(); +// } +// } @Override public void init(final IQueueExtent extent, final int X, final int Z) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java index c31704c8d..2aef7daf7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java @@ -11,8 +11,7 @@ import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedDeque; public abstract class IterableThreadLocal extends ThreadLocal implements Iterable { - private ThreadLocal flag; - private ConcurrentLinkedDeque allValues = new ConcurrentLinkedDeque<>(); + private final ConcurrentLinkedDeque allValues = new ConcurrentLinkedDeque<>(); public IterableThreadLocal() { } @@ -21,7 +20,9 @@ public abstract class IterableThreadLocal extends ThreadLocal implements I protected final T initialValue() { T value = init(); if (value != null) { - allValues.add(value); + synchronized (this) { + allValues.add(value); + } } return value; } @@ -36,7 +37,12 @@ public abstract class IterableThreadLocal extends ThreadLocal implements I } public void clean() { - IterableThreadLocal.clean(this); + if (!allValues.isEmpty()) { + synchronized (this) { + IterableThreadLocal.clean(this); + allValues.clear(); + } + } } public static void clean(ThreadLocal instance) {