- 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"
This commit is contained in:
dordsor21 2020-05-09 13:39:41 +01:00
parent 56c720914e
commit ffa25b1d9a
7 changed files with 51 additions and 10 deletions

View File

@ -162,7 +162,8 @@ public class ParallelQueueExtent extends PassthroughExtent implements IQueueWrap
@Override @Override
public int replaceBlocks(Region region, Mask mask, Pattern pattern) public int replaceBlocks(Region region, Mask mask, Pattern pattern)
throws MaxChangedBlocksException { 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 @Override

View File

@ -189,7 +189,15 @@ public class BlockMask extends ABlockMask {
@Override @Override
public boolean test(Extent extent, BlockVector3 vector) { 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 @Override

View File

@ -26,6 +26,8 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -65,6 +67,11 @@ public class BlockStateMask extends AbstractExtentMask {
.allMatch(entry -> block.getState(entry.getKey()) == entry.getValue()); .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 @Nullable
@Override @Override
public Mask2D toMask2D() { public Mask2D toMask2D() {

View File

@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull;
public class BlockTypeMask extends AbstractExtentMask { public class BlockTypeMask extends AbstractExtentMask {
private final boolean[] types; private final boolean[] types;
private boolean hasAir;
/** /**
* Create a new block mask. * Create a new block mask.
@ -63,7 +64,9 @@ public class BlockTypeMask extends AbstractExtentMask {
public BlockTypeMask(Extent extent, @NotNull BlockType... block) { public BlockTypeMask(Extent extent, @NotNull BlockType... block) {
super(extent); super(extent);
this.types = new boolean[BlockTypes.size()]; 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) { for (BlockType type : blocks) {
add(type); 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) { public void add(@NotNull BlockType... block) {
for (BlockType type : 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; this.types[type.getInternalId()] = true;
} }
} }
@ -110,6 +113,11 @@ public class BlockTypeMask extends AbstractExtentMask {
return test(vector.getBlock(extent).getBlockType()); return test(vector.getBlock(extent).getBlockType());
} }
@Override
public boolean replacesAir() {
return hasAir;
}
public boolean test(BlockType block) { public boolean test(BlockType block) {
return types[block.getInternalId()]; return types[block.getInternalId()];
} }

View File

@ -123,4 +123,8 @@ public interface Mask {
} }
}; };
} }
default boolean replacesAir() {
return false;
}
} }

View File

@ -1,13 +1,12 @@
package com.sk89q.worldedit.function.mask; package com.sk89q.worldedit.function.mask;
import com.boydti.fawe.Fawe;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
public class SingleBlockStateMask extends ABlockMask { public class SingleBlockStateMask extends ABlockMask {
private final char ordinal; private final char ordinal;
private final boolean isAir;
public BlockState getBlockState() { public BlockState getBlockState() {
return BlockState.getFromOrdinal(ordinal); return BlockState.getFromOrdinal(ordinal);
@ -15,12 +14,14 @@ public class SingleBlockStateMask extends ABlockMask {
public SingleBlockStateMask(Extent extent, BlockState state) { public SingleBlockStateMask(Extent extent, BlockState state) {
super(extent); super(extent);
isAir = state.isAir();
this.ordinal = state.getOrdinalChar(); this.ordinal = state.getOrdinalChar();
} }
@Override @Override
public boolean test(Extent extent, BlockVector3 vector) { public boolean test(Extent extent, BlockVector3 vector) {
return ordinal == vector.getOrdinal(extent); int test = vector.getOrdinal(extent);
return ordinal == test || isAir && test == 0;
} }
@Override @Override
@ -33,6 +34,11 @@ public class SingleBlockStateMask extends ABlockMask {
return new InverseSingleBlockStateMask(getExtent(), BlockState.getFromOrdinal(ordinal)); return new InverseSingleBlockStateMask(getExtent(), BlockState.getFromOrdinal(ordinal));
} }
@Override
public boolean replacesAir() {
return isAir;
}
@Override @Override
public Mask tryCombine(Mask mask) { public Mask tryCombine(Mask mask) {
if (mask instanceof ABlockMask) { if (mask instanceof ABlockMask) {

View File

@ -8,10 +8,12 @@ import com.sk89q.worldedit.world.block.BlockTypesCache;
public class SingleBlockTypeMask extends ABlockMask { public class SingleBlockTypeMask extends ABlockMask {
private final int internalId; private final int internalId;
private final boolean isAir;
public SingleBlockTypeMask(Extent extent, BlockType type) { public SingleBlockTypeMask(Extent extent, BlockType type) {
super(extent); super(extent);
this.internalId = type.getInternalId(); isAir = type == BlockTypes.AIR || type == BlockTypes.CAVE_AIR || type == BlockTypes.VOID_AIR;
this.internalId = type.getInternalId();
} }
@Override @Override
@ -27,4 +29,9 @@ public class SingleBlockTypeMask extends ABlockMask {
public BlockType getBlockType() { public BlockType getBlockType() {
return BlockTypes.get(internalId); return BlockTypes.get(internalId);
} }
@Override
public boolean replacesAir() {
return isAir;
}
} }