Some refactoring

This commit is contained in:
Jesse Boyd 2019-05-03 03:38:08 +10:00
parent f5944fbcaf
commit 4116adcfef
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
13 changed files with 232 additions and 160 deletions

View File

@ -2,16 +2,14 @@ package com.boydti.fawe.bukkit.beta;
import com.boydti.fawe.Fawe; import com.boydti.fawe.Fawe;
import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IGetBlocks; import com.boydti.fawe.beta.IGetBlocks;
import com.boydti.fawe.beta.IQueueExtent; import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.ISetBlocks;
import com.boydti.fawe.beta.implementation.QueueHandler; import com.boydti.fawe.beta.implementation.QueueHandler;
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.boydti.fawe.beta.implementation.holder.ChunkHolder; import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13; import com.boydti.fawe.bukkit.v1_13.BukkitQueue_1_13;
import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.ReflectionUtils;
import com.google.common.util.concurrent.Futures;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.LongTag;
@ -20,8 +18,6 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.Constants;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockTypes;
import net.jpountz.util.UnsafeUtils;
import net.minecraft.server.v1_13_R2.BiomeBase; import net.minecraft.server.v1_13_R2.BiomeBase;
import net.minecraft.server.v1_13_R2.BlockPosition; import net.minecraft.server.v1_13_R2.BlockPosition;
import net.minecraft.server.v1_13_R2.Chunk; import net.minecraft.server.v1_13_R2.Chunk;
@ -37,18 +33,14 @@ import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock; import org.bukkit.craftbukkit.v1_13_R2.block.CraftBlock;
import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.CreatureSpawnEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReferenceArray;
public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder { public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
@Override @Override
@ -86,7 +78,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
int Z = getZ(); int Z = getZ();
BukkitQueue extent = (BukkitQueue) getExtent(); BukkitQueue extent = (BukkitQueue) getExtent();
BukkitGetBlocks get = (BukkitGetBlocks) getOrCreateGet(); BukkitGetBlocks get = (BukkitGetBlocks) getOrCreateGet();
CharSetBlocks set = (CharSetBlocks) getOrCreateSet(); ISetBlocks set = getOrCreateSet();
Chunk nmsChunk = extent.ensureLoaded(X, Z); Chunk nmsChunk = extent.ensureLoaded(X, Z);
@ -102,12 +94,10 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
final int ly = pos.getY(); final int ly = pos.getY();
final int lz = pos.getZ() & 15; final int lz = pos.getZ() & 15;
final int layer = ly >> 4; final int layer = ly >> 4;
final char[] array = set.blocks[layer]; if (!set.hasSection(layer)) {
if (array == null) {
continue; continue;
} }
final int index = (((ly & 0xF) << 8) | (lz << 4) | lx); if (set.getBlock(lx, ly, lz).getOrdinal() != 0) {
if (array[index] != 0) {
TileEntity tile = entry.getValue(); TileEntity tile = entry.getValue();
tile.z(); tile.z();
tile.invalidateBlockCache(); tile.invalidateBlockCache();
@ -116,7 +106,6 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
} }
} }
int bitMask = 0; int bitMask = 0;
synchronized (nmsChunk) { synchronized (nmsChunk) {
ChunkSection[] sections = nmsChunk.getSections(); ChunkSection[] sections = nmsChunk.getSections();
@ -128,7 +117,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
bitMask |= 1 << layer; bitMask |= 1 << layer;
char[] setArr = set.blocks[layer]; char[] setArr = set.getArray(layer);
ChunkSection newSection; ChunkSection newSection;
ChunkSection existingSection = sections[layer]; ChunkSection existingSection = sections[layer];
if (existingSection == null) { if (existingSection == null) {
@ -182,11 +171,12 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
} }
// Biomes // Biomes
if (set.biomes != null) { BiomeType[] biomes = set.getBiomes();
if (biomes != null) {
// set biomes // set biomes
final BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex(); final BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex();
for (int i = 0; i < set.biomes.length; i++) { for (int i = 0; i < biomes.length; i++) {
final BiomeType biome = set.biomes[i]; final BiomeType biome = biomes[i];
if (biome != null) { if (biome != null) {
final Biome craftBiome = BukkitAdapter.adapt(biome); final Biome craftBiome = BukkitAdapter.adapt(biome);
currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome); currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome);
@ -200,11 +190,10 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
int bx = X << 4; int bx = X << 4;
int bz = Z << 4; int bz = Z << 4;
if (set.entityRemoves != null && !set.entityRemoves.isEmpty()) { Set<UUID> entityRemoves = set.getEntityRemoves();
if (entityRemoves != null && !entityRemoves.isEmpty()) {
if (syncTasks == null) syncTasks = new Runnable[3]; if (syncTasks == null) syncTasks = new Runnable[3];
HashSet<UUID> entsToRemove = set.entityRemoves;
syncTasks[2] = new Runnable() { syncTasks[2] = new Runnable() {
@Override @Override
public void run() { public void run() {
@ -216,7 +205,7 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
final Iterator<Entity> iter = ents.iterator(); final Iterator<Entity> iter = ents.iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
final Entity entity = iter.next(); final Entity entity = iter.next();
if (entsToRemove.contains(entity.getUniqueID())) { if (entityRemoves.contains(entity.getUniqueID())) {
iter.remove(); iter.remove();
entity.b(false); entity.b(false);
entity.die(); entity.die();
@ -229,15 +218,14 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
}; };
} }
if (set.entities != null && !set.entities.isEmpty()) { Set<CompoundTag> entities = set.getEntities();
if (entities != null && !entities.isEmpty()) {
if (syncTasks == null) syncTasks = new Runnable[2]; if (syncTasks == null) syncTasks = new Runnable[2];
HashSet<CompoundTag> entitiesToSpawn = set.entities;
syncTasks[1] = new Runnable() { syncTasks[1] = new Runnable() {
@Override @Override
public void run() { public void run() {
for (final CompoundTag nativeTag : entitiesToSpawn) { for (final CompoundTag nativeTag : entities) {
final Map<String, Tag> entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); final Map<String, Tag> entityTagMap = ReflectionUtils.getMap(nativeTag.getValue());
final StringTag idTag = (StringTag) entityTagMap.get("Id"); final StringTag idTag = (StringTag) entityTagMap.get("Id");
final ListTag posTag = (ListTag) entityTagMap.get("Pos"); final ListTag posTag = (ListTag) entityTagMap.get("Pos");
@ -274,10 +262,10 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
} }
// set tiles // set tiles
if (set.tiles != null && !set.tiles.isEmpty()) { Map<Short, CompoundTag> tiles = set.getTiles();
if (tiles != null && !tiles.isEmpty()) {
if (syncTasks == null) syncTasks = new Runnable[1]; if (syncTasks == null) syncTasks = new Runnable[1];
HashMap<Short, CompoundTag> tiles = set.tiles;
syncTasks[0] = new Runnable() { syncTasks[0] = new Runnable() {
@Override @Override
public void run() { public void run() {
@ -307,19 +295,22 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
}; };
} }
int finalMask = bitMask; Runnable callback;
Runnable callback = () -> { if (bitMask == 0) {
if (finalMask != 0) { callback = null;
} else {
int finalMask = bitMask;
callback = () -> {
// Set Modified // Set Modified
nmsChunk.f(true); nmsChunk.f(true);
nmsChunk.mustSave = true; nmsChunk.mustSave = true;
nmsChunk.markDirty(); nmsChunk.markDirty();
// send to player // send to player
extent.sendChunk(X, Z, finalMask); extent.sendChunk(X, Z, finalMask);
}
extent.returnToPool(BukkitChunkHolder.this); extent.returnToPool(BukkitChunkHolder.this);
}; };
}
if (syncTasks != null) { if (syncTasks != null) {
QueueHandler queueHandler = Fawe.get().getQueueHandler(); QueueHandler queueHandler = Fawe.get().getQueueHandler();
Runnable[] finalSyncTasks = syncTasks; Runnable[] finalSyncTasks = syncTasks;
@ -335,12 +326,21 @@ public class BukkitChunkHolder<T extends Future<T>> extends ChunkHolder {
task.run(); task.run();
} }
} }
return queueHandler.async(callback, null); if (callback == null) {
extent.returnToPool(BukkitChunkHolder.this);
return null;
} else {
return queueHandler.async(callback, null);
}
} }
}; };
return (T) (Future) queueHandler.sync(chain); return (T) (Future) queueHandler.sync(chain);
} else { } else {
callback.run(); if (callback == null) {
extent.returnToPool(BukkitChunkHolder.this);
} else {
callback.run();
}
} }
} }
return null; return null;

View File

@ -1,7 +1,6 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
@ -14,7 +13,8 @@ import static com.sk89q.worldedit.world.block.BlockTypes.states;
public class CharFilterBlock implements FilterBlock { public class CharFilterBlock implements FilterBlock {
private IQueueExtent queue; private IQueueExtent queue;
private CharGetBlocks get; private CharGetBlocks get;
private CharSetBlocks set;
private ISetBlocks set;
private char[] getArr; private char[] getArr;
private @Nullable char[] setArr; private @Nullable char[] setArr;
@ -39,28 +39,26 @@ public class CharFilterBlock implements FilterBlock {
return this; return this;
} }
public final void filter(final IGetBlocks iget, final ISetBlocks iset, final Filter filter) { @Override
final CharSetBlocks set = (CharSetBlocks) iset; public final void filter(final IGetBlocks iget, final ISetBlocks iset, final int layer, final Filter filter) {
this.layer = layer;
final CharGetBlocks get = (CharGetBlocks) iget; final CharGetBlocks get = (CharGetBlocks) iget;
for (int layer = 0; layer < 16; layer++) { if (!get.hasSection(layer)) return;
if (!get.hasSection(layer)) continue; this.set = iset;
this.set = set; getArr = get.sections[layer].get(get, layer);
getArr = get.sections[layer].get(get, layer); if (set.hasSection(layer)) {
if (set.hasSection(layer)) { setArr = set.getArray(layer);
setArr = set.blocks[layer]; delegate = FULL;
delegate = FULL; } else {
} else { delegate = NULL;
delegate = NULL; setArr = null;
setArr = null; }
} this.yy = layer << 4;
this.layer = layer;
this.yy = layer << 4;
for (y = 0, index = 0; y < 16; y++) { for (y = 0, index = 0; y < 16; y++) {
for (z = 0; z < 16; z++) { for (z = 0; z < 16; z++) {
for (x = 0; x < 16; x++, index++) { for (x = 0; x < 16; x++, index++) {
filter.applyBlock(this); filter.applyBlock(this);
}
} }
} }
} }
@ -305,7 +303,7 @@ public class CharFilterBlock implements FilterBlock {
Set delegate Set delegate
*/ */
private SetDelegate initSet() { private SetDelegate initSet() {
setArr = set.sections[layer].get(set, layer); setArr = set.getArray(layer);
return delegate = FULL; return delegate = FULL;
} }

View File

@ -57,7 +57,7 @@ public interface Filter {
return this; return this;
} }
default void join(final Filter parent) { default void join() {
} }
} }

View File

@ -1,7 +1,5 @@
package com.boydti.fawe.beta; package com.boydti.fawe.beta;
import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks;
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
@ -11,7 +9,7 @@ public interface FilterBlock {
FilterBlock init(int X, int Z, IGetBlocks chunk); FilterBlock init(int X, int Z, IGetBlocks chunk);
void filter(IGetBlocks get, ISetBlocks set, Filter filter); void filter(IGetBlocks get, ISetBlocks set, int layer, Filter filter);
void setOrdinal(int ordinal); void setOrdinal(int ordinal);

View File

@ -27,8 +27,6 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
int getZ(); int getZ();
/** /**
* If the chunk is a delegate, returns it's paren'ts root * If the chunk is a delegate, returns it's paren'ts root
* @return root IChunk * @return root IChunk
@ -42,14 +40,6 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
*/ */
boolean isEmpty(); boolean isEmpty();
/**
* Spend time optimizing for apply<br>
* default behavior: do nothing
*/
default void optimize() {
}
/** /**
* Apply the queued changes to the world<br> * Apply the queued changes to the world<br>
* The future returned may return another future<br> * The future returned may return another future<br>

View File

@ -2,9 +2,13 @@ package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
/** /**
@ -26,4 +30,19 @@ public interface ISetBlocks extends IBlocks {
default void optimize() { default void optimize() {
} }
BlockState getBlock(int x, int y, int z);
char[] getArray(int layer);
BiomeType[] getBiomes();
Map<Short, CompoundTag> getTiles();
Set<CompoundTag> getEntities();
Set<UUID> getEntityRemoves();
@Override
void reset();
} }

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.beta.filters; package com.boydti.fawe.beta.filters;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock; import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
@ -12,11 +11,35 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class CountFilter implements Filter { public class CountFilter extends ForkedFilter<CountFilter> {
private final int[] counter = new int[BlockTypes.states.length]; private final int[] counter = new int[BlockTypes.states.length];
public CountFilter() {
super(null);
}
private CountFilter(CountFilter root) {
super(root);
}
@Override @Override
public void applyBlock(final FilterBlock block) { public CountFilter init() {
return new CountFilter(this);
}
@Override
public void join(CountFilter filter) {
for (int i = 0; i < filter.counter.length; i++) {
this.counter[i] += filter.counter[i];
}
}
/*
Implementation
*/
@Override
public final void applyBlock(final FilterBlock block) {
counter[block.getOrdinal()]++; counter[block.getOrdinal()]++;
} }
@ -42,17 +65,4 @@ public class CountFilter implements Filter {
actor.print(BBC.getPrefix() + str); actor.print(BBC.getPrefix() + str);
} }
} }
@Override
public Filter fork() {
return new CountFilter();
}
@Override
public void join(final Filter parent) {
final CountFilter other = (CountFilter) parent;
for (int i = 0; i < counter.length; i++) {
other.counter[i] += this.counter[i];
}
}
} }

View File

@ -0,0 +1,48 @@
package com.boydti.fawe.beta.filters;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public abstract class ForkedFilter<T extends ForkedFilter<T>> implements Filter {
protected final Map<Thread, T> children;
public ForkedFilter(T root) {
if (root != null) {
children = root.children;
} else {
children = new ConcurrentHashMap<>();
children.put(Thread.currentThread(), (T) this);
}
}
@Override
public final Filter fork() {
return children.computeIfAbsent(Thread.currentThread(), thread -> init());
}
public abstract T init();
@Override
public void join() {
for (Map.Entry<Thread, T> entry : children.entrySet()) {
T filter = entry.getValue();
if (filter != this) {
join(filter);
}
}
children.clear();
}
public abstract void join(T filter);
}

View File

@ -12,7 +12,6 @@ import com.boydti.fawe.object.collection.IterableThreadLocal;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.WorldWrapper; import com.boydti.fawe.wrappers.WorldWrapper;
import com.google.common.util.concurrent.Futures;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
@ -24,7 +23,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask; import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -163,40 +161,30 @@ public abstract class QueueHandler implements Trimable, Runnable {
synchronized (queue) { synchronized (queue) {
FilterBlock block = null; FilterBlock block = null;
try { while (true) {
while (true) { // Get the next chunk pos
// Get the next chunk pos final int X, Z;
final int X, Z; synchronized (chunksIter) {
synchronized (chunksIter) { if (!chunksIter.hasNext()) break;
if (!chunksIter.hasNext()) break; final BlockVector2 pos = chunksIter.next();
final BlockVector2 pos = chunksIter.next(); X = pos.getX();
X = pos.getX(); Z = pos.getZ();
Z = pos.getZ();
}
IChunk chunk = queue.getCachedChunk(X, Z);
// Initialize
chunk.init(queue, X, Z);
if (!newFilter.appliesChunk(X, Z)) {
continue;
}
chunk = newFilter.applyChunk(chunk);
if (chunk == null) continue;
if (block == null) block = queue.initFilterBlock();
chunk.filter(newFilter, block);
newFilter.finishChunk(chunk);
queue.submit(chunk);
} }
} finally { IChunk chunk = queue.getCachedChunk(X, Z);
if (filter != newFilter) { // Initialize
synchronized (filter) { chunk.init(queue, X, Z);
newFilter.join(filter);
} if (!newFilter.appliesChunk(X, Z)) {
continue;
} }
chunk = newFilter.applyChunk(chunk);
if (chunk == null) continue;
if (block == null) block = queue.initFilterBlock();
chunk.filter(newFilter, block);
queue.submit(chunk);
} }
queue.flush(); queue.flush();
} }
@ -210,5 +198,6 @@ public abstract class QueueHandler implements Trimable, Runnable {
task.quietlyJoin(); task.quietlyJoin();
} }
} }
filter.join();
} }
} }

View File

@ -4,10 +4,14 @@ import com.boydti.fawe.beta.ISetBlocks;
import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
public class CharSetBlocks extends CharBlocks implements ISetBlocks { public class CharSetBlocks extends CharBlocks implements ISetBlocks {
@ -16,6 +20,31 @@ public class CharSetBlocks extends CharBlocks implements ISetBlocks {
public HashSet<CompoundTag> entities; public HashSet<CompoundTag> entities;
public HashSet<UUID> entityRemoves; public HashSet<UUID> entityRemoves;
@Override
public char[] getArray(int layer) {
return sections[layer].get(this, layer);
}
@Override
public BiomeType[] getBiomes() {
return biomes;
}
@Override
public Map<Short, CompoundTag> getTiles() {
return tiles;
}
@Override
public Set<CompoundTag> getEntities() {
return entities;
}
@Override
public Set<UUID> getEntityRemoves() {
return entityRemoves;
}
@Override @Override
public boolean setBiome(final int x, final int y, final int z, final BiomeType biome) { public boolean setBiome(final int x, final int y, final int z, final BiomeType biome) {
if (biomes == null) { if (biomes == null) {
@ -25,6 +54,11 @@ public class CharSetBlocks extends CharBlocks implements ISetBlocks {
return true; return true;
} }
@Override
public BlockState getBlock(int x, int y, int z) {
return BlockTypes.states[get(x, y, z)];
}
@Override @Override
public boolean setBlock(final int x, final int y, final int z, final BlockStateHolder holder) { public boolean setBlock(final int x, final int y, final int z, final BlockStateHolder holder) {
set(x, y, z, holder.getOrdinalChar()); set(x, y, z, holder.getOrdinalChar());

View File

@ -1,24 +0,0 @@
package com.boydti.fawe.beta.implementation.blocks;
import com.boydti.fawe.beta.IBlocks;
// TODO implement
public class FullCharBlocks implements IBlocks {
public final boolean[] hasSections = new boolean[16];
public final char[] blocks = new char[65536];
@Override
public boolean hasSection(final int layer) {
return false;
}
@Override
public void reset() {
}
@Override
public boolean trim(final boolean aggressive) {
return false;
}
}

View File

@ -40,7 +40,11 @@ public abstract class ChunkHolder implements IChunk, Supplier<IGetBlocks> {
final IGetBlocks get = getOrCreateGet(); final IGetBlocks get = getOrCreateGet();
final ISetBlocks set = getOrCreateSet(); final ISetBlocks set = getOrCreateSet();
block = block.init(X, Z, get); block = block.init(X, Z, get);
block.filter(get, set, filter); for (int layer = 0; layer < 16; layer++) {
if (!get.hasSection(layer)) continue;
block.filter(get, set, layer, filter);
}
filter.finishChunk(this);
} }
@Override @Override
@ -94,12 +98,12 @@ public abstract class ChunkHolder implements IChunk, Supplier<IGetBlocks> {
return get(); return get();
} }
@Override // @Override
public void optimize() { // public void optimize() {
if (set != null) { // if (set != null) {
set.optimize(); // set.optimize();
} // }
} // }
@Override @Override
public void init(final IQueueExtent extent, final int X, final int Z) { public void init(final IQueueExtent extent, final int X, final int Z) {

View File

@ -11,8 +11,7 @@ import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T> { public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements Iterable<T> {
private ThreadLocal<T> flag; private final ConcurrentLinkedDeque<T> allValues = new ConcurrentLinkedDeque<>();
private ConcurrentLinkedDeque<T> allValues = new ConcurrentLinkedDeque<>();
public IterableThreadLocal() { public IterableThreadLocal() {
} }
@ -21,7 +20,9 @@ public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements I
protected final T initialValue() { protected final T initialValue() {
T value = init(); T value = init();
if (value != null) { if (value != null) {
allValues.add(value); synchronized (this) {
allValues.add(value);
}
} }
return value; return value;
} }
@ -36,7 +37,12 @@ public abstract class IterableThreadLocal<T> extends ThreadLocal<T> implements I
} }
public void clean() { public void clean() {
IterableThreadLocal.clean(this); if (!allValues.isEmpty()) {
synchronized (this) {
IterableThreadLocal.clean(this);
allValues.clear();
}
}
} }
public static void clean(ThreadLocal instance) { public static void clean(ThreadLocal instance) {