Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-12-24 18:10:08 +01:00
some structure
Dieser Commit ist enthalten in:
Ursprung
35fd159e79
Commit
6adf0e6435
@ -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);
|
||||
}
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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<br>
|
||||
* - Return null if you don't want to filter blocks<br>
|
||||
* - Return the chunk if you do want to filter blocks<br>
|
||||
*
|
||||
* @param chunk
|
||||
* @return
|
||||
*/
|
||||
public IChunk applyChunk(IChunk chunk) {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make changes to the block here<br>
|
||||
* - e.g. block.setId(...)<br>
|
||||
* - Note: Performance is critical here<br>
|
||||
*
|
||||
* @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<br>
|
||||
*
|
||||
* @param chunk
|
||||
* @return
|
||||
*/
|
||||
public void finishChunk(IChunk chunk) {
|
||||
}
|
||||
}
|
@ -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];
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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<BlockVector2> chunks = region.getChunks();
|
||||
Iterator<BlockVector2> 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 <T> void apply(Region region, MCAFilter<T> filter) { // TODO not MCAFilter, but another similar class
|
||||
// TODO iterate by mca file
|
||||
Set<BlockVector2> chunks = region.getChunks();
|
||||
Iterator<BlockVector2> 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
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -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<IDelegateChunk> 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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<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();
|
||||
}
|
||||
}
|
||||
|
@ -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<T extends IChunk> 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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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<ChunkHolder> {
|
||||
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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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<T extends IChunk> 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;
|
||||
}
|
||||
|
||||
}
|
@ -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<ChunkHolder> {
|
||||
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);
|
||||
}
|
||||
}
|
@ -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<FinalizedChunk> ref;
|
||||
|
||||
public ReferenceChunk(IChunk parent) {
|
||||
this.ref = toRef(new FinalizedChunk(parent));
|
||||
}
|
||||
|
||||
protected abstract Reference<FinalizedChunk> toRef(FinalizedChunk parent);
|
||||
|
||||
@Override
|
||||
public IChunk getParent() {
|
||||
FinalizedChunk finalized = ref.get();
|
||||
return finalized != null ? finalized.getParent() : null;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<FinalizedChunk> toRef(FinalizedChunk parent) {
|
||||
return new SoftReference<>(parent);
|
||||
}
|
||||
}
|
@ -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<FinalizedChunk> toRef(FinalizedChunk parent) {
|
||||
return new WeakReference<>(parent);
|
||||
}
|
||||
}
|
@ -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<char[]> BLOCK_TO_PALETTE_CHAR = new IterableThreadLocal<char[]>() {
|
||||
@Override
|
||||
public char[] init() {
|
||||
char[] result = new char[BlockTypes.states.length];
|
||||
Arrays.fill(result, Character.MAX_VALUE);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
public static final IterableThreadLocal<char[]> PALETTE_TO_BLOCK_CHAR = new IterableThreadLocal<char[]>() {
|
||||
@Override
|
||||
public char[] init() {
|
||||
return new char[Character.MAX_VALUE];
|
||||
}
|
||||
};
|
||||
|
||||
public static final IterableThreadLocal<char[]> SECTION_BLOCKS_CHAR = new IterableThreadLocal<char[]>() {
|
||||
@Override
|
||||
public char[] init() {
|
||||
return new char[4096];
|
||||
}
|
||||
};
|
||||
|
||||
public static final IterableThreadLocal<int[]> BLOCK_TO_PALETTE = new IterableThreadLocal<int[]>() {
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren