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

View File

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

View File

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

View File

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

View File

@ -27,8 +27,6 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
int getZ();
/**
* If the chunk is a delegate, returns it's paren'ts root
* @return root IChunk
@ -42,14 +40,6 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
*/
boolean isEmpty();
/**
* Spend time optimizing for apply<br>
* default behavior: do nothing
*/
default void optimize() {
}
/**
* Apply the queued changes to the world<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.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
@ -26,4 +30,19 @@ public interface ISetBlocks extends IBlocks {
default void optimize() {
}
BlockState getBlock(int x, int y, int z);
char[] getArray(int layer);
BiomeType[] getBiomes();
Map<Short, CompoundTag> getTiles();
Set<CompoundTag> getEntities();
Set<UUID> getEntityRemoves();
@Override
void reset();
}

View File

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

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

View File

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

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

View File

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