diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java index a0ebaadfa..a1b688151 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java @@ -83,6 +83,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class HybridUtils { private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + HybridUtils.class.getSimpleName()); + private static final BlockState AIR = BlockTypes.AIR.getDefaultState(); public static HybridUtils manager; public static Set regions; @@ -157,40 +158,28 @@ public class HybridUtils { final int height = area.getMaxGenHeight() - area.getMinGenHeight() + 1; final int minHeight = area.getMinGenHeight(); - final BlockState airBlock = BlockTypes.AIR.getDefaultState(); - final BlockState[][][] oldBlocks = new BlockState[height][width][length]; final BlockState[][][] newBlocks = new BlockState[height][width][length]; - for (final BlockState[][] newBlock : newBlocks) { - for (final BlockState[] blockStates : newBlock) { - Arrays.fill(blockStates, airBlock); - } - } - for (final BlockState[][] oldBlock : oldBlocks) { - for (final BlockState[] blockStates : oldBlock) { - Arrays.fill(blockStates, airBlock); - } - } BlockArrayCacheScopedQueueCoordinator oldBlockQueue = new BlockArrayCacheScopedQueueCoordinator( - oldBlocks, - area.getMinGenHeight(), - Location.at("", region.getMinimumPoint()), - Location.at("", region.getMaximumPoint()) + Location.at("", region.getMinimumPoint().withY(hpw.getMinGenHeight())), + Location.at("", region.getMaximumPoint().withY(hpw.getMaxGenHeight())) ); - region.getChunks().forEach(blockVector2 -> { - int relChunkX = blockVector2.getX() - cbx; - int relChunkZ = blockVector2.getZ() - cbz; + region.getChunks().forEach(chunkPos -> { + int relChunkX = chunkPos.getX() - cbx; + int relChunkZ = chunkPos.getZ() - cbz; oldBlockQueue.setOffsetX(relChunkX << 4); oldBlockQueue.setOffsetZ(relChunkZ << 4); hpw.getGenerator().generateChunk(oldBlockQueue, hpw); }); + final BlockState[][][] oldBlocks = oldBlockQueue.getBlockStates(); + QueueCoordinator queue = area.getQueue(); queue.addReadChunks(region.getChunks()); - queue.setChunkConsumer(blockVector2 -> { - int X = blockVector2.getX(); - int Z = blockVector2.getZ(); + queue.setChunkConsumer(chunkPos -> { + int X = chunkPos.getX(); + int Z = chunkPos.getZ(); int minX; if (X == cbx) { minX = bx & 15; @@ -228,6 +217,9 @@ public class HybridUtils { for (int yIndex = 0; yIndex < height; yIndex++) { int y = yIndex + minHeight; BlockState block = queue.getBlock(xx, y, zz); + if (block == null) { + block = AIR; + } int xr = xb + x; int zr = zb + z; newBlocks[yIndex][xr][zr] = block; @@ -248,10 +240,10 @@ public class HybridUtils { for (int z = 0; z < length; z++) { Set types = new HashSet<>(); for (int yIndex = 0; yIndex < height; yIndex++) { - BlockState old = oldBlocks[yIndex][x][z]; + BlockState old = oldBlocks[yIndex][x][z]; // Nullable try { - BlockState now = newBlocks[yIndex][x][z]; - if (!old.equals(now)) { + BlockState now = newBlocks[yIndex][x][z]; // Not null + if (!now.equals(old) && !(old == null && now.getBlockType().equals(BlockTypes.AIR))) { changes[i]++; } if (now.getBlockType().getMaterial().isAir()) { diff --git a/Core/src/main/java/com/plotsquared/core/queue/BlockArrayCacheScopedQueueCoordinator.java b/Core/src/main/java/com/plotsquared/core/queue/BlockArrayCacheScopedQueueCoordinator.java index 055fb1c1f..4d3a21a63 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/BlockArrayCacheScopedQueueCoordinator.java +++ b/Core/src/main/java/com/plotsquared/core/queue/BlockArrayCacheScopedQueueCoordinator.java @@ -37,7 +37,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; /** * {@link QueueCoordinator} that caches all blocks set to it in a given array of form BlockState[][][]. An offset can be - * applied to blocks set to it, and the scope limited. + * applied to blocks set to it, and the scope limited. This should have blocks set to it one chunk at a time, based on the + * result of {@link BlockArrayCacheScopedQueueCoordinator#getMin()} and {@link BlockArrayCacheScopedQueueCoordinator#getMax()}. + * The min and max points of this queue are offset according to the minimum point given in the constructor, and the offsets set + * in {@link BlockArrayCacheScopedQueueCoordinator#setOffsetX(int)} and + * {@link BlockArrayCacheScopedQueueCoordinator#setOffsetZ(int)} */ public class BlockArrayCacheScopedQueueCoordinator extends ScopedQueueCoordinator { @@ -51,39 +55,39 @@ public class BlockArrayCacheScopedQueueCoordinator extends ScopedQueueCoordinato private final int scopeMinZ; private final int scopeMaxX; private final int scopeMaxZ; - private int offsetX = 0; private int offsetZ = 0; - /** * Construct a new instance * - * @param blockStates Array of form BlockState[y][x][z]. Must be fully initialised. - * @param minY Minimum applicable y value. Used to account for negative world heights (e.g. -64). Inclusive - * @param min Inclusive location of the minimum point to limit the scope to. - * @param max Exclusive location of the maximum point to limit the scope to. + * @param min Inclusive location of the minimum point to limit the scope to. + * @param max Inclusive location of the maximum point to limit the scope to. * @since TODO */ - public BlockArrayCacheScopedQueueCoordinator(@NonNull BlockState[][][] blockStates, int minY, Location min, Location max) { + public BlockArrayCacheScopedQueueCoordinator(Location min, Location max) { super(null, min, max); - this.blockStates = blockStates; - this.height = blockStates.length; - this.width = blockStates[0].length; - this.length = blockStates[0][0].length; - this.minY = minY; - this.maxY = height + minY; // exclusive + this.width = max.getX() - min.getX() + 1; + this.length = max.getZ() - min.getZ() + 1; + this.minY = min.getY(); + this.maxY = max.getY(); + this.height = maxY - minY + 1; this.scopeMinX = min.getX() & 15; this.scopeMinZ = min.getZ() & 15; this.scopeMaxX = scopeMinX + width; this.scopeMaxZ = scopeMinZ + length; + this.blockStates = new BlockState[height][width][length]; + } + + public BlockState[][][] getBlockStates() { + return blockStates; } @Override public boolean setBlock(int x, final int y, int z, final @NonNull BlockState id) { x += offsetX; z += offsetZ; - if (x >= scopeMinX && x < scopeMaxX && y >= minY && y < maxY && z >= scopeMinZ && z < scopeMaxZ) { + if (x >= scopeMinX && x < scopeMaxX && y >= minY && y <= maxY && z >= scopeMinZ && z < scopeMaxZ) { blockStates[y - minY][x - scopeMinX][z - scopeMinZ] = id; } return false; @@ -93,7 +97,7 @@ public class BlockArrayCacheScopedQueueCoordinator extends ScopedQueueCoordinato public boolean setBlock(final int x, final int y, final int z, @NonNull final Pattern pattern) { int rx = x + offsetX; int rz = z + offsetZ; - if (rx >= scopeMinX && rx < scopeMaxX && y >= minY && y < maxY && rz >= scopeMinZ && rz < scopeMaxZ) { + if (rx >= scopeMinX && rx < scopeMaxX && y >= minY && y <= maxY && rz >= scopeMinZ && rz < scopeMaxZ) { BlockState state = pattern .applyBlock(super.getMin().getBlockVector3().add(BlockVector3.at(x, y, z))) .toImmutableState(); @@ -116,7 +120,7 @@ public class BlockArrayCacheScopedQueueCoordinator extends ScopedQueueCoordinato public boolean setBlock(int x, int y, int z, final @NonNull BaseBlock id) { x += offsetX; z += offsetZ; - if (x >= scopeMinX && x < scopeMaxX && y >= minY && y < maxY && z >= scopeMinZ && z < scopeMaxZ) { + if (x >= scopeMinX && x < scopeMaxX && y >= minY && y <= maxY && z >= scopeMinZ && z < scopeMaxZ) { blockStates[y - minY][x][z] = id.toImmutableState(); } return false; @@ -124,7 +128,7 @@ public class BlockArrayCacheScopedQueueCoordinator extends ScopedQueueCoordinato @Override public @Nullable BlockState getBlock(final int x, final int y, final int z) { - if (x >= 0 && x < width && y >= minY && y < maxY && z >= 0 && z < length) { + if (x >= 0 && x < width && y >= minY && y <= maxY && z >= 0 && z < length) { return blockStates[y - minY][x][z]; } return null;