From ffa25b1d9a5be02218e34bc81a01849fb061108e Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 9 May 2020 13:39:41 +0100 Subject: [PATCH] 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; + } }