From 57b5be84f400258b2e00bdc8f5c53ef3be3c1fc6 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 29 Apr 2019 01:44:59 +1000 Subject: [PATCH] more structure --- .../fawe/bukkit/beta/BukkitChunkHolder.java | 46 +++ .../fawe/bukkit/beta/BukkitFullChunk.java | 37 +++ .../fawe/bukkit/beta/BukkitGetBlocks.java | 8 + .../boydti/fawe/bukkit/beta/BukkitQueue.java | 32 +++ .../fawe/bukkit/v1_13/BukkitChunk_1_13.java | 266 +++++++++--------- .../fawe/bukkit/v1_13/BukkitQueue_1_13.java | 194 ++++++------- .../fawe/bukkit/v1_13/IQueueExtent.java | 42 --- .../fawe/bukkit/v1_13/beta/CharBlocks.java | 5 - .../v1_13/beta/DelegateQueueExtent.java | 7 - .../fawe/bukkit/v1_13/beta/IBlocks.java | 5 - .../fawe/bukkit/v1_13/beta/QueueHandler.java | 83 ------ .../v1_13/beta/SingleThreadQueueExtent.java | 104 ------- .../beta/bukkit/BukkitReusableExtent.java | 30 -- .../bukkit/v1_13/beta/holder/ChunkHolder.java | 21 -- .../v1_13/beta/holder/FinalizedChunk.java | 16 -- .../bukkit/v1_13/beta/holder/FullChunk.java | 44 --- .../bukkit/v1_13/beta/holder/GetChunk.java | 34 --- .../bukkit/v1_13/beta/holder/InitChunk.java | 47 ---- .../v1_13/beta/holder/ReferenceChunk.java | 23 -- .../bukkit/v1_13/beta/holder/SetChunk.java | 30 -- .../bukkit/v1_13/beta/holder/SoftChunk.java | 18 -- .../src/main/java/com/boydti/fawe/Fawe.java | 12 +- .../main/java/com/boydti/fawe/FaweCache.java | 202 ++++++++----- .../java/com/boydti/fawe}/beta/Filter.java | 12 +- .../java/com/boydti/fawe/beta/IBlocks.java | 5 + .../java/com/boydti/fawe}/beta/IChunk.java | 12 +- .../com/boydti/fawe/beta}/IDelegateChunk.java | 39 +-- .../fawe/beta/IDelegateQueueExtent.java | 44 +++ .../com/boydti/fawe}/beta/IGetBlocks.java | 4 +- .../com/boydti/fawe/beta/IQueueExtent.java | 56 ++++ .../com/boydti/fawe}/beta/ISetBlocks.java | 6 +- .../java/com/boydti/fawe/beta/Trimable.java | 5 + .../beta/implementation/QueueHandler.java | 122 ++++++++ .../SingleThreadQueueExtent.java | 154 ++++++++++ .../beta/implementation/WorldChunkCache.java | 62 ++++ .../implementation/blocks/CharBlocks.java | 7 + .../implementation/blocks}/CharGetBlocks.java | 12 +- .../implementation/blocks}/CharSetBlocks.java | 3 +- .../blocks}/FullCharBlocks.java | 4 +- .../implementation/holder/ChunkHolder.java | 243 ++++++++++++++++ .../implementation}/holder/DelegateChunk.java | 11 +- .../implementation/holder/FinalizedChunk.java | 30 ++ .../implementation/holder/ReferenceChunk.java | 23 ++ .../beta/implementation/holder/SoftChunk.java | 19 ++ .../implementation}/holder/WeakChunk.java | 8 +- 45 files changed, 1317 insertions(+), 870 deletions(-) create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitFullChunk.java create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitGetBlocks.java create mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/IQueueExtent.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharBlocks.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IBlocks.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13 => worldedit-core/src/main/java/com/boydti/fawe}/beta/Filter.java (71%) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13 => worldedit-core/src/main/java/com/boydti/fawe}/beta/IChunk.java (72%) rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder => worldedit-core/src/main/java/com/boydti/fawe/beta}/IDelegateChunk.java (51%) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateQueueExtent.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13 => worldedit-core/src/main/java/com/boydti/fawe}/beta/IGetBlocks.java (87%) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13 => worldedit-core/src/main/java/com/boydti/fawe}/beta/ISetBlocks.java (50%) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/Trimable.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/SingleThreadQueueExtent.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/WorldChunkCache.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta => worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks}/CharGetBlocks.java (51%) rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta => worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks}/CharSetBlocks.java (78%) rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta => worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks}/FullCharBlocks.java (64%) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta => worldedit-core/src/main/java/com/boydti/fawe/beta/implementation}/holder/DelegateChunk.java (50%) create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/FinalizedChunk.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ReferenceChunk.java create mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/SoftChunk.java rename {worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta => worldedit-core/src/main/java/com/boydti/fawe/beta/implementation}/holder/WeakChunk.java (50%) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java new file mode 100644 index 000000000..5a9fcd233 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitChunkHolder.java @@ -0,0 +1,46 @@ +package com.boydti.fawe.bukkit.beta; + +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.IGetBlocks; +import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; +import com.boydti.fawe.beta.implementation.holder.ChunkHolder; + +public class BukkitChunkHolder extends ChunkHolder { + @Override + public void init(final BukkitQueue extent, final int X, final int Z) { + super.init(extent, X, Z); + } + + @Override + public IGetBlocks get() { + BukkitQueue extent = getExtent(); + return null; + } + + @Override + public Boolean apply() { + BukkitGetBlocks get = (BukkitGetBlocks) cachedGet(); + CharSetBlocks set = (CharSetBlocks) cachedSet(); +// - getBlocks +// - set lock +// - synchronize on chunk object +// - verify section is same object as chunk's section +// - merge with setblocks +// - set section +// - verify chunk is same +// - verify section is same +// - Otherwise repeat steps on main thread +// - set status to needs relighting +// - mark as dirty +// - skip verification if main thread + throw new UnsupportedOperationException("Not implemented"); +// return true; + } + + @Override + public void filter(final Filter filter) { + // for each block + // filter.applyBlock(block) + throw new UnsupportedOperationException("Not implemented"); + } +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitFullChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitFullChunk.java new file mode 100644 index 000000000..27104553b --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitFullChunk.java @@ -0,0 +1,37 @@ +package com.boydti.fawe.bukkit.beta; + +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.ISetBlocks; +import com.boydti.fawe.beta.implementation.holder.ChunkHolder; + +public class BukkitFullChunk extends ChunkHolder { + public BukkitFullChunk() { + throw new UnsupportedOperationException("Not implemented"); + } + + @Override + public void init(IQueueExtent extent, int X, int Z) { + + } + + @Override + public Object apply() { + return null; + } + + @Override + public void filter(Filter filter) { + + } + + @Override + public Object get() { + return null; + } + + @Override + public ISetBlocks set() { + return null; + } +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitGetBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitGetBlocks.java new file mode 100644 index 000000000..85fa55a11 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitGetBlocks.java @@ -0,0 +1,8 @@ +package com.boydti.fawe.bukkit.beta; + +import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; +import net.minecraft.server.v1_13_R2.ChunkSection; + +public class BukkitGetBlocks extends CharGetBlocks { + private ChunkSection[] sections; +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java new file mode 100644 index 000000000..b8fab4466 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/beta/BukkitQueue.java @@ -0,0 +1,32 @@ +package com.boydti.fawe.bukkit.beta; + +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent; +import com.boydti.fawe.beta.implementation.WorldChunkCache; +import com.boydti.fawe.object.collection.IterableThreadLocal; +import com.sk89q.worldedit.world.World; + +public class BukkitQueue extends SingleThreadQueueExtent { + + @Override + public synchronized void init(WorldChunkCache cache) { + World world = cache.getWorld(); + super.init(cache); + } + + private static final IterableThreadLocal FULL_CHUNKS = new IterableThreadLocal() { + @Override + public BukkitFullChunk init() { + return new BukkitFullChunk(); + } + }; + + @Override + public IChunk create(boolean full) { + if (full) { + return FULL_CHUNKS.get(); + } else { + return new BukkitChunkHolder(); + } + } +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java index 2ccfa8b5d..4b9146f8c 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitChunk_1_13.java @@ -81,15 +81,15 @@ public class BukkitChunk_1_13 extends IntFaweChunk { * @param x * @param z */ - public BukkitChunk_1_13(FaweQueue parent, int x, int z) { + public BukkitChunk_1_13(final FaweQueue parent, final int x, final int z) { super(parent, x, z); } - public BukkitChunk_1_13(FaweQueue parent, int x, int z, int[][] ids, short[] count, short[] air) { + public BukkitChunk_1_13(final FaweQueue parent, final int x, final int z, final int[][] ids, final short[] count, final short[] air) { super(parent, x, z, ids, count, air); } - public void storeBiomes(BiomeBase[] biomes) { + public void storeBiomes(final BiomeBase[] biomes) { if (biomes != null) { if (this.biomes == null) { this.biomes = new BiomeType[256]; @@ -111,33 +111,33 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } @Override - public int[] getIdArray(int layer) { + public int[] getIdArray(final int layer) { if (this.setBlocks[layer] == null && this.sectionPalettes != null) { - ChunkSection section = this.sectionPalettes[layer]; + final ChunkSection section = this.sectionPalettes[layer]; int[] idsArray = this.setBlocks[layer]; if (section != null && idsArray == null) { this.setBlocks[layer] = idsArray = new int[4096]; if (!section.a()) { try { - DataPaletteBlock blocks = section.getBlocks(); - DataBits bits = (DataBits) BukkitQueue_1_13.fieldBits.get(blocks); - DataPalette palette = (DataPalette) BukkitQueue_1_13.fieldPalette.get(blocks); + final DataPaletteBlock blocks = section.getBlocks(); + final DataBits bits = (DataBits) BukkitQueue_1_13.fieldBits.get(blocks); + final DataPalette palette = (DataPalette) BukkitQueue_1_13.fieldPalette.get(blocks); - long[] raw = bits.a(); - int bitsPerEntry = bits.c(); + final long[] raw = bits.a(); + final int bitsPerEntry = bits.c(); new BitArray4096(raw, bitsPerEntry).toRaw(idsArray); - IBlockData defaultBlock = (IBlockData) BukkitQueue_1_13.fieldDefaultBlock.get(blocks); + final IBlockData defaultBlock = (IBlockData) BukkitQueue_1_13.fieldDefaultBlock.get(blocks); // TODO optimize away palette.a for (int i = 0; i < 4096; i++) { IBlockData ibd = palette.a(idsArray[i]); if (ibd == null) { ibd = defaultBlock; } - int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd); + final int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd); idsArray[i] = BlockTypes.states[ordinal].getInternalId(); } - } catch (IllegalAccessException e) { + } catch (final IllegalAccessException e) { e.printStackTrace(); } } @@ -146,23 +146,23 @@ public class BukkitChunk_1_13 extends IntFaweChunk { return this.setBlocks[layer]; } - public boolean storeTile(TileEntity tile, BlockPosition pos) { - CompoundTag nativeTag = getParent().getTag(tile); + public boolean storeTile(final TileEntity tile, final BlockPosition pos) { + final CompoundTag nativeTag = getParent().getTag(tile); setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag); return true; } - public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException { + public boolean storeEntity(final Entity ent) throws InvocationTargetException, IllegalAccessException { if (ent instanceof EntityPlayer || BukkitQueue_0.getAdapter() == null) { return false; } - EntityTypes type = ent.P(); - MinecraftKey id = EntityTypes.getName(type); + final EntityTypes type = ent.P(); + final MinecraftKey id = EntityTypes.getName(type); if (id != null) { - NBTTagCompound tag = new NBTTagCompound(); + final NBTTagCompound tag = new NBTTagCompound(); ent.save(tag); // readEntityIntoTag - CompoundTag nativeTag = (CompoundTag) BukkitQueue_0.toNative(tag); - Map map = ReflectionUtils.getMap(nativeTag.getValue()); + final CompoundTag nativeTag = (CompoundTag) BukkitQueue_0.toNative(tag); + final Map map = ReflectionUtils.getMap(nativeTag.getValue()); map.put("Id", new StringTag(id.toString())); setEntity(nativeTag); return true; @@ -171,7 +171,7 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } } - public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException { + public boolean storeSection(final ChunkSection section, final int layer) throws IllegalAccessException { if (sectionPalettes == null) { // TODO optimize don't copy light sectionPalettes = new ChunkSection[16]; @@ -180,56 +180,56 @@ public class BukkitChunk_1_13 extends IntFaweChunk { return true; } - public ChunkSection copy(ChunkSection current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { - ChunkSection newSection = new ChunkSection(current.getYPosition(), current.getSkyLightArray() != null); + public ChunkSection copy(final ChunkSection current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { + final ChunkSection newSection = new ChunkSection(current.getYPosition(), current.getSkyLightArray() != null); // Copy light - NibbleArray skyLight = current.getSkyLightArray(); - NibbleArray blockLight = current.getEmittedLightArray(); + final NibbleArray skyLight = current.getSkyLightArray(); + final NibbleArray blockLight = current.getEmittedLightArray(); - NibbleArray newBlockLight = newSection.getEmittedLightArray(); - NibbleArray newSkyLight = newSection.getSkyLightArray(); + final NibbleArray newBlockLight = newSection.getEmittedLightArray(); + final NibbleArray newSkyLight = newSection.getSkyLightArray(); - byte[] newBlockBytes = newBlockLight.asBytes(); - byte[] blockLightBytes = blockLight.asBytes(); + final byte[] newBlockBytes = newBlockLight.asBytes(); + final byte[] blockLightBytes = blockLight.asBytes(); for (int i = 0; i < 2048; i++) newBlockBytes[i] = blockLightBytes[i]; if (skyLight != null) { - byte[] newSkyBytes = newSkyLight.asBytes(); - byte[] skyLightBytes = skyLight.asBytes(); + final byte[] newSkyBytes = newSkyLight.asBytes(); + final byte[] skyLightBytes = skyLight.asBytes(); for (int i = 0; i < 2048; i++) newSkyBytes[i] = skyLightBytes[i]; } // Copy counters - Object nonEmptyBlockCount = BukkitQueue_1_13.fieldNonEmptyBlockCount.get(current); + final Object nonEmptyBlockCount = BukkitQueue_1_13.fieldNonEmptyBlockCount.get(current); BukkitQueue_1_13.fieldNonEmptyBlockCount.set(newSection, nonEmptyBlockCount); - Object tickingBlockCount = BukkitQueue_1_13.fieldTickingBlockCount.get(current); + final Object tickingBlockCount = BukkitQueue_1_13.fieldTickingBlockCount.get(current); BukkitQueue_1_13.fieldTickingBlockCount.set(newSection, tickingBlockCount); - Object liquidCount = BukkitQueue_1_13.fieldLiquidCount.get(current); + final Object liquidCount = BukkitQueue_1_13.fieldLiquidCount.get(current); BukkitQueue_1_13.fieldLiquidCount.set(newSection, liquidCount); // Copy blocks - DataPaletteBlock blocks = current.getBlocks(); - DataPaletteBlock blocksCopy = copy(blocks); + final DataPaletteBlock blocks = current.getBlocks(); + final DataPaletteBlock blocksCopy = copy(blocks); BukkitQueue_1_13.fieldSection.set(newSection, blocksCopy); return newSection; } - public DataPaletteBlock copy(DataPaletteBlock current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { + public DataPaletteBlock copy(final DataPaletteBlock current) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException { // Clone palette - DataPalette currentPalette = (DataPalette) BukkitQueue_1_13.fieldPalette.get(current); - DataPaletteBlock paletteBlock = newDataPaletteBlock(); - int size = BukkitQueue_1_13.fieldSize.getInt(current); + final DataPalette currentPalette = (DataPalette) BukkitQueue_1_13.fieldPalette.get(current); + final DataPaletteBlock paletteBlock = newDataPaletteBlock(); + final int size = BukkitQueue_1_13.fieldSize.getInt(current); DataPalette newPalette = currentPalette; if (currentPalette instanceof DataPaletteHash) { // TODO optimize resize newPalette = new DataPaletteHash<>(Block.REGISTRY_ID, size, paletteBlock, GameProfileSerializer::d, GameProfileSerializer::a); - RegistryID currReg = (RegistryID) BukkitQueue_1_13.fieldHashBlocks.get(currentPalette); - RegistryID newReg = (RegistryID) BukkitQueue_1_13.fieldHashBlocks.get(newPalette); - int arrLen = 1 << size; + final RegistryID currReg = (RegistryID) BukkitQueue_1_13.fieldHashBlocks.get(currentPalette); + final RegistryID newReg = (RegistryID) BukkitQueue_1_13.fieldHashBlocks.get(newPalette); + final int arrLen = 1 << size; System.arraycopy(fieldRegistryb.get(currReg), 0, fieldRegistryb.get(newReg), 0, arrLen); System.arraycopy(fieldRegistryc.get(currReg), 0, fieldRegistryc.get(newReg), 0, arrLen); System.arraycopy(fieldRegistryd.get(currReg), 0, fieldRegistryd.get(newReg), 0, arrLen); @@ -238,8 +238,8 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } else if (currentPalette instanceof DataPaletteLinear) { // TODO optimize resize newPalette = new DataPaletteLinear<>(Block.REGISTRY_ID, size, paletteBlock, GameProfileSerializer::d); - Object[] currArray = ((Object[]) BukkitQueue_1_13.fieldLinearBlocks.get(currentPalette)); - Object[] newArray = ((Object[]) BukkitQueue_1_13.fieldLinearBlocks.get(newPalette)); + final Object[] currArray = ((Object[]) BukkitQueue_1_13.fieldLinearBlocks.get(currentPalette)); + final Object[] newArray = ((Object[]) BukkitQueue_1_13.fieldLinearBlocks.get(newPalette)); BukkitQueue_1_13.fieldLinearIndex.set(newPalette, BukkitQueue_1_13.fieldLinearIndex.get(currentPalette)); for (int i = 0; i < newArray.length; i++) newArray[i] = currArray[i]; } @@ -248,12 +248,12 @@ public class BukkitChunk_1_13 extends IntFaweChunk { // Clone size BukkitQueue_1_13.fieldSize.set(paletteBlock, size); // Clone palette - DataBits currentBits = (DataBits) BukkitQueue_1_13.fieldBits.get(current); - DataBits newBits = new DataBits(currentBits.c(), currentBits.b(), currentBits.a().clone()); + final DataBits currentBits = (DataBits) BukkitQueue_1_13.fieldBits.get(current); + final DataBits newBits = new DataBits(currentBits.c(), currentBits.b(), currentBits.a().clone()); BukkitQueue_1_13.fieldBits.set(paletteBlock, newBits); // TODO copy only if different - Object defaultBlock = BukkitQueue_1_13.fieldDefaultBlock.get(current); + final Object defaultBlock = BukkitQueue_1_13.fieldDefaultBlock.get(current); if (defaultBlock != AIR) { ReflectionUtils.setFailsafeFieldValue(BukkitQueue_1_13.fieldDefaultBlock, paletteBlock, BukkitQueue_1_13.fieldDefaultBlock.get(current)); } @@ -262,8 +262,8 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } @Override - public IntFaweChunk copy(boolean shallow) { - BukkitChunk_1_13 copy; + public IntFaweChunk copy(final boolean shallow) { + final BukkitChunk_1_13 copy; if (shallow) { copy = new BukkitChunk_1_13(getParent(), getX(), getZ(), setBlocks, count, air); copy.biomes = biomes; @@ -277,13 +277,13 @@ public class BukkitChunk_1_13 extends IntFaweChunk { copy.sectionPalettes = new ChunkSection[16]; try { for (int i = 0; i < sectionPalettes.length; i++) { - ChunkSection current = sectionPalettes[i]; + final ChunkSection current = sectionPalettes[i]; if (current == null) { continue; } copy.sectionPalettes[i] = copy(current); } - } catch (Throwable e) { + } catch (final Throwable e) { MainUtil.handleError(e); } } @@ -303,13 +303,13 @@ public class BukkitChunk_1_13 extends IntFaweChunk { if (sectionPalettes != null) { return; } - int[][] arrays = getCombinedIdArrays(); + final int[][] arrays = getCombinedIdArrays(); for (int layer = 0; layer < 16; layer++) { if (getCount(layer) > 0) { if (sectionPalettes == null) { sectionPalettes = new ChunkSection[16]; } - int[] array = arrays[layer]; + final int[] array = arrays[layer]; sectionPalettes[layer] = BukkitQueue_1_13.newChunkSection(layer, getParent().hasSky(), array); } } @@ -320,7 +320,7 @@ public class BukkitChunk_1_13 extends IntFaweChunk { getChunk().load(true); } - private void removeEntity(Entity entity) { + private void removeEntity(final Entity entity) { entity.b(false); entity.die(); entity.valid = false; @@ -328,32 +328,32 @@ public class BukkitChunk_1_13 extends IntFaweChunk { @Override public FaweChunk call() { - Spigot_v1_13_R2 adapter = (Spigot_v1_13_R2) BukkitQueue_0.getAdapter(); + final Spigot_v1_13_R2 adapter = (Spigot_v1_13_R2) BukkitQueue_0.getAdapter(); try { - BukkitChunk_1_13 copy = getParent().getChangeTask() != null ? new BukkitChunk_1_13(getParent(), getX(), getZ()) : null; + final BukkitChunk_1_13 copy = getParent().getChangeTask() != null ? new BukkitChunk_1_13(getParent(), getX(), getZ()) : null; final Chunk chunk = this.getChunk(); final World world = chunk.getWorld(); - Settings settings = getParent().getSettings(); - int bx = this.getX() << 4; - int bz = this.getZ() << 4; + final Settings settings = getParent().getSettings(); + final int bx = this.getX() << 4; + final int bz = this.getZ() << 4; final boolean flag = world.getEnvironment() == World.Environment.NORMAL; - net.minecraft.server.v1_13_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + final net.minecraft.server.v1_13_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); nmsChunk.f(true); // Set Modified nmsChunk.mustSave = true; nmsChunk.markDirty(); - net.minecraft.server.v1_13_R2.World nmsWorld = nmsChunk.world; - ChunkSection[] sections = nmsChunk.getSections(); - List[] entities = nmsChunk.getEntitySlices(); - Map tiles = nmsChunk.getTileEntities(); + final net.minecraft.server.v1_13_R2.World nmsWorld = nmsChunk.world; + final ChunkSection[] sections = nmsChunk.getSections(); + final List[] entities = nmsChunk.getEntitySlices(); + final Map tiles = nmsChunk.getTileEntities(); // Remove entities - HashSet entsToRemove = this.getEntityRemoves(); + final HashSet entsToRemove = this.getEntityRemoves(); if (!entsToRemove.isEmpty()) { for (int i = 0; i < entities.length; i++) { - Collection ents = entities[i]; + final Collection ents = entities[i]; if (!ents.isEmpty()) { - Iterator iter = ents.iterator(); + final Iterator iter = ents.iterator(); while (iter.hasNext()) { - Entity entity = iter.next(); + final Entity entity = iter.next(); if (entsToRemove.contains(entity.getUniqueID())) { if (copy != null) { copy.storeEntity(entity); @@ -368,16 +368,16 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } } for (int i = 0; i < entities.length; i++) { - int count = this.getCount(i); + final int count = this.getCount(i); if (count == 0 || settings.EXPERIMENTAL.KEEP_ENTITIES_IN_BLOCKS) { continue; } else if (count >= 4096) { - Collection ents = entities[i]; + final Collection ents = entities[i]; if (!ents.isEmpty()) { synchronized (BukkitQueue_0.class) { - Iterator iter = ents.iterator(); + final Iterator iter = ents.iterator(); while (iter.hasNext()) { - Entity entity = iter.next(); + final Entity entity = iter.next(); if (entity instanceof EntityPlayer) { continue; } @@ -390,24 +390,24 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } } } else { - Collection ents = entities[i]; + final Collection ents = entities[i]; if (!ents.isEmpty()) { - int layerYStart = i << 4; - int layerYEnd = layerYStart + 15; - int[] array = this.getIdArray(i); + final int layerYStart = i << 4; + final int layerYEnd = layerYStart + 15; + final int[] array = this.getIdArray(i); if (array == null) continue; - Iterator iter = ents.iterator(); + final Iterator iter = ents.iterator(); while (iter.hasNext()) { - Entity entity = iter.next(); + final Entity entity = iter.next(); if (entity instanceof EntityPlayer) { continue; } - int y = MathMan.roundInt(entity.locY); + final int y = MathMan.roundInt(entity.locY); if (y > layerYEnd || y < layerYStart) continue; - int x = (MathMan.roundInt(entity.locX) & 15); - int z = (MathMan.roundInt(entity.locZ) & 15); + final int x = (MathMan.roundInt(entity.locX) & 15); + final int z = (MathMan.roundInt(entity.locZ) & 15); - int index = (((y & 0xF) << 8) | (z << 4) | x); + final int index = (((y & 0xF) << 8) | (z << 4) | x); if (array[index] != 0) { if (copy != null) { copy.storeEntity(entity); @@ -422,32 +422,32 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } } // Set entities - Set entitiesToSpawn = this.getEntities(); + final Set entitiesToSpawn = this.getEntities(); if (!entitiesToSpawn.isEmpty()) { synchronized (BukkitQueue_0.class) { - for (CompoundTag nativeTag : entitiesToSpawn) { - Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); - StringTag idTag = (StringTag) entityTagMap.get("Id"); - ListTag posTag = (ListTag) entityTagMap.get("Pos"); - ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + for (final CompoundTag nativeTag : entitiesToSpawn) { + final Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); + final StringTag idTag = (StringTag) entityTagMap.get("Id"); + final ListTag posTag = (ListTag) entityTagMap.get("Pos"); + final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); if (idTag == null || posTag == null || rotTag == null) { Fawe.debug("Unknown entity tag: " + nativeTag); continue; } - double x = posTag.getDouble(0); - double y = posTag.getDouble(1); - double z = posTag.getDouble(2); - float yaw = rotTag.getFloat(0); - float pitch = rotTag.getFloat(1); - String id = idTag.getValue(); - Entity entity = EntityTypes.a(nmsWorld, new MinecraftKey(id)); + final double x = posTag.getDouble(0); + final double y = posTag.getDouble(1); + final double z = posTag.getDouble(2); + final float yaw = rotTag.getFloat(0); + final float pitch = rotTag.getFloat(1); + final String id = idTag.getValue(); + final Entity entity = EntityTypes.a(nmsWorld, new MinecraftKey(id)); if (entity != null) { - UUID uuid = entity.getUniqueID(); + final UUID uuid = entity.getUniqueID(); entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); if (nativeTag != null) { - NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag); - for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + final NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag); + for (final String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { tag.remove(name); } entity.f(tag); @@ -462,11 +462,11 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } // Set blocks for (int j = 0; j < sections.length; j++) { - int count = this.getCount(j); + final int count = this.getCount(j); if (count == 0) { continue; } - int countAir = this.getAir(j); + final int countAir = this.getAir(j); final int[] array = this.getIdArray(j); if (array == null) { continue; @@ -501,15 +501,15 @@ public class BukkitChunk_1_13 extends IntFaweChunk { continue; } } - int by = j << 4; - DataPaletteBlock nibble = section.getBlocks(); + final int by = j << 4; + final DataPaletteBlock nibble = section.getBlocks(); int nonEmptyBlockCount = 0; IBlockData existing; for (int y = 0, i = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x= 0; x < 16; x++, i++) { - int combinedId = array[i]; + final int combinedId = array[i]; switch (combinedId) { case 0: continue; @@ -534,8 +534,8 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } else { nonEmptyBlockCount++; } - BlockState state = BlockState.getFromInternalId(combinedId); - IBlockData ibd = ((BlockMaterial_1_13) state.getMaterial()).getState(); + final BlockState state = BlockState.getFromInternalId(combinedId); + final IBlockData ibd = ((BlockMaterial_1_13) state.getMaterial()).getState(); nibble.setBlock(x, y, z, ibd); } } @@ -547,19 +547,19 @@ public class BukkitChunk_1_13 extends IntFaweChunk { // Trim tiles HashMap toRemove = null; if (!tiles.isEmpty()) { - Iterator> iterator = tiles.entrySet().iterator(); + final Iterator> iterator = tiles.entrySet().iterator(); while (iterator.hasNext()) { - Map.Entry tile = iterator.next(); - BlockPosition pos = tile.getKey(); - int lx = pos.getX() & 15; - int ly = pos.getY(); - int lz = pos.getZ() & 15; - int layer = ly >> 4; - int[] array = this.getIdArray(layer); + final Map.Entry tile = iterator.next(); + final BlockPosition pos = tile.getKey(); + final int lx = pos.getX() & 15; + final int ly = pos.getY(); + final int lz = pos.getZ() & 15; + final int layer = ly >> 4; + final int[] array = this.getIdArray(layer); if (array == null) { continue; } - int index = (((ly & 0xF) << 8) | (lz << 4) | lx); + final int index = (((ly & 0xF) << 8) | (lz << 4) | lx); if (array[index] != 0) { if (toRemove == null) { toRemove = new HashMap<>(); @@ -572,9 +572,9 @@ public class BukkitChunk_1_13 extends IntFaweChunk { } if (toRemove != null) { synchronized (BukkitQueue_0.class) { - for (Map.Entry entry : toRemove.entrySet()) { - BlockPosition bp = entry.getKey(); - TileEntity tile = entry.getValue(); + for (final Map.Entry entry : toRemove.entrySet()) { + final BlockPosition bp = entry.getKey(); + final TileEntity tile = entry.getValue(); nmsWorld.n(bp); tiles.remove(bp); tile.z(); @@ -586,32 +586,32 @@ public class BukkitChunk_1_13 extends IntFaweChunk { // Set biomes if (this.biomes != null) { - BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex(); + final BiomeBase[] currentBiomes = nmsChunk.getBiomeIndex(); if (copy != null) { copy.storeBiomes(currentBiomes); } for (int i = 0 ; i < this.biomes.length; i++) { - BiomeType biome = this.biomes[i]; + final BiomeType biome = this.biomes[i]; if (biome != null) { - Biome craftBiome = adapter.adapt(biome); + final Biome craftBiome = adapter.adapt(biome); currentBiomes[i] = CraftBlock.biomeToBiomeBase(craftBiome); } } } // Set tiles - Map tilesToSpawn = this.getTiles(); + final Map tilesToSpawn = this.getTiles(); if (!tilesToSpawn.isEmpty()) { - for (Map.Entry entry : tilesToSpawn.entrySet()) { - CompoundTag nativeTag = entry.getValue(); - short blockHash = entry.getKey(); - int x = (blockHash >> 12 & 0xF) + bx; - int y = (blockHash & 0xFF); - int z = (blockHash >> 8 & 0xF) + bz; - BlockPosition pos = new BlockPosition(x, y, z); // Set pos + for (final Map.Entry entry : tilesToSpawn.entrySet()) { + final CompoundTag nativeTag = entry.getValue(); + final short blockHash = entry.getKey(); + final int x = (blockHash >> 12 & 0xF) + bx; + final int y = (blockHash & 0xFF); + final int z = (blockHash >> 8 & 0xF) + bz; + final BlockPosition pos = new BlockPosition(x, y, z); // Set pos synchronized (BukkitQueue_0.class) { - TileEntity tileEntity = nmsWorld.getTileEntity(pos); + final TileEntity tileEntity = nmsWorld.getTileEntity(pos); if (tileEntity != null) { - NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag); + final NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_13.fromNative(nativeTag); tag.set("x", new NBTTagInt(x)); tag.set("y", new NBTTagInt(y)); tag.set("z", new NBTTagInt(z)); @@ -624,7 +624,7 @@ public class BukkitChunk_1_13 extends IntFaweChunk { if (copy != null) { getParent().getChangeTask().run(copy, this); } - } catch (Throwable e) { + } catch (final Throwable e) { MainUtil.handleError(e); } return this; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java index 3cc50d56e..f72b821ec 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/BukkitQueue_1_13.java @@ -195,7 +195,7 @@ public class BukkitQueue_1_13 extends BukkitQueue_0 dataPalette = lastSection.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); - int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd); + public int getCombinedId4Data(final ChunkSection lastSection, final int x, final int y, final int z) { + final DataPaletteBlock dataPalette = lastSection.getBlocks(); + final IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + final int ordinal = ((Spigot_v1_13_R2) getAdapter()).adaptToInt(ibd); return BlockTypes.states[ordinal].getInternalId(); } @Override - public BiomeType getBiome(net.minecraft.server.v1_13_R2.Chunk chunk, int x, int z) { - BiomeBase base = chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)]; + public BiomeType getBiome(final net.minecraft.server.v1_13_R2.Chunk chunk, final int x, final int z) { + final BiomeBase base = chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)]; return getAdapter().adapt(CraftBlock.biomeBaseToBiome(base)); } @Override - public int getOpacity(ChunkSection section, int x, int y, int z) { - DataPaletteBlock dataPalette = section.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + public int getOpacity(final ChunkSection section, final int x, final int y, final int z) { + final DataPaletteBlock dataPalette = section.getBlocks(); + final IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); pos.a(x, y, z); return ibd.b(nmsWorld, pos); } @Override - public int getBrightness(ChunkSection section, int x, int y, int z) { - DataPaletteBlock dataPalette = section.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + public int getBrightness(final ChunkSection section, final int x, final int y, final int z) { + final DataPaletteBlock dataPalette = section.getBlocks(); + final IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); return ibd.e(); } @Override - public int getOpacityBrightnessPair(ChunkSection section, int x, int y, int z) { - DataPaletteBlock dataPalette = section.getBlocks(); - IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + public int getOpacityBrightnessPair(final ChunkSection section, final int x, final int y, final int z) { + final DataPaletteBlock dataPalette = section.getBlocks(); + final IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); pos.a(x, y, z); - int opacity = ibd.b(nmsWorld, pos); - int brightness = ibd.e(); + final int opacity = ibd.b(nmsWorld, pos); + final int brightness = ibd.e(); return MathMan.pair16(brightness, opacity); } @Override - public void sendChunk(int x, int z, int bitMask) { - net.minecraft.server.v1_13_R2.Chunk chunk = getCachedChunk(getWorld(), x, z); + public void sendChunk(final int x, final int z, final int bitMask) { + final net.minecraft.server.v1_13_R2.Chunk chunk = getCachedChunk(getWorld(), x, z); if (chunk != null) { sendChunk(getPlayerChunk((WorldServer) chunk.getWorld(), chunk.locX, chunk.locZ), chunk, bitMask); } } @Override - public void sendChunkUpdatePLIB(FaweChunk chunk, FawePlayer... players) { + public void sendChunkUpdatePLIB(final FaweChunk chunk, final FawePlayer... players) { // PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap(); // ProtocolManager manager = ProtocolLibrary.getProtocolManager(); // WirePacket packet = null; @@ -602,13 +602,13 @@ public class BukkitQueue_1_13 extends BukkitQueue_0[] entities = nmsChunk.entitySlices; for (int i = 0; i < entities.length; i++) { - Collection slice = entities[i]; + final Collection slice = entities[i]; if (slice != null && !slice.isEmpty()) { return true; } } - } catch (Throwable ignore) {} + } catch (final Throwable ignore) {} return false; } @Override - public boolean removeSectionLighting(ChunkSection section, int layer, boolean sky) { + public boolean removeSectionLighting(final ChunkSection section, final int layer, final boolean sky) { if (section != null) { Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0); if (sky) { - byte[] light = section.getSkyLightArray().asBytes(); + final byte[] light = section.getSkyLightArray().asBytes(); if (light != null) { Arrays.fill(light, (byte) 0); } @@ -779,40 +779,40 @@ public class BukkitQueue_1_13 extends BukkitQueue_0> 6; + final int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6; if (num_palette == 1) { for (int i = 0; i < blockBitArrayEnd; i++) blockstates[i] = 0; } else { - BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry); + final BitArray4096 bitArray = new BitArray4096(blockstates, bitsPerEntry); bitArray.fromRaw(blocksCopy); } // set palette & data bits - DataPaletteBlock dataPaletteBlocks = section.getBlocks(); + final DataPaletteBlock dataPaletteBlocks = section.getBlocks(); // private DataPalette h; // protected DataBits a; - long[] bits = Arrays.copyOfRange(blockstates, 0, blockBitArrayEnd); - DataBits nmsBits = new DataBits(bitsPerEntry, 4096, bits); - DataPalette palette; + final long[] bits = Arrays.copyOfRange(blockstates, 0, blockBitArrayEnd); + final DataBits nmsBits = new DataBits(bitsPerEntry, 4096, bits); + final DataPalette palette; // palette = new DataPaletteHash<>(Block.REGISTRY_ID, bitsPerEntry, dataPaletteBlocks, GameProfileSerializer::d, GameProfileSerializer::a); palette = new DataPaletteLinear<>(Block.REGISTRY_ID, bitsPerEntry, dataPaletteBlocks, GameProfileSerializer::d); // set palette for (int i = 0; i < num_palette; i++) { - int ordinal = paletteToBlock[i]; + final int ordinal = paletteToBlock[i]; blockToPalette[ordinal] = Integer.MAX_VALUE; - BlockState state = BlockTypes.states[ordinal]; - IBlockData ibd = ((BlockMaterial_1_13) state.getMaterial()).getState(); + final BlockState state = BlockTypes.states[ordinal]; + final IBlockData ibd = ((BlockMaterial_1_13) state.getMaterial()).getState(); palette.a(ibd); } try { @@ -916,12 +916,12 @@ public class BukkitQueue_1_13 extends BukkitQueue_0 tiles = chunk.getTileEntities(); + public CompoundTag getTileEntity(final net.minecraft.server.v1_13_R2.Chunk chunk, final int x, final int y, final int z) { + final Map tiles = chunk.getTileEntities(); pos.c(x, y, z); - TileEntity tile = tiles.get(pos); + final TileEntity tile = tiles.get(pos); return tile != null ? getTag(tile) : null; } - public CompoundTag getTag(TileEntity tile) { + public CompoundTag getTag(final TileEntity tile) { try { - NBTTagCompound tag = new NBTTagCompound(); + final NBTTagCompound tag = new NBTTagCompound(); tile.save(tag); // readTagIntoEntity return (CompoundTag) toNative(tag); - } catch (Exception e) { + } catch (final Exception e) { MainUtil.handleError(e); return null; } @@ -951,7 +951,7 @@ public class BukkitQueue_1_13 extends BukkitQueue_0> 4, z >> 4); - return chunk.setBlock(x & 15, y, z & 15, state); - } - - default boolean setBiome(int x, int y, int z, BiomeType biome) { - IChunk chunk = getCachedChunk(x >> 4, z >> 4); - return chunk.setBiome(x & 15, y, z & 15, biome); - } - - default BlockState getBlock(int x, int y, int z) { - IChunk chunk = getCachedChunk(x >> 4, z >> 4); - return chunk.getBlock(x & 15, y, z & 15); - } - - default BiomeType getBiome(int x, int z) { - IChunk chunk = getCachedChunk(x >> 4, z >> 4); - return chunk.getBiome(x & 15, z & 15); - } - - // Return ChunkHolder - ChunkHolder create(boolean full); - - // Region restrictions - IDelegateChunk wrap(IChunk root); -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharBlocks.java deleted file mode 100644 index b1a202380..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharBlocks.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta; - -public class CharBlocks implements IBlocks { - protected char[][] blocks; -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java deleted file mode 100644 index 72ac950cf..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/DelegateQueueExtent.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta; - -import com.boydti.fawe.bukkit.v1_13.IQueueExtent; - -public interface IDelegateQueueExtent { - IQueueExtent getParent(); -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IBlocks.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IBlocks.java deleted file mode 100644 index 187a914d3..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IBlocks.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta; - -public interface IBlocks { - -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java deleted file mode 100644 index 9461531ab..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/QueueHandler.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta; - -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.TaskManager; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.regions.Region; - -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; - -public class QueueHandler { - private SingleThreadQueueExtent mainExtent; - private SingleThreadQueueExtent[] pool; - - - - public static void apply(Region region, Filter filter) { // TODO not MCAFilter, but another similar class - // The chunks positions to iterate over - Set chunks = region.getChunks(); - Iterator chunksIter = chunks.iterator(); - - // Get a pool, to operate on the chunks in parallel - ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool(); - int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS); - ForkJoinTask[] tasks = new ForkJoinTask[size]; - - for (int i = 0; i < size; i++) { - tasks[i] = pool.submit(new Runnable() { - @Override - public void run() { - // Create a chunk that we will reuse/reset for each operation - IChunk chunk = create(true); - - while (true) { - // Get the next chunk pos - BlockVector2 pos; - synchronized (chunksIter) { - if (!chunksIter.hasNext()) return; - pos = chunksIter.next(); - } - int X = pos.getX(); - int Z = pos.getZ(); - long pair = MathMan.pairInt(X, Z); - - // Initialize - chunk.init(SingleThreadQueueExtent.this, X, Z); - - { // Start set - lastPair = pair; - lastChunk = chunk; - } - try { - if (!filter.appliesChunk(X, Z)) { - continue; - } - chunk = filter.applyChunk(chunk); - - if (chunk == null) continue; - - chunk.filter(filter); - - filter.finishChunk(chunk); - - chunk.apply(); - } finally - { // End set - lastPair = Long.MAX_VALUE; - lastChunk = null; - } - } - } - }); - } - - // Join the tasks - for (ForkJoinTask task : tasks) { - task.join(); - } - } -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java deleted file mode 100644 index 53f1984e4..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/SingleThreadQueueExtent.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta; - -import com.boydti.fawe.bukkit.v1_13.IQueueExtent; -import com.boydti.fawe.bukkit.v1_13.beta.holder.ChunkHolder; -import com.boydti.fawe.bukkit.v1_13.beta.holder.IDelegateChunk; -import com.boydti.fawe.bukkit.v1_13.beta.holder.ReferenceChunk; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.MemUtil; -import com.boydti.fawe.wrappers.WorldWrapper; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.world.World; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; - -import static com.google.common.base.Preconditions.checkNotNull; - -public abstract class SingleThreadQueueExtent implements IQueueExtent { - private WorldWrapper wrapped; - private World world; - - public World getWorld() { - return world; - } - - public WorldWrapper getWrappedWorld() { - return wrapped; - } - - private void reset() { - wrapped = null; - world = null; - chunks.clear(); - lastChunk = null; - lastPair = Long.MAX_VALUE; - } - - public synchronized void init(World world) { - if (world != null) { - reset(); - } - checkNotNull(world); - if (world instanceof EditSession) { - world = ((EditSession) world).getWorld(); - } - checkNotNull(world); - if (world instanceof WorldWrapper) { - this.wrapped = (WorldWrapper) world; - world = WorldWrapper.unwrap(world); - } else { - this.wrapped = WorldWrapper.wrap(world); - } - this.world = world; - } - - private IChunk lastChunk; - private long lastPair = Long.MAX_VALUE; - private final Long2ObjectLinkedOpenHashMap chunks = new Long2ObjectLinkedOpenHashMap<>(); - - private final IDelegateChunk getCachedChunk2(long pair) { - IDelegateChunk chunk = chunks.get(pair); - if (chunk instanceof ReferenceChunk) { - chunk = (ReferenceChunk) (chunk).getParent(); - } - if (chunk != null) { - lastPair = pair; - lastChunk = chunk; - } - return chunk; - } - - public final IChunk getCachedChunk(int X, int Z) { - long pair = MathMan.pairInt(X, Z); - if (pair == lastPair) { - return lastChunk; - } - - IDelegateChunk chunk = getCachedChunk2(pair); - if (chunk != null) return chunk; - - chunk = getCachedChunk2(pair); - if (chunk != null) return chunk; - - int size = chunks.size(); - if (size > Settings.IMP.QUEUE.TARGET_SIZE || MemUtil.isMemoryLimited()) { - if (size > Settings.IMP.QUEUE.PARALLEL_THREADS * 2 + 16) { - chunk = chunks.removeFirst(); - chunk.apply(); - chunk = (IDelegateChunk) chunk.findParent(ChunkHolder.class); - chunk.init(this, X, Z); - } else { - chunk = create(false); - } - } else { - chunk = create(false); - } - chunk = wrap(chunk); - - chunks.put(pair, chunk); - lastPair = pair; - lastChunk = chunk; - - return chunk; - } -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java deleted file mode 100644 index 90f34b5dd..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/bukkit/BukkitReusableExtent.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.bukkit; - -import com.boydti.fawe.bukkit.v1_13.beta.SingleThreadQueueExtent; -import com.sk89q.worldedit.bukkit.BukkitWorld; -import com.sk89q.worldedit.world.World; -import net.minecraft.server.v1_13_R2.WorldServer; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class BukkitReusableExtent extends SingleThreadQueueExtent { - private org.bukkit.World bukkitWorld; - private WorldServer nmsWorld; - - public void init(World world) { - super.init(world); - world = getWorld(); - - if (world instanceof BukkitWorld) { - this.bukkitWorld = ((BukkitWorld) world).getWorld(); - } else { - this.bukkitWorld = Bukkit.getWorld(world.getName()); - } - checkNotNull(this.bukkitWorld); - CraftWorld craftWorld = ((CraftWorld) bukkitWorld); - this.nmsWorld = craftWorld.getHandle(); - } - -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java deleted file mode 100644 index cf4ebf092..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ChunkHolder.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.CharGetBlocks; -import com.boydti.fawe.bukkit.v1_13.beta.CharSetBlocks; -import com.boydti.fawe.bukkit.v1_13.beta.IGetBlocks; -import com.boydti.fawe.bukkit.v1_13.beta.ISetBlocks; - -public class ChunkHolder extends DelegateChunk { - public ChunkHolder() { - super(new InitChunk(null)); - getParent().setParent(this); - } - - protected final IGetBlocks get() { - return new CharGetBlocks(); - } - - protected final ISetBlocks set() { - return new CharSetBlocks(); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java deleted file mode 100644 index bd2e9092f..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FinalizedChunk.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; - -public class FinalizedChunk extends DelegateChunk { - public FinalizedChunk(IChunk parent) { - super(parent); - } - - @Override - protected void finalize() throws Throwable { - apply(); - setParent(null); - super.finalize(); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java deleted file mode 100644 index c5c7b3272..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/FullChunk.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.IGetBlocks; -import com.boydti.fawe.bukkit.v1_13.beta.ISetBlocks; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -public class FullChunk extends DelegateChunk { - private final ISetBlocks set; - private final IGetBlocks get; - - public FullChunk(ChunkHolder parent, IGetBlocks get, ISetBlocks set) { - super(parent); - this.set = set == null ? parent.set() : set; - this.get = get == null ? parent.get() : get; - } - - @Override - public BaseBlock getFullBlock(int x, int y, int z) { - return get.getFullBlock(x, y, z); - } - - @Override - public BiomeType getBiome(int x, int z) { - return get.getBiome(x, z); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - return get.getBlock(x, y, z); - } - - @Override - public void setBiome(int x, int z, BiomeType biome) { - set.setBiome(x, z, biome); - } - - @Override - public void setBlock(int x, int y, int z, BlockStateHolder holder) { - set.setBlock(x, y, z, holder); - } -} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java deleted file mode 100644 index d6747c328..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/GetChunk.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.IGetBlocks; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; - -public class GetChunk extends InitChunk { - private final IGetBlocks get; - - public GetChunk(ChunkHolder parent) { - super(parent); - this.get = parent.get(); - } - - protected void init() { - getParent().setParent(new FullChunk(getParent(), get, null)); - } - - @Override - public BaseBlock getFullBlock(int x, int y, int z) { - return get.getFullBlock(x, y, z); - } - - @Override - public BiomeType getBiome(int x, int z) { - return get.getBiome(x, z); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - return get.getBlock(x, y, z); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java deleted file mode 100644 index d2a9599b2..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/InitChunk.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -public class InitChunk extends DelegateChunk { - public InitChunk(ChunkHolder parent) { - super(parent); - } - - protected void init() { - getParent().setParent(new SetChunk(getParent())); - } - - @Override - public void setBiome(int x, int z, BiomeType biome) { - init(); - super.setBiome(x, z, biome); - } - - @Override - public void setBlock(int x, int y, int z, BlockStateHolder holder) { - init(); - super.setBlock(x, y, z, holder); - } - - @Override - public BiomeType getBiome(int x, int z) { - init(); - return super.getBiome(x, z); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - init(); - return super.getBlock(x, y, z); - } - - @Override - public BaseBlock getFullBlock(int x, int y, int z) { - init(); - return super.getFullBlock(x, y, z); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java deleted file mode 100644 index 24607335a..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/ReferenceChunk.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; - -import java.lang.ref.PhantomReference; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; - -public abstract class ReferenceChunk implements IDelegateChunk { - private final Reference ref; - - public ReferenceChunk(IChunk parent) { - this.ref = toRef(new FinalizedChunk(parent)); - } - - protected abstract Reference toRef(FinalizedChunk parent); - - @Override - public IChunk getParent() { - FinalizedChunk finalized = ref.get(); - return finalized != null ? finalized.getParent() : null; - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java deleted file mode 100644 index 3b34c7617..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SetChunk.java +++ /dev/null @@ -1,30 +0,0 @@ -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 InitChunk { - - private final ISetBlocks set; - - public SetChunk(ChunkHolder parent) { - super(parent); - this.set = parent.set(); - } - - protected void init() { - getParent().setParent(new FullChunk(getParent(), null, set)); - } - - @Override - public void setBiome(int x, int z, BiomeType biome) { - set.setBiome(x, z, biome); - } - - @Override - public void setBlock(int x, int y, int z, BlockStateHolder holder) { - set.setBlock(x, y, z, holder); - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java deleted file mode 100644 index 5c435d7a6..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/SoftChunk.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; - -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; - -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; - -public class SoftChunk extends ReferenceChunk { - - public SoftChunk(IChunk parent) { - super(parent); - } - - @Override - protected Reference toRef(FinalizedChunk parent) { - return new SoftReference<>(parent); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java index ef9625376..a7bdb8334 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java @@ -31,22 +31,22 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * [ WorldEdit action] - * | + * | * \|/ * [ EditSession ] - The change is processed (area restrictions, change limit, block type) - * | + * | * \|/ * [Block change] - A block change from some location - * | + * | * \|/ * [ Set Queue ] - The SetQueue manages the implementation specific queue - * | + * | * \|/ * [ Fawe Queue] - A queue of chunks - check if the queue has the chunk for a change - * | + * | * \|/ * [ Fawe Chunk Implementation ] - Otherwise create a new FaweChunk object which is a wrapper around the Chunk object - * | + * | * \|/ * [ Execution ] - When done, the queue then sets the blocks for the chunk, performs lighting updates and sends the chunk packet to the clients *

diff --git a/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java b/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java index bf8369411..ab34b9fc5 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java @@ -1,5 +1,6 @@ package com.boydti.fawe; +import com.boydti.fawe.beta.Trimable; import com.boydti.fawe.jnbt.anvil.BitArray4096; import com.boydti.fawe.object.collection.IterableThreadLocal; import com.boydti.fawe.util.MathMan; @@ -11,29 +12,21 @@ import com.sk89q.worldedit.world.block.BlockTypes; import java.lang.reflect.Field; import java.util.*; -public class FaweCache { - public static final IterableThreadLocal BLOCK_TO_PALETTE_CHAR = new IterableThreadLocal() { - @Override - public char[] init() { - char[] result = new char[BlockTypes.states.length]; - Arrays.fill(result, Character.MAX_VALUE); - return result; - } - }; +public class FaweCache implements Trimable { - public static final IterableThreadLocal PALETTE_TO_BLOCK_CHAR = new IterableThreadLocal() { - @Override - public char[] init() { - return new char[Character.MAX_VALUE]; - } - }; + /* + Palette buffers / cache + */ - public static final IterableThreadLocal SECTION_BLOCKS_CHAR = new IterableThreadLocal() { - @Override - public char[] init() { - return new char[4096]; - } - }; + @Override + public boolean trim(boolean aggressive) { + BLOCK_TO_PALETTE.clean(); + PALETTE_TO_BLOCK.clean(); + BLOCK_STATES.clean(); + SECTION_BLOCKS.clean(); + PALETTE_CACHE.clean(); + return false; + } public static final IterableThreadLocal BLOCK_TO_PALETTE = new IterableThreadLocal() { @Override @@ -75,6 +68,121 @@ public class FaweCache { return map; } + private static final class Palette { + public int paletteToBlockLength; + /** + * Reusable buffer array, MUST check paletteToBlockLength for actual length + */ + public int[] paletteToBlock; + + public int blockstatesLength; + /** + * Reusable buffer array, MUST check blockstatesLength for actual length + */ + public long[] blockstates; + } + + private static final IterableThreadLocal PALETTE_CACHE = new IterableThreadLocal() { + @Override + public Palette init() { + return new Palette(); + } + }; + + /** + * Convert raw char array to palette + * @param layer + * @param blocks + * @return palette + */ + public static Palette toPalette(int layer, char[] blocks) { + return toPalette(layer, null, blocks); + } + + /** + * Convert raw int array to palette + * @param layer + * @param blocks + * @return palette + */ + public static Palette toPalette(int layer, int[] blocks) { + return toPalette(layer, blocks, null); + } + + private static Palette toPalette(int layer, int[] blocksInts, char[] blocksChars) { + int[] blockToPalette = BLOCK_TO_PALETTE.get(); + int[] paletteToBlock = PALETTE_TO_BLOCK.get(); + long[] blockstates = BLOCK_STATES.get(); + int[] blocksCopy = SECTION_BLOCKS.get(); + + int blockIndexStart = layer << 12; + int blockIndexEnd = blockIndexStart + 4096; + int num_palette = 0; + try { + if (blocksChars != null) { + for (int i = blockIndexStart, j = 0; i < blockIndexEnd; i++, j++) { + int ordinal = blocksChars[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; + } + } else if (blocksInts != null) { + for (int i = blockIndexStart, j = 0; i < blockIndexEnd; i++, j++) { + int ordinal = blocksInts[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; + } + } else { + throw new IllegalArgumentException(); + } + + 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); + } + + // Construct palette + Palette palette = PALETTE_CACHE.get(); + palette.paletteToBlockLength = num_palette; + palette.paletteToBlock = paletteToBlock; + + palette.blockstatesLength = blockBitArrayEnd; + palette.blockstates = blockstates; + + return palette; + } catch (Throwable e) { + Arrays.fill(blockToPalette, Integer.MAX_VALUE); + e.printStackTrace(); + throw e; + } + } + + /* + Conversion methods between JNBT tags and raw values + */ + public static ShortTag asTag(short value) { return new ShortTag(value); } @@ -205,56 +313,4 @@ 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; - } - } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/Filter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java similarity index 71% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/Filter.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java index e2bb721c1..6038aacb5 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/Filter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/Filter.java @@ -1,8 +1,8 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.beta; import com.sk89q.worldedit.world.block.BaseBlock; -public class Filter { +public interface Filter { /** * Check whether a chunk should be read * @@ -10,7 +10,7 @@ public class Filter { * @param cz * @return */ - public boolean appliesChunk(int cx, int cz) { + default boolean appliesChunk(final int cx, final int cz) { return true; } @@ -22,7 +22,7 @@ public class Filter { * @param chunk * @return */ - public IChunk applyChunk(IChunk chunk) { + default IChunk applyChunk(final IChunk chunk) { return chunk; } @@ -36,7 +36,7 @@ public class Filter { * @param z * @param block */ - public void applyBlock(int x, int y, int z, BaseBlock block) { + default void applyBlock(final int x, final int y, final int z, final BaseBlock block) { } /** @@ -45,6 +45,6 @@ public class Filter { * @param chunk * @return */ - public void finishChunk(IChunk chunk) { + default void finishChunk(final IChunk chunk) { } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java new file mode 100644 index 000000000..951ec4a9b --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java @@ -0,0 +1,5 @@ +package com.boydti.fawe.beta; + +public interface IBlocks { + +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java similarity index 72% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java index 21452e0b0..5472773fc 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunk.java @@ -1,15 +1,15 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.beta; 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 IChunk { +public interface IChunk { /* set */ boolean setBiome(int x, int y, int z, BiomeType biome); - boolean setBlock(int x, int y, int z, BlockStateHolder holder); + boolean setBlock(int x, int y, int z, BlockStateHolder block); /* get */ BiomeType getBiome(int x, int z); @@ -18,14 +18,14 @@ public interface IChunk { BaseBlock getFullBlock(int x, int y, int z); - void init(SingleThreadQueueExtent extent, int X, int Z); + void init(V extent, int X, int Z); + + T apply(); int getX(); int getZ(); - void apply(); - default IChunk getRoot() { return this; } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/IDelegateChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java similarity index 51% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/IDelegateChunk.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java index e71172bc4..bc36a19f1 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/IDelegateChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateChunk.java @@ -1,14 +1,13 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; +package com.boydti.fawe.beta; -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; -import com.boydti.fawe.bukkit.v1_13.beta.SingleThreadQueueExtent; +import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -public interface IDelegateChunk extends IChunk { - T getParent(); +public interface IDelegateChunk> extends IChunk { + U getParent(); default IChunk getRoot() { IChunk root = getParent(); @@ -19,32 +18,32 @@ public interface IDelegateChunk extends IChunk { } @Override - default void setBiome(int x, int z, BiomeType biome) { - getParent().setBiome(x, z, biome); + default boolean setBiome(final int x, final int y, final int z, final BiomeType biome) { + return getParent().setBiome(x, y, z, biome); } @Override - default void setBlock(int x, int y, int z, BlockStateHolder holder) { - getParent().setBlock(x, y, z, holder); + default boolean setBlock(final int x, final int y, final int z, final BlockStateHolder holder) { + return getParent().setBlock(x, y, z, holder); } @Override - default BiomeType getBiome(int x, int z) { + default BiomeType getBiome(final int x, final int z) { return getParent().getBiome(x, z); } @Override - default BlockState getBlock(int x, int y, int z) { + default BlockState getBlock(final int x, final int y, final int z) { return getParent().getBlock(x, y, z); } @Override - default BaseBlock getFullBlock(int x, int y, int z) { + default BaseBlock getFullBlock(final int x, final int y, final int z) { return getParent().getFullBlock(x, y, z); } @Override - default void init(SingleThreadQueueExtent extent, int X, int Z) { + default void init(final V extent, final int X, final int Z) { getParent().init(extent, X, Z); } @@ -59,18 +58,22 @@ public interface IDelegateChunk extends IChunk { } @Override - default void apply() { - getParent().apply(); + default T apply() { + return getParent().apply(); } - default IChunk findParent(Class clazz) { + default T findParent(final Class clazz) { IChunk root = getParent(); - if (clazz.isAssignableFrom(root.getClass())) return root; + if (clazz.isAssignableFrom(root.getClass())) return (T) root; while (root instanceof IDelegateChunk) { root = ((IDelegateChunk) root).getParent(); - if (clazz.isAssignableFrom(root.getClass())) return root; + if (clazz.isAssignableFrom(root.getClass())) return (T) root; } return null; } + @Override + default void filter(Filter filter) { + getParent().filter(filter); + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateQueueExtent.java new file mode 100644 index 000000000..32f78095d --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IDelegateQueueExtent.java @@ -0,0 +1,44 @@ +package com.boydti.fawe.beta; + +import com.boydti.fawe.beta.implementation.WorldChunkCache; + +import java.util.concurrent.Future; + +public interface IDelegateQueueExtent extends IQueueExtent { + IQueueExtent getParent(); + + @Override + default void init(WorldChunkCache cache) { + getParent().init(cache); + } + + @Override + default IChunk getCachedChunk(int X, int Z) { + return getParent().getCachedChunk(X, Z); + } + + @Override + default Future submit(IChunk chunk) { + return getParent().submit(chunk); + } + + @Override + default IChunk create(boolean full) { + return getParent().create(full); + } + + @Override + default IChunk wrap(IChunk root) { + return getParent().wrap(root); + } + + @Override + default void flush() { + getParent().flush(); + } + + @Override + default boolean trim(boolean aggressive) { + return getParent().trim(aggressive); + } +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IGetBlocks.java similarity index 87% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/IGetBlocks.java index f0c1346d4..bd4ca9271 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/IGetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IGetBlocks.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.beta; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BaseBlock; @@ -10,4 +10,6 @@ public interface IGetBlocks extends IBlocks { BiomeType getBiome(int x, int z); BlockState getBlock(int x, int y, int z); + + void trim(); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java new file mode 100644 index 000000000..67cc845df --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java @@ -0,0 +1,56 @@ +package com.boydti.fawe.beta; + +import com.boydti.fawe.beta.implementation.WorldChunkCache; +import com.sk89q.worldedit.world.biome.BiomeType; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockStateHolder; + +import java.io.Flushable; +import java.util.concurrent.Future; + +public interface IQueueExtent extends Flushable, Trimable { + void init(WorldChunkCache world); + + IChunk getCachedChunk(int X, int Z); + + Future submit(IChunk chunk); + + default boolean setBlock(final int x, final int y, final int z, final BlockStateHolder state) { + final IChunk chunk = getCachedChunk(x >> 4, z >> 4); + return chunk.setBlock(x & 15, y, z & 15, state); + } + + default boolean setBiome(final int x, final int y, final int z, final BiomeType biome) { + final IChunk chunk = getCachedChunk(x >> 4, z >> 4); + return chunk.setBiome(x & 15, y, z & 15, biome); + } + + default BlockState getBlock(final int x, final int y, final int z) { + final IChunk chunk = getCachedChunk(x >> 4, z >> 4); + return chunk.getBlock(x & 15, y, z & 15); + } + + default BiomeType getBiome(final int x, final int z) { + final IChunk chunk = getCachedChunk(x >> 4, z >> 4); + return chunk.getBiome(x & 15, z & 15); + } + + /** + * Return the IChunk + * @param full + * @return + */ + IChunk create(boolean full); + + /** + * Wrap the chunk object (i.e. for region restrictions etc.) + * @param root + * @return wrapped chunk + */ + default IChunk wrap(IChunk root) { + return root; + } + + @Override + void flush(); +} \ No newline at end of file diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java similarity index 50% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java index 6793775b1..f4b453e12 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/ISetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/ISetBlocks.java @@ -1,10 +1,10 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.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); + 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); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/Trimable.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/Trimable.java new file mode 100644 index 000000000..3cfaffd34 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/Trimable.java @@ -0,0 +1,5 @@ +package com.boydti.fawe.beta; + +public interface Trimable { + boolean trim(boolean aggressive); +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java new file mode 100644 index 000000000..d6dbff8ac --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/QueueHandler.java @@ -0,0 +1,122 @@ +package com.boydti.fawe.beta.implementation; + +import com.boydti.fawe.beta.Filter; +import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.Trimable; +import com.boydti.fawe.object.collection.IterableThreadLocal; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.world.World; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public abstract class QueueHandler implements Trimable { + private Map> chunkCache = new HashMap<>(); + private IterableThreadLocal pool = new IterableThreadLocal() { + @Override + public IQueueExtent init() { + return create(); + } + }; + + public WorldChunkCache getOrCreate(final World world) { + synchronized (chunkCache) { + final WeakReference ref = chunkCache.get(world); + if (ref != null) { + final WorldChunkCache cached = ref.get(); + if (cached != null) { + return cached; + } + } + final WorldChunkCache created = new WorldChunkCache(world); + chunkCache.put(world, new WeakReference<>(created)); + return created; + } + } + + public abstract IQueueExtent create(); + + public boolean trim(final boolean aggressive) { + boolean result = true; + synchronized (chunkCache) { + final Iterator>> iter = chunkCache.entrySet().iterator(); + while (iter.hasNext()) { + final Map.Entry> entry = iter.next(); + final WeakReference value = entry.getValue(); + final WorldChunkCache cache = value.get(); + if (cache == null || cache.size() == 0 || cache.trim(aggressive)) { + iter.remove(); + continue; + } + result = false; + } + } + return result; + } + + public static void apply(final Region region, final Filter filter) { // TODO not MCAFilter, but another similar class +// // The chunks positions to iterate over +// final Set chunks = region.getChunks(); +// final Iterator chunksIter = chunks.iterator(); +// +// // Get a pool, to operate on the chunks in parallel +// final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool(); +// final int size = Math.min(chunks.size(), Settings.IMP.QUEUE.PARALLEL_THREADS); +// final 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 +// final BlockVector2 pos; +// synchronized (chunksIter) { +// if (!chunksIter.hasNext()) return; +// pos = chunksIter.next(); +// } +// final int X = pos.getX(); +// final int Z = pos.getZ(); +// final 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 (final ForkJoinTask task : tasks) { +// task.join(); +// } + } +} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/SingleThreadQueueExtent.java new file mode 100644 index 000000000..fa66b8395 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/SingleThreadQueueExtent.java @@ -0,0 +1,154 @@ +package com.boydti.fawe.beta.implementation; + +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.implementation.holder.ReferenceChunk; +import com.boydti.fawe.config.Settings; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.MemUtil; +import com.boydti.fawe.util.TaskManager; +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; + +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class SingleThreadQueueExtent implements IQueueExtent { + private WorldChunkCache cache; + private Thread currentThread; + + private void checkThread() { + if (Thread.currentThread() != currentThread && currentThread != null) { + throw new UnsupportedOperationException("This class must be used from a single thread. Use multiple queues for concurrent operations"); + } + } + + public WorldChunkCache getCache() { + return cache; + } + + protected synchronized void reset() { + checkThread(); + cache = null; + if (!chunks.isEmpty()) { + for (IChunk chunk : chunks.values()) { + chunk = chunk.getRoot(); + if (chunk != null) { + chunkPool.add(chunk); + } + } + chunks.clear(); + } + lastChunk = null; + lastPair = Long.MAX_VALUE; + currentThread = null; + } + + @Override + public synchronized void init(final WorldChunkCache cache) { + if (cache != null) { + reset(); + } + currentThread = Thread.currentThread(); + checkNotNull(cache); + this.cache = cache; + } + + private IChunk lastChunk; + private long lastPair = Long.MAX_VALUE; + private final Long2ObjectLinkedOpenHashMap chunks = new Long2ObjectLinkedOpenHashMap<>(); + private final ConcurrentLinkedQueue chunkPool = new ConcurrentLinkedQueue<>(); + + @Override + public ForkJoinTask submit(final IChunk tmp) { + final ForkJoinPool pool = TaskManager.IMP.getPublicForkJoinPool(); + return pool.submit(new Callable() { + @Override + public T call() { + IChunk chunk = tmp; + + T result = chunk.apply(); + + chunk = chunk.getRoot(); + if (chunk != null) { + chunkPool.add(chunk); + } + return result; + } + }); + } + + @Override + public synchronized boolean trim(boolean aggressive) { + chunkPool.clear(); + if (Thread.currentThread() == currentThread) { + lastChunk = null; + lastPair = Long.MAX_VALUE; + return chunks.isEmpty(); + } + synchronized (this) { + return currentThread == null; + } + } + + private IChunk pool(final int X, final int Z) { + IChunk next = chunkPool.poll(); + if (next == null) next = create(false); + next.init(this, X, Z); + return next; + } + + public final IChunk getCachedChunk(final int X, final int Z) { + final long pair = MathMan.pairInt(X, Z); + if (pair == lastPair) { + return lastChunk; + } + + IChunk chunk = chunks.get(pair); + if (chunk instanceof ReferenceChunk) { + chunk = ((ReferenceChunk) (chunk)).getParent(); + } + if (chunk != null) { + lastPair = pair; + lastChunk = chunk; + } + if (chunk != null) return chunk; + + checkThread(); + final 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(); + submit(chunk); + } + } + chunk = pool(X, Z); + chunk = wrap(chunk); + + chunks.put(pair, chunk); + lastPair = pair; + lastChunk = chunk; + + return chunk; + } + + @Override + public synchronized void flush() { + checkThread(); + if (!chunks.isEmpty()) { + final ForkJoinTask[] tasks = new ForkJoinTask[chunks.size()]; + int i = 0; + for (final IChunk chunk : chunks.values()) { + tasks[i++] = submit(chunk); + } + chunks.clear(); + for (final ForkJoinTask task : tasks) { + if (task != null) task.join(); + } + } + reset(); + } +} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/WorldChunkCache.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/WorldChunkCache.java new file mode 100644 index 000000000..93ee2fda9 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/WorldChunkCache.java @@ -0,0 +1,62 @@ +package com.boydti.fawe.beta.implementation; + +import com.boydti.fawe.beta.IGetBlocks; +import com.boydti.fawe.beta.Trimable; +import com.sk89q.worldedit.world.World; +import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.objects.ObjectIterator; + +import java.lang.ref.WeakReference; +import java.util.function.Supplier; + +public class WorldChunkCache implements Trimable { + protected final Long2ObjectLinkedOpenHashMap> getCache; + private final World world; + + protected WorldChunkCache(final World world) { + this.world = world; + this.getCache = new Long2ObjectLinkedOpenHashMap<>(); + } + + public World getWorld() { + return world; + } + + public synchronized int size() { + return getCache.size(); + } + + public synchronized IGetBlocks get(final long index, final Supplier provider) { + final WeakReference ref = getCache.get(index); + if (ref != null) { + final IGetBlocks blocks = ref.get(); + if (blocks != null) return blocks; + } + final IGetBlocks blocks = provider.get(); + getCache.put(index, new WeakReference<>(blocks)); + return blocks; + } + + @Override + public synchronized boolean trim(final boolean aggressive) { + boolean result = true; + if (!getCache.isEmpty()) { + final ObjectIterator>> iter = getCache.long2ObjectEntrySet().fastIterator(); + while (iter.hasNext()) { + final Long2ObjectMap.Entry> entry = iter.next(); + final WeakReference value = entry.getValue(); + final IGetBlocks igb = value.get(); + if (igb == null) iter.remove(); + else { + result = false; + if (!aggressive) return result; + synchronized (igb) { + igb.trim(); + } + } + } + } + return result; + } +} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java new file mode 100644 index 000000000..f07b8b44b --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java @@ -0,0 +1,7 @@ +package com.boydti.fawe.beta.implementation.blocks; + +import com.boydti.fawe.beta.IBlocks; + +public class CharBlocks implements IBlocks { + protected char[][] blocks; +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java similarity index 51% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java index c33ef3100..fe3287145 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java @@ -1,25 +1,23 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.beta.implementation.blocks; +import com.boydti.fawe.beta.IGetBlocks; 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) { + public BaseBlock getFullBlock(final int x, final int y, final int z) { return null; } @Override - public BiomeType getBiome(int x, int z) { - return null; + public BiomeType getBiome(final int x, final int z) { } @Override - public BlockState getBlock(int x, int y, int z) { + public BlockState getBlock(final int x, final int y, final int z) { return null; } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java similarity index 78% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharSetBlocks.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java index 66c2f4197..f7395d847 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java @@ -1,5 +1,6 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.beta.implementation.blocks; +import com.boydti.fawe.beta.ISetBlocks; import com.sk89q.jnbt.CompoundTag; import java.util.HashMap; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/FullCharBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FullCharBlocks.java similarity index 64% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/FullCharBlocks.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FullCharBlocks.java index e07e6e5b0..695387bca 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/FullCharBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FullCharBlocks.java @@ -1,4 +1,6 @@ -package com.boydti.fawe.bukkit.v1_13.beta; +package com.boydti.fawe.beta.implementation.blocks; + +import com.boydti.fawe.beta.IBlocks; public class FullCharBlocks implements IBlocks { public final boolean[] hasSections = new boolean[16]; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java new file mode 100644 index 000000000..9204fa951 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ChunkHolder.java @@ -0,0 +1,243 @@ +package com.boydti.fawe.beta.implementation.holder; + +import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; +import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks; +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.IGetBlocks; +import com.boydti.fawe.beta.ISetBlocks; +import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent; +import com.boydti.fawe.beta.implementation.WorldChunkCache; +import com.boydti.fawe.util.MathMan; +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 java.util.function.Supplier; + +public abstract class ChunkHolder implements IChunk, Supplier { + private IGetBlocks get; + private ISetBlocks set; + private IBlockDelegate delegate; + private SingleThreadQueueExtent extent; + private int X,Z; + + public ChunkHolder() { + this.delegate = NULL; + } + + public ChunkHolder(IBlockDelegate delegate) { + this.delegate = delegate; + } + + public final IGetBlocks cachedGet() { + if (get == null) get = newGet(); + return get; + } + + public final ISetBlocks cachedSet() { + if (set == null) set = set(); + return set; + } + + public ISetBlocks set() { + return new CharSetBlocks(); + } + + private IGetBlocks newGet() { + WorldChunkCache cache = extent.getCache(); + cache.get(MathMan.pairInt(X, Z), this); + return new CharGetBlocks(); + } + + public void init(final SingleThreadQueueExtent extent, final int X, final int Z) { + this.extent = extent; + this.X = X; + this.Z = Z; + set = null; + if (delegate == BOTH) { + delegate = GET; + } else if (delegate == SET) { + delegate = NULL; + } + } + + public V getExtent() { + return (V) extent; + } + + @Override + public int getX() { + return X; + } + + @Override + public int getZ() { + return Z; + } + + @Override + public boolean setBiome(final int x, final int y, final int z, final BiomeType biome) { + return delegate.setBiome(this, x, y, z, biome); + } + + @Override + public boolean setBlock(final int x, final int y, final int z, final BlockStateHolder block) { + return delegate.setBlock(this, x, y, z, block); + } + + @Override + public BiomeType getBiome(final int x, final int z) { + return delegate.getBiome(this, x, z); + } + + @Override + public BlockState getBlock(final int x, final int y, final int z) { + return delegate.getBlock(this, x, y, z); + } + + @Override + public BaseBlock getFullBlock(final int x, final int y, final int z) { + return delegate.getFullBlock(this, x, y, z); + } + + public interface IBlockDelegate { + boolean setBiome(final ChunkHolder chunk, final int x, final int y, final int z, final BiomeType biome); + + boolean setBlock(final ChunkHolder chunk, final int x, final int y, final int z, final BlockStateHolder holder); + + BiomeType getBiome(final ChunkHolder chunk, final int x, final int z); + + BlockState getBlock(final ChunkHolder chunk, final int x, final int y, final int z); + + BaseBlock getFullBlock(final ChunkHolder chunk, final int x, final int y, final int z); + } + + public static final IBlockDelegate NULL = new IBlockDelegate() { + @Override + public boolean setBiome(final ChunkHolder chunk, final int x, final int y, final int z, final BiomeType biome) { + chunk.cachedSet(); + chunk.delegate = SET; + return chunk.setBiome(x, y, z, biome); + } + + @Override + public boolean setBlock(final ChunkHolder chunk, final int x, final int y, final int z, final BlockStateHolder block) { + chunk.cachedSet(); + chunk.delegate = SET; + return chunk.setBlock(x, y, z, block); + } + + @Override + public BiomeType getBiome(final ChunkHolder chunk, final int x, final int z) { + chunk.cachedGet(); + chunk.delegate = GET; + return chunk.getBiome(x, z); + } + + @Override + public BlockState getBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + chunk.cachedGet(); + chunk.delegate = GET; + return chunk.getBlock(x, y, z); + } + + @Override + public BaseBlock getFullBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + chunk.cachedGet(); + chunk.delegate = GET; + return chunk.getFullBlock(x, y, z); + } + }; + + public static final IBlockDelegate GET = new IBlockDelegate() { + @Override + public boolean setBiome(final ChunkHolder chunk, final int x, final int y, final int z, final BiomeType biome) { + chunk.cachedSet(); + chunk.delegate = BOTH; + return chunk.setBiome(x, y, z, biome); + } + + @Override + public boolean setBlock(final ChunkHolder chunk, final int x, final int y, final int z, final BlockStateHolder block) { + chunk.cachedSet(); + chunk.delegate = BOTH; + return chunk.setBlock(x, y, z, block); + } + + @Override + public BiomeType getBiome(final ChunkHolder chunk, final int x, final int z) { + return chunk.get.getBiome(x, z); + } + + @Override + public BlockState getBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + return chunk.get.getBlock(x, y, z); + } + + @Override + public BaseBlock getFullBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + return chunk.get.getFullBlock(x, y, z); + } + }; + + public static final IBlockDelegate SET = new IBlockDelegate() { + @Override + public boolean setBiome(final ChunkHolder chunk, final int x, final int y, final int z, final BiomeType biome) { + return chunk.set.setBiome(x, y, z, biome); + } + + @Override + public boolean setBlock(final ChunkHolder chunk, final int x, final int y, final int z, final BlockStateHolder block) { + return chunk.set.setBlock(x, y, z, block); + } + + @Override + public BiomeType getBiome(final ChunkHolder chunk, final int x, final int z) { + chunk.cachedGet(); + chunk.delegate = BOTH; + return chunk.getBiome(x, z); + } + + @Override + public BlockState getBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + chunk.cachedGet(); + chunk.delegate = BOTH; + return chunk.getBlock(x, y, z); + } + + @Override + public BaseBlock getFullBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + chunk.cachedGet(); + chunk.delegate = BOTH; + return chunk.getFullBlock(x, y, z); + } + }; + + public static final IBlockDelegate BOTH = new IBlockDelegate() { + @Override + public boolean setBiome(final ChunkHolder chunk, final int x, final int y, final int z, final BiomeType biome) { + return chunk.set.setBiome(x, y, z, biome); + } + + @Override + public boolean setBlock(final ChunkHolder chunk, final int x, final int y, final int z, final BlockStateHolder block) { + return chunk.set.setBlock(x, y, z, block); + } + + @Override + public BiomeType getBiome(final ChunkHolder chunk, final int x, final int z) { + return chunk.get.getBiome(x, z); + } + + @Override + public BlockState getBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + return chunk.get.getBlock(x, y, z); + } + + @Override + public BaseBlock getFullBlock(final ChunkHolder chunk, final int x, final int y, final int z) { + return chunk.get.getFullBlock(x, y, z); + } + }; +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/DelegateChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/DelegateChunk.java similarity index 50% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/DelegateChunk.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/DelegateChunk.java index 19ddffbc0..73ee2db00 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/DelegateChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/DelegateChunk.java @@ -1,11 +1,12 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; +package com.boydti.fawe.beta.implementation.holder; -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.IDelegateChunk; public class DelegateChunk implements IDelegateChunk { private T parent; - public DelegateChunk(T parent) { + public DelegateChunk(final T parent) { this.parent = parent; } @@ -13,7 +14,7 @@ public class DelegateChunk implements IDelegateChunk { return parent; } - public final void setParent(T parent) { + public final void setParent(final T parent) { this.parent = parent; } -} +} \ No newline at end of file diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/FinalizedChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/FinalizedChunk.java new file mode 100644 index 000000000..18d6e2d6a --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/FinalizedChunk.java @@ -0,0 +1,30 @@ +package com.boydti.fawe.beta.implementation.holder; + +import com.boydti.fawe.beta.IQueueExtent; +import com.boydti.fawe.beta.IChunk; + +/** + * Used by {@link ReferenceChunk} to allow the chunk to be garbage collected + * - When the object is finalized, add it to the queue + */ +public class FinalizedChunk extends DelegateChunk { + private final IQueueExtent queueExtent; + + public FinalizedChunk(final IChunk parent, IQueueExtent queueExtent) { + super(parent); + this.queueExtent = queueExtent; + } + + /** + * Submit the chunk to the queue + * @throws Throwable + */ + @Override + protected void finalize() throws Throwable { + if (getParent() != null) { + apply(); + setParent(null); + } + super.finalize(); + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ReferenceChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ReferenceChunk.java new file mode 100644 index 000000000..956865d6a --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/ReferenceChunk.java @@ -0,0 +1,23 @@ +package com.boydti.fawe.beta.implementation.holder; + +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.IDelegateChunk; +import com.boydti.fawe.beta.IQueueExtent; + +import java.lang.ref.Reference; + +public abstract class ReferenceChunk implements IDelegateChunk { + private final Reference ref; + + public ReferenceChunk(final IChunk parent, IQueueExtent queueExtent) { + this.ref = toRef(new FinalizedChunk(parent, queueExtent)); + } + + protected abstract Reference toRef(FinalizedChunk parent); + + @Override + public IChunk getParent() { + final FinalizedChunk finalized = ref.get(); + return finalized != null ? finalized.getParent() : null; + } +} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/SoftChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/SoftChunk.java new file mode 100644 index 000000000..d23c28f57 --- /dev/null +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/SoftChunk.java @@ -0,0 +1,19 @@ +package com.boydti.fawe.beta.implementation.holder; + +import com.boydti.fawe.beta.IChunk; +import com.boydti.fawe.beta.IQueueExtent; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; + +public class SoftChunk extends ReferenceChunk { + + public SoftChunk(final IChunk parent, IQueueExtent queueExtent) { + super(parent, queueExtent); + } + + @Override + protected Reference toRef(final FinalizedChunk parent) { + return new SoftReference<>(parent); + } +} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/WeakChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/WeakChunk.java similarity index 50% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/WeakChunk.java rename to worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/WeakChunk.java index b574ed010..ad8225bea 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/v1_13/beta/holder/WeakChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/holder/WeakChunk.java @@ -1,17 +1,17 @@ -package com.boydti.fawe.bukkit.v1_13.beta.holder; +package com.boydti.fawe.beta.implementation.holder; -import com.boydti.fawe.bukkit.v1_13.beta.IChunk; +import com.boydti.fawe.beta.IChunk; import java.lang.ref.Reference; import java.lang.ref.WeakReference; public class WeakChunk extends ReferenceChunk { - public WeakChunk(IChunk parent) { + public WeakChunk(final IChunk parent) { super(parent); } @Override - protected Reference toRef(FinalizedChunk parent) { + protected Reference toRef(final FinalizedChunk parent) { return new WeakReference<>(parent); } }