diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java index c495dc47..70cf8c1b 100644 --- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java +++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/HeightMapMCAGenerator.java @@ -1058,6 +1058,13 @@ public class HeightMapMCAGenerator extends MCAWriter implements SimpleWorld, Faw return heights.getByte(index) & 0xFF; } + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { + int index = z * getWidth() + x; + if (index < 0 || index >= getArea()) index = Math.floorMod(index, getArea()); + return heights.getByte(index) & 0xFF; + } + public void setBiome(BufferedImage img, byte biome, boolean white) { if (img.getWidth() != getWidth() || img.getHeight() != getLength()) throw new IllegalArgumentException("Input image dimensions do not match the current height map!"); diff --git a/core/src/main/java/com/boydti/fawe/object/queue/IDelegateFaweQueue.java b/core/src/main/java/com/boydti/fawe/object/queue/IDelegateFaweQueue.java index d8d5acf6..a000c271 100644 --- a/core/src/main/java/com/boydti/fawe/object/queue/IDelegateFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/object/queue/IDelegateFaweQueue.java @@ -483,6 +483,11 @@ public interface IDelegateFaweQueue extends FaweQueue { return getQueue().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); } + @Override + default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { + return getQueue().getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); + } + @Override default void addCaves(Region region) throws WorldEditException { getQueue().addCaves(region); diff --git a/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index 86dc8344..456d80a3 100644 --- a/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -202,6 +202,11 @@ public class AbstractDelegateExtent implements LightingExtent { return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); } + @Override + public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { + return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); + } + @Override public final @Nullable diff --git a/core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/core/src/main/java/com/sk89q/worldedit/extent/Extent.java index 15eb366b..7a709c56 100644 --- a/core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -118,10 +118,14 @@ public interface Extent extends InputExtent, OutputExtent { } } } - return maxY << 4; + return (state ? minY : maxY) << 4; } public default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { + return getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, minY, maxY); + } + + public default int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) { y = Math.max(minY, Math.min(maxY, y)); int clearanceAbove = maxY - y; int clearanceBelow = y - minY; @@ -150,7 +154,7 @@ public interface Extent extends InputExtent, OutputExtent { } } } - return maxY == 255 && minY == 0 ? maxY : -1; + return state ? failedMin : failedMax; } default public void addCaves(Region region) throws WorldEditException { diff --git a/core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java b/core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java index cc8d1c5b..b6c8e3e2 100644 --- a/core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java +++ b/core/src/main/java/com/sk89q/worldedit/math/convolution/HeightMap.java @@ -25,6 +25,7 @@ public class HeightMap { private final boolean layers; private int[] data; + private boolean[] invalid; private int width; private int height; @@ -62,12 +63,12 @@ public class HeightMap { int minZ = region.getMinimumPoint().getBlockZ(); int maxY = region.getMaximumPoint().getBlockY(); + data = new int[width * height]; + invalid = new boolean[data.length]; + if (layers) { Vector min = region.getMinimumPoint(); Vector max = region.getMaximumPoint(); - int width = region.getWidth(); - int height = region.getLength(); - data = new int[width * height]; int bx = min.getBlockX(); int bz = min.getBlockZ(); Iterable flat = Regions.asFlatRegion(region).asFlatRegion(); @@ -83,7 +84,6 @@ public class HeightMap { } } else { // Store current heightmap data - data = new int[width * height]; int index = 0; if (naturalOnly) { for (int z = 0; z < height; ++z) { @@ -95,13 +95,25 @@ public class HeightMap { int yTmp = 255; for (int z = 0; z < height; ++z) { for (int x = 0; x < width; ++x, index++) { - data[index] = yTmp = session.getNearestSurfaceTerrainBlock(x + minX, z + minZ, yTmp, minY, maxY); + yTmp = session.getNearestSurfaceTerrainBlock(x + minX, z + minZ, yTmp, minY, maxY, Integer.MIN_VALUE, Integer.MAX_VALUE); + switch (yTmp) { + case Integer.MIN_VALUE: + yTmp = minY; + invalid[index] = true; + break; + case Integer.MAX_VALUE: + yTmp = maxY; + invalid[index] = true; + break; + } + data[index] = yTmp; } } } } } + @Deprecated public HeightMap(EditSession session, Region region, int[] data, boolean layers) { this.session = session; this.region = region; @@ -179,7 +191,7 @@ public class HeightMap { int zr = z + originZ; for (int x = 0; x < width; ++x) { int curHeight = this.data[index]; - if (curHeight == -1) continue; + if (this.invalid != null && this.invalid[index]) continue; int newHeight = Math.min(maxY4, data[index++]); int curBlock = (curHeight) >> 3; int newBlock = (newHeight + 7) >> 3; @@ -235,7 +247,6 @@ public class HeightMap { } public int apply(int[] data) throws WorldEditException { - long start = System.currentTimeMillis(); checkNotNull(data); Vector minY = region.getMinimumPoint(); @@ -254,10 +265,11 @@ public class HeightMap { int index = 0; for (int z = 0; z < height; ++z) { int zr = z + originZ; - for (int x = 0; x < width; ++x) { + for (int x = 0; x < width; ++x, index++) { int curHeight = this.data[index]; - if (curHeight == -1) continue; - int newHeight = Math.min(maxY, data[index++]); + if (this.invalid != null && this.invalid[index]) continue; + int newHeight = Math.min(maxY, data[index]); + int xr = x + originX; // Depending on growing or shrinking we need to start at the bottom or top