- 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
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

View File

@ -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

View File

@ -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() {

View File

@ -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()];
}

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;
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) {

View File

@ -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;
}
}