some structure

This commit is contained in:
Jesse Boyd 2019-04-27 11:15:08 +10:00
parent 35fd159e79
commit 6adf0e6435
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
26 changed files with 781 additions and 197 deletions

View File

@ -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);
}

View File

@ -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) {
}
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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) {
}
}

View File

@ -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];
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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
}
}
}
});
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}