diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index 3c64766c0..a985821e6 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -81,6 +81,9 @@ public class HybridPlotWorld extends ClassicPlotWorld { public short PATH_WIDTH_UPPER; public HashMap G_SCH; public HashMap G_SCH_B; + /** + * The Y level at which schematic generation will start, lowest of either road or plot schematic generation. + */ public int SCHEM_Y; private Location SIGN_LOCATION; private File root = null; @@ -273,33 +276,57 @@ public class HybridPlotWorld extends ClassicPlotWorld { int oddshift = (this.ROAD_WIDTH & 1); SCHEM_Y = schematicStartHeight(); + + // plotY and roadY are important to allow plot and/or road schematic "overflow" into each other without causing AIOOB + // exceptions when attempting either to set blocks to, or get block from G_SCH + // Default plot schematic start height, normalized to the minimum height schematics are pasted from. int plotY = PLOT_HEIGHT - SCHEM_Y; int minRoadWall = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? Math.min(ROAD_HEIGHT, WALL_HEIGHT) : ROAD_HEIGHT; + // Default road schematic start height, normalized to the minimum height schematics are pasted from. int roadY = minRoadWall - SCHEM_Y; - int worldHeight = getMaxGenHeight() - getMinGenHeight() + 1; + int worldGenHeight = getMaxGenHeight() - getMinGenHeight() + 1; + + int maxSchematicHeight = 0; // SCHEM_Y should be normalised to the plot "start" height if (schematic3 != null) { - if (schematic3.getClipboard().getDimensions().getY() == worldHeight) { - SCHEM_Y = plotY = 0; + if ((maxSchematicHeight = schematic3.getClipboard().getDimensions().getY()) == worldGenHeight) { + SCHEM_Y = getMinGenHeight(); + plotY = 0; } else if (!Settings.Schematics.PASTE_ON_TOP) { - SCHEM_Y = plotY = getMinBuildHeight() - getMinGenHeight(); + SCHEM_Y = getMinBuildHeight(); + plotY = 0; } } if (schematic1 != null) { - if (schematic1.getClipboard().getDimensions().getY() == worldHeight) { - SCHEM_Y = roadY = getMinGenHeight(); - if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldHeight - && !Settings.Schematics.PASTE_ON_TOP) { - plotY = PLOT_HEIGHT; + if ((maxSchematicHeight = Math.max( + schematic1.getClipboard().getDimensions().getY(), + maxSchematicHeight + )) == worldGenHeight) { + SCHEM_Y = getMinGenHeight(); + roadY = 0; // Road is the lowest schematic + if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldGenHeight) { + // Road is the lowest schematic. Normalize plotY to it. + if (Settings.Schematics.PASTE_ON_TOP) { + plotY = PLOT_HEIGHT - getMinGenHeight(); + } else { + plotY = getMinBuildHeight() - getMinGenHeight(); + } } } else if (!Settings.Schematics.PASTE_ROAD_ON_TOP) { - SCHEM_Y = roadY = getMinBuildHeight(); - if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldHeight - && !Settings.Schematics.PASTE_ON_TOP) { - plotY = PLOT_HEIGHT; + if (SCHEM_Y == getMinGenHeight()) { // Only possible if plot schematic is enabled + // Plot is still the lowest schematic, normalize roadY to it + roadY = getMinBuildHeight() - getMinGenHeight(); + } else if (schematic3 != null) { + SCHEM_Y = getMinBuildHeight(); + roadY = 0;// Road is the lowest schematic + if (Settings.Schematics.PASTE_ON_TOP) { + // Road is the lowest schematic. Normalize plotY to it. + plotY = PLOT_HEIGHT - getMinBuildHeight(); + } + // If plot schematic is not paste-on-top, it will be from min build height thus plotY = 0 as well already. } } } @@ -337,17 +364,15 @@ public class HybridPlotWorld extends ClassicPlotWorld { y + min.getBlockY(), z + min.getBlockZ() )); - if (!id.getBlockType().getMaterial().isAir()) { - schem3PopulationNeeded |= id.hasNbtData(); - addOverlayBlock( - (short) (x + shift + oddshift + centerShiftX), - (short) (y + plotY), - (short) (z + shift + oddshift + centerShiftZ), - id, - false, - h3 - ); - } + schem3PopulationNeeded |= id.hasNbtData(); + addOverlayBlock( + (short) (x + shift + oddshift + centerShiftX), + (short) (y + plotY), + (short) (z + shift + oddshift + centerShiftZ), + id, + false, + maxSchematicHeight + ); } if (blockArrayClipboard3.hasBiomes()) { BiomeType biome = blockArrayClipboard3.getBiome(BlockVector2.at( @@ -397,18 +422,23 @@ public class HybridPlotWorld extends ClassicPlotWorld { y + min.getBlockY(), z + min.getBlockZ() )); - if (!id.getBlockType().getMaterial().isAir()) { - schem1PopulationNeeded |= id.hasNbtData(); - addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z + shift + oddshift), id, false, h1); - addOverlayBlock( - (short) (z + shift + oddshift), - (short) (y + roadY), - (short) (shift - x + (oddshift - 1)), - id, - true, - h1 - ); - } + schem1PopulationNeeded |= id.hasNbtData(); + addOverlayBlock( + (short) (x - shift), + (short) (y + roadY), + (short) (z + shift + oddshift), + id, + false, + maxSchematicHeight + ); + addOverlayBlock( + (short) (z + shift + oddshift), + (short) (y + roadY), + (short) (shift - x + (oddshift - 1)), + id, + true, + maxSchematicHeight + ); } if (blockArrayClipboard1.hasBiomes()) { BiomeType biome = blockArrayClipboard1.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); @@ -436,10 +466,15 @@ public class HybridPlotWorld extends ClassicPlotWorld { y + min.getBlockY(), z + min.getBlockZ() )); - if (!id.getBlockType().getMaterial().isAir()) { - schem2PopulationNeeded |= id.hasNbtData(); - addOverlayBlock((short) (x - shift), (short) (y + roadY), (short) (z - shift), id, false, h2); - } + schem2PopulationNeeded |= id.hasNbtData(); + addOverlayBlock( + (short) (x - shift), + (short) (y + roadY), + (short) (z - shift), + id, + false, + maxSchematicHeight + ); } if (blockArrayClipboard2.hasBiomes()) { BiomeType biome = blockArrayClipboard2.getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); @@ -449,6 +484,11 @@ public class HybridPlotWorld extends ClassicPlotWorld { } } + /** + * @deprecated This method should not be available for public API usage and will be made private. + * @since TODO + */ + @Deprecated(forRemoval = true, since = "TODO") public void addOverlayBlock(short x, short y, short z, BaseBlock id, boolean rotate, int height) { if (z < 0) { z += this.SIZE; @@ -475,6 +515,11 @@ public class HybridPlotWorld extends ClassicPlotWorld { existing[y] = id; } + /** + * @deprecated This method should not be available for public API usage and will be made private. + * @since TODO + */ + @Deprecated(forRemoval = true, since = "TODO") public void addOverlayBiome(short x, short z, BiomeType id) { if (z < 0) { z += this.SIZE;