diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/IQueueExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/IQueueExtent.java
new file mode 100644
index 000000000..7a0148ea3
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/IQueueExtent.java
@@ -0,0 +1,42 @@
+package com.boydti.fawe.bukkit.v1_13;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+import com.boydti.fawe.bukkit.v1_13.beta.holder.ChunkHolder;
+import com.boydti.fawe.bukkit.v1_13.beta.holder.IDelegateChunk;
+import com.sk89q.worldedit.extent.Extent;
+import com.sk89q.worldedit.world.World;
+import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BlockState;
+import com.sk89q.worldedit.world.block.BlockStateHolder;
+
+public interface IQueueExtent {
+ void init(World world);
+
+ IChunk getCachedChunk(int X, int Z);
+
+ default boolean setBlock(int x, int y, int z, BlockStateHolder state) {
+ IChunk chunk = getCachedChunk(x >> 4, z >> 4);
+ return chunk.setBlock(x & 15, y, z & 15, state);
+ }
+
+ default boolean setBiome(int x, int y, int z, BiomeType biome) {
+ IChunk chunk = getCachedChunk(x >> 4, z >> 4);
+ return chunk.setBiome(x & 15, y, z & 15, biome);
+ }
+
+ default BlockState getBlock(int x, int y, int z) {
+ IChunk chunk = getCachedChunk(x >> 4, z >> 4);
+ return chunk.getBlock(x & 15, y, z & 15);
+ }
+
+ default BiomeType getBiome(int x, int z) {
+ IChunk chunk = getCachedChunk(x >> 4, z >> 4);
+ return chunk.getBiome(x & 15, z & 15);
+ }
+
+ // Return ChunkHolder
+ ChunkHolder create(boolean full);
+
+ // Region restrictions
+ IDelegateChunk wrap(IChunk root);
+}
\ No newline at end of file
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CachedChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CachedChunk.java
deleted file mode 100644
index 3a2df1006..000000000
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CachedChunk.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.boydti.fawe.bukkit.v1_13.beta;
-
-import com.sk89q.jnbt.CompoundTag;
-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 net.minecraft.server.v1_13_R2.Chunk;
-import net.minecraft.server.v1_13_R2.ChunkSection;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.UUID;
-
-public class CachedChunk {
- private GetBlocks get;
- private SetBlocks set;
-
- public CachedChunk(ReusableExtent parent) {
-
- }
-
-
- public void init(int X, int Z) {
-
- }
-
-
-}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java
index 62a05b707..c33ef3100 100644
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java
@@ -1,7 +1,25 @@
package com.boydti.fawe.bukkit.v1_13.beta;
+import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BaseBlock;
+import com.sk89q.worldedit.world.block.BlockState;
import net.minecraft.server.v1_13_R2.ChunkSection;
public class CharGetBlocks extends CharBlocks implements IGetBlocks {
private ChunkSection[] sections;
+
+ @Override
+ public BaseBlock getFullBlock(int x, int y, int z) {
+ return null;
+ }
+
+ @Override
+ public BiomeType getBiome(int x, int z) {
+ return null;
+ }
+
+ @Override
+ public BlockState getBlock(int x, int y, int z) {
+ return null;
+ }
}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java
new file mode 100644
index 000000000..72ac950cf
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java
@@ -0,0 +1,7 @@
+package com.boydti.fawe.bukkit.v1_13.beta;
+
+import com.boydti.fawe.bukkit.v1_13.IQueueExtent;
+
+public interface IDelegateQueueExtent {
+ IQueueExtent getParent();
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/Filter.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/Filter.java
new file mode 100644
index 000000000..e2bb721c1
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/Filter.java
@@ -0,0 +1,50 @@
+package com.boydti.fawe.bukkit.v1_13.beta;
+
+import com.sk89q.worldedit.world.block.BaseBlock;
+
+public class Filter {
+ /**
+ * Check whether a chunk should be read
+ *
+ * @param cx
+ * @param cz
+ * @return
+ */
+ public boolean appliesChunk(int cx, int cz) {
+ return true;
+ }
+
+ /**
+ * Do something with the IChunk
+ * - Return null if you don't want to filter blocks
+ * - Return the chunk if you do want to filter blocks
+ *
+ * @param chunk
+ * @return
+ */
+ public IChunk applyChunk(IChunk chunk) {
+ return chunk;
+ }
+
+ /**
+ * Make changes to the block here
+ * - e.g. block.setId(...)
+ * - Note: Performance is critical here
+ *
+ * @param x
+ * @param y
+ * @param z
+ * @param block
+ */
+ public void applyBlock(int x, int y, int z, BaseBlock block) {
+ }
+
+ /**
+ * Do something with the IChunk after block filtering
+ *
+ * @param chunk
+ * @return
+ */
+ public void finishChunk(IChunk chunk) {
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/FullCharBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/FullCharBlocks.java
new file mode 100644
index 000000000..e07e6e5b0
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/FullCharBlocks.java
@@ -0,0 +1,6 @@
+package com.boydti.fawe.bukkit.v1_13.beta;
+
+public class FullCharBlocks implements IBlocks {
+ public final boolean[] hasSections = new boolean[16];
+ public final char[] blocks = new char[65536];
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java
index b9372b0d2..21452e0b0 100644
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java
@@ -7,9 +7,9 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
public interface IChunk {
/* set */
- void setBiome(int x, int z, BiomeType biome);
+ boolean setBiome(int x, int y, int z, BiomeType biome);
- void setBlock(int x, int y, int z, BlockStateHolder holder);
+ boolean setBlock(int x, int y, int z, BlockStateHolder holder);
/* get */
BiomeType getBiome(int x, int z);
@@ -17,4 +17,18 @@ public interface IChunk {
BlockState getBlock(int x, int y, int z);
BaseBlock getFullBlock(int x, int y, int z);
+
+ void init(SingleThreadQueueExtent extent, int X, int Z);
+
+ int getX();
+
+ int getZ();
+
+ void apply();
+
+ default IChunk getRoot() {
+ return this;
+ }
+
+ void filter(Filter filter);
}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java
index 446a6a4d6..f0c1346d4 100644
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java
@@ -1,4 +1,13 @@
package com.boydti.fawe.bukkit.v1_13.beta;
+import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BaseBlock;
+import com.sk89q.worldedit.world.block.BlockState;
+
public interface IGetBlocks extends IBlocks {
+ BaseBlock getFullBlock(int x, int y, int z);
+
+ BiomeType getBiome(int x, int z);
+
+ BlockState getBlock(int x, int y, int z);
}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java
index 90f45b8c8..6793775b1 100644
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java
@@ -1,4 +1,10 @@
package com.boydti.fawe.bukkit.v1_13.beta;
+import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BlockStateHolder;
+
public interface ISetBlocks extends IBlocks {
+ void setBiome(int x, int z, BiomeType biome);
+
+ void setBlock(int x, int y, int z, BlockStateHolder holder);
}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java
new file mode 100644
index 000000000..9461531ab
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java
@@ -0,0 +1,83 @@
+package com.boydti.fawe.bukkit.v1_13.beta;
+
+import com.boydti.fawe.config.Settings;
+import com.boydti.fawe.util.MathMan;
+import com.boydti.fawe.util.TaskManager;
+import com.sk89q.worldedit.math.BlockVector2;
+import com.sk89q.worldedit.regions.Region;
+
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+
+public class QueueHandler {
+ private SingleThreadQueueExtent mainExtent;
+ private SingleThreadQueueExtent[] pool;
+
+
+
+ public static void apply(Region region, Filter filter) { // TODO not MCAFilter, but another similar class
+ // The chunks positions to iterate over
+ Set chunks = region.getChunks();
+ Iterator chunksIter = chunks.iterator();
+
+ // Get a pool, to operate on the chunks in parallel
+ ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
+ int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS);
+ ForkJoinTask[] tasks = new ForkJoinTask[size];
+
+ for (int i = 0; i < size; i++) {
+ tasks[i] = pool.submit(new Runnable() {
+ @Override
+ public void run() {
+ // Create a chunk that we will reuse/reset for each operation
+ IChunk chunk = create(true);
+
+ while (true) {
+ // Get the next chunk pos
+ BlockVector2 pos;
+ synchronized (chunksIter) {
+ if (!chunksIter.hasNext()) return;
+ pos = chunksIter.next();
+ }
+ int X = pos.getX();
+ int Z = pos.getZ();
+ long pair = MathMan.pairInt(X, Z);
+
+ // Initialize
+ chunk.init(SingleThreadQueueExtent.this, X, Z);
+
+ { // Start set
+ lastPair = pair;
+ lastChunk = chunk;
+ }
+ try {
+ if (!filter.appliesChunk(X, Z)) {
+ continue;
+ }
+ chunk = filter.applyChunk(chunk);
+
+ if (chunk == null) continue;
+
+ chunk.filter(filter);
+
+ filter.finishChunk(chunk);
+
+ chunk.apply();
+ } finally
+ { // End set
+ lastPair = Long.MAX_VALUE;
+ lastChunk = null;
+ }
+ }
+ }
+ });
+ }
+
+ // Join the tasks
+ for (ForkJoinTask task : tasks) {
+ task.join();
+ }
+ }
+}
\ No newline at end of file
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/RegionCachedChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/RegionCachedChunk.java
deleted file mode 100644
index 7984a0b80..000000000
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/RegionCachedChunk.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.boydti.fawe.bukkit.v1_13.beta;
-
-import net.minecraft.server.v1_13_R2.Chunk;
-
-public class RegionCachedChunk extends CachedChunk {
- public RegionCachedChunk(Chunk chunk) {
- super(chunk);
- }
-}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ReusableExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ReusableExtent.java
deleted file mode 100644
index e095eb27c..000000000
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ReusableExtent.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.boydti.fawe.bukkit.v1_13.beta;
-
-import com.boydti.fawe.Fawe;
-import com.boydti.fawe.jnbt.anvil.MCAFilter;
-import com.boydti.fawe.util.TaskManager;
-import com.boydti.fawe.wrappers.WorldWrapper;
-import com.sk89q.worldedit.EditSession;
-import com.sk89q.worldedit.bukkit.BukkitWorld;
-import com.sk89q.worldedit.function.mask.Mask;
-import com.sk89q.worldedit.math.BlockVector2;
-import com.sk89q.worldedit.regions.Region;
-import com.sk89q.worldedit.world.World;
-import com.sk89q.worldedit.world.biome.BiomeType;
-import com.sk89q.worldedit.world.block.BlockState;
-import com.sk89q.worldedit.world.block.BlockStateHolder;
-import net.minecraft.server.v1_13_R2.WorldServer;
-import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
-
-import java.util.Iterator;
-import java.util.Set;
-import java.util.concurrent.ForkJoinPool;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-public class ReusableExtent {
- private WorldWrapper wrapped;
- private World world;
- private org.bukkit.World bukkitWorld;
- private WorldServer nmsWorld;
-
- private void reset() {
- if (world != null) {
- wrapped = null;
- world = null;
- bukkitWorld = null;
- nmsWorld = null;
- lowMemory = false;
- }
- }
-
- public void init(World world) {
- reset();
- checkNotNull(world);
- if (world instanceof EditSession) {
- world = ((EditSession) world).getWorld();
- }
- checkNotNull(world);
- if (world instanceof WorldWrapper) {
- this.wrapped = (WorldWrapper) world;
- world = WorldWrapper.unwrap(world);
- } else {
- this.world = WorldWrapper.wrap(world);
- }
- this.world = world;
- if (world instanceof BukkitWorld) {
- this.bukkitWorld = ((BukkitWorld) world).getWorld();
- } else {
- this.bukkitWorld = Bukkit.getWorld(world.getName());
- }
- checkNotNull(this.bukkitWorld);
- CraftWorld craftWorld = ((CraftWorld) bukkitWorld);
- this.nmsWorld = craftWorld.getHandle();
- // Save world
- }
-
- private boolean lowMemory;
-
- public void setLowMemory() {
- lowMemory = true;
- // set queue state to active
- // trim cached chunks
- }
-
- private CachedChunk getCachedChunk(int x, int z) {
- // check last
- // otherwise create/load
- // get cached chunk from bukkit
- // otherwise load
- // TODO load async (with paper)
- if (lowMemory) {
- if (Fawe.isMainThread()) {
- // submit other chunks
- next();
- } else {
- // wait until empty
- }
- }
- }
-
- void setBlock(int x, int y, int z, BlockStateHolder holder) {
- CachedChunk chunk = getCachedChunk(x, z);
- chunk.setBlock(x & 15, y, z & 15, holder);
- }
-
- void setBiome(int x, int z, BiomeType biome) {
- CachedChunk chunk = getCachedChunk(x, z);
- chunk.setBiome(x, z, biome);
- }
-
- BlockState getBlock(int x, int y, int z) {
- CachedChunk chunk = getCachedChunk(x, z);
- return chunk.getBlock(x & 15, y, z & 15);
- }
-
- BiomeType getBiome(int x, int z) {
- CachedChunk chunk = getCachedChunk(x, z);
- return chunk.getBiome(x, z);
- }
-
- public void apply(Region region, MCAFilter filter) { // TODO not MCAFilter, but another similar class
- // TODO iterate by mca file
- Set chunks = region.getChunks();
- Iterator chunksIter = chunks.iterator();
- ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool();
- for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) {
- pool.submit(new Runnable() {
- @Override
- public void run() {
- while (true) {
- BlockVector2 pos;
- synchronized (chunksIter) {
- if (!chunksIter.hasNext()) return;
- pos = chunksIter.next();
- }
- int cx = pos.getX();
- int cz = pos.getZ();
- CachedChunk chunk = getCachedChunk(cx, cz);
- try {
- if (!filter.appliesChunk(cx, cz)) {
- continue;
- }
- T value = filter.get();
- chunk = filter.applyChunk(chunk, value);
-
- if (chunk == null) continue;
-
- // TODO if region contains all parts
- chunk.filter(filter);
- // else
- chunk.filter(region, filter);
- } finally {
- // TODO submit chunk
- }
- }
- }
- });
- }
- }
-}
\ No newline at end of file
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java
new file mode 100644
index 000000000..53f1984e4
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java
@@ -0,0 +1,104 @@
+package com.boydti.fawe.bukkit.v1_13.beta;
+
+import com.boydti.fawe.bukkit.v1_13.IQueueExtent;
+import com.boydti.fawe.bukkit.v1_13.beta.holder.ChunkHolder;
+import com.boydti.fawe.bukkit.v1_13.beta.holder.IDelegateChunk;
+import com.boydti.fawe.bukkit.v1_13.beta.holder.ReferenceChunk;
+import com.boydti.fawe.config.Settings;
+import com.boydti.fawe.util.MathMan;
+import com.boydti.fawe.util.MemUtil;
+import com.boydti.fawe.wrappers.WorldWrapper;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.world.World;
+import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public abstract class SingleThreadQueueExtent implements IQueueExtent {
+ private WorldWrapper wrapped;
+ private World world;
+
+ public World getWorld() {
+ return world;
+ }
+
+ public WorldWrapper getWrappedWorld() {
+ return wrapped;
+ }
+
+ private void reset() {
+ wrapped = null;
+ world = null;
+ chunks.clear();
+ lastChunk = null;
+ lastPair = Long.MAX_VALUE;
+ }
+
+ public synchronized void init(World world) {
+ if (world != null) {
+ reset();
+ }
+ checkNotNull(world);
+ if (world instanceof EditSession) {
+ world = ((EditSession) world).getWorld();
+ }
+ checkNotNull(world);
+ if (world instanceof WorldWrapper) {
+ this.wrapped = (WorldWrapper) world;
+ world = WorldWrapper.unwrap(world);
+ } else {
+ this.wrapped = WorldWrapper.wrap(world);
+ }
+ this.world = world;
+ }
+
+ private IChunk lastChunk;
+ private long lastPair = Long.MAX_VALUE;
+ private final Long2ObjectLinkedOpenHashMap chunks = new Long2ObjectLinkedOpenHashMap<>();
+
+ private final IDelegateChunk getCachedChunk2(long pair) {
+ IDelegateChunk chunk = chunks.get(pair);
+ if (chunk instanceof ReferenceChunk) {
+ chunk = (ReferenceChunk) (chunk).getParent();
+ }
+ if (chunk != null) {
+ lastPair = pair;
+ lastChunk = chunk;
+ }
+ return chunk;
+ }
+
+ public final IChunk getCachedChunk(int X, int Z) {
+ long pair = MathMan.pairInt(X, Z);
+ if (pair == lastPair) {
+ return lastChunk;
+ }
+
+ IDelegateChunk chunk = getCachedChunk2(pair);
+ if (chunk != null) return chunk;
+
+ chunk = getCachedChunk2(pair);
+ if (chunk != null) return chunk;
+
+ int size = chunks.size();
+ if (size > Settings.IMP.QUEUE.TARGET_SIZE || MemUtil.isMemoryLimited()) {
+ if (size > Settings.IMP.QUEUE.PARALLEL_THREADS * 2 + 16) {
+ chunk = chunks.removeFirst();
+ chunk.apply();
+ chunk = (IDelegateChunk) chunk.findParent(ChunkHolder.class);
+ chunk.init(this, X, Z);
+ } else {
+ chunk = create(false);
+ }
+ } else {
+ chunk = create(false);
+ }
+ chunk = wrap(chunk);
+
+ chunks.put(pair, chunk);
+ lastPair = pair;
+ lastChunk = chunk;
+
+ return chunk;
+ }
+}
\ No newline at end of file
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java
new file mode 100644
index 000000000..90f34b5dd
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java
@@ -0,0 +1,30 @@
+package com.boydti.fawe.bukkit.v1_13.beta.bukkit;
+
+import com.boydti.fawe.bukkit.v1_13.beta.SingleThreadQueueExtent;
+import com.sk89q.worldedit.bukkit.BukkitWorld;
+import com.sk89q.worldedit.world.World;
+import net.minecraft.server.v1_13_R2.WorldServer;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_13_R2.CraftWorld;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class BukkitReusableExtent extends SingleThreadQueueExtent {
+ private org.bukkit.World bukkitWorld;
+ private WorldServer nmsWorld;
+
+ public void init(World world) {
+ super.init(world);
+ world = getWorld();
+
+ if (world instanceof BukkitWorld) {
+ this.bukkitWorld = ((BukkitWorld) world).getWorld();
+ } else {
+ this.bukkitWorld = Bukkit.getWorld(world.getName());
+ }
+ checkNotNull(this.bukkitWorld);
+ CraftWorld craftWorld = ((CraftWorld) bukkitWorld);
+ this.nmsWorld = craftWorld.getHandle();
+ }
+
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java
index cba2c2e3a..cf4ebf092 100644
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java
@@ -1,13 +1,21 @@
package com.boydti.fawe.bukkit.v1_13.beta.holder;
-import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
-
-public class ChunkHolder implements IChunk {
- private ChunkHolder implementation;
+import com.boydti.fawe.bukkit.v1_13.beta.CharGetBlocks;
+import com.boydti.fawe.bukkit.v1_13.beta.CharSetBlocks;
+import com.boydti.fawe.bukkit.v1_13.beta.IGetBlocks;
+import com.boydti.fawe.bukkit.v1_13.beta.ISetBlocks;
+public class ChunkHolder extends DelegateChunk {
public ChunkHolder() {
-
+ super(new InitChunk(null));
+ getParent().setParent(this);
}
- public ChunkHolder(IChunkH)
+ protected final IGetBlocks get() {
+ return new CharGetBlocks();
+ }
+
+ protected final ISetBlocks set() {
+ return new CharSetBlocks();
+ }
}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/DelegateChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/DelegateChunk.java
new file mode 100644
index 000000000..19ddffbc0
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/DelegateChunk.java
@@ -0,0 +1,19 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+
+public class DelegateChunk implements IDelegateChunk {
+ private T parent;
+
+ public DelegateChunk(T parent) {
+ this.parent = parent;
+ }
+
+ public final T getParent() {
+ return parent;
+ }
+
+ public final void setParent(T parent) {
+ this.parent = parent;
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java
new file mode 100644
index 000000000..bd2e9092f
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java
@@ -0,0 +1,16 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+
+public class FinalizedChunk extends DelegateChunk {
+ public FinalizedChunk(IChunk parent) {
+ super(parent);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ apply();
+ setParent(null);
+ super.finalize();
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java
new file mode 100644
index 000000000..c5c7b3272
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java
@@ -0,0 +1,44 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IGetBlocks;
+import com.boydti.fawe.bukkit.v1_13.beta.ISetBlocks;
+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;
+
+public class FullChunk extends DelegateChunk {
+ private final ISetBlocks set;
+ private final IGetBlocks get;
+
+ public FullChunk(ChunkHolder parent, IGetBlocks get, ISetBlocks set) {
+ super(parent);
+ this.set = set == null ? parent.set() : set;
+ this.get = get == null ? parent.get() : get;
+ }
+
+ @Override
+ public BaseBlock getFullBlock(int x, int y, int z) {
+ return get.getFullBlock(x, y, z);
+ }
+
+ @Override
+ public BiomeType getBiome(int x, int z) {
+ return get.getBiome(x, z);
+ }
+
+ @Override
+ public BlockState getBlock(int x, int y, int z) {
+ return get.getBlock(x, y, z);
+ }
+
+ @Override
+ public void setBiome(int x, int z, BiomeType biome) {
+ set.setBiome(x, z, biome);
+ }
+
+ @Override
+ public void setBlock(int x, int y, int z, BlockStateHolder holder) {
+ set.setBlock(x, y, z, holder);
+ }
+}
\ No newline at end of file
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java
new file mode 100644
index 000000000..d6747c328
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java
@@ -0,0 +1,34 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IGetBlocks;
+import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BaseBlock;
+import com.sk89q.worldedit.world.block.BlockState;
+
+public class GetChunk extends InitChunk {
+ private final IGetBlocks get;
+
+ public GetChunk(ChunkHolder parent) {
+ super(parent);
+ this.get = parent.get();
+ }
+
+ protected void init() {
+ getParent().setParent(new FullChunk(getParent(), get, null));
+ }
+
+ @Override
+ public BaseBlock getFullBlock(int x, int y, int z) {
+ return get.getFullBlock(x, y, z);
+ }
+
+ @Override
+ public BiomeType getBiome(int x, int z) {
+ return get.getBiome(x, z);
+ }
+
+ @Override
+ public BlockState getBlock(int x, int y, int z) {
+ return get.getBlock(x, y, z);
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/IDelegateChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/IDelegateChunk.java
new file mode 100644
index 000000000..e71172bc4
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/IDelegateChunk.java
@@ -0,0 +1,76 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+import com.boydti.fawe.bukkit.v1_13.beta.SingleThreadQueueExtent;
+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;
+
+public interface IDelegateChunk extends IChunk {
+ T getParent();
+
+ default IChunk getRoot() {
+ IChunk root = getParent();
+ while (root instanceof IDelegateChunk) {
+ root = ((IDelegateChunk) root).getParent();
+ }
+ return root;
+ }
+
+ @Override
+ default void setBiome(int x, int z, BiomeType biome) {
+ getParent().setBiome(x, z, biome);
+ }
+
+ @Override
+ default void setBlock(int x, int y, int z, BlockStateHolder holder) {
+ getParent().setBlock(x, y, z, holder);
+ }
+
+ @Override
+ default BiomeType getBiome(int x, int z) {
+ return getParent().getBiome(x, z);
+ }
+
+ @Override
+ default BlockState getBlock(int x, int y, int z) {
+ return getParent().getBlock(x, y, z);
+ }
+
+ @Override
+ default BaseBlock getFullBlock(int x, int y, int z) {
+ return getParent().getFullBlock(x, y, z);
+ }
+
+ @Override
+ default void init(SingleThreadQueueExtent extent, int X, int Z) {
+ getParent().init(extent, X, Z);
+ }
+
+ @Override
+ default int getX() {
+ return getParent().getX();
+ }
+
+ @Override
+ default int getZ() {
+ return getParent().getZ();
+ }
+
+ @Override
+ default void apply() {
+ getParent().apply();
+ }
+
+ default IChunk findParent(Class> clazz) {
+ IChunk root = getParent();
+ if (clazz.isAssignableFrom(root.getClass())) return root;
+ while (root instanceof IDelegateChunk) {
+ root = ((IDelegateChunk) root).getParent();
+ if (clazz.isAssignableFrom(root.getClass())) return root;
+ }
+ return null;
+ }
+
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java
new file mode 100644
index 000000000..d2a9599b2
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java
@@ -0,0 +1,47 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+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;
+
+public class InitChunk extends DelegateChunk {
+ public InitChunk(ChunkHolder parent) {
+ super(parent);
+ }
+
+ protected void init() {
+ getParent().setParent(new SetChunk(getParent()));
+ }
+
+ @Override
+ public void setBiome(int x, int z, BiomeType biome) {
+ init();
+ super.setBiome(x, z, biome);
+ }
+
+ @Override
+ public void setBlock(int x, int y, int z, BlockStateHolder holder) {
+ init();
+ super.setBlock(x, y, z, holder);
+ }
+
+ @Override
+ public BiomeType getBiome(int x, int z) {
+ init();
+ return super.getBiome(x, z);
+ }
+
+ @Override
+ public BlockState getBlock(int x, int y, int z) {
+ init();
+ return super.getBlock(x, y, z);
+ }
+
+ @Override
+ public BaseBlock getFullBlock(int x, int y, int z) {
+ init();
+ return super.getFullBlock(x, y, z);
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java
new file mode 100644
index 000000000..24607335a
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java
@@ -0,0 +1,23 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+
+public abstract class ReferenceChunk implements IDelegateChunk {
+ private final Reference ref;
+
+ public ReferenceChunk(IChunk parent) {
+ this.ref = toRef(new FinalizedChunk(parent));
+ }
+
+ protected abstract Reference toRef(FinalizedChunk parent);
+
+ @Override
+ public IChunk getParent() {
+ FinalizedChunk finalized = ref.get();
+ return finalized != null ? finalized.getParent() : null;
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java
index 6d58ef8c4..3b34c7617 100644
--- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java
@@ -1,7 +1,30 @@
package com.boydti.fawe.bukkit.v1_13.beta.holder;
import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+import com.boydti.fawe.bukkit.v1_13.beta.ISetBlocks;
+import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BlockStateHolder;
-public class SetChunk extends ChunkHolder {
+public class SetChunk extends InitChunk {
+ private final ISetBlocks set;
+
+ public SetChunk(ChunkHolder parent) {
+ super(parent);
+ this.set = parent.set();
+ }
+
+ protected void init() {
+ getParent().setParent(new FullChunk(getParent(), null, set));
+ }
+
+ @Override
+ public void setBiome(int x, int z, BiomeType biome) {
+ set.setBiome(x, z, biome);
+ }
+
+ @Override
+ public void setBlock(int x, int y, int z, BlockStateHolder holder) {
+ set.setBlock(x, y, z, holder);
+ }
}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java
new file mode 100644
index 000000000..5c435d7a6
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java
@@ -0,0 +1,18 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+
+public class SoftChunk extends ReferenceChunk {
+
+ public SoftChunk(IChunk parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Reference toRef(FinalizedChunk parent) {
+ return new SoftReference<>(parent);
+ }
+}
diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/WeakChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/WeakChunk.java
new file mode 100644
index 000000000..b574ed010
--- /dev/null
+++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/WeakChunk.java
@@ -0,0 +1,17 @@
+package com.boydti.fawe.bukkit.v1_13.beta.holder;
+
+import com.boydti.fawe.bukkit.v1_13.beta.IChunk;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+
+public class WeakChunk extends ReferenceChunk {
+ public WeakChunk(IChunk parent) {
+ super(parent);
+ }
+
+ @Override
+ protected Reference toRef(FinalizedChunk parent) {
+ return new WeakReference<>(parent);
+ }
+}
diff --git a/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java b/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java
index c3ed20bf8..bf8369411 100644
--- a/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java
+++ b/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java
@@ -1,14 +1,40 @@
package com.boydti.fawe;
+import com.boydti.fawe.jnbt.anvil.BitArray4096;
import com.boydti.fawe.object.collection.IterableThreadLocal;
+import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.world.biome.BiomeType;
+import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.lang.reflect.Field;
import java.util.*;
public class FaweCache {
+ public static final IterableThreadLocal BLOCK_TO_PALETTE_CHAR = new IterableThreadLocal() {
+ @Override
+ public char[] init() {
+ char[] result = new char[BlockTypes.states.length];
+ Arrays.fill(result, Character.MAX_VALUE);
+ return result;
+ }
+ };
+
+ public static final IterableThreadLocal PALETTE_TO_BLOCK_CHAR = new IterableThreadLocal() {
+ @Override
+ public char[] init() {
+ return new char[Character.MAX_VALUE];
+ }
+ };
+
+ public static final IterableThreadLocal SECTION_BLOCKS_CHAR = new IterableThreadLocal() {
+ @Override
+ public char[] init() {
+ return new char[4096];
+ }
+ };
+
public static final IterableThreadLocal BLOCK_TO_PALETTE = new IterableThreadLocal() {
@Override
public int[] init() {
@@ -179,4 +205,56 @@ public class FaweCache {
if (clazz == null) clazz = EndTag.class;
return new ListTag(clazz, list);
}
+
+ private static final class Palette {
+
+ }
+
+ public void toPalette(int layer, char[] blocks) {
+ int[] blockToPalette = FaweCache.BLOCK_TO_PALETTE.get();
+ int[] paletteToBlock = FaweCache.PALETTE_TO_BLOCK.get();
+ long[] blockstates = FaweCache.BLOCK_STATES.get();
+ int[] blocksCopy = FaweCache.SECTION_BLOCKS.get();
+
+ int blockIndexStart = layer << 12;
+ int blockIndexEnd = blockIndexStart + 4096;
+ int num_palette = 0;
+ try {
+ for (int i = blockIndexStart, j = 0; i < blockIndexEnd; i++, j++) {
+ int ordinal = blocks[i];
+ int palette = blockToPalette[ordinal];
+ if (palette == Integer.MAX_VALUE) {
+ BlockState state = BlockTypes.states[ordinal];
+ blockToPalette[ordinal] = palette = num_palette;
+ paletteToBlock[num_palette] = ordinal;
+ num_palette++;
+ }
+ blocksCopy[j] = palette;
+ }
+
+ for (int i = 0; i < num_palette; i++) {
+ blockToPalette[paletteToBlock[i]] = Integer.MAX_VALUE;
+ }
+
+ // BlockStates
+ int bitsPerEntry = MathMan.log2nlz(num_palette - 1);
+ int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6;
+ if (num_palette == 1) {
+ // Set a value, because minecraft needs it for some reason
+ blockstates[0] = 0;
+ blockBitArrayEnd = 1;
+ } else {
+ BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry);
+ bitArray.fromRaw(blocksCopy);
+ }
+
+ // num_palette
+ // paletteToBlock
+ // blockstates (range: blockBitArrayEnd)
+ } catch (Throwable e) {
+ Arrays.fill(blockToPalette, Integer.MAX_VALUE);
+ e.printStackTrace();
+ throw e;
+ }
+ }
}