From a2b0a5e6225e0530e0695e0b4c421db6c679163c Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 7 May 2020 19:38:42 +0100 Subject: [PATCH 01/27] Fix offset mask (< and >) --- .../java/com/sk89q/worldedit/function/mask/OffsetMask.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java index 5fab17454..d6a3dc7f6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java @@ -88,7 +88,11 @@ public class OffsetMask extends AbstractMask { @Override public boolean test(Extent extent, BlockVector3 pos) { - return getMask().test(extent, pos); + BlockVector3 testPos = pos.add(offset); + if (testPos.getBlockY() < 0 || testPos.getBlockY() > 255) { + return false; + } + return getMask().test(extent, pos.add(offset)); } @Nullable From 56972ee40b7b59bfa8d427c8b00e82432dc86fa4 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 7 May 2020 23:00:13 +0100 Subject: [PATCH 02/27] Trim performance (#451) * Increase performance slightly when trimming. If the chunk section is all one blocks (common in plotworlds) it'll be a nice little boost. * Cache whether blocks are ticking or not. Greatly reduces the time required to create a palette * collapse 5 lines to 2. * Also apply to 14 and 15 for the numpties * Cleanup Actually ignore the exception - remove my debug print. Remove double semi-colon * Apparently 1.14/15 matter too still. --- .../fawe/bukkit/adapter/NMSAdapter.java | 15 +++++++-- .../adapter/mc1_14/BukkitGetBlocks_1_14.java | 33 ++++++++++++++++++- .../adapter/mc1_15/BukkitGetBlocks_1_15.java | 33 ++++++++++++++++++- .../mc1_15_2/BukkitGetBlocks_1_15_2.java | 33 ++++++++++++++++++- .../com/boydti/fawe/beta/CombinedBlocks.java | 5 +++ .../java/com/boydti/fawe/beta/IBlocks.java | 2 ++ .../implementation/blocks/BitSetBlocks.java | 5 +++ .../implementation/blocks/CharBlocks.java | 11 +++++++ .../implementation/blocks/CharGetBlocks.java | 7 ++++ .../blocks/FallbackChunkGet.java | 5 +++ .../implementation/blocks/NullChunkGet.kt | 4 +++ .../implementation/chunk/ChunkHolder.java | 5 +++ .../beta/implementation/chunk/NullChunk.kt | 4 +++ .../processors/BatchProcessorHolder.java | 1 - .../com/boydti/fawe/jnbt/anvil/MCAChunk.java | 5 +++ .../world/block/BlockTypesCache.java | 13 +++++--- 16 files changed, 171 insertions(+), 10 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java index 38284966c..e15a8a9c5 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java @@ -4,6 +4,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockID; import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockTypesCache; import java.util.Map; import java.util.function.Function; @@ -49,6 +50,8 @@ public class NMSAdapter { int air = 0; int num_palette = 0; char[] getArr = null; + char lastOrdinal = BlockID.__RESERVED__; + boolean lastticking = false; for (int i = 0; i < 4096; i++) { char ordinal = set[i]; switch (ordinal) { @@ -75,8 +78,16 @@ public class NMSAdapter { air++; break; } - BlockState state = BlockState.getFromOrdinal(ordinal); - if (state.getMaterial().isTicksRandomly()) { + boolean ticking; + if (ordinal != lastOrdinal) { + ticking = BlockTypesCache.ticking[ordinal]; + lastOrdinal = ordinal; + lastticking = ticking; + } else { + ticking = lastticking; + } + if (ticking) { + BlockState state = BlockState.getFromOrdinal(ordinal); ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), WorldEditPlugin.getInstance().getBukkitImplAdapter() .getInternalBlockStateId(state).orElse(0)); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java index 6514b8053..bbe859074 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java @@ -5,6 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.IChunkSet; +import com.boydti.fawe.beta.implementation.blocks.CharBlocks; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.DelegateLock; @@ -620,7 +621,37 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { if (aggressive) { sections = null; nmsChunk = null; + return super.trim(true); + } else { + for (int i = 0; i < 16; i++) { + if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { + continue; + } + ChunkSection existing = getSections()[i]; + try { + final DataPaletteBlock blocksExisting = existing.getBlocks(); + + final DataPalette palette = (DataPalette) BukkitAdapter_1_14.fieldPalette.get(blocksExisting); + int paletteSize; + + if (palette instanceof DataPaletteLinear) { + paletteSize = ((DataPaletteLinear) palette).b(); + } else if (palette instanceof DataPaletteHash) { + paletteSize = ((DataPaletteHash) palette).b(); + } else { + super.trim(false, i); + continue; + } + if (paletteSize == 1) { + //If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks. + continue; + } + super.trim(false, i); + } catch (IllegalAccessException ignored) { + super.trim(false, i); + } + } + return true; } - return super.trim(aggressive); } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java index 8f05ad098..63b04265e 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java @@ -5,6 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.IChunkSet; +import com.boydti.fawe.beta.implementation.blocks.CharBlocks; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.DelegateLock; @@ -640,7 +641,37 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { if (aggressive) { sections = null; nmsChunk = null; + return super.trim(true); + } else { + for (int i = 0; i < 16; i++) { + if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { + continue; + } + ChunkSection existing = getSections()[i]; + try { + final DataPaletteBlock blocksExisting = existing.getBlocks(); + + final DataPalette palette = (DataPalette) BukkitAdapter_1_15.fieldPalette.get(blocksExisting); + int paletteSize; + + if (palette instanceof DataPaletteLinear) { + paletteSize = ((DataPaletteLinear) palette).b(); + } else if (palette instanceof DataPaletteHash) { + paletteSize = ((DataPaletteHash) palette).b(); + } else { + super.trim(false, i); + continue; + } + if (paletteSize == 1) { + //If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks. + continue; + } + super.trim(false, i); + } catch (IllegalAccessException ignored) { + super.trim(false, i); + } + } + return true; } - return super.trim(aggressive); } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index cd4d6bc2a..8056f6e21 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.adapter.mc1_15_2; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.IChunkSet; +import com.boydti.fawe.beta.implementation.blocks.CharBlocks; import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.DelegateLock; @@ -644,7 +645,37 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { if (aggressive) { sections = null; nmsChunk = null; + return super.trim(true); + } else { + for (int i = 0; i < 16; i++) { + if (!hasSection(i) || super.sections[i] == CharBlocks.EMPTY) { + continue; + } + ChunkSection existing = getSections()[i]; + try { + final DataPaletteBlock blocksExisting = existing.getBlocks(); + + final DataPalette palette = (DataPalette) BukkitAdapter_1_15_2.fieldPalette.get(blocksExisting); + int paletteSize; + + if (palette instanceof DataPaletteLinear) { + paletteSize = ((DataPaletteLinear) palette).b(); + } else if (palette instanceof DataPaletteHash) { + paletteSize = ((DataPaletteHash) palette).b(); + } else { + super.trim(false, i); + continue; + } + if (paletteSize == 1) { + //If the cached palette size is 1 then no blocks can have been changed i.e. do not need to update these chunks. + continue; + } + super.trim(false, i); + } catch (IllegalAccessException ignored) { + super.trim(false, i); + } + } + return true; } - return super.trim(aggressive); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java index 0915fed10..b5ae0014e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java @@ -145,4 +145,9 @@ public class CombinedBlocks implements IBlocks { public boolean trim(boolean aggressive) { return false; } + + @Override + public boolean trim(boolean aggressive, int layer) { + return false; + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java index 1f91546e7..c042e7a23 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IBlocks.java @@ -41,6 +41,8 @@ public interface IBlocks extends Trimable { .map(layer -> (1 << layer)).sum(); } + boolean trim(boolean aggressive, int layer); + IBlocks reset(); default byte[] toByteArray(boolean full) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/BitSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/BitSetBlocks.java index a3712a053..4d7a6a21b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/BitSetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/BitSetBlocks.java @@ -153,4 +153,9 @@ public class BitSetBlocks implements IChunkSet { public boolean trim(boolean aggressive) { return false; } + + @Override + public boolean trim(boolean aggressive, int layer) { + return false; + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java index ba49152ee..81a5c32cc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java @@ -60,6 +60,17 @@ public abstract class CharBlocks implements IBlocks { return result; } + @Override + public boolean trim(boolean aggressive, int layer) { + boolean result = true; + if (sections[layer] == EMPTY && blocks[layer] != null) { + blocks[layer] = null; + } else { + result = false; + } + return result; + } + @Override public IChunkSet reset() { for (int i = 0; i < 16; i++) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java index 931c676be..f38d1bae4 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharGetBlocks.java @@ -25,6 +25,13 @@ public abstract class CharGetBlocks extends CharBlocks implements IChunkGet { return true; } + @Override + public boolean trim(boolean aggressive, int layer) { + sections[layer] = EMPTY; + blocks[layer] = null; + return true; + } + @Override public IChunkSet reset() { super.reset(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java index 0c0ab3d44..c6b596f43 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/FallbackChunkGet.java @@ -85,6 +85,11 @@ public class FallbackChunkGet implements IChunkGet { return true; } + @Override + public boolean trim(boolean aggressive, int layer) { + return true; + } + @Override public > T call(IChunkSet set, Runnable finalize) { for (int layer = 0; layer < 16; layer++) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/NullChunkGet.kt b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/NullChunkGet.kt index 77e85f715..a7a5e43de 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/NullChunkGet.kt +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/NullChunkGet.kt @@ -50,6 +50,10 @@ object NullChunkGet : IChunkGet { return true } + override fun trim(aggressive: Boolean, layer: Int): Boolean { + return true + } + override fun > call(set: IChunkSet, finalize: Runnable): T? { return null } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java index 4442faff4..a844b3079 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java @@ -344,6 +344,11 @@ public class ChunkHolder> implements IQueueChunk { return false; } + @Override + public boolean trim(boolean aggressive, int layer) { + return this.trim(aggressive); + } + @Override public boolean isEmpty() { return chunkSet == null || chunkSet.isEmpty(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/NullChunk.kt b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/NullChunk.kt index 06a3d6e8c..6a6f33358 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/NullChunk.kt +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/NullChunk.kt @@ -117,5 +117,9 @@ object NullChunk : IQueueChunk { override fun trim(aggressive: Boolean): Boolean { return true } + + override fun trim(aggressive: Boolean, layer: Int): Boolean { + return true + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/BatchProcessorHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/BatchProcessorHolder.java index be64c28ea..0bd4346db 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/BatchProcessorHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/BatchProcessorHolder.java @@ -4,7 +4,6 @@ import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.beta.IChunk; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkSet; -import com.sk89q.worldedit.extent.Extent; public class BatchProcessorHolder implements IBatchProcessorHolder { private IBatchProcessor processor = EmptyBatchProcessor.INSTANCE; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java index 66f60ac69..e8717012e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java @@ -549,6 +549,11 @@ public class MCAChunk implements IChunk { return isEmpty(); } + @Override + public boolean trim(boolean aggressive, int layer) { + return hasSection(layer); + } + @Override public CompoundTag getEntity(UUID uuid) { return this.entities.get(uuid); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java index 4fb47affe..897340388 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockTypesCache.java @@ -1,6 +1,7 @@ package com.sk89q.worldedit.world.block; import com.boydti.fawe.util.MathMan; +import com.google.common.primitives.Booleans; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Platform; @@ -166,12 +167,14 @@ public class BlockTypesCache { public static final BlockType[] values; public static final BlockState[] states; + public static final boolean[] ticking; protected static final Set $NAMESPACES = new LinkedHashSet<>(); static { try { ArrayList stateList = new ArrayList<>(); + ArrayList tickList = new ArrayList<>(); Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS); Registries registries = platform.getRegistries(); @@ -202,7 +205,7 @@ public class BlockTypesCache { if (values[internalId] != null) { throw new IllegalStateException("Invalid duplicate id for " + field.getName()); } - BlockType type = register(defaultState, internalId, stateList); + BlockType type = register(defaultState, internalId, stateList, tickList); // Note: Throws IndexOutOfBoundsError if nothing is registered and blocksMap is empty values[internalId] = type; } @@ -214,7 +217,7 @@ public class BlockTypesCache { String defaultState = entry.getValue(); // Skip already registered ids for (; values[internalId] != null; internalId++); - BlockType type = register(defaultState, internalId, stateList); + BlockType type = register(defaultState, internalId, stateList, tickList); values[internalId] = type; } } @@ -223,7 +226,7 @@ public class BlockTypesCache { } states = stateList.toArray(new BlockState[stateList.size()]); - + ticking = Booleans.toArray(tickList); } catch (Throwable e) { e.printStackTrace(); @@ -231,12 +234,14 @@ public class BlockTypesCache { } } - private static BlockType register(final String id, int internalId, List states) { + private static BlockType register(final String id, int internalId, List states, List tickList) { // Get the enum name (remove namespace if minecraft:) int propStart = id.indexOf('['); String typeName = id.substring(0, propStart == -1 ? id.length() : propStart); String enumName = (typeName.startsWith("minecraft:") ? typeName.substring(10) : typeName).toUpperCase(Locale.ROOT); + int oldsize = states.size(); BlockType existing = new BlockType(id, internalId, states); + tickList.addAll(Collections.nCopies(states.size() - oldsize, existing.getMaterial().isTicksRandomly())); // register states BlockType.REGISTRY.register(typeName, existing); String nameSpace = typeName.substring(0, typeName.indexOf(':')); From c757b0180316ca62fc3ce2298a4486e182a5c7b2 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 8 May 2020 16:16:08 +0100 Subject: [PATCH 03/27] By default only allow existing blocks to tick. - Revert back to default FAWE behaviour where placed blocks do not tick by default (until a restart, or another edit is done in the same chunksection without changing the block) --- .../fawe/bukkit/adapter/NMSAdapter.java | 47 ++++++++++++++----- .../java/com/boydti/fawe/config/Settings.java | 6 +++ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java index e15a8a9c5..e5b9073ee 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java @@ -1,5 +1,6 @@ package com.boydti.fawe.bukkit.adapter; +import com.boydti.fawe.config.Settings; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockID; @@ -68,6 +69,24 @@ public class NMSAdapter { case BlockID.VOID_AIR: air++; break; + default: + if (!Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED) { + boolean ticking; + if (ordinal != lastOrdinal) { + ticking = BlockTypesCache.ticking[ordinal]; + lastOrdinal = ordinal; + lastticking = ticking; + } else { + ticking = lastticking; + } + if (ticking) { + BlockState state = BlockState.getFromOrdinal(ordinal); + ticking_blocks + .put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), + WorldEditPlugin.getInstance().getBukkitImplAdapter() + .getInternalBlockStateId(state).orElse(0)); + } + } } set[i] = ordinal; break; @@ -78,19 +97,21 @@ public class NMSAdapter { air++; break; } - boolean ticking; - if (ordinal != lastOrdinal) { - ticking = BlockTypesCache.ticking[ordinal]; - lastOrdinal = ordinal; - lastticking = ticking; - } else { - ticking = lastticking; - } - if (ticking) { - BlockState state = BlockState.getFromOrdinal(ordinal); - ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), - WorldEditPlugin.getInstance().getBukkitImplAdapter() - .getInternalBlockStateId(state).orElse(0)); + if (Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED) { + boolean ticking; + if (ordinal != lastOrdinal) { + ticking = BlockTypesCache.ticking[ordinal]; + lastOrdinal = ordinal; + lastticking = ticking; + } else { + ticking = lastticking; + } + if (ticking) { + BlockState state = BlockState.getFromOrdinal(ordinal); + ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), + WorldEditPlugin.getInstance().getBukkitImplAdapter() + .getInternalBlockStateId(state).orElse(0)); + } } int palette = blockToPalette[ordinal]; if (palette == Integer.MAX_VALUE) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index 561f2330d..989e8ef05 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -369,6 +369,12 @@ public class Settings extends Config { "Other experimental features" }) public boolean OTHER = false; + + @Comment({ + "Allow blocks placed by WorldEdit to tick. This could cause the big lags.", + "This has no effect on existing blocks one way or the other." + }) + public boolean ALLOW_TICK_PLACED = false; } public static class WEB { From 56c720914efc422ebec7cf0bdac9bc8c2fe72aac Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 8 May 2020 18:17:47 +0100 Subject: [PATCH 04/27] Settings.IMP is terrible. Don't initialise it thousands of times. --- .../fawe/bukkit/adapter/NMSAdapter.java | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java index e5b9073ee..eb7bb9673 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java @@ -15,6 +15,9 @@ public class NMSAdapter { int[] num_palette_buffer, char[] set, Map ticking_blocks) { int air = 0; int num_palette = 0; + char lastOrdinal = BlockID.__RESERVED__; + boolean lastticking = false; + boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED; for (int i = 0; i < 4096; i++) { char ordinal = set[i]; switch (ordinal) { @@ -26,11 +29,22 @@ public class NMSAdapter { air++; break; default: - BlockState state = BlockState.getFromOrdinal(ordinal); - if (state.getMaterial().isTicksRandomly()) { - ticking_blocks.put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), - WorldEditPlugin.getInstance().getBukkitImplAdapter() - .getInternalBlockStateId(state).orElse(0)); + if (!tick_placed) { + boolean ticking; + if (ordinal != lastOrdinal) { + ticking = BlockTypesCache.ticking[ordinal]; + lastOrdinal = ordinal; + lastticking = ticking; + } else { + ticking = lastticking; + } + if (ticking) { + BlockState state = BlockState.getFromOrdinal(ordinal); + ticking_blocks + .put(BlockVector3.at(i & 15, (i >> 8) & 15, (i >> 4) & 15), + WorldEditPlugin.getInstance().getBukkitImplAdapter() + .getInternalBlockStateId(state).orElse(0)); + } } } int palette = blockToPalette[ordinal]; @@ -53,6 +67,7 @@ public class NMSAdapter { char[] getArr = null; char lastOrdinal = BlockID.__RESERVED__; boolean lastticking = false; + boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED; for (int i = 0; i < 4096; i++) { char ordinal = set[i]; switch (ordinal) { @@ -70,7 +85,7 @@ public class NMSAdapter { air++; break; default: - if (!Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED) { + if (!tick_placed) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; @@ -97,7 +112,7 @@ public class NMSAdapter { air++; break; } - if (Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED) { + if (tick_placed) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; From ffa25b1d9a5be02218e34bc81a01849fb061108e Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 13:39:41 +0100 Subject: [PATCH 05/27] Fixes #452 - ChunkSections containing only air are technically null according to NMS Chunks - Therefore if we're replacing air, we should ignore the result of get.hasSection(layer) by using "full = true" as it returns false if the chunksection is only air - We also then need to ensure that the masks correctly identify that the block is "air" --- .../queue/ParallelQueueExtent.java | 3 ++- .../sk89q/worldedit/function/mask/BlockMask.java | 10 +++++++++- .../worldedit/function/mask/BlockStateMask.java | 7 +++++++ .../worldedit/function/mask/BlockTypeMask.java | 16 ++++++++++++---- .../com/sk89q/worldedit/function/mask/Mask.java | 4 ++++ .../function/mask/SingleBlockStateMask.java | 12 +++++++++--- .../function/mask/SingleBlockTypeMask.java | 9 ++++++++- 7 files changed, 51 insertions(+), 10 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java index c93052360..fe314104a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java @@ -162,7 +162,8 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap @Override public int replaceBlocks(Region region, Mask mask, Pattern pattern) throws MaxChangedBlocksException { - return this.changes = apply(region, mask.toFilter(pattern), false).getBlocksApplied(); + boolean full = mask.replacesAir(); + return this.changes = apply(region, mask.toFilter(pattern), full).getBlocksApplied(); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java index 550d95adf..e13026ba7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockMask.java @@ -189,7 +189,15 @@ public class BlockMask extends ABlockMask { @Override public boolean test(Extent extent, BlockVector3 vector) { - return ordinals[vector.getOrdinal(extent)]; + int test = vector.getOrdinal(extent); + return ordinals[test] || replacesAir() && test == 0; + } + + @Override + public boolean replacesAir() { + return ordinals[BlockTypes.AIR.getDefaultState().getOrdinal()] + || ordinals[BlockTypes.CAVE_AIR.getDefaultState().getOrdinal()] + || ordinals[BlockTypes.VOID_AIR.getDefaultState().getOrdinal()]; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java index b8bc72e8f..b3580631b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockStateMask.java @@ -26,6 +26,8 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; + import java.util.Map; import javax.annotation.Nullable; @@ -65,6 +67,11 @@ public class BlockStateMask extends AbstractExtentMask { .allMatch(entry -> block.getState(entry.getKey()) == entry.getValue()); } + @Override + public boolean replacesAir() { + return test(BlockTypes.AIR.getDefaultState()) || test(BlockTypes.CAVE_AIR.getDefaultState()) || test(BlockTypes.VOID_AIR.getDefaultState()); + } + @Nullable @Override public Mask2D toMask2D() { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java index c33db1738..2d420cd6c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BlockTypeMask.java @@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull; public class BlockTypeMask extends AbstractExtentMask { private final boolean[] types; + private boolean hasAir; /** * Create a new block mask. @@ -63,7 +64,9 @@ public class BlockTypeMask extends AbstractExtentMask { public BlockTypeMask(Extent extent, @NotNull BlockType... block) { super(extent); this.types = new boolean[BlockTypes.size()]; - for (BlockType type : block) this.types[type.getInternalId()] = true; + for (BlockType type : block) { + add(type); + } } /** @@ -76,9 +79,6 @@ public class BlockTypeMask extends AbstractExtentMask { for (BlockType type : blocks) { add(type); } - for (BlockType type : blocks) { - this.types[type.getInternalId()] = true; - } } /** @@ -88,6 +88,9 @@ public class BlockTypeMask extends AbstractExtentMask { */ public void add(@NotNull BlockType... block) { for (BlockType type : block) { + if (!hasAir && (type == BlockTypes.AIR || type == BlockTypes.CAVE_AIR || type == BlockTypes.VOID_AIR)) { + hasAir = true; + } this.types[type.getInternalId()] = true; } } @@ -110,6 +113,11 @@ public class BlockTypeMask extends AbstractExtentMask { return test(vector.getBlock(extent).getBlockType()); } + @Override + public boolean replacesAir() { + return hasAir; + } + public boolean test(BlockType block) { return types[block.getInternalId()]; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java index 7267cb13c..8a9c9a4aa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -123,4 +123,8 @@ public interface Mask { } }; } + + default boolean replacesAir() { + return false; + } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockStateMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockStateMask.java index ff022f7c7..f776335ac 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockStateMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockStateMask.java @@ -1,13 +1,12 @@ package com.sk89q.worldedit.function.mask; -import com.boydti.fawe.Fawe; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; public class SingleBlockStateMask extends ABlockMask { private final char ordinal; + private final boolean isAir; public BlockState getBlockState() { return BlockState.getFromOrdinal(ordinal); @@ -15,12 +14,14 @@ public class SingleBlockStateMask extends ABlockMask { public SingleBlockStateMask(Extent extent, BlockState state) { super(extent); + isAir = state.isAir(); this.ordinal = state.getOrdinalChar(); } @Override public boolean test(Extent extent, BlockVector3 vector) { - return ordinal == vector.getOrdinal(extent); + int test = vector.getOrdinal(extent); + return ordinal == test || isAir && test == 0; } @Override @@ -33,6 +34,11 @@ public class SingleBlockStateMask extends ABlockMask { return new InverseSingleBlockStateMask(getExtent(), BlockState.getFromOrdinal(ordinal)); } + @Override + public boolean replacesAir() { + return isAir; + } + @Override public Mask tryCombine(Mask mask) { if (mask instanceof ABlockMask) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java index 01d4aad7c..466f51c7e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/SingleBlockTypeMask.java @@ -8,10 +8,12 @@ import com.sk89q.worldedit.world.block.BlockTypesCache; public class SingleBlockTypeMask extends ABlockMask { private final int internalId; + private final boolean isAir; public SingleBlockTypeMask(Extent extent, BlockType type) { super(extent); - this.internalId = type.getInternalId(); + isAir = type == BlockTypes.AIR || type == BlockTypes.CAVE_AIR || type == BlockTypes.VOID_AIR; + this.internalId = type.getInternalId(); } @Override @@ -27,4 +29,9 @@ public class SingleBlockTypeMask extends ABlockMask { public BlockType getBlockType() { return BlockTypes.get(internalId); } + + @Override + public boolean replacesAir() { + return isAir; + } } From 42d7419b4b37cfe5f11e8c93feec93580917a696 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 13:56:41 +0100 Subject: [PATCH 06/27] Fixes #402 - Similar to previous commit. If the chunksection was empty, then __reserved__ was parsed to the clipboard, and then not correctly identified as air - Now assume all __reserved__ is air when writing to clipboards --- .../boydti/fawe/object/clipboard/CPUOptimizedClipboard.java | 6 +++++- .../fawe/object/clipboard/DiskOptimizedClipboard.java | 3 +++ .../fawe/object/clipboard/MemoryOptimizedClipboard.java | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java index 671e4b351..0a1507828 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/CPUOptimizedClipboard.java @@ -184,7 +184,11 @@ public class CPUOptimizedClipboard extends LinearClipboard { @Override public > boolean setBlock(int index, B block) { - states[index] = block.getOrdinalChar(); + char ordinal = block.getOrdinalChar(); + if (ordinal == 0) { + ordinal = 1; + } + states[index] = ordinal; boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); if (hasNbt) { setTile(index, block.getNbtData()); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java index 2b1c613fd..a66f9b84c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/DiskOptimizedClipboard.java @@ -388,6 +388,9 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable try { int index = HEADER_SIZE + (getIndex(x, y, z) << 1); char ordinal = block.getOrdinalChar(); + if (ordinal == 0) { + ordinal = 1; + } byteBuffer.putChar(index, ordinal); boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); if (hasNbt) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java index 825415310..7a30348e2 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/clipboard/MemoryOptimizedClipboard.java @@ -263,6 +263,9 @@ public class MemoryOptimizedClipboard extends LinearClipboard { @Override public > boolean setBlock(int index, B block) { int ordinal = block.getOrdinal(); + if (ordinal == 0) { + ordinal = 1; + } setOrdinal(index, ordinal); boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); if (hasNbt) { From 8f60544aad6215910cd91dbc645778164e38f85d Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 15:11:40 +0100 Subject: [PATCH 07/27] Override some methods in AsyncWorld --- .../com/boydti/fawe/bukkit/wrapper/AsyncWorld.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index d451c5625..157747fed 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -1053,6 +1053,18 @@ public class AsyncWorld extends PassthroughExtent implements World { return parent.getViewDistance(); } + @Override public void setViewDistance(int i) { + parent.setViewDistance(i); + } + + @Override public int getNoTickViewDistance() { + return parent.getNoTickViewDistance(); + } + + @Override public void setNoTickViewDistance(int i) { + parent.setNoTickViewDistance(i); + } + @Override public RayTraceResult rayTrace(Location arg0, Vector arg1, double arg2, FluidCollisionMode arg3, boolean arg4, double arg5, Predicate arg6) { From b1f1c0f4f0372b58ad00463dcd702bc7287f5ca0 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 16:23:38 +0100 Subject: [PATCH 08/27] Possible fix for #331 - Should ensure the server doesn't tick the chunksection while we're editing it - Basically using the old issue with FAWE breaking block ticking by setting this to zero :) --- .../fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java | 4 ++++ .../fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java | 4 ++++ .../fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java index bbe859074..32365cfbd 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java @@ -262,6 +262,10 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { char[] setArr = set.load(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; + + //ensure that the server doesn't try to tick the chunksection while we're editing it. + BukkitAdapter_1_14.fieldTickingBlockCount.set(existingSection, (short) 0); + if (existingSection == null) { newSection = BukkitAdapter_1_14.newChunkSection(layer, setArr); if (BukkitAdapter_1_14.setSectionAtomic(sections, null, newSection, layer)) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java index 63b04265e..37ce658a7 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java @@ -270,6 +270,10 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { char[] setArr = set.load(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; + + //ensure that the server doesn't try to tick the chunksection while we're editing it. + BukkitAdapter_1_15.fieldTickingBlockCount.set(existingSection, (short) 0); + if (existingSection == null) { newSection = BukkitAdapter_1_15.newChunkSection(layer, setArr); if (BukkitAdapter_1_15.setSectionAtomic(sections, null, newSection, layer)) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index 8056f6e21..e8fb25b4a 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -282,6 +282,10 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { char[] setArr = set.load(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; + + //ensure that the server doesn't try to tick the chunksection while we're editing it. + BukkitAdapter_1_15_2.fieldTickingBlockCount.set(existingSection, (short) 0); + if (existingSection == null) { newSection = BukkitAdapter_1_15_2.newChunkSection(layer, setArr); if (BukkitAdapter_1_15_2.setSectionAtomic(sections, null, newSection, layer)) { From 56175ffe0facbdd215413b2cd95bd48d0a76b1a2 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 16:30:28 +0100 Subject: [PATCH 09/27] Revert this so it compiles on the ci for now. --- .../com/boydti/fawe/bukkit/wrapper/AsyncWorld.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index 157747fed..d451c5625 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -1053,18 +1053,6 @@ public class AsyncWorld extends PassthroughExtent implements World { return parent.getViewDistance(); } - @Override public void setViewDistance(int i) { - parent.setViewDistance(i); - } - - @Override public int getNoTickViewDistance() { - return parent.getNoTickViewDistance(); - } - - @Override public void setNoTickViewDistance(int i) { - parent.setNoTickViewDistance(i); - } - @Override public RayTraceResult rayTrace(Location arg0, Vector arg1, double arg2, FluidCollisionMode arg3, boolean arg4, double arg5, Predicate arg6) { From cb20cef0e6db35e80b479fb469fc121c777ebb07 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 16:45:42 +0100 Subject: [PATCH 10/27] Fix loading schematic from URLs --- .../main/java/com/sk89q/worldedit/command/SchematicCommands.java | 1 + 1 file changed, 1 insertion(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index d5e4f4b49..17f1e22b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -212,6 +212,7 @@ public class SchematicCommands { } UUID uuid = UUID.fromString(filename.substring(4)); URL webUrl = new URL(Settings.IMP.WEB.URL); + format = ClipboardFormats.findByAlias(formatName); URL url = new URL(webUrl, "uploads/" + uuid + "." + format.getPrimaryFileExtension()); ReadableByteChannel byteChannel = Channels.newChannel(url.openStream()); in = Channels.newInputStream(byteChannel); From 0dee452e1a0f296777369aa233a67a52e8fa3a3d Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 17:42:40 +0100 Subject: [PATCH 11/27] Don't attempt to set field on null ChunkSection --- .../fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java | 8 ++++---- .../fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java | 8 ++++---- .../bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java index 32365cfbd..4d14bfe92 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java @@ -262,10 +262,6 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { char[] setArr = set.load(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; - - //ensure that the server doesn't try to tick the chunksection while we're editing it. - BukkitAdapter_1_14.fieldTickingBlockCount.set(existingSection, (short) 0); - if (existingSection == null) { newSection = BukkitAdapter_1_14.newChunkSection(layer, setArr); if (BukkitAdapter_1_14.setSectionAtomic(sections, null, newSection, layer)) { @@ -279,6 +275,10 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { } } } + + //ensure that the server doesn't try to tick the chunksection while we're editing it. + BukkitAdapter_1_14.fieldTickingBlockCount.set(existingSection, (short) 0); + DelegateLock lock = BukkitAdapter_1_14.applyLock(existingSection); synchronized (this) { synchronized (lock) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java index 37ce658a7..abf00c2fb 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java @@ -270,10 +270,6 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { char[] setArr = set.load(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; - - //ensure that the server doesn't try to tick the chunksection while we're editing it. - BukkitAdapter_1_15.fieldTickingBlockCount.set(existingSection, (short) 0); - if (existingSection == null) { newSection = BukkitAdapter_1_15.newChunkSection(layer, setArr); if (BukkitAdapter_1_15.setSectionAtomic(sections, null, newSection, layer)) { @@ -287,6 +283,10 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { } } } + + //ensure that the server doesn't try to tick the chunksection while we're editing it. + BukkitAdapter_1_15.fieldTickingBlockCount.set(existingSection, (short) 0); + DelegateLock lock = BukkitAdapter_1_15.applyLock(existingSection); synchronized (this) { synchronized (lock) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index e8fb25b4a..ea0d2c089 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -282,10 +282,6 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { char[] setArr = set.load(layer); ChunkSection newSection; ChunkSection existingSection = sections[layer]; - - //ensure that the server doesn't try to tick the chunksection while we're editing it. - BukkitAdapter_1_15_2.fieldTickingBlockCount.set(existingSection, (short) 0); - if (existingSection == null) { newSection = BukkitAdapter_1_15_2.newChunkSection(layer, setArr); if (BukkitAdapter_1_15_2.setSectionAtomic(sections, null, newSection, layer)) { @@ -299,7 +295,11 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { } } } + BukkitAdapter_1_15_2.fieldTickingBlockCount.set(existingSection, (short) 0); + + //ensure that the server doesn't try to tick the chunksection while we're editing it. DelegateLock lock = BukkitAdapter_1_15_2.applyLock(existingSection); + synchronized (this) { synchronized (lock) { lock.untilFree(); From 73f8f1a0a79bfec2da47da001794562fb273091d Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Sat, 9 May 2020 20:58:47 +0200 Subject: [PATCH 12/27] Fix wrong translation key --- worldedit-core/src/main/resources/lang/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 819f15ddf..4764d5170 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -238,7 +238,7 @@ "fawe.error.command.syntax": "Usage: {0}", "fawe.error.no-perm": "You are lacking the permission node: {0}", - "fawe.error.block.not.allowed": "You are not allowed to use", + "fawe.error.block.not.allowed": "You are not allowed to use: {0}", "fawe.error.setting.disable": "Lacking setting: {0}", "fawe.error.brush.not.found": "Available brushes: {0}", "fawe.error.brush.incompatible": "Brush not compatible with this version", From 4f2b0e6f4e65322ce71b8e8ac8437b7db13ceb62 Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Sat, 9 May 2020 21:08:14 +0200 Subject: [PATCH 13/27] Fix missing space --- worldedit-core/src/main/resources/lang/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 4764d5170..1f7b50b4e 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -72,7 +72,7 @@ "fawe.worldedit.history.command.history.clear": "History cleared", "fawe.worldedit.history.command.redo.error": "Nothing left to redo. (See also `/inspect` and `/frb`)", "fawe.worldedit.history.command.history.other.error": "Unable to find session for {0}.", - "fawe.worldedit.history.command.redo.success": "Redo successful{0}.", + "fawe.worldedit.history.command.redo.success": "Redo successful {0}.", "fawe.worldedit.history.command.undo.error": "Nothing left to undo. (See also `/inspect` and `/frb`)", "fawe.worldedit.history.command.undo.disabled": "Undo disabled, use: //fast", "fawe.worldedit.history.command.undo.success": "Undo successful{0}.", From a813cbfcdfb57e4f0059d7e4c46b89fc235df967 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Sun, 10 May 2020 20:57:24 -0400 Subject: [PATCH 14/27] Update world interface --- .../fawe/bukkit/wrapper/AsyncWorld.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java index d451c5625..4252d3f32 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java @@ -55,6 +55,7 @@ import org.bukkit.entity.Item; import org.bukkit.entity.LightningStrike; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; +import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; import org.bukkit.inventory.ItemStack; @@ -649,6 +650,11 @@ public class AsyncWorld extends PassthroughExtent implements World { return TaskManager.IMP.sync(() -> parent.spawn(location, clazz, function)); } + @Override + public @NotNull T spawn(@NotNull Location location, @NotNull Class clazz, @Nullable Consumer function, CreatureSpawnEvent.@NotNull SpawnReason reason) throws IllegalArgumentException { + return null; + } + @Override public FallingBlock spawnFallingBlock(Location location, MaterialData data) throws IllegalArgumentException { return TaskManager.IMP.sync(() -> parent.spawnFallingBlock(location, data)); @@ -1053,6 +1059,21 @@ public class AsyncWorld extends PassthroughExtent implements World { return parent.getViewDistance(); } + @Override + public void setViewDistance(int viewDistance) { + + } + + @Override + public int getNoTickViewDistance() { + return 0; + } + + @Override + public void setNoTickViewDistance(int viewDistance) { + + } + @Override public RayTraceResult rayTrace(Location arg0, Vector arg1, double arg2, FluidCollisionMode arg3, boolean arg4, double arg5, Predicate arg6) { @@ -1174,6 +1195,11 @@ public class AsyncWorld extends PassthroughExtent implements World { return parent.getChunkAtAsync(arg0, arg1, arg2); } + @Override + public @NotNull CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent) { + return null; + } + @Override public boolean isDayTime() { return parent.isDayTime(); From ec6ca633a88a5938fd1206e14941134c00d07fbb Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Sun, 10 May 2020 20:58:52 -0400 Subject: [PATCH 15/27] Update Gradle for Java 14 support --- gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 58694 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 29 ++++++++++------------- gradlew.bat | 3 +++ 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..490fda8577df6c95960ba7077c43220e5bb2c0d9 100644 GIT binary patch delta 22806 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 Z!$zsDgoO%|(a?lZ=Qe6kxv{^r{{!uYR<-~D delta 19980 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 Z5H)%VJiSWIAOn$sbP+#;Q{V4m{s)AkOUM8K diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4a6ebceac..4c5803d13 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfdc..2fe81a7d9 100755 --- a/gradlew +++ b/gradlew @@ -154,19 +154,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -175,14 +175,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a141..9109989e3 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" From 8c38ac0fbca1426ad626c9ddd3665bdf3b2cee4c Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Mon, 11 May 2020 13:38:06 +0100 Subject: [PATCH 16/27] Fix #460 --- .../extension/factory/parser/DefaultBlockParser.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java index 659760670..31491b2b8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/DefaultBlockParser.java @@ -364,6 +364,12 @@ public class DefaultBlockParser extends InputParser { } state = fuzzyBuilder.build(); } + } else { + for (Map.Entry, Object> blockState : blockStates.entrySet()) { + @SuppressWarnings("unchecked") + Property objProp = (Property) blockState.getKey(); + state = state.with(objProp, blockState.getValue()); + } } } // this should be impossible but IntelliJ isn't that smart From 31da111e1e9ceb0f7f40c07f03cad2e3ca356bda Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Mon, 11 May 2020 15:07:47 +0200 Subject: [PATCH 17/27] Fix anvil translation string --- worldedit-core/src/main/resources/lang/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index 1f7b50b4e..c479c6422 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -97,7 +97,7 @@ "fawe.worldedit.selection.selection.shift": "Region shifted", "fawe.worldedit.selection.selection.cleared": "Selection cleared", - "fawe.worldedit.anvil.world.is.loaded": "The world shouldn't be in use when executing. Unload the world, or use use -f to override (save first)", + "fawe.worldedit.anvil.world.is.loaded": "The world shouldn't be in use when executing. Unload the world, or use -f to override (save first)", "fawe.worldedit.brush.brush.reset": "Reset your brush. (SHIFT + Click)", "fawe.worldedit.brush.brush.none": "You aren't holding a brush!", From 36faf107e6eb9eeeb7f0a223bd4d4f73fc0bca64 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Mon, 11 May 2020 15:36:52 +0100 Subject: [PATCH 18/27] Allow fastmode to be used in a lot more places - Option to stop fastmode from bothering to fix existing ticking blocks --- .../fawe/bukkit/adapter/NMSAdapter.java | 10 +++++----- .../adapter/mc1_14/BukkitAdapter_1_14.java | 10 +++++----- .../adapter/mc1_14/BukkitGetBlocks_1_14.java | 6 ++++-- .../adapter/mc1_15/BukkitAdapter_1_15.java | 10 +++++----- .../adapter/mc1_15/BukkitGetBlocks_1_15.java | 6 ++++-- .../mc1_15_2/BukkitAdapter_1_15_2.java | 19 ++++++++++--------- .../mc1_15_2/BukkitGetBlocks_1_15_2.java | 6 ++++-- .../java/com/boydti/fawe/beta/IChunkSet.java | 13 +++++++++---- .../com/boydti/fawe/beta/IQueueExtent.java | 5 +++++ .../implementation/blocks/CharSetBlocks.java | 11 +++++++++++ .../implementation/chunk/ChunkHolder.java | 12 ++++++++++++ .../queue/ParallelQueueExtent.java | 5 ++++- .../queue/SingleThreadQueueExtent.java | 12 ++++++++++++ .../java/com/boydti/fawe/config/Settings.java | 5 +++++ .../boydti/fawe/util/EditSessionBuilder.java | 2 +- 15 files changed, 96 insertions(+), 36 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java index eb7bb9673..09e672526 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java @@ -12,7 +12,7 @@ import java.util.function.Function; public class NMSAdapter { public static int createPalette(int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy, - int[] num_palette_buffer, char[] set, Map ticking_blocks) { + int[] num_palette_buffer, char[] set, Map ticking_blocks, boolean fastmode) { int air = 0; int num_palette = 0; char lastOrdinal = BlockID.__RESERVED__; @@ -29,7 +29,7 @@ public class NMSAdapter { air++; break; default: - if (!tick_placed) { + if (!tick_placed && !tick_placed) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; @@ -61,7 +61,7 @@ public class NMSAdapter { public static int createPalette(int layer, int[] blockToPalette, int[] paletteToBlock, int[] blocksCopy, int[] num_palette_buffer, Function get, char[] set, - Map ticking_blocks) { + Map ticking_blocks, boolean fastmode) { int air = 0; int num_palette = 0; char[] getArr = null; @@ -85,7 +85,7 @@ public class NMSAdapter { air++; break; default: - if (!tick_placed) { + if (!fastmode && !tick_placed) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; @@ -112,7 +112,7 @@ public class NMSAdapter { air++; break; } - if (tick_placed) { + if (!fastmode && tick_placed) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitAdapter_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitAdapter_1_14.java index be718e964..7542e8257 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitAdapter_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitAdapter_1_14.java @@ -199,11 +199,11 @@ public final class BukkitAdapter_1_14 extends NMSAdapter { /* NMS conversion */ - public static ChunkSection newChunkSection(final int layer, final char[] blocks) { - return newChunkSection(layer, null, blocks); + public static ChunkSection newChunkSection(final int layer, final char[] blocks, boolean fastmode) { + return newChunkSection(layer, null, blocks, fastmode); } - public static ChunkSection newChunkSection(final int layer, final Function get, char[] set) { + public static ChunkSection newChunkSection(final int layer, final Function get, char[] set, boolean fastmode) { if (set == null) { return newChunkSection(layer); } @@ -216,9 +216,9 @@ public final class BukkitAdapter_1_14 extends NMSAdapter { Map ticking_blocks = new HashMap<>(); int air; if (get == null) { - air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks); + air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks, fastmode); } else { - air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks); + air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks, fastmode); } int num_palette = num_palette_buffer[0]; // BlockStates diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java index 4d14bfe92..db000c51d 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_14/BukkitGetBlocks_1_14.java @@ -10,6 +10,7 @@ import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.DelegateLock; import com.boydti.fawe.bukkit.adapter.mc1_14.nbt.LazyCompoundTag_1_14; +import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.AdaptedMap; import com.boydti.fawe.object.collection.BitArray; import com.google.common.base.Suppliers; @@ -228,6 +229,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { try { WorldServer nmsWorld = world; Chunk nmsChunk = ensureLoaded(nmsWorld, X, Z); + boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE; // Remove existing tiles { @@ -263,7 +265,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { ChunkSection newSection; ChunkSection existingSection = sections[layer]; if (existingSection == null) { - newSection = BukkitAdapter_1_14.newChunkSection(layer, setArr); + newSection = BukkitAdapter_1_14.newChunkSection(layer, setArr, fastmode); if (BukkitAdapter_1_14.setSectionAtomic(sections, null, newSection, layer)) { updateGet(this, nmsChunk, sections, newSection, setArr, layer); continue; @@ -295,7 +297,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks { } else if (lock.isModified()) { this.reset(layer); } - newSection = BukkitAdapter_1_14.newChunkSection(layer, this::load, setArr); + newSection = BukkitAdapter_1_14.newChunkSection(layer, this::load, setArr, fastmode); if (!BukkitAdapter_1_14.setSectionAtomic(sections, existingSection, newSection, layer)) { System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer); continue; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitAdapter_1_15.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitAdapter_1_15.java index 92293e721..6e4c60a45 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitAdapter_1_15.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitAdapter_1_15.java @@ -186,11 +186,11 @@ public final class BukkitAdapter_1_15 extends NMSAdapter { /* NMS conversion */ - public static ChunkSection newChunkSection(final int layer, final char[] blocks) { - return newChunkSection(layer, null, blocks); + public static ChunkSection newChunkSection(final int layer, final char[] blocks, boolean fastmode) { + return newChunkSection(layer, null, blocks, fastmode); } - public static ChunkSection newChunkSection(final int layer, final Function get, char[] set) { + public static ChunkSection newChunkSection(final int layer, final Function get, char[] set, boolean fastmode) { if (set == null) { return newChunkSection(layer); } @@ -203,9 +203,9 @@ public final class BukkitAdapter_1_15 extends NMSAdapter { Map ticking_blocks = new HashMap<>(); int air; if (get == null) { - air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks); + air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, set, ticking_blocks, fastmode); } else { - air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks); + air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, get, set, ticking_blocks, fastmode); } int num_palette = num_palette_buffer[0]; // BlockStates diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java index abf00c2fb..68ef24f11 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15/BukkitGetBlocks_1_15.java @@ -10,6 +10,7 @@ import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.DelegateLock; import com.boydti.fawe.bukkit.adapter.mc1_15.nbt.LazyCompoundTag_1_15; +import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.AdaptedMap; import com.boydti.fawe.object.collection.BitArray; import com.google.common.base.Suppliers; @@ -236,6 +237,7 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { try { WorldServer nmsWorld = world; Chunk nmsChunk = ensureLoaded(nmsWorld, X, Z); + boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE; // Remove existing tiles { @@ -271,7 +273,7 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { ChunkSection newSection; ChunkSection existingSection = sections[layer]; if (existingSection == null) { - newSection = BukkitAdapter_1_15.newChunkSection(layer, setArr); + newSection = BukkitAdapter_1_15.newChunkSection(layer, setArr, fastmode); if (BukkitAdapter_1_15.setSectionAtomic(sections, null, newSection, layer)) { updateGet(this, nmsChunk, sections, newSection, setArr, layer); continue; @@ -303,7 +305,7 @@ public class BukkitGetBlocks_1_15 extends CharGetBlocks { } else if (lock.isModified()) { this.reset(layer); } - newSection = BukkitAdapter_1_15.newChunkSection(layer, this::load, setArr); + newSection = BukkitAdapter_1_15.newChunkSection(layer, this::load, setArr, fastmode); if (!BukkitAdapter_1_15.setSectionAtomic(sections, existingSection, newSection, layer)) { System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer); continue; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java index 578e023ed..4b5851de0 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java @@ -187,11 +187,11 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { /* NMS conversion */ - public static ChunkSection newChunkSection(final int layer, final char[] blocks) { - return newChunkSection(layer, null, blocks); + public static ChunkSection newChunkSection(final int layer, final char[] blocks, boolean fastmode) { + return newChunkSection(layer, null, blocks, fastmode); } - public static ChunkSection newChunkSection(final int layer, final Function get, char[] set) { + public static ChunkSection newChunkSection(final int layer, final Function get, char[] set, boolean fastmode) { if (set == null) { return newChunkSection(layer); } @@ -205,10 +205,10 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { int air; if (get == null) { air = createPalette(blockToPalette, paletteToBlock, blocksCopy, num_palette_buffer, - set, ticking_blocks); + set, ticking_blocks, fastmode); } else { air = createPalette(layer, blockToPalette, paletteToBlock, blocksCopy, - num_palette_buffer, get, set, ticking_blocks); + num_palette_buffer, get, set, ticking_blocks, fastmode); } int num_palette = num_palette_buffer[0]; // BlockStates @@ -251,10 +251,11 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { fieldPalette.set(dataPaletteBlocks, palette); fieldSize.set(dataPaletteBlocks, bitsPerEntry); setCount(ticking_blocks.size(), 4096 - air, section); - ticking_blocks.forEach((pos, ordinal) -> { - section.setType(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), - Block.getByCombinedId(ordinal)); - }); + if (!fastmode) { + ticking_blocks.forEach((pos, ordinal) -> section + .setType(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), + Block.getByCombinedId(ordinal))); + } } catch (final IllegalAccessException | NoSuchFieldException e) { throw new RuntimeException(e); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index ea0d2c089..87c3062a9 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -8,6 +8,7 @@ import com.boydti.fawe.beta.implementation.blocks.CharGetBlocks; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.DelegateLock; import com.boydti.fawe.bukkit.adapter.mc1_15_2.nbt.LazyCompoundTag_1_15_2; +import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.AdaptedMap; import com.boydti.fawe.object.collection.BitArray; import com.google.common.base.Suppliers; @@ -243,6 +244,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { try { WorldServer nmsWorld = world; Chunk nmsChunk = ensureLoaded(nmsWorld, X, Z); + boolean fastmode = set.isFastMode() && Settings.IMP.QUEUE.NO_TICK_FASTMODE; // Remove existing tiles { @@ -283,7 +285,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { ChunkSection newSection; ChunkSection existingSection = sections[layer]; if (existingSection == null) { - newSection = BukkitAdapter_1_15_2.newChunkSection(layer, setArr); + newSection = BukkitAdapter_1_15_2.newChunkSection(layer, setArr, fastmode); if (BukkitAdapter_1_15_2.setSectionAtomic(sections, null, newSection, layer)) { updateGet(this, nmsChunk, sections, newSection, setArr, layer); continue; @@ -315,7 +317,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks { } else if (lock.isModified()) { this.reset(layer); } - newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr); + newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr, fastmode); if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) { System.out.println("Failed to set chunk section:" + X + "," + Z + " layer: " + layer); continue; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java index 65b24872c..168120f46 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IChunkSet.java @@ -3,14 +3,12 @@ package com.boydti.fawe.beta; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.extent.OutputExtent; import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -import java.util.Map; + +import javax.annotation.Nullable; import java.util.Set; import java.util.UUID; -import javax.annotation.Nullable; /** * Interface for setting blocks @@ -42,6 +40,13 @@ public interface IChunkSet extends IBlocks, OutputExtent { return getBiomes() != null; } + default boolean isFastMode() { + return false; + } + + //default to avoid tricky child classes. We only need it in a few cases anyway. + default void setFastMode(boolean fastMode){} + @Override IChunkSet reset(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java index a3e74a806..eed76600e 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java @@ -82,6 +82,10 @@ public interface IQueueExtent extends Flushable, Trimable, ICh return BlockVector3.at(30000000, FaweCache.IMP.WORLD_MAX_Y, 30000000); } + void setFastMode(boolean fastMode); + + boolean isFastMode(); + /** * Create a new root IChunk object
- Full chunks will be reused, so a more optimized chunk * can be returned in that case
- Don't wrap the chunk, that should be done in {@link @@ -143,6 +147,7 @@ public interface IQueueExtent extends Flushable, Trimable, ICh T chunk = this.getOrCreateChunk(chunkX, chunkZ); // Initialize chunk.init(this, chunkX, chunkZ); + chunk.setFastMode(isFastMode()); T newChunk = filter.applyChunk(chunk, region); if (newChunk != null) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java index 39947092c..b7eda2724 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharSetBlocks.java @@ -34,6 +34,7 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { public BlockVector3ChunkMap tiles; public HashSet entities; public HashSet entityRemoves; + private boolean fastMode = false; private CharSetBlocks() {} @@ -131,6 +132,16 @@ public class CharSetBlocks extends CharBlocks implements IChunkSet { entityRemoves.add(uuid); } + @Override + public void setFastMode(boolean fastMode) { + this.fastMode = fastMode; + } + + @Override + public boolean isFastMode() { + return fastMode; + } + @Override public boolean isEmpty() { if (biomes != null) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java index a844b3079..7449cbec0 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/chunk/ChunkHolder.java @@ -42,6 +42,7 @@ public class ChunkHolder> implements IQueueChunk { private IQueueExtent extent; // the parent queue extent which has this chunk private int chunkX; private int chunkZ; + private boolean fastmode; private ChunkHolder() { this.delegate = NULL; @@ -100,6 +101,16 @@ public class ChunkHolder> implements IQueueChunk { return getOrCreateGet().load(layer); } + @Override + public boolean isFastMode() { + return fastmode; + } + + @Override + public void setFastMode(boolean fastmode) { + this.fastmode = fastmode; + } + @Override public CompoundTag getEntity(UUID uuid) { return delegate.get(this).getEntity(uuid); @@ -313,6 +324,7 @@ public class ChunkHolder> implements IQueueChunk { public void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) { final IChunkGet get = getOrCreateGet(); final IChunkSet set = getOrCreateSet(); + set.setFastMode(fastmode); try { block.filter(this, get, set, filter, region, full); } finally { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java index fe314104a..b68207afe 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/ParallelQueueExtent.java @@ -44,12 +44,14 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap private final QueueHandler handler; private final BatchProcessorHolder processor; private int changes; + private final boolean fastmode; - public ParallelQueueExtent(QueueHandler handler, World world) { + public ParallelQueueExtent(QueueHandler handler, World world, boolean fastmode) { super(handler.getQueue(world, new BatchProcessorHolder())); this.world = world; this.handler = handler; this.processor = (BatchProcessorHolder) getExtent().getProcessor(); + this.fastmode = fastmode; } @Override @@ -94,6 +96,7 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap final Filter newFilter = filter.fork(); // Create a chunk that we will reuse/reset for each operation final IQueueExtent queue = getNewQueue(); + queue.setFastMode(fastmode); synchronized (queue) { ChunkFilterBlock block = null; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java index 62a199e6a..d079d2c81 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java @@ -49,6 +49,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen private boolean enabledQueue = true; + private boolean fastmode = false; + /** * Safety check to ensure that the thread being used matches the one being initialized on. - Can * be removed later @@ -80,6 +82,16 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen return cacheSet.get(chunkX, chunkZ); } + @Override + public void setFastMode(boolean fastmode) { + this.fastmode = fastmode; + } + + @Override + public boolean isFastMode() { + return fastmode; + } + /** * Resets the queue. */ diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index 989e8ef05..07783b8da 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -309,6 +309,11 @@ public class Settings extends Config { }) public int DISCARD_AFTER_MS = 60000; + @Comment({ + "When using fastmode also do not bother to fix existing ticking blocks" + }) + public boolean NO_TICK_FASTMODE = true; + public static class PROGRESS { @Comment({"Display constant titles about the progress of a user's edit", " - false = disabled", diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java index 1ca86ccbb..d2a84c00b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java @@ -296,7 +296,7 @@ public class EditSessionBuilder { if (unwrapped instanceof IQueueExtent) { extent = queue = (IQueueExtent) unwrapped; } else if (Settings.IMP.QUEUE.PARALLEL_THREADS > 1 && threaded) { - ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.get().getQueueHandler(), world); + ParallelQueueExtent parallel = new ParallelQueueExtent(Fawe.get().getQueueHandler(), world, fastmode); queue = parallel.getExtent(); extent = parallel; } else { From be58cd42ac62811c1c555d92f7f784d4a2ae2701 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Mon, 11 May 2020 16:09:31 +0100 Subject: [PATCH 19/27] Add option to disable ticking existing blocks when not fastmode --- .../java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java | 5 +++-- .../src/main/java/com/boydti/fawe/config/Settings.java | 6 ++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java index 09e672526..0160fdd51 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/NMSAdapter.java @@ -29,7 +29,7 @@ public class NMSAdapter { air++; break; default: - if (!tick_placed && !tick_placed) { + if (!fastmode && !tick_placed) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; @@ -68,6 +68,7 @@ public class NMSAdapter { char lastOrdinal = BlockID.__RESERVED__; boolean lastticking = false; boolean tick_placed = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_PLACED; + boolean tick_existing = Settings.IMP.EXPERIMENTAL.ALLOW_TICK_EXISTING; for (int i = 0; i < 4096; i++) { char ordinal = set[i]; switch (ordinal) { @@ -85,7 +86,7 @@ public class NMSAdapter { air++; break; default: - if (!fastmode && !tick_placed) { + if (!fastmode && !tick_placed && tick_existing) { boolean ticking; if (ordinal != lastOrdinal) { ticking = BlockTypesCache.ticking[ordinal]; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index 07783b8da..2dea1937d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -380,6 +380,12 @@ public class Settings extends Config { "This has no effect on existing blocks one way or the other." }) public boolean ALLOW_TICK_PLACED = false; + + @Comment({ + "Force re-ticking of existing blocks not edited by FAWE.", + "This will increase time taken slightly." + }) + public boolean ALLOW_TICK_EXISTING = true; } public static class WEB { From 74f9b37a392a39a116ce5d3e6d697ebe47332ce8 Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Mon, 11 May 2020 18:47:14 +0200 Subject: [PATCH 20/27] Fix missing space --- worldedit-core/src/main/resources/lang/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index c479c6422..bb33d8f28 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -75,7 +75,7 @@ "fawe.worldedit.history.command.redo.success": "Redo successful {0}.", "fawe.worldedit.history.command.undo.error": "Nothing left to undo. (See also `/inspect` and `/frb`)", "fawe.worldedit.history.command.undo.disabled": "Undo disabled, use: //fast", - "fawe.worldedit.history.command.undo.success": "Undo successful{0}.", + "fawe.worldedit.history.command.undo.success": "Undo successful {0}.", "fawe.worldedit.operation.operation": "Operation queued ({0})", From 7c35477b8cc4e2f36eb50878b897652775d63829 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Mon, 11 May 2020 17:46:41 -0400 Subject: [PATCH 21/27] Remove Empcraft messages --- .../java/com/sk89q/worldedit/command/GenerationCommands.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 8db4bdec4..e78809bf6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -134,8 +134,8 @@ public class GenerationCommands { @Arg(desc = "TODO", def = "100") int threshold, @Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException { TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold); URL url = new URL(argStr); - if (!url.getHost().equalsIgnoreCase("i.imgur.com") && !url.getHost().equalsIgnoreCase("empcraft.com")) { - throw new IOException("Only i.imgur.com or empcraft.com/ui links are allowed!"); + if (!url.getHost().equalsIgnoreCase("i.imgur.com")) { + throw new IOException("Only i.imgur.com links are allowed!"); } BufferedImage image = MainUtil.readImage(url); if (dimensions != null) { From 0fffdb98dc76d82d99ff8125bce73c8879d8f8d2 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Mon, 11 May 2020 23:53:27 +0200 Subject: [PATCH 22/27] Add crowdin link --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0a9757109..cb22e55f7 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ FAWE is a fork of WorldEdit that has huge speed and memory improvements and cons * [Discord](https://discord.gg/KxkjDVg) * [Wiki](https://github.com/IntellectualSites/FastAsyncWorldEdit-1.13/wiki) * [Report Issue](https://github.com/IntellectualSites/FastAsyncWorldEdit-1.13/issues) +* [Crowdin](https://intellectualsites.crowdin.com/fastasyncworldedit) ## Downloads ### 1.13+ From 44c5ab164c519e6239fbbdef47d0f1fc79f39929 Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Tue, 12 May 2020 11:11:24 +0200 Subject: [PATCH 23/27] Remove whitespace Regarding https://github.com/EngineHub/WorldEdit/pull/1339/commits/fc537b92e0c67e8ffc22c2523d8aac7c934b378e --- worldedit-core/src/main/resources/lang/strings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index bb33d8f28..f0abf6b9a 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -373,7 +373,7 @@ "worldedit.limit.set": "Block change limit set to {0}.", "worldedit.limit.return-to-default": "(Use //limit to go back to the default.)", "worldedit.timeout.too-high": "Your maximum allowable timeout is {0}ms.", - "worldedit.timeout.set": "Timeout time set to {0} ms.", + "worldedit.timeout.set": "Timeout time set to {0}ms.", "worldedit.timeout.return-to-default": " (Use //timeout to go back to the default.)", "worldedit.fast.disabled": "Fast mode disabled.", "worldedit.fast.enabled": "Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.", From 999b063762e209ad8fcb61af2bab3238e18e3077 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Tue, 12 May 2020 10:58:43 +0100 Subject: [PATCH 24/27] Don't write reserved to schematics --- .../worldedit/extent/clipboard/io/FastSchematicWriter.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicWriter.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicWriter.java index b57a50448..3bbb2c02d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicWriter.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicWriter.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.extent.clipboard.io; import com.boydti.fawe.jnbt.streamer.IntValueReader; import com.boydti.fawe.object.FaweOutputStream; -import com.boydti.fawe.object.clipboard.LinearClipboard; import com.boydti.fawe.util.IOUtil; import com.google.common.collect.Maps; import com.sk89q.jnbt.CompoundTag; @@ -45,7 +44,6 @@ import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypesCache; import net.jpountz.lz4.LZ4BlockInputStream; import net.jpountz.lz4.LZ4BlockOutputStream; @@ -181,6 +179,9 @@ public class FastSchematicWriter implements ClipboardWriter { } int ordinal = block.getOrdinal(); + if (ordinal == 0) { + ordinal = 1; + } char value = palette[ordinal]; if (value == Character.MAX_VALUE) { int size = paletteMax++; @@ -338,4 +339,4 @@ public class FastSchematicWriter implements ClipboardWriter { public void close() throws IOException { outputStream.close(); } -} \ No newline at end of file +} From 32c30f45fea5e223c66e4209fa5fef35660154cc Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Tue, 12 May 2020 11:00:54 +0100 Subject: [PATCH 25/27] don't read __reserved__ --- .../clipboard/io/FastSchematicReader.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java index 3b2332fb8..0263e334a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java @@ -223,11 +223,19 @@ public class FastSchematicReader extends NBTSchematicReader { int volume = width * height * length; if (palette.length < 128) { for (int index = 0; index < volume; index++) { - linear.setBlock(index, getBlockState(fis.read())); + int ordinal = fis.read(); + if (ordinal == 0) { + ordinal = 1; + } + linear.setBlock(index, getBlockState(ordinal)); } } else { for (int index = 0; index < volume; index++) { - linear.setBlock(index, getBlockState(fis.readVarInt())); + int ordinal = fis.readVarInt(); + if (ordinal == 0) { + ordinal = 1; + } + linear.setBlock(index, getBlockState(ordinal)); } } } else { @@ -235,7 +243,11 @@ public class FastSchematicReader extends NBTSchematicReader { for (int y = 0; y < height; y++) { for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++) { - clipboard.setBlock(x, y, z, getBlockState(fis.read())); + int ordinal = fis.read(); + if (ordinal == 0) { + ordinal = 1; + } + clipboard.setBlock(x, y, z, getBlockState(ordinal)); } } } @@ -243,7 +255,11 @@ public class FastSchematicReader extends NBTSchematicReader { for (int y = 0; y < height; y++) { for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++) { - clipboard.setBlock(x, y, z, getBlockState(fis.readVarInt())); + int ordinal = fis.readVarInt(); + if (ordinal == 0) { + ordinal = 1; + } + clipboard.setBlock(x, y, z, getBlockState(ordinal)); } } } From 1183c7c957a663b5bcfea953d79c6afd328aaa03 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Wed, 13 May 2020 10:23:38 -0400 Subject: [PATCH 26/27] Fixes #466 --- .../java/com/sk89q/worldedit/command/ClipboardCommands.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java index 76baa9082..59817d210 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ClipboardCommands.java @@ -72,6 +72,7 @@ import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TranslatableComponent; +import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.world.World; import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.CommandContainer; @@ -366,7 +367,7 @@ public class ClipboardCommands { e.printStackTrace(); } } - player.print(Caption.of("fawe.web.download.link" , urlText)); + player.print(Caption.of("fawe.web.download.link" , urlText).clickEvent(ClickEvent.openUrl(urlText))); } } From 2ccda8577210989ec31c1f1730446b868b904f99 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 May 2020 22:36:08 +0100 Subject: [PATCH 27/27] Fix #468 That's not how it works --- .../extent/clipboard/io/FastSchematicReader.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java index 0263e334a..64cdf882e 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/FastSchematicReader.java @@ -224,17 +224,11 @@ public class FastSchematicReader extends NBTSchematicReader { if (palette.length < 128) { for (int index = 0; index < volume; index++) { int ordinal = fis.read(); - if (ordinal == 0) { - ordinal = 1; - } linear.setBlock(index, getBlockState(ordinal)); } } else { for (int index = 0; index < volume; index++) { int ordinal = fis.readVarInt(); - if (ordinal == 0) { - ordinal = 1; - } linear.setBlock(index, getBlockState(ordinal)); } } @@ -244,9 +238,6 @@ public class FastSchematicReader extends NBTSchematicReader { for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++) { int ordinal = fis.read(); - if (ordinal == 0) { - ordinal = 1; - } clipboard.setBlock(x, y, z, getBlockState(ordinal)); } } @@ -256,9 +247,6 @@ public class FastSchematicReader extends NBTSchematicReader { for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++) { int ordinal = fis.readVarInt(); - if (ordinal == 0) { - ordinal = 1; - } clipboard.setBlock(x, y, z, getBlockState(ordinal)); } }