From aadd6ac81af93090e781bce54f144c9f53302953 Mon Sep 17 00:00:00 2001 From: JayemCeekay Date: Sun, 16 Apr 2023 13:47:31 -0500 Subject: [PATCH] Apply DataArray Patch and update bukkit adapters. --- .../ext/fawe/v1_20_R2/PaperweightAdapter.java | 3 +- .../v1_20_R2/PaperweightDataConverters.java | 2 +- .../PaperweightWorldNativeAccess.java | 2 +- .../fawe/v1_20_R2/PaperweightGetBlocks.java | 55 ++++----- .../v1_20_R2/PaperweightGetBlocks_Copy.java | 16 +-- .../v1_20_R2/PaperweightPlatformAdapter.java | 7 +- .../v1_20_R2/PaperweightPostProcessor.java | 62 ++-------- .../ext.fawe/v1_20_R3/PaperweightAdapter.java | 2 +- .../v1_20_R3/PaperweightDataConverters.java | 2 +- .../PaperweightWorldNativeAccess.java | 2 +- .../fawe/v1_20_R3/PaperweightGetBlocks.java | 55 ++++----- .../v1_20_R3/PaperweightGetBlocks_Copy.java | 16 +-- .../v1_20_R3/PaperweightPlatformAdapter.java | 7 +- .../v1_20_R3/PaperweightPostProcessor.java | 77 ++---------- .../ext.fawe/v1_20_R4/PaperweightAdapter.java | 3 +- .../v1_20_R4/PaperweightDataConverters.java | 2 +- .../PaperweightWorldNativeAccess.java | 4 +- .../fawe/v1_20_R4/PaperweightGetBlocks.java | 56 ++++----- .../v1_20_R4/PaperweightGetBlocks_Copy.java | 16 +-- .../v1_20_R4/PaperweightPlatformAdapter.java | 7 +- .../v1_20_R4/PaperweightPostProcessor.java | 77 ++---------- .../ext/fawe/v1_21_R1/PaperweightAdapter.java | 1 + .../fawe/v1_21_R1/PaperweightGetBlocks.java | 56 ++++----- .../v1_21_R1/PaperweightGetBlocks_Copy.java | 16 +-- .../v1_21_R1/PaperweightPlatformAdapter.java | 7 +- .../v1_21_R1/PaperweightPostProcessor.java | 77 ++---------- .../bukkit/adapter/NMSAdapter.java | 21 ++-- .../bukkit/adapter/PostProcessor.java | 78 +++++++++++++ .../fastasyncworldedit/core/FaweCache.java | 110 +++++++----------- .../core/extent/DisallowedBlocksExtent.java | 17 +-- ...erBlock.java => DataArrayFilterBlock.java} | 47 ++++---- .../heightmap/HeightmapProcessor.java | 86 +++++++++----- .../history/changeset/AbstractChangeSet.java | 29 ++--- .../core/math/BitArrayUnstretched.java | 7 +- .../core/queue/IBatchProcessor.java | 25 ++-- .../core/queue/IBlocks.java | 13 ++- .../core/queue/IChunkSet.java | 3 +- .../SingleThreadQueueExtent.java | 9 +- .../implementation/blocks/BitSetBlocks.java | 18 +-- .../implementation/blocks/CharDataArray.java | 56 +++++++++ .../blocks/ChunkSectionedChunk.java | 45 +++++++ .../implementation/blocks/DataArray.java | 95 +++++++++++++++ .../{CharBlocks.java => DataArrayBlocks.java} | 77 +++++------- ...GetBlocks.java => DataArrayGetBlocks.java} | 13 +-- ...SetBlocks.java => DataArraySetBlocks.java} | 31 ++--- .../implementation/blocks/IntDataArray.java | 54 +++++++++ .../implementation/blocks/NullChunkGet.java | 6 +- .../blocks/ThreadUnsafeCharBlocks.java | 50 ++++---- .../implementation/chunk/ChunkHolder.java | 7 +- .../queue/implementation/chunk/NullChunk.java | 8 +- .../sk89q/worldedit/extent/MaskingExtent.java | 4 +- .../sk89q/worldedit/regions/CuboidRegion.java | 35 ++---- .../com/sk89q/worldedit/regions/Region.java | 61 +++++----- 53 files changed, 824 insertions(+), 811 deletions(-) create mode 100644 worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/PostProcessor.java rename worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/{CharFilterBlock.java => DataArrayFilterBlock.java} (89%) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharDataArray.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ChunkSectionedChunk.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArray.java rename worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/{CharBlocks.java => DataArrayBlocks.java} (76%) rename worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/{CharGetBlocks.java => DataArrayGetBlocks.java} (78%) rename worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/{CharSetBlocks.java => DataArraySetBlocks.java} (93%) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/IntDataArray.java diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java index 9aaeb7bc23..e7523973fb 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightAdapter.java @@ -28,6 +28,7 @@ import com.google.common.util.concurrent.Futures; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; +import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTConstants; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseItem; @@ -145,7 +146,6 @@ import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -168,6 +168,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; +import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightDataConverters.java index be25d079a9..80bc50a06f 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightDataConverters.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightDataConverters.java @@ -49,7 +49,6 @@ import org.apache.logging.log4j.Logger; import org.enginehub.linbus.tree.LinCompoundTag; -import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.EnumMap; @@ -63,6 +62,7 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.stream.Collectors; +import javax.annotation.Nullable; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java index a27f01b704..2386e69690 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_20_R2/PaperweightWorldNativeAccess.java @@ -37,9 +37,9 @@ import org.bukkit.event.block.BlockPhysicsEvent; import org.enginehub.linbus.tree.LinCompoundTag; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; +import javax.annotation.Nullable; public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index 93f84a1ec4..4306f9192e 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -10,7 +10,8 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArrayGetBlocks; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; @@ -86,7 +87,7 @@ import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { +public class PaperweightGetBlocks extends DataArrayGetBlocks implements BukkitGetBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -495,7 +496,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz ); LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, - new char[4096], + DataArray.createEmpty(), adapter, biomeRegistry, biomeData @@ -506,7 +507,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz newSection, getSectionIndex )) { - updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex); + updateGet(nmsChunk, levelChunkSections, newSection, DataArray.createEmpty(), getSectionIndex); continue; } else { existingSection = levelChunkSections[getSectionIndex]; @@ -536,9 +537,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to // this chunk GET when #updateGet is called. Future dords, please listen this time. - char[] tmp = set.load(layerNo); - char[] setArr = new char[tmp.length]; - System.arraycopy(tmp, 0, setArr, 0, tmp.length); + DataArray setArr = DataArray.createCopy(set.load(layerNo)); // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was // submitted to keep loaded internal chunks to queue target size. @@ -555,10 +554,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } if (createCopy) { - char[] tmpLoad = loadPrivately(layerNo); - char[] copyArr = new char[4096]; - System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); - copy.storeSection(getSectionIndex, copyArr); + copy.storeSection(getSectionIndex, DataArray.createCopy(loadPrivately(layerNo))); if (biomes != null && existingSection != null) { copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); } @@ -616,10 +612,8 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } else if (existingSection != getSections(false)[getSectionIndex]) { this.sections[getSectionIndex] = existingSection; this.reset(); - } else if (!Arrays.equals( - update(getSectionIndex, new char[4096], true), - loadPrivately(layerNo) - )) { + } else if (!update(getSectionIndex, DataArray.createEmpty(), true) + .equals(loadPrivately(layerNo))) { this.reset(layerNo); /*} else if (lock.isModified()) { this.reset(layerNo);*/ @@ -889,7 +883,7 @@ private void updateGet( LevelChunk nmsChunk, LevelChunkSection[] chunkSections, LevelChunkSection section, - char[] arr, + DataArray arr, int layer ) { try { @@ -914,7 +908,7 @@ private void updateGet( this.blocks[layer] = arr; } - private char[] loadPrivately(int layer) { + private DataArray loadPrivately(int layer) { layer -= getMinSectionPosition(); if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { @@ -945,21 +939,14 @@ public void send() { */ @Override @SuppressWarnings("unchecked") - public char[] update(int layer, char[] data, boolean aggressive) { + public DataArray update(int layer, DataArray data, boolean aggressive) { LevelChunkSection section = getSections(aggressive)[layer]; // Section is null, return empty array if (section == null) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - return data; + return DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } - if (data != null && data.length != 4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + if (data == null || data == FaweCache.INSTANCE.EMPTY_DATA) { + data = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } Semaphore lock = PaperweightPlatformAdapter.applyLock(section); synchronized (lock) { @@ -972,7 +959,7 @@ public char[] update(int layer, char[] data, boolean aggressive) { final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject); if (bits instanceof ZeroBitStorage) { - Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper + data.setAll(adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper return data; } @@ -989,9 +976,9 @@ public char[] update(int layer, char[] data, boolean aggressive) { } else { // The section's palette is the global block palette. for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char ordinal = adapter.ibdIDToOrdinal(paletteVal); - data[i] = ordinal; + data.setAt(i, ordinal); } return data; } @@ -1004,17 +991,17 @@ public char[] update(int layer, char[] data, boolean aggressive) { paletteToOrdinal[i] = ordinal; } for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char val = paletteToOrdinal[paletteVal]; if (val == Character.MAX_VALUE) { val = ordinal(palette.valueFor(i), adapter); paletteToOrdinal[i] = val; } - data[i] = val; + data.setAt(i, val); } } else { char ordinal = ordinal(palette.valueFor(0), adapter); - Arrays.fill(data, ordinal); + data.setAll(ordinal); } } finally { for (int i = 0; i < num_palette; i++) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java index b6f4c7d947..b541d1940d 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -40,7 +41,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private final Map tiles = new HashMap<>(); private final Set entities = new HashSet<>(); - private final char[][] blocks; + private final DataArray[] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; @@ -52,7 +53,7 @@ protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.serverLevel = levelChunk.level; this.minHeight = serverLevel.getMinBuildHeight(); this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.blocks = new char[getSectionCount()][]; + this.blocks = new DataArray[getSectionCount()]; } protected void storeTile(BlockEntity blockEntity) { @@ -167,7 +168,7 @@ public int getSectionCount() { return serverLevel.getSectionsCount(); } - protected void storeSection(int layer, char[] data) { + protected void storeSection(int layer, DataArray data) { blocks[layer] = data; } @@ -204,17 +205,16 @@ public boolean hasSection(int layer) { } @Override - public char[] load(int layer) { + public DataArray load(int layer) { layer -= getMinSectionPosition(); if (blocks[layer] == null) { - blocks[layer] = new char[4096]; - Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + blocks[layer] = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } return blocks[layer]; } @Override - public char[] loadIfPresent(int layer) { + public DataArray loadIfPresent(int layer) { layer -= getMinSectionPosition(); return blocks[layer]; } @@ -247,7 +247,7 @@ public > T call(IChunkSet set, Runnable finalize) { public char get(int x, int y, int z) { final int layer = (y >> 4) - getMinSectionPosition(); final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer][index]; + return (char) blocks[layer].getAt(index); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 23f59e8bf1..de7c45b46a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -393,7 +394,7 @@ private static List nearbyPlayers(ServerLevel serverLevel, ChunkPo */ public static LevelChunkSection newChunkSection( final int layer, - final char[] blocks, + final DataArray blocks, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes @@ -403,8 +404,8 @@ public static LevelChunkSection newChunkSection( public static LevelChunkSection newChunkSection( final int layer, - final Function get, - char[] set, + final Function get, + DataArray set, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java index 5fafdc4398..7c01e7d586 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPostProcessor.java @@ -1,11 +1,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; +import com.fastasyncworldedit.bukkit.adapter.PostProcessor; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.registry.state.PropertyKey; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BlockState; @@ -18,12 +19,7 @@ import javax.annotation.Nullable; -public class PaperweightPostProcessor implements IBatchProcessor { - - @Override - public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - return set; - } +public class PaperweightPostProcessor extends PostProcessor { @SuppressWarnings("deprecation") @Override @@ -36,14 +32,14 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; layer: for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { - char[] set = iChunkSet.loadIfPresent(layer); + DataArray set = iChunkSet.loadIfPresent(layer); if (set == null) { // No edit means no need to process continue; } - char[] get = null; + DataArray get = null; for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; boolean fromGet = false; // Used for liquids if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { @@ -56,7 +52,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh continue layer; } fromGet = true; - ordinal = replacedOrdinal = get[i]; + ordinal = replacedOrdinal = (char) get.getAt(i); } if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { continue; @@ -64,7 +60,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh if (get == null) { get = getBlocks.load(layer); } - replacedOrdinal = get[i]; + replacedOrdinal = (char) get.getAt(i); } boolean ticking = BlockTypesCache.ticking[ordinal]; boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; @@ -115,48 +111,6 @@ public ProcessorScope getScope() { return ProcessorScope.READING_SET_BLOCKS; } - private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { - if (set == null || get == null) { - return false; - } - char ordinal; - char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; - if (x > 0 && set[i - 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { - return true; - } - } - if (x < 15 && set[i + 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { - return true; - } - } - if (z > 0 && set[i - 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { - return true; - } - } - if (z < 15 && set[i + 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { - return true; - } - } - if (y > 0 && set[i - 256] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { - return true; - } - } - if (y < 15 && set[i + 256] != reserved) { - return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); - } - return false; - } - - @SuppressWarnings("deprecation") - private boolean isFluid(char ordinal) { - return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); - } - @SuppressWarnings("deprecation") private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { Fluid type; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java index ded4bcfdd7..a9eb86ee65 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightAdapter.java @@ -145,7 +145,6 @@ import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -168,6 +167,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; +import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightDataConverters.java index 3a80b6a3a1..177d3158ae 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightDataConverters.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightDataConverters.java @@ -49,7 +49,6 @@ import org.apache.logging.log4j.Logger; import org.enginehub.linbus.tree.LinCompoundTag; -import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.EnumMap; @@ -63,6 +62,7 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.stream.Collectors; +import javax.annotation.Nullable; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java index 1f51c66ca9..1caf8d7843 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R3/PaperweightWorldNativeAccess.java @@ -38,9 +38,9 @@ import org.bukkit.event.block.BlockPhysicsEvent; import org.enginehub.linbus.tree.LinCompoundTag; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; +import javax.annotation.Nullable; public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java index d2d18968aa..69170e6303 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java @@ -10,7 +10,8 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArrayGetBlocks; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; @@ -86,7 +87,7 @@ import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { +public class PaperweightGetBlocks extends DataArrayGetBlocks implements BukkitGetBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -494,7 +495,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz ); LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, - new char[4096], + DataArray.createEmpty(), adapter, biomeRegistry, biomeData @@ -505,7 +506,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz newSection, getSectionIndex )) { - updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex); + updateGet(nmsChunk, levelChunkSections, newSection, DataArray.createEmpty(), getSectionIndex); continue; } else { existingSection = levelChunkSections[getSectionIndex]; @@ -535,9 +536,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to // this chunk GET when #updateGet is called. Future dords, please listen this time. - char[] tmp = set.load(layerNo); - char[] setArr = new char[tmp.length]; - System.arraycopy(tmp, 0, setArr, 0, tmp.length); + DataArray setArr = DataArray.createCopy(set.load(layerNo)); // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was // submitted to keep loaded internal chunks to queue target size. @@ -554,10 +553,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } if (createCopy) { - char[] tmpLoad = loadPrivately(layerNo); - char[] copyArr = new char[4096]; - System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); - copy.storeSection(getSectionIndex, copyArr); + copy.storeSection(getSectionIndex, DataArray.createCopy(loadPrivately(layerNo))); if (biomes != null && existingSection != null) { copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); } @@ -615,10 +611,8 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } else if (existingSection != getSections(false)[getSectionIndex]) { this.sections[getSectionIndex] = existingSection; this.reset(); - } else if (!Arrays.equals( - update(getSectionIndex, new char[4096], true), - loadPrivately(layerNo) - )) { + } else if (!update(getSectionIndex, DataArray.createEmpty(), true) + .equals(loadPrivately(layerNo))) { this.reset(layerNo); /*} else if (lock.isModified()) { this.reset(layerNo);*/ @@ -888,7 +882,7 @@ private void updateGet( LevelChunk nmsChunk, LevelChunkSection[] chunkSections, LevelChunkSection section, - char[] arr, + DataArray arr, int layer ) { try { @@ -913,7 +907,7 @@ private void updateGet( this.blocks[layer] = arr; } - private char[] loadPrivately(int layer) { + private DataArray loadPrivately(int layer) { layer -= getMinSectionPosition(); if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { @@ -942,21 +936,14 @@ public void send() { */ @Override @SuppressWarnings("unchecked") - public char[] update(int layer, char[] data, boolean aggressive) { + public DataArray update(int layer, DataArray data, boolean aggressive) { LevelChunkSection section = getSections(aggressive)[layer]; // Section is null, return empty array if (section == null) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - return data; + return DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } - if (data != null && data.length != 4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + if (data == null || data == FaweCache.INSTANCE.EMPTY_DATA) { + data = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } Semaphore lock = PaperweightPlatformAdapter.applyLock(section); synchronized (lock) { @@ -969,7 +956,7 @@ public char[] update(int layer, char[] data, boolean aggressive) { final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject); if (bits instanceof ZeroBitStorage) { - Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper + data.setAll(adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper return data; } @@ -986,9 +973,9 @@ public char[] update(int layer, char[] data, boolean aggressive) { } else { // The section's palette is the global block palette. for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char ordinal = adapter.ibdIDToOrdinal(paletteVal); - data[i] = ordinal; + data.setAt(i, ordinal); } return data; } @@ -1001,17 +988,17 @@ public char[] update(int layer, char[] data, boolean aggressive) { paletteToOrdinal[i] = ordinal; } for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char val = paletteToOrdinal[paletteVal]; if (val == Character.MAX_VALUE) { val = ordinal(palette.valueFor(i), adapter); paletteToOrdinal[i] = val; } - data[i] = val; + data.setAt(i, val); } } else { char ordinal = ordinal(palette.valueFor(0), adapter); - Arrays.fill(data, ordinal); + data.setAll(ordinal); } } finally { for (int i = 0; i < num_palette; i++) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java index 23c8822842..bef6da5a66 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks_Copy.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -40,7 +41,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private final Map tiles = new HashMap<>(); private final Set entities = new HashSet<>(); - private final char[][] blocks; + private final DataArray[] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; @@ -52,7 +53,7 @@ protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.serverLevel = levelChunk.level; this.minHeight = serverLevel.getMinBuildHeight(); this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.blocks = new char[getSectionCount()][]; + this.blocks = new DataArray[getSectionCount()]; } protected void storeTile(BlockEntity blockEntity) { @@ -167,7 +168,7 @@ public int getSectionCount() { return serverLevel.getSectionsCount(); } - protected void storeSection(int layer, char[] data) { + protected void storeSection(int layer, DataArray data) { blocks[layer] = data; } @@ -204,17 +205,16 @@ public boolean hasSection(int layer) { } @Override - public char[] load(int layer) { + public DataArray load(int layer) { layer -= getMinSectionPosition(); if (blocks[layer] == null) { - blocks[layer] = new char[4096]; - Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + blocks[layer] = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } return blocks[layer]; } @Override - public char[] loadIfPresent(int layer) { + public DataArray loadIfPresent(int layer) { layer -= getMinSectionPosition(); return blocks[layer]; } @@ -247,7 +247,7 @@ public > T call(IChunkSet set, Runnable finalize) { public char get(int x, int y, int z) { final int layer = (y >> 4) - getMinSectionPosition(); final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer][index]; + return (char) blocks[layer].getAt(index); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index b69f476d35..484e31829a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -393,7 +394,7 @@ private static List nearbyPlayers(ServerLevel serverLevel, ChunkPo */ public static LevelChunkSection newChunkSection( final int layer, - final char[] blocks, + final DataArray blocks, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes @@ -403,8 +404,8 @@ public static LevelChunkSection newChunkSection( public static LevelChunkSection newChunkSection( final int layer, - final Function get, - char[] set, + final Function get, + DataArray set, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java index cfd9e27536..8fa2238bd1 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPostProcessor.java @@ -1,13 +1,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; +import com.fastasyncworldedit.bukkit.adapter.PostProcessor; import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.registry.state.PropertyKey; -import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; @@ -16,14 +15,7 @@ import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; -import javax.annotation.Nullable; - -public class PaperweightPostProcessor implements IBatchProcessor { - - @Override - public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - return set; - } +public class PaperweightPostProcessor extends PostProcessor { @SuppressWarnings("deprecation") @Override @@ -36,14 +28,14 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; layer: for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { - char[] set = iChunkSet.loadIfPresent(layer); + DataArray set = iChunkSet.loadIfPresent(layer); if (set == null) { // No edit means no need to process continue; } - char[] get = null; + DataArray get = null; for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; boolean fromGet = false; // Used for liquids if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { @@ -56,7 +48,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh continue layer; } fromGet = true; - ordinal = replacedOrdinal = get[i]; + ordinal = replacedOrdinal = (char) get.getAt(i); } if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { continue; @@ -64,7 +56,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh if (get == null) { get = getBlocks.load(layer); } - replacedOrdinal = get[i]; + replacedOrdinal = (char) get.getAt(i); } boolean ticking = BlockTypesCache.ticking[ordinal]; boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; @@ -104,59 +96,6 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh } } - @Nullable - @Override - public Extent construct(final Extent child) { - throw new UnsupportedOperationException("Processing only"); - } - - @Override - public ProcessorScope getScope() { - return ProcessorScope.READING_SET_BLOCKS; - } - - private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { - if (set == null || get == null) { - return false; - } - char ordinal; - char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; - if (x > 0 && set[i - 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { - return true; - } - } - if (x < 15 && set[i + 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { - return true; - } - } - if (z > 0 && set[i - 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { - return true; - } - } - if (z < 15 && set[i + 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { - return true; - } - } - if (y > 0 && set[i - 256] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { - return true; - } - } - if (y < 15 && set[i + 256] != reserved) { - return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); - } - return false; - } - - @SuppressWarnings("deprecation") - private boolean isFluid(char ordinal) { - return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); - } - @SuppressWarnings("deprecation") private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { Fluid type; diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java index 206ade66a5..9383d2caf9 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightAdapter.java @@ -24,6 +24,7 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.mojang.serialization.Codec; @@ -149,7 +150,6 @@ import org.spigotmc.SpigotConfig; import org.spigotmc.WatchdogThread; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -172,6 +172,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; +import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java index c566f0ae88..4403391bf2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightDataConverters.java @@ -51,7 +51,6 @@ import org.apache.logging.log4j.Logger; import org.enginehub.linbus.tree.LinCompoundTag; -import javax.annotation.Nullable; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.EnumMap; @@ -65,6 +64,7 @@ import java.util.UUID; import java.util.concurrent.Executor; import java.util.stream.Collectors; +import javax.annotation.Nullable; /** * Handles converting all Pre 1.13.2 data using the Legacy DataFix System (ported to 1.13.2) diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java index c83733bf28..dd2061ebe1 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext.fawe/v1_20_R4/PaperweightWorldNativeAccess.java @@ -37,9 +37,9 @@ import org.bukkit.event.block.BlockPhysicsEvent; import org.enginehub.linbus.tree.LinCompoundTag; -import javax.annotation.Nullable; import java.lang.ref.WeakReference; import java.util.Objects; +import javax.annotation.Nullable; public class PaperweightWorldNativeAccess implements WorldNativeAccess { private static final int UPDATE = 1; @@ -186,6 +186,6 @@ public void onBlockStateChange(BlockPos pos, net.minecraft.world.level.block.sta @Override public void flush() { - + } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java index 47466ac5e7..5c891fa3cb 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks.java @@ -10,7 +10,8 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArrayGetBlocks; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; @@ -87,7 +88,7 @@ import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { +public class PaperweightGetBlocks extends DataArrayGetBlocks implements BukkitGetBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -497,7 +498,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz ); LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, - new char[4096], + DataArray.createEmpty(), adapter, biomeRegistry, biomeData @@ -508,7 +509,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz newSection, getSectionIndex )) { - updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex); + updateGet(nmsChunk, levelChunkSections, newSection, DataArray.createEmpty(), getSectionIndex); continue; } else { existingSection = levelChunkSections[getSectionIndex]; @@ -538,9 +539,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to // this chunk GET when #updateGet is called. Future dords, please listen this time. - char[] tmp = set.load(layerNo); - char[] setArr = new char[tmp.length]; - System.arraycopy(tmp, 0, setArr, 0, tmp.length); + DataArray setArr = DataArray.createCopy(set.load(layerNo)); // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was // submitted to keep loaded internal chunks to queue target size. @@ -557,10 +556,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } if (createCopy) { - char[] tmpLoad = loadPrivately(layerNo); - char[] copyArr = new char[4096]; - System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); - copy.storeSection(getSectionIndex, copyArr); + copy.storeSection(getSectionIndex, DataArray.createCopy(loadPrivately(layerNo))); if (biomes != null && existingSection != null) { copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); } @@ -618,10 +614,8 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } else if (existingSection != getSections(false)[getSectionIndex]) { this.sections[getSectionIndex] = existingSection; this.reset(); - } else if (!Arrays.equals( - update(getSectionIndex, new char[4096], true), - loadPrivately(layerNo) - )) { + } else if (!update(getSectionIndex, DataArray.createEmpty(), true) + .equals(loadPrivately(layerNo))) { this.reset(layerNo); /*} else if (lock.isModified()) { this.reset(layerNo);*/ @@ -889,7 +883,7 @@ private void updateGet( LevelChunk nmsChunk, LevelChunkSection[] chunkSections, LevelChunkSection section, - char[] arr, + DataArray arr, int layer ) { try { @@ -914,7 +908,7 @@ private void updateGet( this.blocks[layer] = arr; } - private char[] loadPrivately(int layer) { + private DataArray loadPrivately(int layer) { layer -= getMinSectionPosition(); if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { @@ -945,21 +939,14 @@ public void send() { */ @Override @SuppressWarnings("unchecked") - public char[] update(int layer, char[] data, boolean aggressive) { + public DataArray update(int layer, DataArray data, boolean aggressive) { LevelChunkSection section = getSections(aggressive)[layer]; // Section is null, return empty array if (section == null) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - return data; + return DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } - if (data != null && data.length != 4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + if (data == null || data == FaweCache.INSTANCE.EMPTY_DATA) { + data = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } Semaphore lock = PaperweightPlatformAdapter.applyLock(section); synchronized (lock) { @@ -972,7 +959,7 @@ public char[] update(int layer, char[] data, boolean aggressive) { final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject); if (bits instanceof ZeroBitStorage) { - Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper + data.setAll(adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper return data; } @@ -989,9 +976,9 @@ public char[] update(int layer, char[] data, boolean aggressive) { } else { // The section's palette is the global block palette. for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char ordinal = adapter.ibdIDToOrdinal(paletteVal); - data[i] = ordinal; + data.setAt(i, ordinal); } return data; } @@ -1004,17 +991,17 @@ public char[] update(int layer, char[] data, boolean aggressive) { paletteToOrdinal[i] = ordinal; } for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char val = paletteToOrdinal[paletteVal]; if (val == Character.MAX_VALUE) { val = ordinal(palette.valueFor(i), adapter); paletteToOrdinal[i] = val; } - data[i] = val; + data.setAt(i, val); } } else { char ordinal = ordinal(palette.valueFor(0), adapter); - Arrays.fill(data, ordinal); + data.setAll(ordinal); } } finally { for (int i = 0; i < num_palette; i++) { @@ -1188,5 +1175,4 @@ public synchronized boolean trim(boolean aggressive) { return true; } } - } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java index 1467600201..9eccbfa6f4 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightGetBlocks_Copy.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -41,7 +42,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private final Map tiles = new HashMap<>(); private final Set entities = new HashSet<>(); - private final char[][] blocks; + private final DataArray[] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; @@ -53,7 +54,7 @@ protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.serverLevel = levelChunk.level; this.minHeight = serverLevel.getMinBuildHeight(); this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.blocks = new char[getSectionCount()][]; + this.blocks = new DataArray[getSectionCount()]; } protected void storeTile(BlockEntity blockEntity) { @@ -168,7 +169,7 @@ public int getSectionCount() { return serverLevel.getSectionsCount(); } - protected void storeSection(int layer, char[] data) { + protected void storeSection(int layer, DataArray data) { blocks[layer] = data; } @@ -205,17 +206,16 @@ public boolean hasSection(int layer) { } @Override - public char[] load(int layer) { + public DataArray load(int layer) { layer -= getMinSectionPosition(); if (blocks[layer] == null) { - blocks[layer] = new char[4096]; - Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + blocks[layer] = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } return blocks[layer]; } @Override - public char[] loadIfPresent(int layer) { + public DataArray loadIfPresent(int layer) { layer -= getMinSectionPosition(); return blocks[layer]; } @@ -248,7 +248,7 @@ public > T call(IChunkSet set, Runnable finalize) { public char get(int x, int y, int z) { final int layer = (y >> 4) - getMinSectionPosition(); final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer][index]; + return (char) blocks[layer].getAt(index); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java index 03eabc6981..d48be13bca 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPlatformAdapter.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -389,7 +390,7 @@ private static List nearbyPlayers(ServerLevel serverLevel, ChunkPo */ public static LevelChunkSection newChunkSection( final int layer, - final char[] blocks, + final DataArray blocks, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes @@ -399,8 +400,8 @@ public static LevelChunkSection newChunkSection( public static LevelChunkSection newChunkSection( final int layer, - final Function get, - char[] set, + final Function get, + DataArray set, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes diff --git a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java index bc094a916f..0c7a04cd26 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_20_5/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R4/PaperweightPostProcessor.java @@ -1,13 +1,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R4; +import com.fastasyncworldedit.bukkit.adapter.PostProcessor; import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.registry.state.PropertyKey; -import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; @@ -16,14 +15,7 @@ import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; -import javax.annotation.Nullable; - -public class PaperweightPostProcessor implements IBatchProcessor { - - @Override - public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - return set; - } +public class PaperweightPostProcessor extends PostProcessor { @SuppressWarnings("deprecation") @Override @@ -36,14 +28,14 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; layer: for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { - char[] set = iChunkSet.loadIfPresent(layer); + DataArray set = iChunkSet.loadIfPresent(layer); if (set == null) { // No edit means no need to process continue; } - char[] get = null; + DataArray get = null; for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; boolean fromGet = false; // Used for liquids if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { @@ -56,7 +48,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh continue layer; } fromGet = true; - ordinal = replacedOrdinal = get[i]; + ordinal = replacedOrdinal = (char) get.getAt(i); } if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { continue; @@ -64,7 +56,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh if (get == null) { get = getBlocks.load(layer); } - replacedOrdinal = get[i]; + replacedOrdinal = (char) get.getAt(i); } boolean ticking = BlockTypesCache.ticking[ordinal]; boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; @@ -104,59 +96,6 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh } } - @Nullable - @Override - public Extent construct(final Extent child) { - throw new UnsupportedOperationException("Processing only"); - } - - @Override - public ProcessorScope getScope() { - return ProcessorScope.READING_SET_BLOCKS; - } - - private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { - if (set == null || get == null) { - return false; - } - char ordinal; - char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; - if (x > 0 && set[i - 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { - return true; - } - } - if (x < 15 && set[i + 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { - return true; - } - } - if (z > 0 && set[i - 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { - return true; - } - } - if (z < 15 && set[i + 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { - return true; - } - } - if (y > 0 && set[i - 256] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { - return true; - } - } - if (y < 15 && set[i + 256] != reserved) { - return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); - } - return false; - } - - @SuppressWarnings("deprecation") - private boolean isFluid(char ordinal) { - return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); - } - @SuppressWarnings("deprecation") private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { Fluid type; diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java index b958c8ba7f..d2698afc89 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/ext/fawe/v1_21_R1/PaperweightAdapter.java @@ -24,6 +24,7 @@ import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.util.concurrent.Futures; import com.mojang.serialization.Codec; diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java index bdd9d0648c..312d58d53f 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks.java @@ -10,7 +10,8 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArrayGetBlocks; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; @@ -87,7 +88,7 @@ import static net.minecraft.core.registries.Registries.BIOME; -public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { +public class PaperweightGetBlocks extends DataArrayGetBlocks implements BukkitGetBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); @@ -497,7 +498,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz ); LevelChunkSection newSection = PaperweightPlatformAdapter.newChunkSection( layerNo, - new char[4096], + DataArray.createEmpty(), adapter, biomeRegistry, biomeData @@ -508,7 +509,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz newSection, getSectionIndex )) { - updateGet(nmsChunk, levelChunkSections, newSection, new char[4096], getSectionIndex); + updateGet(nmsChunk, levelChunkSections, newSection, DataArray.createEmpty(), getSectionIndex); continue; } else { existingSection = levelChunkSections[getSectionIndex]; @@ -538,9 +539,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz // setArr is modified by PaperweightPlatformAdapter#newChunkSection. This is in order to write changes to // this chunk GET when #updateGet is called. Future dords, please listen this time. - char[] tmp = set.load(layerNo); - char[] setArr = new char[tmp.length]; - System.arraycopy(tmp, 0, setArr, 0, tmp.length); + DataArray setArr = DataArray.createCopy(set.load(layerNo)); // synchronise on internal section to avoid circular locking with a continuing edit if the chunk was // submitted to keep loaded internal chunks to queue target size. @@ -554,10 +553,7 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } if (createCopy) { - char[] tmpLoad = loadPrivately(layerNo); - char[] copyArr = new char[4096]; - System.arraycopy(tmpLoad, 0, copyArr, 0, 4096); - copy.storeSection(getSectionIndex, copyArr); + copy.storeSection(getSectionIndex, DataArray.createCopy(loadPrivately(layerNo))); if (biomes != null && existingSection != null) { copy.storeBiomes(getSectionIndex, existingSection.getBiomes()); } @@ -612,10 +608,8 @@ public synchronized > T call(IChunkSet set, Runnable finaliz } else if (existingSection != getSections(false)[getSectionIndex]) { this.sections[getSectionIndex] = existingSection; this.reset(); - } else if (!Arrays.equals( - update(getSectionIndex, new char[4096], true), - loadPrivately(layerNo) - )) { + } else if (! + update(getSectionIndex, DataArray.createEmpty(), true).equals(loadPrivately(layerNo))) { this.reset(layerNo); /*} else if (lock.isModified()) { this.reset(layerNo);*/ @@ -883,7 +877,7 @@ private void updateGet( LevelChunk nmsChunk, LevelChunkSection[] chunkSections, LevelChunkSection section, - char[] arr, + DataArray arr, int layer ) { try { @@ -908,7 +902,7 @@ private void updateGet( this.blocks[layer] = arr; } - private char[] loadPrivately(int layer) { + private DataArray loadPrivately(int layer) { layer -= getMinSectionPosition(); if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { @@ -939,21 +933,14 @@ public void send() { */ @Override @SuppressWarnings("unchecked") - public char[] update(int layer, char[] data, boolean aggressive) { + public DataArray update(int layer, DataArray data, boolean aggressive) { LevelChunkSection section = getSections(aggressive)[layer]; // Section is null, return empty array if (section == null) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - return data; + return DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } - if (data != null && data.length != 4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); - } - if (data == null || data == FaweCache.INSTANCE.EMPTY_CHAR_4096) { - data = new char[4096]; - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + if (data == null || data == FaweCache.INSTANCE.EMPTY_DATA) { + data = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } Semaphore lock = PaperweightPlatformAdapter.applyLock(section); synchronized (lock) { @@ -966,7 +953,7 @@ public char[] update(int layer, char[] data, boolean aggressive) { final BitStorage bits = (BitStorage) PaperweightPlatformAdapter.fieldStorage.get(dataObject); if (bits instanceof ZeroBitStorage) { - Arrays.fill(data, adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper + data.setAll(adapter.adaptToChar(blocks.get(0, 0, 0))); // get(int) is only public on paper return data; } @@ -983,9 +970,9 @@ public char[] update(int layer, char[] data, boolean aggressive) { } else { // The section's palette is the global block palette. for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char ordinal = adapter.ibdIDToOrdinal(paletteVal); - data[i] = ordinal; + data.setAt(i, ordinal); } return data; } @@ -998,17 +985,17 @@ public char[] update(int layer, char[] data, boolean aggressive) { paletteToOrdinal[i] = ordinal; } for (int i = 0; i < 4096; i++) { - char paletteVal = data[i]; + char paletteVal = (char) data.getAt(i); char val = paletteToOrdinal[paletteVal]; if (val == Character.MAX_VALUE) { val = ordinal(palette.valueFor(i), adapter); paletteToOrdinal[i] = val; } - data[i] = val; + data.setAt(i, val); } } else { char ordinal = ordinal(palette.valueFor(0), adapter); - Arrays.fill(data, ordinal); + data.setAll(ordinal); } } finally { for (int i = 0; i < num_palette; i++) { @@ -1182,5 +1169,4 @@ public synchronized boolean trim(boolean aggressive) { return true; } } - } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java index a0a4d02d92..67a47c3bfd 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightGetBlocks_Copy.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.queue.IBlocks; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -41,7 +42,7 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { private final Map tiles = new HashMap<>(); private final Set entities = new HashSet<>(); - private final char[][] blocks; + private final DataArray[] blocks; private final int minHeight; private final int maxHeight; final ServerLevel serverLevel; @@ -53,7 +54,7 @@ protected PaperweightGetBlocks_Copy(LevelChunk levelChunk) { this.serverLevel = levelChunk.level; this.minHeight = serverLevel.getMinBuildHeight(); this.maxHeight = serverLevel.getMaxBuildHeight() - 1; // Minecraft max limit is exclusive. - this.blocks = new char[getSectionCount()][]; + this.blocks = new DataArray[getSectionCount()]; } protected void storeTile(BlockEntity blockEntity) { @@ -168,7 +169,7 @@ public int getSectionCount() { return serverLevel.getSectionsCount(); } - protected void storeSection(int layer, char[] data) { + protected void storeSection(int layer, DataArray data) { blocks[layer] = data; } @@ -205,17 +206,16 @@ public boolean hasSection(int layer) { } @Override - public char[] load(int layer) { + public DataArray load(int layer) { layer -= getMinSectionPosition(); if (blocks[layer] == null) { - blocks[layer] = new char[4096]; - Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + blocks[layer] = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); } return blocks[layer]; } @Override - public char[] loadIfPresent(int layer) { + public DataArray loadIfPresent(int layer) { layer -= getMinSectionPosition(); return blocks[layer]; } @@ -248,7 +248,7 @@ public > T call(IChunkSet set, Runnable finalize) { public char get(int x, int y, int z) { final int layer = (y >> 4) - getMinSectionPosition(); final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer][index]; + return (char) blocks[layer].getAt(index); } diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java index ab55c7814d..cb0b10fac2 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPlatformAdapter.java @@ -8,6 +8,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -374,7 +375,7 @@ private static List nearbyPlayers(ServerLevel serverLevel, ChunkPo */ public static LevelChunkSection newChunkSection( final int layer, - final char[] blocks, + final DataArray blocks, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes @@ -384,8 +385,8 @@ public static LevelChunkSection newChunkSection( public static LevelChunkSection newChunkSection( final int layer, - final Function get, - char[] set, + final Function get, + DataArray set, CachedBukkitAdapter adapter, Registry biomeRegistry, @Nullable PalettedContainer> biomes diff --git a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java index 3b4c47087e..7f8bf08fc9 100644 --- a/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java +++ b/worldedit-bukkit/adapters/adapter-1_21/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_21_R1/PaperweightPostProcessor.java @@ -1,13 +1,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_21_R1; +import com.fastasyncworldedit.bukkit.adapter.PostProcessor; import com.fastasyncworldedit.core.configuration.Settings; -import com.fastasyncworldedit.core.extent.processor.ProcessorScope; -import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.registry.state.PropertyKey; -import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; @@ -16,14 +15,7 @@ import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.Fluids; -import javax.annotation.Nullable; - -public class PaperweightPostProcessor implements IBatchProcessor { - - @Override - public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { - return set; - } +public class PaperweightPostProcessor extends PostProcessor { @SuppressWarnings("deprecation") @Override @@ -36,14 +28,14 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh PaperweightGetBlocks_Copy getBlocks = (PaperweightGetBlocks_Copy) iChunkGet; layer: for (int layer = iChunkSet.getMinSectionPosition(); layer <= iChunkSet.getMaxSectionPosition(); layer++) { - char[] set = iChunkSet.loadIfPresent(layer); + DataArray set = iChunkSet.loadIfPresent(layer); if (set == null) { // No edit means no need to process continue; } - char[] get = null; + DataArray get = null; for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); char replacedOrdinal = BlockTypesCache.ReservedIDs.__RESERVED__; boolean fromGet = false; // Used for liquids if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { @@ -56,7 +48,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh continue layer; } fromGet = true; - ordinal = replacedOrdinal = get[i]; + ordinal = replacedOrdinal = (char) get.getAt(i); } if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { continue; @@ -64,7 +56,7 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh if (get == null) { get = getBlocks.load(layer); } - replacedOrdinal = get[i]; + replacedOrdinal = (char) get.getAt(i); } boolean ticking = BlockTypesCache.ticking[ordinal]; boolean replacedWasTicking = BlockTypesCache.ticking[replacedOrdinal]; @@ -104,59 +96,6 @@ public void postProcess(final IChunk chunk, final IChunkGet iChunkGet, final ICh } } - @Nullable - @Override - public Extent construct(final Extent child) { - throw new UnsupportedOperationException("Processing only"); - } - - @Override - public ProcessorScope getScope() { - return ProcessorScope.READING_SET_BLOCKS; - } - - private boolean wasAdjacentToWater(char[] get, char[] set, int i, int x, int y, int z) { - if (set == null || get == null) { - return false; - } - char ordinal; - char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; - if (x > 0 && set[i - 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 1])] && isFluid(ordinal)) { - return true; - } - } - if (x < 15 && set[i + 1] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 1])] && isFluid(ordinal)) { - return true; - } - } - if (z > 0 && set[i - 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 16])] && isFluid(ordinal)) { - return true; - } - } - if (z < 15 && set[i + 16] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i + 16])] && isFluid(ordinal)) { - return true; - } - } - if (y > 0 && set[i - 256] != reserved) { - if (BlockTypesCache.ticking[(ordinal = get[i - 256])] && isFluid(ordinal)) { - return true; - } - } - if (y < 15 && set[i + 256] != reserved) { - return BlockTypesCache.ticking[(ordinal = get[i + 256])] && isFluid(ordinal); - } - return false; - } - - @SuppressWarnings("deprecation") - private boolean isFluid(char ordinal) { - return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); - } - @SuppressWarnings("deprecation") private void addFluid(final ServerLevel serverLevel, final BlockState replacedState, final BlockPos position) { Fluid type; diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java index 711c0fecc3..7458280ae1 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/NMSAdapter.java @@ -2,6 +2,7 @@ import com.fastasyncworldedit.core.FAWEPlatformAdapterImpl; import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; import com.sk89q.worldedit.world.block.BlockTypesCache; import org.apache.logging.log4j.LogManager; @@ -17,14 +18,14 @@ public static int createPalette( int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy, - char[] set, + DataArray set, CachedBukkitAdapter adapter, short[] nonEmptyBlockCount ) { short nonAir = 4096; int num_palette = 0; for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); switch (ordinal) { case BlockTypesCache.ReservedIDs.__RESERVED__ -> { ordinal = BlockTypesCache.ReservedIDs.AIR; @@ -49,7 +50,7 @@ public static int createPalette( System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length); } for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { ordinal = BlockTypesCache.ReservedIDs.AIR; } @@ -68,16 +69,16 @@ public static int createPalette( int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy, - Function get, - char[] set, + Function get, + DataArray set, CachedBukkitAdapter adapter, short[] nonEmptyBlockCount ) { short nonAir = 4096; int num_palette = 0; - char[] getArr = null; + DataArray getArr = null; for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); switch (ordinal) { case BlockTypesCache.ReservedIDs.__RESERVED__ -> { if (getArr == null) { @@ -85,7 +86,7 @@ public static int createPalette( } // write to set array as this should be a copied array, and will be important when the changes are written // to the GET chunk cached by FAWE. Future dords, actually read this comment please. - set[i] = switch (ordinal = getArr[i]) { + set.setAt(i, switch (ordinal = (char) getArr.getAt(i)) { case BlockTypesCache.ReservedIDs.__RESERVED__ -> { nonAir--; yield (ordinal = BlockTypesCache.ReservedIDs.AIR); @@ -96,7 +97,7 @@ public static int createPalette( yield ordinal; } default -> ordinal; - }; + }); } case BlockTypesCache.ReservedIDs.AIR, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR -> nonAir--; } @@ -117,7 +118,7 @@ public static int createPalette( System.arraycopy(adapter.getOrdinalToIbdID(), 0, blockToPalette, 0, adapter.getOrdinalToIbdID().length); } for (int i = 0; i < 4096; i++) { - char ordinal = set[i]; + char ordinal = (char) set.getAt(i); if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { LOGGER.error("Empty (__RESERVED__) ordinal given where not expected, default to air."); ordinal = BlockTypesCache.ReservedIDs.AIR; diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/PostProcessor.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/PostProcessor.java new file mode 100644 index 0000000000..3f67f81bc2 --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/PostProcessor.java @@ -0,0 +1,78 @@ +package com.fastasyncworldedit.bukkit.adapter; + +import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.queue.IBatchProcessor; +import com.fastasyncworldedit.core.queue.IChunk; +import com.fastasyncworldedit.core.queue.IChunkGet; +import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypesCache; + +import javax.annotation.Nullable; + +/** + * Common code for post-processing on different versions + */ +public abstract class PostProcessor implements IBatchProcessor { + + @Nullable + @Override + public Extent construct(final Extent child) { + throw new UnsupportedOperationException("Processing only"); + } + + protected boolean wasAdjacentToWater(DataArray get, DataArray set, int i, int x, int y, int z) { + if (set == null || get == null) { + return false; + } + char ordinal; + char reserved = BlockTypesCache.ReservedIDs.__RESERVED__; + if (x > 0 && set.getAt(i - 1) != reserved) { + if (BlockTypesCache.ticking[(ordinal = (char) get.getAt(i - 1))] && isFluid(ordinal)) { + return true; + } + } + if (x < 15 && set.getAt(i + 1) != reserved) { + if (BlockTypesCache.ticking[(ordinal = (char) get.getAt(i + 1))] && isFluid(ordinal)) { + return true; + } + } + if (z > 0 && set.getAt(i - 16) != reserved) { + if (BlockTypesCache.ticking[(ordinal = (char) get.getAt(i - 16))] && isFluid(ordinal)) { + return true; + } + } + if (z < 15 && set.getAt(i + 16) != reserved) { + if (BlockTypesCache.ticking[(ordinal = (char) get.getAt(i + 16))] && isFluid(ordinal)) { + return true; + } + } + if (y > 0 && set.getAt(i - 256) != reserved) { + if (BlockTypesCache.ticking[(ordinal = (char) get.getAt(i - 256))] && isFluid(ordinal)) { + return true; + } + } + if (y < 15 && set.getAt(i + 256) != reserved) { + return BlockTypesCache.ticking[(ordinal = (char) get.getAt(i + 256))] && isFluid(ordinal); + } + return false; + } + + @SuppressWarnings("deprecation") + private boolean isFluid(char ordinal) { + return BlockState.getFromOrdinal(ordinal).getMaterial().isLiquid(); + } + + @Override + public ProcessorScope getScope() { + return ProcessorScope.READING_SET_BLOCKS; + } + + @Override + public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChunkSet set) { + return set; + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java index 5265702962..dd2bbb9e8d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java @@ -2,6 +2,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.extent.filter.block.DataArrayFilterBlock; import com.fastasyncworldedit.core.internal.exception.FaweBlockBagException; import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.internal.exception.FaweException.Type; @@ -13,6 +14,7 @@ import com.fastasyncworldedit.core.queue.Pool; import com.fastasyncworldedit.core.queue.Trimable; import com.fastasyncworldedit.core.queue.implementation.QueuePool; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.CleanableThreadLocal; import com.google.common.cache.CacheBuilder; @@ -77,6 +79,16 @@ public enum FaweCache implements Trimable { public final char[] EMPTY_CHAR_4096 = new char[4096]; + /** + * @since TODO + */ + public final DataArray EMPTY_DATA = DataArray.createEmpty(); + + /** + * @since TODO + */ + public final int[] EMPTY_INT_4096 = new int[4096]; + private final IdentityHashMap, Pool> REGISTERED_POOLS = new IdentityHashMap<>(); /* @@ -93,6 +105,7 @@ public synchronized boolean trim(boolean aggressive) { SECTION_BLOCKS.clean(); PALETTE_CACHE.clean(); PALETTE_TO_BLOCK_CHAR.clean(); + PALETTE_TO_BLOCK_INT.clean(); INDEX_STORE.clean(); MUTABLE_VECTOR3.clean(); @@ -144,9 +157,9 @@ public V load(@Nonnull T key) { * from the main thread, it will return a {@link Function} referencing the {@link LoadingCache} returned by * {@link FaweCache#createCache(Supplier)}. If it is called from the main thread, it will return a {@link Function} that * will always return the result of the given {@link Supplier}. It is designed to prevent issues caused by - * internally-mutable and resettable classes such as {@link com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock} + * internally-mutable and resettable classes such as {@link DataArrayFilterBlock} * from causing issues when used in edits on the main thread. - * + *

* This method is designed for specific internal use. * * @param withInitial The supplier used to determine the initial value if a thread cache is created, else to provide a new @@ -257,8 +270,12 @@ public V apply(final long input) { public final CleanableThreadLocal PALETTE_TO_BLOCK_CHAR = new CleanableThreadLocal<>( () -> new char[Character.MAX_VALUE + 1], a -> { Arrays.fill(a, Character.MAX_VALUE); - } - ); + }); + + public final CleanableThreadLocal PALETTE_TO_BLOCK_INT = new CleanableThreadLocal<>( + () -> new int[Character.MAX_VALUE + 1], a -> { + Arrays.fill(a, Integer.MAX_VALUE); + }); public final CleanableThreadLocal BLOCK_STATES = new CleanableThreadLocal<>(() -> new long[2048]); @@ -291,21 +308,10 @@ public static final class Palette { /** * Convert raw char array to palette + * * @return palette */ - public Palette toPalette(int layerOffset, char[] blocks) { - return toPalette(layerOffset, null, blocks); - } - - /** - * Convert raw int array to palette - * @return palette - */ - public Palette toPalette(int layerOffset, int[] blocks) { - return toPalette(layerOffset, blocks, null); - } - - private Palette toPalette(int layerOffset, int[] blocksInts, char[] blocksChars) { + public Palette toPalette(int layerOffset, DataArray blocks) { int[] blockToPalette = BLOCK_TO_PALETTE.get(); int[] paletteToBlock = PALETTE_TO_BLOCK.get(); long[] blockStates = BLOCK_STATES.get(); @@ -315,31 +321,15 @@ private Palette toPalette(int layerOffset, int[] blocksInts, char[] blocksChars) int num_palette = 0; int blockIndexStart = layerOffset << 12; int blockIndexEnd = blockIndexStart + 4096; - 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) { - 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 = BlockTypesCache.states[ordinal]; - blockToPalette[ordinal] = palette = num_palette; - paletteToBlock[num_palette] = ordinal; - num_palette++; - } - blocksCopy[j] = palette; + for (int i = blockIndexStart, j = 0; i < blockIndexEnd; i++, j++) { + int ordinal = blocks.getAt(i); + int palette = blockToPalette[ordinal]; + if (palette == Integer.MAX_VALUE) { + blockToPalette[ordinal] = palette = num_palette; + paletteToBlock[num_palette] = ordinal; + num_palette++; } - } else { - throw new IllegalArgumentException(); + blocksCopy[j] = palette; } for (int i = 0; i < num_palette; i++) { @@ -385,11 +375,7 @@ private Palette toPalette(int layerOffset, int[] blocksInts, char[] blocksChars) * * @return palette */ - public Palette toPaletteUnstretched(int layerOffset, char[] blocks) { - return toPaletteUnstretched(layerOffset, null, blocks); - } - - private Palette toPaletteUnstretched(int layerOffset, int[] blocksInts, char[] blocksChars) { + public Palette toPaletteUnstretched(int layerOffset, DataArray blocks) { int[] blockToPalette = BLOCK_TO_PALETTE.get(); int[] paletteToBlock = PALETTE_TO_BLOCK.get(); long[] blockStates = BLOCK_STATES.get(); @@ -399,31 +385,15 @@ private Palette toPaletteUnstretched(int layerOffset, int[] blocksInts, char[] b int num_palette = 0; int blockIndexStart = layerOffset << 12; int blockIndexEnd = blockIndexStart + 4096; - 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) { - blockToPalette[ordinal] = palette = num_palette; - paletteToBlock[num_palette] = ordinal; - num_palette++; - } - blocksCopy[j] = palette; + for (int i = blockIndexStart, j = 0; i < blockIndexEnd; i++, j++) { + int ordinal = blocks.getAt(i); + int palette = blockToPalette[ordinal]; + if (palette == Integer.MAX_VALUE) { + blockToPalette[ordinal] = palette = num_palette; + paletteToBlock[num_palette] = ordinal; + num_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 = BlockTypesCache.states[ordinal]; - blockToPalette[ordinal] = palette = num_palette; - paletteToBlock[num_palette] = ordinal; - num_palette++; - } - blocksCopy[j] = palette; - } - } else { - throw new IllegalArgumentException(); + blocksCopy[j] = palette; } for (int i = 0; i < num_palette; i++) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java index 2773f0b98a..f6a2844187 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java @@ -6,6 +6,7 @@ import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.ExtentTraverser; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extension.factory.parser.DefaultBlockParser; @@ -29,6 +30,8 @@ import java.util.Set; import java.util.stream.Collectors; +import static com.sk89q.worldedit.world.block.BlockTypesCache.states; + public final class DisallowedBlocksExtent extends AbstractDelegateExtent implements IBatchProcessor { private static final BlockState RESERVED = BlockTypes.__RESERVED__.getDefaultState(); @@ -131,17 +134,17 @@ public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChun if (!set.hasSection(layer)) { continue; } - char[] blocks = Objects.requireNonNull(set.loadIfPresent(layer)); + DataArray blocks = Objects.requireNonNull(set.loadIfPresent(layer)); it: - for (int i = 0; i < blocks.length; i++) { - char block = blocks[i]; + for (int i = 0; i < DataArray.CHUNK_SECTION_SIZE; i++) { + int block = blocks.getAt(i); if (block == BlockTypesCache.ReservedIDs.__RESERVED__) { continue; } BlockState state = BlockTypesCache.states[block]; if (blockedBlocks != null) { if (blockedBlocks.contains(state.getBlockType().id())) { - blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; + blocks.setAt(i, BlockTypesCache.ReservedIDs.__RESERVED__); continue; } } @@ -150,18 +153,18 @@ public IChunkSet processSet(final IChunk chunk, final IChunkGet get, final IChun } for (FuzzyBlockState fuzzy : blockedStates) { if (fuzzy.equalsFuzzy(state)) { - blocks[i] = BlockTypesCache.ReservedIDs.__RESERVED__; + blocks.setAt(i, BlockTypesCache.ReservedIDs.__RESERVED__); continue it; } } if (remaps == null || remaps.isEmpty()) { - blocks[i] = block; + blocks.setAt(i, block); continue; } for (PropertyRemap remap : remaps) { state = remap.apply(state); } - blocks[i] = state.getOrdinalChar(); + blocks.setAt(i, state.getOrdinal()); } } return set; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/DataArrayFilterBlock.java similarity index 89% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java rename to worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/DataArrayFilterBlock.java index 579f04a9a6..4921214839 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/CharFilterBlock.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/filter/block/DataArrayFilterBlock.java @@ -7,7 +7,8 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.implementation.Flood; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArrayGetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; @@ -26,18 +27,18 @@ import static com.sk89q.worldedit.world.block.BlockTypesCache.states; -public class CharFilterBlock extends ChunkFilterBlock { +public class DataArrayFilterBlock extends ChunkFilterBlock { - private static final SetDelegate FULL = (block, value) -> block.setArr[block.index] = value; + private static final SetDelegate FULL = (block, value) -> block.setArr.setAt(block.index, value); private static final SetDelegate NULL = (block, value) -> block.initSet().set(block, value); private int maxLayer; private int minLayer; - private CharGetBlocks get; + private DataArrayGetBlocks get; private IChunkSet set; - private char[] getArr; + private DataArray getArr; @Nullable - private char[] setArr; + private DataArray setArr; private SetDelegate delegate; // local private int layer; @@ -51,7 +52,7 @@ public class CharFilterBlock extends ChunkFilterBlock { private int chunkX; private int chunkZ; - public CharFilterBlock(Extent extent) { + public DataArrayFilterBlock(Extent extent) { super(extent); } @@ -66,12 +67,12 @@ public synchronized final ChunkFilterBlock initChunk(int chunkX, int chunkZ) { @Override public synchronized final ChunkFilterBlock initLayer(IBlocks iget, IChunkSet iset, int layer) { - this.get = (CharGetBlocks) iget; + this.get = (DataArrayGetBlocks) iget; minLayer = this.get.getMinSectionPosition(); maxLayer = this.get.getMaxSectionPosition(); this.layer = layer; if (!iget.hasSection(layer)) { - getArr = FaweCache.INSTANCE.EMPTY_CHAR_4096; + getArr = FaweCache.INSTANCE.EMPTY_DATA; } else { getArr = iget.load(layer); } @@ -230,22 +231,22 @@ public final int getChunkZ() { } public final char getOrdinalChar() { - return getArr[index]; + return (char) getArr.getAt(index); } @Override public final int getOrdinal() { - return getArr[index]; + return getArr.getAt(index); } @Override public void setOrdinal(int ordinal) { - delegate.set(this, (char) ordinal); + delegate.set(this, ordinal); } @Override public final BlockState getBlock() { - final int ordinal = getArr[index]; + final int ordinal = getArr.getAt(index); return BlockTypesCache.states[ordinal]; } @@ -302,7 +303,7 @@ public boolean hasNbtData() { @Override public final BlockState getBlockNorth() { if (z > 0) { - return states[getArr[index - 16]]; + return states[getArr.getAt(index - 16)]; } return getExtent().getBlock(x(), y(), z() - 1); } @@ -310,7 +311,7 @@ public final BlockState getBlockNorth() { @Override public final BlockState getBlockEast() { if (x < 15) { - return states[getArr[index + 1]]; + return states[getArr.getAt(index + 1)]; } return getExtent().getBlock(x() + 1, y(), z()); } @@ -318,7 +319,7 @@ public final BlockState getBlockEast() { @Override public final BlockState getBlockSouth() { if (z < 15) { - return states[getArr[index + 16]]; + return states[getArr.getAt(index + 16)]; } return getExtent().getBlock(x(), y(), z() + 1); } @@ -326,7 +327,7 @@ public final BlockState getBlockSouth() { @Override public final BlockState getBlockWest() { if (x > 0) { - return states[getArr[index - 1]]; + return states[getArr.getAt(index - 1)]; } return getExtent().getBlock(x() - 1, y(), z()); } @@ -334,11 +335,11 @@ public final BlockState getBlockWest() { @Override public final BlockState getBlockBelow() { if (y > 0) { - return states[getArr[index - 256]]; + return states[getArr.getAt(index - 256)]; } if (layer > minLayer) { final int newLayer = layer - 1; - final CharGetBlocks chunk = this.get; + final DataArrayGetBlocks chunk = this.get; return states[chunk.sections[newLayer].get(chunk, newLayer, index + 3840)]; } return BlockTypes.__RESERVED__.getDefaultState(); @@ -347,11 +348,11 @@ public final BlockState getBlockBelow() { @Override public final BlockState getBlockAbove() { if (y < 16) { - return states[getArr[index + 256]]; + return states[getArr.getAt(index + 256)]; } if (layer < maxLayer) { final int newLayer = layer + 1; - final CharGetBlocks chunk = this.get; + final DataArrayGetBlocks chunk = this.get; return states[chunk.sections[newLayer].get(chunk, newLayer, index - 3840)]; } return BlockTypes.__RESERVED__.getDefaultState(); @@ -362,7 +363,7 @@ public final BlockState getBlockRelativeY(int y) { final int newY = this.y + y; final int layerAdd = newY >> 4; if (layerAdd == 0) { - return states[getArr[this.index + (y << 8)]]; + return states[getArr.getAt(this.index + (y << 8))]; } else if ((layerAdd > 0 && layerAdd < (maxLayer - layer)) || (layerAdd < 0 && layerAdd < (minLayer - layer))) { final int newLayer = layer + layerAdd; final int index = this.index + ((y & 15) << 8); @@ -414,7 +415,7 @@ public boolean setBiome(int x, int y, int z, BiomeType biome) { private interface SetDelegate { - void set(@Nonnull CharFilterBlock block, char value); + void set(@Nonnull DataArrayFilterBlock block, int value); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java index 5d8f81e39d..a4fcf908a3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/heightmap/HeightmapProcessor.java @@ -1,11 +1,11 @@ package com.fastasyncworldedit.core.extent.processor.heightmap; -import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; import com.fastasyncworldedit.core.queue.IBatchProcessor; import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; @@ -19,11 +19,10 @@ public class HeightmapProcessor implements IBatchProcessor { private static final int BLOCKS_PER_Y_SHIFT = 8; // log2(256) private static final int BLOCKS_PER_Y = 256; // 16 x 16 private static final boolean[] COMPLETE = new boolean[BLOCKS_PER_Y]; - private static final char[] AIR_LAYER = new char[4096]; + private static final DataArray AIR_LAYER = DataArray.createFilled(BlockTypesCache.ReservedIDs.AIR); static { Arrays.fill(COMPLETE, true); - Arrays.fill(AIR_LAYER, (char) BlockTypesCache.ReservedIDs.AIR); } private final int minY; @@ -59,21 +58,21 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { if (!(hasSectionSet || hasSectionGet)) { continue; } - char[] setSection = hasSectionSet ? set.loadIfPresent(layer) : null; - if (setSection == null || Arrays.equals(setSection, FaweCache.INSTANCE.EMPTY_CHAR_4096) || - Arrays.equals(setSection, AIR_LAYER)) { + DataArray setSection = hasSectionSet ? set.loadIfPresent(layer) : null; + if (setSection == null || setSection.isEmpty() || + setSection.equals(AIR_LAYER)) { hasSectionSet = false; } if (!hasSectionSet && !hasSectionGet) { continue; } - char[] getSection = null; + DataArray getSection = null; for (int y = 15; y >= 0; y--) { // We don't need to actually iterate over x and z as we're both reading and writing an index for (int j = 0; j < BLOCKS_PER_Y; j++) { - char ordinal = BlockTypesCache.ReservedIDs.__RESERVED__; + int ordinal = BlockTypesCache.ReservedIDs.__RESERVED__; if (hasSectionSet) { - ordinal = setSection[index(y, j)]; + ordinal = setSection.getAt(index(y, j)); } if (ordinal == BlockTypesCache.ReservedIDs.__RESERVED__) { if (!hasSectionGet) { @@ -84,8 +83,8 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { } else if (getSection == null) { getSection = get.load(layer); // skip empty layer - if (Arrays.equals(getSection, FaweCache.INSTANCE.EMPTY_CHAR_4096) - || Arrays.equals(getSection, AIR_LAYER)) { + if (getSection.isEmpty() + || getSection.equals(AIR_LAYER)) { hasSectionGet = false; if (!hasSectionSet) { continue layer; @@ -93,28 +92,19 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { continue; } } - ordinal = getSection[index(y, j)]; - } - // fast skip if block isn't relevant for any height map (air or empty) - if (ordinal < 4) { - continue; - } - BlockState block = BlockTypesCache.states[ordinal]; - if (block == null) { - continue; - } - for (int i = 0; i < TYPES.length; i++) { - if ((skip & (1 << i)) != 0) { - continue; // skip finished height map - } - HeightMapType type = TYPES[i]; - // ignore if that position was already set - if (!updated[i][j] && type.includes(block)) { - // mc requires + 1, heightmaps are normalized internally, thus we need to "zero" them. - heightmaps[i][j] = ((layer - get.getMinSectionPosition()) << 4) + y + 1; - updated[i][j] = true; // mark as updated - } + ordinal = getSection.getAt(index(y, j)); } + skipOrUpdateHeightmap( + get, + heightmaps, + updated, + skip, + layer, + y, + j, + BlockTypesCache.states[ordinal], + ordinal + ); } } for (int i = 0; i < updated.length; i++) { @@ -134,6 +124,38 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { return set; } + private void skipOrUpdateHeightmap( + final IChunkGet get, + final int[][] heightmaps, + final boolean[][] updated, + final int skip, + final int layer, + final int y, + final int j, + final BlockState state, + final int ordinal + ) { + // fast skip if block isn't relevant for any height map (air or empty) + if (ordinal < 4) { + return; + } + if (state == null) { + return; + } + for (int i = 0; i < TYPES.length; i++) { + if ((skip & (1 << i)) != 0) { + continue; // skip finished height map + } + HeightMapType type = TYPES[i]; + // ignore if that position was already set + if (!updated[i][j] && type.includes(state)) { + // mc requires + 1, heightmaps are normalized internally, thus we need to "zero" them. + heightmaps[i][j] = ((layer - get.getMinSectionPosition()) << 4) + y + 1; + updated[i][j] = true; // mark as updated + } + } + } + @Override @Nullable public Extent construct(Extent child) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java index 346543a0b8..0decb9ca8d 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/AbstractChangeSet.java @@ -8,6 +8,7 @@ import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.util.concurrent.Futures; @@ -131,7 +132,8 @@ public final synchronized IChunkSet processSet(IChunk chunk, IChunkGet get, IChu BlockState toBlock = set.getBlock(pos.x() & 15, pos.y(), pos.z() & 15); if (fromBlock != toBlock || tilesTo.containsKey(pos)) { addTileRemove(MainUtil.setPosition(entry.getValue(), entry.getKey().x(), entry.getKey().y(), - entry.getKey().z())); + entry.getKey().z() + )); } } } @@ -160,17 +162,18 @@ public final synchronized IChunkSet processSet(IChunk chunk, IChunkGet get, IChu if (!set.hasSection(layer)) { continue; } + // add each block and tile - char[] blocksGet; - char[] tmp = get.load(layer); - if (tmp == null) { - blocksGet = FaweCache.INSTANCE.EMPTY_CHAR_4096; + DataArray blocksGet; + DataArray tmpGet = get.load(layer); + if (tmpGet == null) { + blocksGet = FaweCache.INSTANCE.EMPTY_DATA; } else { - System.arraycopy(tmp, 0, (blocksGet = new char[4096]), 0, 4096); + blocksGet = DataArray.createCopy(tmpGet); } - char[] blocksSet; // loadIfPresent shouldn't be null if set.hasSection(layer) is true - System.arraycopy(Objects.requireNonNull(set.loadIfPresent(layer)), 0, (blocksSet = new char[4096]), 0, 4096); + DataArray tmpSet = Objects.requireNonNull(set.loadIfPresent(layer)); + DataArray blocksSet = DataArray.createCopy(tmpSet); // Account for negative layers int by = layer << 4; @@ -179,10 +182,10 @@ public final synchronized IChunkSet processSet(IChunk chunk, IChunkGet get, IChu for (int z = 0; z < 16; z++) { int zz = z + bz; for (int x = 0; x < 16; x++, index++) { - final int combinedTo = blocksSet[index]; + final int combinedTo = blocksSet.getAt(index); if (combinedTo != BlockTypesCache.ReservedIDs.__RESERVED__) { int xx = bx + x; - int from = blocksGet[index]; + int from = blocksGet.getAt(index); if (from == BlockTypesCache.ReservedIDs.__RESERVED__) { from = BlockTypesCache.ReservedIDs.AIR; } @@ -203,9 +206,9 @@ public final synchronized IChunkSet processSet(IChunk chunk, IChunkGet get, IChu BiomeType[] biomeSection = biomes[layer - set.getMinSectionPosition()]; int index = 0; int yy = layer << 4; - for (int y = 0; y < 16; y+= 4) { - for (int z = 0; z < 16; z+= 4) { - for (int x = 0; x < 16; x+= 4, index++) { + for (int y = 0; y < 16; y += 4) { + for (int z = 0; z < 16; z += 4) { + for (int x = 0; x < 16; x += 4, index++) { BiomeType newBiome = biomeSection[index]; if (newBiome != null) { BiomeType oldBiome = get.getBiomeType(x, yy + y, z); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BitArrayUnstretched.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BitArrayUnstretched.java index 94f1249254..523b1bf3a8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BitArrayUnstretched.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/math/BitArrayUnstretched.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.core.math; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.fastasyncworldedit.core.util.MathMan; public final class BitArrayUnstretched { @@ -108,7 +109,7 @@ public int[] toRaw(int[] buffer) { return buffer; } - public char[] toRaw(char[] buffer) { + public DataArray toRaw(DataArray buffer) { final long[] data = this.data; final int bitsPerEntry = this.bitsPerEntry; final int maxSeqLocIndex = this.maxSeqLocIndex; @@ -118,9 +119,9 @@ public char[] toRaw(char[] buffer) { for (int i = 0; i < longLen; i++) { long l = data[i]; char lastVal; - for (; localStart <= maxSeqLocIndex && arrI < buffer.length; localStart += bitsPerEntry) { + for (; localStart <= maxSeqLocIndex && arrI < DataArray.CHUNK_SECTION_SIZE; localStart += bitsPerEntry) { lastVal = (char) (l >>> localStart & this.mask); - buffer[arrI++] = lastVal; + buffer.setAt(arrI++, lastVal); } localStart = 0; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java index 4ba91a4f38..c770bae755 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBatchProcessor.java @@ -3,6 +3,7 @@ import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.MultiBatchProcessor; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extent.Extent; @@ -68,12 +69,10 @@ default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsid for (int layer = set.getMinSectionPosition(); layer <= minLayer; layer++) { if (set.hasSection(layer)) { if (layer == minLayer) { - char[] arr = set.loadIfPresent(layer); + DataArray arr = set.loadIfPresent(layer); if (arr != null) { int index = (minY & 15) << 8; - for (int i = 0; i < index; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(0, index, BlockTypesCache.ReservedIDs.__RESERVED__); set.setBlocks(layer, arr); } } else { @@ -84,12 +83,10 @@ default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsid for (int layer = maxLayer; layer <= set.getMaxSectionPosition(); layer++) { if (set.hasSection(layer)) { if (layer == maxLayer) { - char[] arr = set.loadIfPresent(layer); + DataArray arr = set.loadIfPresent(layer); if (arr != null) { int index = ((maxY + 1) & 15) << 8; - for (int i = index; i < arr.length; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(index, DataArray.CHUNK_SECTION_SIZE, BlockTypesCache.ReservedIDs.__RESERVED__); set.setBlocks(layer, arr); } } else { @@ -123,21 +120,17 @@ default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsid continue; } if (layer == minLayer) { - char[] arr = set.loadIfPresent(layer); + DataArray arr = set.loadIfPresent(layer); if (arr != null) { int index = (minY & 15) << 8; - for (int i = index; i < 4096; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(index, DataArray.CHUNK_SECTION_SIZE, BlockTypesCache.ReservedIDs.__RESERVED__); } set.setBlocks(layer, arr); } else if (layer == maxLayer) { - char[] arr = set.loadIfPresent(layer); + DataArray arr = set.loadIfPresent(layer); if (arr != null) { int index = ((maxY + 1) & 15) << 8; - for (int i = 0; i < index; i++) { - arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(0, index, BlockTypesCache.ReservedIDs.__RESERVED__); } set.setBlocks(layer, arr); } else { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java index ff6842c0ac..00e38243db 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IBlocks.java @@ -3,6 +3,7 @@ import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; @@ -40,7 +41,7 @@ public interface IBlocks extends Trimable { * @param layer chunk section layer (may be negative) * @return char array of ordinals of the chunk section */ - char[] load(int layer); + DataArray load(int layer); /** * Obtain the specified chunk section stored as an array of ordinals if present or null. Uses normal minecraft chunk-section @@ -50,7 +51,7 @@ public interface IBlocks extends Trimable { * @return char array of ordinals of the chunk section if present */ @Nullable - char[] loadIfPresent(int layer); + DataArray loadIfPresent(int layer); BlockState getBlock(int x, int y, int z); @@ -110,14 +111,14 @@ default byte[] toByteArray(byte[] buffer, int bitMask, boolean full, boolean str continue; } - char[] ids = this.load(layer); + DataArray ids = this.load(layer); int nonEmpty = 0; // TODO optimize into same loop as toPalette - for (int i = 0; i < ids.length; i++) { - char ordinal = ids[i]; + for (int i = 0; i < DataArray.CHUNK_SECTION_SIZE; i++) { + int ordinal = ids.getAt(i); switch (ordinal) { case BlockTypesCache.ReservedIDs.__RESERVED__, BlockTypesCache.ReservedIDs.CAVE_AIR, BlockTypesCache.ReservedIDs.VOID_AIR: - ids[i] = BlockTypesCache.ReservedIDs.AIR; + ids.setAt(i, BlockTypesCache.ReservedIDs.AIR); case BlockTypesCache.ReservedIDs.AIR: continue; default: diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java index bc621e66a5..65c064e4a9 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkSet.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.queue; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.OutputExtent; import com.sk89q.worldedit.function.operation.Operation; @@ -31,7 +32,7 @@ default boolean setBiome(BlockVector3 position, BiomeType biome) { @Override > boolean setBlock(int x, int y, int z, T holder); - void setBlocks(int layer, char[] data); + void setBlocks(int layer, DataArray data); boolean isEmpty(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java index 802561ce9e..d2ba0fbdf8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java @@ -3,7 +3,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.extent.PassthroughExtent; -import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock; +import com.fastasyncworldedit.core.extent.filter.block.DataArrayFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.processor.EmptyBatchProcessor; import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder; @@ -14,7 +14,7 @@ import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IQueueChunk; import com.fastasyncworldedit.core.queue.IQueueExtent; -import com.fastasyncworldedit.core.queue.implementation.blocks.CharSetBlocks; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArraySetBlocks; import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkHolder; import com.fastasyncworldedit.core.queue.implementation.chunk.NullChunk; import com.fastasyncworldedit.core.util.MathMan; @@ -171,7 +171,7 @@ public synchronized void init(Extent extent, IChunkCache get, IChunkC }; } if (set == null) { - set = (x, z) -> CharSetBlocks.newInstance(); + set = (x, z) -> DataArraySetBlocks.newInstance(); } this.cacheGet = get; this.cacheSet = set; @@ -188,6 +188,7 @@ public synchronized void init(Extent extent, IChunkCache get, IChunkC } } + @Override public int size() { return chunks.size() + submissions.size(); @@ -474,7 +475,7 @@ public synchronized void flush() { @Override public ChunkFilterBlock createFilterBlock() { - return new CharFilterBlock(this); + return new DataArrayFilterBlock(this); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java index ae976777c4..931f6e5f00 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/BitSetBlocks.java @@ -53,14 +53,14 @@ public > boolean setBlock(int x, int y, int z, T h } @Override - public void setBlocks(int layer, char[] data) { + public void setBlocks(int layer, final DataArray data) { layer -= minSectionPosition; row.reset(layer); int by = layer << 4; for (int y = 0, index = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++, index++) { - if (data[index] != BlockTypesCache.ReservedIDs.__RESERVED__) { + if (data.getAt(index) != BlockTypesCache.ReservedIDs.__RESERVED__) { row.set(null, x, by + y, z, minSectionPosition, maxSectionPosition); } } @@ -123,9 +123,9 @@ public BlockState getBlock(int x, int y, int z) { } @Override - public char[] load(int layer) { + public DataArray load(int layer) { layer -= minSectionPosition; - char[] arr = FaweCache.INSTANCE.SECTION_BITS_TO_CHAR.get(); + DataArray array = DataArray.createEmpty(); MemBlockSet.IRow nullRowY = row.getRow(layer); if (nullRowY instanceof MemBlockSet.RowY rowY) { char value = blockState.getOrdinalChar(); @@ -135,14 +135,14 @@ public char[] load(int layer) { long bitBuffer = bits[longIndex]; if (bitBuffer != 0) { if (bitBuffer == -1L) { - Arrays.fill(arr, blockIndex, blockIndex + 64, value); + array.setRange(blockIndex, blockIndex + 64, value); continue; } - Arrays.fill(arr, Character.MIN_VALUE); + array.setAll(Character.MIN_VALUE); do { final long lowBit = Long.lowestOneBit(bitBuffer); final int bitIndex = Long.bitCount(lowBit - 1); - arr[blockIndex + bitIndex] = value; + array.setAt(blockIndex + bitIndex, value); bitBuffer = bitBuffer ^ lowBit; } while (bitBuffer != 0); } @@ -150,13 +150,13 @@ public char[] load(int layer) { } } } - return arr; + return array; } // No need to do anything different @Nullable @Override - public char[] loadIfPresent(final int layer) { + public DataArray loadIfPresent(final int layer) { return load(layer); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharDataArray.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharDataArray.java new file mode 100644 index 0000000000..3d30cd1153 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharDataArray.java @@ -0,0 +1,56 @@ +package com.fastasyncworldedit.core.queue.implementation.blocks; + +import com.fastasyncworldedit.core.FaweCache; +import com.sk89q.worldedit.world.block.BlockTypesCache; + +import java.util.Arrays; + +final class CharDataArray implements DataArray { + static final boolean CAN_USE_CHAR_ARRAY = BlockTypesCache.states.length < Character.MAX_VALUE; + private final char[] data; + + public CharDataArray() { + this.data = new char[CHUNK_SECTION_SIZE]; + } + + @Override + public int getAt(final int index) { + return this.data[index]; + } + + @Override + public void setAt(final int index, final int value) { + this.data[index] = (char) value; + } + + @Override + public void setRange(final int start, final int end, final int value) { + Arrays.fill(this.data, start, end, (char) value); + } + + @Override + public void setAll(final int value) { + Arrays.fill(this.data, (char) value); + } + + @Override + public void copyInto(final DataArray other) { + assert other.getClass() == CharDataArray.class; + final char[] otherData = ((CharDataArray) other).data; + System.arraycopy(this.data, 0, otherData, 0, CHUNK_SECTION_SIZE); + } + + @Override + public boolean isEmpty() { + return Arrays.equals(this.data, FaweCache.INSTANCE.EMPTY_CHAR_4096); + } + + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof CharDataArray other)) { + return false; + } + return Arrays.equals(this.data, other.data); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ChunkSectionedChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ChunkSectionedChunk.java new file mode 100644 index 0000000000..90105f7ed9 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ChunkSectionedChunk.java @@ -0,0 +1,45 @@ +package com.fastasyncworldedit.core.queue.implementation.blocks; + +import com.sk89q.worldedit.world.biome.BiomeType; + +public class ChunkSectionedChunk { + + public Object[] sectionLocks; + protected int minSectionPosition; + protected int maxSectionPosition; + protected int sectionCount; + + static BiomeType getBiomeType( + final int x, + final int y, + final int z, + final BiomeType[][] biomes, + final int minSectionPosition, + final int maxSectionPosition + ) { + int layer; + if (biomes == null || (y >> 4) < minSectionPosition || (y >> 4) > maxSectionPosition) { + return null; + } else if (biomes[(layer = (y >> 4) - minSectionPosition)] == null) { + return null; + } + return biomes[layer][(y & 15) >> 2 | (z >> 2) << 2 | x >> 2]; + } + + /** + * Get the number of stored sections + */ + public int getSectionCount() { + return sectionCount; + } + + public int getMaxSectionPosition() { + return maxSectionPosition; + } + + public int getMinSectionPosition() { + return minSectionPosition; + } + + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArray.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArray.java new file mode 100644 index 0000000000..a16d4ae69b --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArray.java @@ -0,0 +1,95 @@ +package com.fastasyncworldedit.core.queue.implementation.blocks; + +/** + * This interface represents the block states stored in a chunk section. + * It provides methods for efficient bulk operations. + */ +public sealed interface DataArray permits CharDataArray, IntDataArray { + + /** + * The amount of entries in a {@link DataArray}. + */ + int CHUNK_SECTION_SIZE = 16 * 16 * 16; + + /** + * Creates a new {@link DataArray} with all entries set to {@code 0}. + * + * @return an empty {@link DataArray}. + */ + static DataArray createEmpty() { + if (CharDataArray.CAN_USE_CHAR_ARRAY) { + return new CharDataArray(); + } + return new IntDataArray(); + } + + /** + * @param value the value to set all entries to. + * {@return a {@link DataArray} with all entries set to the given value} + */ + static DataArray createFilled(int value) { + final DataArray array = createEmpty(); + array.setAll(value); + return array; + } + + /** + * @param other the {@link DataArray} to copy. + * @return a copy of the given {@link DataArray}. + */ + static DataArray createCopy(DataArray other) { + final DataArray array = createEmpty(); + other.copyInto(array); + return array; + } + + /** + * @param index the index to look up. + * @return the value at the given index. + */ + int getAt(int index); + + /** + * Sets the value at the given index to the given value. + * + * @param index the index to set. + * @param value the value to set at the index. + * @throws IndexOutOfBoundsException if {@code index > } {@value CHUNK_SECTION_SIZE} + * or {@code index < 0}. + */ + void setAt(int index, int value); + + /** + * Sets all values in the given range to the given value. + * + * @param start the start of the range to set, inclusive. + * @param end the end of the range to set, exclusive + * @param value the value to set all entries in the given range to. + * @throws IndexOutOfBoundsException if {@code start > } {@value CHUNK_SECTION_SIZE} + * or {@code start < 0} + * or {@code end + 1 > } {@value CHUNK_SECTION_SIZE} + * or {@code end < 0}. + */ + void setRange(int start, int end, int value); + + /** + * Sets all entries to the given value. + * This is equivalent to calling {@link #setRange(int, int, int) setRange(0, CHUNK_SECTION_SIZE, value) } + * + * @param value the value to set all entries to. + */ + void setAll(int value); + + /** + * Copies the data from this array into {@code other}. + * + * @param other the {@link DataArray} to copy the values from this array into. + */ + void copyInto(DataArray other); + + /** + * {@return {@code true} if all values are {@code 0}} + */ + boolean isEmpty(); + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArrayBlocks.java similarity index 76% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java rename to worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArrayBlocks.java index c338033f0a..b2dd857a26 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArrayBlocks.java @@ -10,14 +10,14 @@ import javax.annotation.Nullable; -public abstract class CharBlocks implements IBlocks { +public abstract class DataArrayBlocks extends ChunkSectionedChunk implements IBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); protected static final Section FULL = new Section() { @Override - public char[] get(CharBlocks blocks, int layer) { - char[] arr = blocks.blocks[layer]; + public DataArray get(DataArrayBlocks blocks, int layer) { + DataArray arr = blocks.blocks[layer]; if (arr == null) { // Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues return EMPTY.get(blocks, layer, false); @@ -27,8 +27,8 @@ public char[] get(CharBlocks blocks, int layer) { // Ignore aggressive switch here. @Override - public char[] get(CharBlocks blocks, int layer, boolean aggressive) { - char[] arr = blocks.blocks[layer]; + public DataArray get(DataArrayBlocks blocks, int layer, boolean aggressive) { + DataArray arr = blocks.blocks[layer]; if (arr == null) { // Chunk probably trimmed mid-operations, but do nothing about it to avoid other issues synchronized (blocks.sectionLocks[layer]) { @@ -45,13 +45,13 @@ public boolean isFull() { }; protected static final Section EMPTY = new Section() { @Override - public char[] get(CharBlocks blocks, int layer) { + public DataArray get(DataArrayBlocks blocks, int layer) { // Defaults to aggressive as it should only be avoided where we know we've reset a chunk during an edit return get(blocks, layer, true); } @Override - public char[] get(CharBlocks blocks, int layer, boolean aggressive) { + public DataArray get(DataArrayBlocks blocks, int layer, boolean aggressive) { synchronized (blocks.sectionLocks[layer]) { if (blocks.sections[layer] == FULL) { return FULL.get(blocks, layer); @@ -65,21 +65,17 @@ public boolean isFull() { return false; } }; - public char[][] blocks; + public DataArray[] blocks; public Section[] sections; - public Object[] sectionLocks; - protected int minSectionPosition; - protected int maxSectionPosition; - protected int sectionCount; /** * New instance given initial min/max section indices. Can be negative. */ - public CharBlocks(int minSectionPosition, int maxSectionPosition) { + public DataArrayBlocks(int minSectionPosition, int maxSectionPosition) { this.minSectionPosition = minSectionPosition; this.maxSectionPosition = maxSectionPosition; this.sectionCount = maxSectionPosition - minSectionPosition + 1; - blocks = new char[sectionCount][]; + blocks = new DataArray[sectionCount]; sections = new Section[sectionCount]; sectionLocks = new Object[sectionCount]; for (int i = 0; i < sectionCount; i++) { @@ -130,13 +126,11 @@ public void reset(int layer) { } } - public char[] update(int layer, char[] data, boolean aggressive) { + public DataArray update(int layer, DataArray data, boolean aggressive) { if (data == null) { - return new char[4096]; - } - for (int i = 0; i < 4096; i++) { - data[i] = defaultOrdinal(); + return DataArray.createEmpty(); } + data.setAll(defaultOrdinal()); return data; } @@ -148,7 +142,7 @@ public boolean hasSection(int layer) { } @Override - public char[] load(int layer) { + public DataArray load(int layer) { layer -= minSectionPosition; synchronized (sectionLocks[layer]) { return sections[layer].get(this, layer); @@ -157,7 +151,7 @@ public char[] load(int layer) { @Nullable @Override - public char[] loadIfPresent(int layer) { + public DataArray loadIfPresent(int layer) { if (layer < minSectionPosition || layer > maxSectionPosition) { return null; } @@ -165,27 +159,12 @@ public char[] loadIfPresent(int layer) { return sections[layer].isFull() ? blocks[layer] : null; } - @Override - public int getSectionCount() { - return sectionCount; - } - - @Override - public int getMaxSectionPosition() { - return maxSectionPosition; - } - - @Override - public int getMinSectionPosition() { - return minSectionPosition; - } - @Override public BlockState getBlock(int x, int y, int z) { return BlockTypesCache.states[get(x, y, z)]; } - public char get(int x, int y, int z) { + public int get(int x, int y, int z) { int layer = y >> 4; final int index = (y & 15) << 8 | z << 4 | x; if (layer > maxSectionPosition || layer < minSectionPosition) { @@ -200,7 +179,7 @@ public char get(int x, int y, int z) { protected abstract char defaultOrdinal(); // Not synchronized as it refers to a synchronized method and includes nothing that requires synchronization - public void set(int x, int y, int z, char value) { + public void set(int x, int y, int z, int value) { final int layer = y >> 4; final int index = (y & 15) << 8 | z << 4 | x; try { @@ -216,41 +195,41 @@ public void set(int x, int y, int z, char value) { Section */ - public final char get(int layer, int index) { + public final int get(int layer, int index) { return sections[layer - minSectionPosition].get(this, layer, index); } - public final void set(int layer, int index, char value) throws ArrayIndexOutOfBoundsException { + public final void set(int layer, int index, int value) throws ArrayIndexOutOfBoundsException { sections[layer - minSectionPosition].set(this, layer, index, value); } public abstract static class Section { - abstract char[] get(CharBlocks blocks, int layer); + abstract DataArray get(DataArrayBlocks blocks, int layer); - abstract char[] get(CharBlocks blocks, int layer, boolean aggressive); + abstract DataArray get(DataArrayBlocks blocks, int layer, boolean aggressive); public abstract boolean isFull(); - public final char get(CharBlocks blocks, int layer, int index) { + public final int get(DataArrayBlocks blocks, int layer, int index) { int normalized = layer - blocks.minSectionPosition; - char[] section = get(blocks, normalized); + DataArray section = get(blocks, normalized); if (section == null) { synchronized (blocks.sectionLocks[normalized]) { blocks.reset(layer); section = EMPTY.get(blocks, normalized, false); } } - return section[index]; + return section.getAt(index); } - public final synchronized void set(CharBlocks blocks, int layer, int index, char value) { + public final synchronized void set(DataArrayBlocks blocks, int layer, int index, int value) { layer -= blocks.minSectionPosition; - get(blocks, layer)[index] = value; + get(blocks, layer).setAt(index, value); } - static char[] getSkipFull(CharBlocks blocks, int layer, boolean aggressive) { - char[] arr = blocks.blocks[layer]; + static DataArray getSkipFull(DataArrayBlocks blocks, int layer, boolean aggressive) { + DataArray arr = blocks.blocks[layer]; if (arr == null) { arr = blocks.blocks[layer] = blocks.update(layer, null, aggressive); if (arr == null) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArrayGetBlocks.java similarity index 78% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java rename to worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArrayGetBlocks.java index 2c89a71080..3a0025291e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArrayGetBlocks.java @@ -6,14 +6,12 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; -import java.util.Arrays; - -public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { +public abstract class DataArrayGetBlocks extends DataArrayBlocks implements IChunkGet { /** * New instance given the min/max section indices */ - public CharGetBlocks(final int minSectionPosition, final int maxSectionPosition) { + public DataArrayGetBlocks(final int minSectionPosition, final int maxSectionPosition) { super(minSectionPosition, maxSectionPosition); } @@ -33,11 +31,11 @@ public synchronized boolean trim(boolean aggressive) { } @Override - public char[] update(int layer, char[] data, boolean aggressive) { + public DataArray update(int layer, DataArray data, boolean aggressive) { if (data == null) { - data = new char[4096]; + data = DataArray.createEmpty(); } - Arrays.fill(data, (char) BlockTypesCache.ReservedIDs.AIR); + data.setAll(BlockTypesCache.ReservedIDs.AIR); return data; } @@ -59,5 +57,4 @@ public IChunkSet reset() { super.reset(); return null; } - } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArraySetBlocks.java similarity index 93% rename from worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java rename to worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArraySetBlocks.java index da28e59254..889532a708 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/DataArraySetBlocks.java @@ -21,15 +21,15 @@ import java.util.Set; import java.util.UUID; -public class CharSetBlocks extends CharBlocks implements IChunkSet { +public class DataArraySetBlocks extends DataArrayBlocks implements IChunkSet { - private static final Pool POOL = FaweCache.INSTANCE.registerPool( - CharSetBlocks.class, - CharSetBlocks::new, + private static final Pool POOL = FaweCache.INSTANCE.registerPool( + DataArraySetBlocks.class, + DataArraySetBlocks::new, Settings.settings().QUEUE.POOL ); - public static CharSetBlocks newInstance() { + public static DataArraySetBlocks newInstance() { return POOL.poll(); } @@ -43,7 +43,7 @@ public static CharSetBlocks newInstance() { private boolean fastMode = false; private int bitMask = -1; - private CharSetBlocks() { + private DataArraySetBlocks() { // Expand as we go super(0, 15); } @@ -61,13 +61,7 @@ public BiomeType[][] getBiomes() { @Override public BiomeType getBiomeType(int x, int y, int z) { - int layer; - if (biomes == null || (y >> 4) < minSectionPosition || (y >> 4) > maxSectionPosition) { - return null; - } else if (biomes[(layer = (y >> 4) - minSectionPosition)] == null) { - return null; - } - return biomes[layer][(y & 15) >> 2 | (z >> 2) << 2 | x >> 2]; + return getBiomeType(x, y, z, biomes, minSectionPosition, maxSectionPosition); } @Override @@ -118,7 +112,7 @@ public > boolean setBlock(int x, int y, int z, T h } @Override - public void setBlocks(int layer, char[] data) { + public void setBlocks(int layer, final DataArray data) { updateSectionIndexRange(layer); layer -= minSectionPosition; this.sections[layer] = data == null ? EMPTY : FULL; @@ -337,11 +331,10 @@ public boolean hasBiomes(int layer) { @Override public ThreadUnsafeCharBlocks createCopy() { - char[][] blocksCopy = new char[sectionCount][]; + DataArray[] blocksCopy = new DataArray[sectionCount]; for (int i = 0; i < sectionCount; i++) { if (blocks[i] != null) { - blocksCopy[i] = new char[FaweCache.INSTANCE.BLOCKS_PER_LAYER]; - System.arraycopy(blocks[i], 0, blocksCopy[i], 0, FaweCache.INSTANCE.BLOCKS_PER_LAYER); + blocksCopy[i] = DataArray.createCopy(blocks[i]); } } BiomeType[][] biomesCopy; @@ -392,7 +385,7 @@ static char[][] createLightCopy(char[][] lightArr, int sectionCount) { } @Override - public char[] load(final int layer) { + public DataArray load(final int layer) { updateSectionIndexRange(layer); return super.load(layer); } @@ -421,7 +414,7 @@ private void updateSectionIndexRange(int layer) { } private void resizeSectionsArrays(int diff, boolean appendNew) { - char[][] tmpBlocks = new char[sectionCount][]; + DataArray[] tmpBlocks = new DataArray[sectionCount]; Section[] tmpSections = new Section[sectionCount]; Object[] tmpSectionLocks = new Object[sectionCount]; int destPos = appendNew ? 0 : diff; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/IntDataArray.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/IntDataArray.java new file mode 100644 index 0000000000..2d10dd703c --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/IntDataArray.java @@ -0,0 +1,54 @@ +package com.fastasyncworldedit.core.queue.implementation.blocks; + +import com.fastasyncworldedit.core.FaweCache; + +import java.util.Arrays; + +final class IntDataArray implements DataArray { + private final int[] data; + + public IntDataArray() { + this.data = new int[CHUNK_SECTION_SIZE]; + } + + @Override + public int getAt(final int index) { + return this.data[index]; + } + + @Override + public void setAt(final int index, final int value) { + this.data[index] = value; + } + + @Override + public void setRange(final int start, final int end, final int value) { + Arrays.fill(this.data, start, end, value); + } + + @Override + public void setAll(final int value) { + Arrays.fill(this.data, value); + } + + @Override + public void copyInto(final DataArray other) { + assert other.getClass() == IntDataArray.class; + final int[] otherData = ((IntDataArray) other).data; + System.arraycopy(this.data, 0, otherData, 0, CHUNK_SECTION_SIZE); + } + + @Override + public boolean isEmpty() { + return Arrays.equals(this.data, FaweCache.INSTANCE.EMPTY_INT_4096); + } + + @Override + public boolean equals(final Object obj) { + if (!(obj instanceof IntDataArray other)) { + return false; + } + return Arrays.equals(this.data, other.data); + } + +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java index 0428706660..49923afc5b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java @@ -124,13 +124,13 @@ public > T call(@Nonnull IChunkSet set, @Nonnull Runnable fi } @Nonnull - public char[] load(int layer) { - return FaweCache.INSTANCE.EMPTY_CHAR_4096; + public DataArray load(int layer) { + return FaweCache.INSTANCE.EMPTY_DATA; } @Nullable @Override - public char[] loadIfPresent(final int layer) { + public DataArray loadIfPresent(final int layer) { return null; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java index 90ae6b32e9..7b459405fa 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/ThreadUnsafeCharBlocks.java @@ -1,7 +1,6 @@ package com.fastasyncworldedit.core.queue.implementation.blocks; import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.extent.processor.heightmap.HeightMapType; import com.fastasyncworldedit.core.math.BlockVector3ChunkMap; import com.fastasyncworldedit.core.queue.IBlocks; @@ -26,8 +25,8 @@ import java.util.UUID; /** - * Equivalent to {@link CharSetBlocks} without any attempt to make thread-safe for improved performance. - * This is currently only used as a "copy" of {@link CharSetBlocks} to provide to + * Equivalent to {@link DataArraySetBlocks} without any attempt to make thread-safe for improved performance. + * This is currently only used as a "copy" of {@link DataArraySetBlocks} to provide to * {@link com.fastasyncworldedit.core.queue.IBatchProcessor} instances for processing without overlapping the continuing edit. * * @since 2.6.2 @@ -37,7 +36,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { private static final Logger LOGGER = LogManagerCompat.getLogger(); private final char defaultOrdinal; - private char[][] blocks; + private DataArray[] blocks; private int minSectionPosition; private int maxSectionPosition; private int sectionCount; @@ -52,12 +51,12 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { private int bitMask; /** - * New instance given the data stored in a {@link CharSetBlocks} instance. + * New instance given the data stored in a {@link DataArraySetBlocks} instance. * * @since 2.6.2 */ ThreadUnsafeCharBlocks( - char[][] blocks, + DataArray[] blocks, int minSectionPosition, int maxSectionPosition, BiomeType[][] biomes, @@ -91,23 +90,23 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks { @Override public boolean hasSection(int layer) { layer -= minSectionPosition; - return layer >= 0 && layer < blocks.length && blocks[layer] != null && blocks[layer].length == FaweCache.INSTANCE.BLOCKS_PER_LAYER; + return layer >= 0 && layer < blocks.length && blocks[layer] != null; } @Override - public char[] load(int layer) { + public DataArray load(int layer) { updateSectionIndexRange(layer); layer -= minSectionPosition; - char[] arr = blocks[layer]; + DataArray arr = blocks[layer]; if (arr == null) { - arr = blocks[layer] = new char[FaweCache.INSTANCE.BLOCKS_PER_LAYER]; + arr = blocks[layer] = DataArray.createEmpty(); } return arr; } @Nullable @Override - public char[] loadIfPresent(int layer) { + public DataArray loadIfPresent(int layer) { if (layer < minSectionPosition || layer > maxSectionPosition) { return null; } @@ -183,18 +182,12 @@ public char get(int x, int y, int z) { return defaultOrdinal; } final int index = (y & 15) << 8 | z << 4 | x; - return blocks[layer - minSectionPosition][index]; + return (char) blocks[layer - minSectionPosition].getAt(index); } @Override public BiomeType getBiomeType(int x, int y, int z) { - int layer; - if (biomes == null || (y >> 4) < minSectionPosition || (y >> 4) > maxSectionPosition) { - return null; - } else if (biomes[(layer = (y >> 4) - minSectionPosition)] == null) { - return null; - } - return biomes[layer][(y & 15) >> 2 | (z >> 2) << 2 | x >> 2]; + return ChunkSectionedChunk.getBiomeType(x, y, z, biomes, minSectionPosition, maxSectionPosition); } @Override @@ -225,7 +218,7 @@ public void set(int x, int y, int z, char value) { final int layer = (y >> 4) - minSectionPosition; final int index = (y & 15) << 8 | z << 4 | x; try { - blocks[layer][index] = value; + blocks[layer].setAt(index, value); } catch (ArrayIndexOutOfBoundsException exception) { LOGGER.error("Tried setting block at coordinates (" + x + "," + y + "," + z + ")"); assert Fawe.platform() != null; @@ -242,7 +235,7 @@ public > boolean setBlock(int x, int y, int z, T h } @Override - public void setBlocks(int layer, char[] data) { + public void setBlocks(int layer, DataArray data) { updateSectionIndexRange(layer); layer -= minSectionPosition; this.blocks[layer] = data; @@ -425,7 +418,7 @@ public boolean hasLight() { @Override public IChunkSet reset() { - blocks = new char[sectionCount][]; + blocks = new DataArray[sectionCount]; biomes = new BiomeType[sectionCount][]; light = new char[sectionCount][]; skyLight = new char[sectionCount][]; @@ -444,11 +437,12 @@ public boolean hasBiomes(int layer) { @Override public IChunkSet createCopy() { - char[][] blocksCopy = new char[sectionCount][]; + DataArray[] blocksCopy = new DataArray[sectionCount]; for (int i = 0; i < sectionCount; i++) { - blocksCopy[i] = new char[FaweCache.INSTANCE.BLOCKS_PER_LAYER]; if (blocks[i] != null) { - System.arraycopy(blocks[i], 0, blocksCopy[i], 0, FaweCache.INSTANCE.BLOCKS_PER_LAYER); + blocksCopy[i] = DataArray.createCopy(blocks[i]); + } else { + blocksCopy[i] = DataArray.createEmpty(); } } BiomeType[][] biomesCopy; @@ -463,8 +457,8 @@ public IChunkSet createCopy() { } } } - char[][] lightCopy = CharSetBlocks.createLightCopy(light, sectionCount); - char[][] skyLightCopy = CharSetBlocks.createLightCopy(skyLight, sectionCount); + char[][] lightCopy = DataArraySetBlocks.createLightCopy(light, sectionCount); + char[][] skyLightCopy = DataArraySetBlocks.createLightCopy(skyLight, sectionCount); return new ThreadUnsafeCharBlocks( blocksCopy, minSectionPosition, @@ -507,7 +501,7 @@ private void updateSectionIndexRange(int layer) { } private void resizeSectionsArrays(int layer, int diff, boolean appendNew) { - char[][] tmpBlocks = new char[sectionCount][]; + DataArray[] tmpBlocks = new DataArray[sectionCount]; int destPos = appendNew ? 0 : diff; System.arraycopy(blocks, 0, tmpBlocks, destPos, blocks.length); blocks = tmpBlocks; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java index a7417eddf5..899156b236 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java @@ -11,6 +11,7 @@ import com.fastasyncworldedit.core.queue.IQueueExtent; import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent; import com.fastasyncworldedit.core.util.MemUtil; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.math.BlockVector3; @@ -117,18 +118,18 @@ public char[][] getSkyLight() { } @Override - public void setBlocks(int layer, char[] data) { + public void setBlocks(int layer, DataArray data) { delegate.set(this).setBlocks(layer, data); } @Override - public char[] load(int layer) { + public DataArray load(int layer) { return getOrCreateGet().load(layer); } @Nullable @Override - public char[] loadIfPresent(final int layer) { + public DataArray loadIfPresent(final int layer) { if (chunkExisting == null) { return null; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java index 8cc6471ba3..9af58ddf62 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java @@ -5,6 +5,7 @@ import com.fastasyncworldedit.core.queue.Filter; import com.fastasyncworldedit.core.queue.IChunkSet; import com.fastasyncworldedit.core.queue.IQueueChunk; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; @@ -130,7 +131,8 @@ public > boolean setBlock(int x, int y, int z, T h return false; } - public void setBlocks(int layer, @Nonnull char[] data) { + @Override + public void setBlocks(int layer, @Nonnull DataArray data) { } @Nullable @@ -168,13 +170,13 @@ public Set getEntities() { } @Nullable - public char[] load(int layer) { + public DataArray load(int layer) { return null; } @Nullable @Override - public char[] loadIfPresent(final int layer) { + public DataArray loadIfPresent(final int layer) { return null; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java index 0abc801536..4c5b3f63c1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java @@ -20,7 +20,7 @@ package com.sk89q.worldedit.extent; import com.fastasyncworldedit.core.FaweCache; -import com.fastasyncworldedit.core.extent.filter.block.CharFilterBlock; +import com.fastasyncworldedit.core.extent.filter.block.DataArrayFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock; import com.fastasyncworldedit.core.extent.filter.block.FilterBlock; import com.fastasyncworldedit.core.extent.processor.ProcessorScope; @@ -60,7 +60,7 @@ public MaskingExtent(Extent extent, Mask mask) { checkNotNull(mask); this.mask = mask; //FAWE start - this.getOrCreateFilterBlock = FaweCache.INSTANCE.createMainThreadSafeCache(() -> new CharFilterBlock(getExtent())); + this.getOrCreateFilterBlock = FaweCache.INSTANCE.createMainThreadSafeCache(() -> new DataArrayFilterBlock(getExtent())); //FAWE end } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index 4b0894d918..bc9a5e822d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -27,6 +27,7 @@ import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.World; @@ -831,7 +832,7 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { if (!set.hasSection(layer)) { continue; } - char[] arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true + DataArray arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true int indexY = 0; for (int y = 0; y < 16; y++, indexY += 256) { // For each y layer within a chunk section int index; @@ -839,34 +840,26 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { index = indexY; for (int z = 0; z < lowerZ; z++) { // null the z values - for (int x = 0; x < 16; x++, index++) { - arr[index] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(index, index += 16, BlockTypesCache.ReservedIDs.__RESERVED__); } index = indexY + upperZi; for (int z = upperZ + 1; z < 16; z++) { // null the z values - for (int x = 0; x < 16; x++, index++) { - arr[index] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(index, index += 16, BlockTypesCache.ReservedIDs.__RESERVED__); } } if (trimX) { index = indexY + lowerZi; // Skip blocks already removed by trimZ for (int z = lowerZ; z <= upperZ; z++, index += 16) { - for (int x = 0; x < lowerX; x++) { - // null the x values - arr[index + x] = BlockTypesCache.ReservedIDs.__RESERVED__; - } - for (int x = upperX + 1; x < 16; x++) { - // null the x values - arr[index + x] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + // null the x values + arr.setRange(index, index + lowerX, BlockTypesCache.ReservedIDs.__RESERVED__); + arr.setRange(index + upperX + 1, index + upperX + 16, BlockTypesCache.ReservedIDs.__RESERVED__); } } } set.setBlocks(layer, arr); } + final BlockVector3 chunkPos = BlockVector3.at(chunk.getX() << 4, 0, chunk.getZ() << 4); trimNBT(set, this::contains, pos -> this.contains(pos.add(chunkPos))); return set; @@ -915,7 +908,7 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean if (!set.hasSection(layer)) { continue; } - char[] arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true + DataArray arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true if (!(trimX || trimZ)) { continue; } @@ -926,18 +919,14 @@ public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean index = indexY; for (int z = lowerZ; z <= upperZ; z++) { // null the z values - for (int x = 0; x < 16; x++, index++) { - arr[index] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + arr.setRange(index, index += 16, BlockTypesCache.ReservedIDs.__RESERVED__); } } if (trimX) { index = indexY + lowerZi; // Skip blocks already removed by trimZ for (int z = lowerZ; z <= upperZ; z++, index += 16) { - for (int x = lowerX; x <= upperX; x++) { - // null the x values - arr[index + x] = BlockTypesCache.ReservedIDs.__RESERVED__; - } + // null the x values + arr.setRange(index + lowerX, index + upperX + 1, BlockTypesCache.ReservedIDs.__RESERVED__); } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java index 085274772c..8cdaa6da2e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/Region.java @@ -29,6 +29,7 @@ import com.fastasyncworldedit.core.queue.IChunk; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkSet; +import com.fastasyncworldedit.core.queue.implementation.blocks.DataArray; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.Extent; @@ -407,20 +408,11 @@ default IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { int ty = by + 15; if (!containsEntireCuboid(bx, tx, by, ty, bz, tz)) { processExtra = true; - char[] arr = set.loadIfPresent(layer); + DataArray arr = set.loadIfPresent(layer); if (arr == null) { continue; } - for (int y = 0, index = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, index++) { - if (arr[index] != BlockTypesCache.ReservedIDs.__RESERVED__ && !contains(bx + x, by + y, bz + z)) { - arr[index] = BlockTypesCache.ReservedIDs.__RESERVED__; - } - } - } - } - set.setBlocks(layer, arr); + processCuboid(set, layer, arr); } } if (processExtra) { @@ -433,6 +425,19 @@ default IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { } } + private void processCuboid(IChunkSet set, int layer, DataArray dataArray) { + for (int y = 0, index = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++, index++) { + if (dataArray.getAt(index) != BlockTypesCache.ReservedIDs.__RESERVED__ && !contains(x, y, z)) { + dataArray.setAt(index, BlockTypesCache.ReservedIDs.__RESERVED__); + } + } + } + } + set.setBlocks(layer, dataArray); + } + /** * Process the chunk, with the option to process as if the region is a blacklisted region, and thus any contained blocks * should be removed, rather than uncontained blocks being removed. @@ -457,24 +462,11 @@ default IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean int by = layer << 4; int ty = by + 15; if (containsEntireCuboid(bx, tx, by, ty, bz, tz)) { - set.setBlocks(layer, FaweCache.INSTANCE.EMPTY_CHAR_4096); + set.setBlocks(layer, FaweCache.INSTANCE.EMPTY_DATA); processExtra = true; continue; } - char[] arr = set.load(layer); - for (int y = 0, index = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++, index++) { - if (arr[index] != BlockTypesCache.ReservedIDs.__RESERVED__ && contains(x, y, z)) { - arr[index] = BlockTypesCache.ReservedIDs.__RESERVED__; - processExtra = true; - } - } - } - } - if (processExtra) { - set.setBlocks(layer, arr); - } + processExtra = isProcessExtra(set, processExtra, layer, set.load(layer)); } if (processExtra) { BlockVector3 chunkPos = chunk.getChunkBlockCoord().withY(0); @@ -486,6 +478,23 @@ default IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean } } + private boolean isProcessExtra(IChunkSet set, boolean processExtra, int layer, DataArray arr) { + for (int y = 0, index = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++, index++) { + if (arr.getAt(index) != BlockTypesCache.ReservedIDs.__RESERVED__ && contains(x, y, z)) { + arr.setAt(index, BlockTypesCache.ReservedIDs.__RESERVED__); + processExtra = true; + } + } + } + } + if (processExtra) { + set.setBlocks(layer, arr); + } + return processExtra; + } + @Override default Extent construct(Extent child) { if (isGlobal()) {