From 90f920ba31244520e033516cc531e7264322b386 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 6 Jul 2023 15:14:29 +0100 Subject: [PATCH] fix: even better handling of schematic heights - Fixes #4083 - Fixes #4050 (with WorldEdit not FAWE) - Pre-requisite of fixing schematic issues in FAWE as well --- .../bukkit/generator/BukkitPlotGenerator.java | 7 +++- .../plotsquared/core/generator/HybridGen.java | 4 +-- .../core/generator/HybridPlotManager.java | 11 ++++-- .../core/generator/HybridPlotWorld.java | 36 +++++++++++++++---- .../core/generator/HybridUtils.java | 2 +- .../plot/world/DefaultPlotAreaManager.java | 4 +-- 6 files changed, 49 insertions(+), 15 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java index 6d7e2accb..bfccaeb3d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/generator/BukkitPlotGenerator.java @@ -34,6 +34,7 @@ import com.plotsquared.core.queue.ZeroedDelegateScopedQueueCoordinator; import com.plotsquared.core.util.ChunkManager; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bukkit.HeightMap; @@ -420,7 +421,11 @@ public class BukkitPlotGenerator extends ChunkGenerator implements GeneratorWrap if (lastPlotArea != null && name.equals(this.levelName) && chunkX == lastChunkX && chunkZ == lastChunkZ) { return lastPlotArea; } - PlotArea area = UncheckedWorldLocation.at(name, chunkX << 4, 0, chunkZ << 4).getPlotArea(); + BlockVector3 loc = BlockVector3.at(chunkX << 4, 0, chunkZ << 4); + if (lastPlotArea != null && lastPlotArea.getRegion().contains(loc) && lastPlotArea.getRegion().contains(loc)) { + return lastPlotArea; + } + PlotArea area = UncheckedWorldLocation.at(name, loc).getPlotArea(); if (area == null) { throw new IllegalStateException(String.format( "Cannot generate chunk that does not belong to a plot area. World: %s", diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java b/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java index a51d86004..175184c9c 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridGen.java @@ -69,8 +69,8 @@ public class HybridGen extends IndependentPlotGenerator { EnumSet features ) { int minY; // Math.min(world.PLOT_HEIGHT, world.ROAD_HEIGHT); - if ((features.contains(SchematicFeature.ROAD) && Settings.Schematics.PASTE_ROAD_ON_TOP) - || (!features.contains(SchematicFeature.ROAD) && Settings.Schematics.PASTE_ON_TOP)) { + boolean isRoad = features.contains(SchematicFeature.ROAD); + if ((isRoad && Settings.Schematics.PASTE_ROAD_ON_TOP) || (!isRoad && Settings.Schematics.PASTE_ON_TOP)) { minY = world.SCHEM_Y; } else { minY = world.getMinBuildHeight(); diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java index 92b3c9a27..2ecdff4a2 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotManager.java @@ -162,6 +162,7 @@ public class HybridPlotManager extends ClassicPlotManager { } else { minY = hybridPlotWorld.getMinBuildHeight(); } + int schemYDiff = (isRoad ? hybridPlotWorld.getRoadYStart() : hybridPlotWorld.getPlotYStart()) - minY; BaseBlock airBlock = BlockTypes.AIR.getDefaultState().toBaseBlock(); for (int x = pos1.getX(); x <= pos2.getX(); x++) { short absX = (short) ((x - hybridPlotWorld.ROAD_OFFSET_X) % size); @@ -178,10 +179,14 @@ public class HybridPlotManager extends ClassicPlotManager { for (int y = 0; y < blocks.length; y++) { if (blocks[y] != null) { queue.setBlock(x, minY + y, z, blocks[y]); - } else if (!isRoad) { - // This is necessary, otherwise any blocks not specified in the schematic will remain after a clear - // Do not set air for road as this may cause cavernous roads when debugroadregen is used + } else if (y > schemYDiff) { + // This is necessary, otherwise any blocks not specified in the schematic will remain after a clear. + // This should only be done where the schematic has actually "started" queue.setBlock(x, minY + y, z, airBlock); + } else if (isRoad) { + queue.setBlock(x, minY + y, z, hybridPlotWorld.ROAD_BLOCK.toPattern()); + } else { + queue.setBlock(x, minY + y, z, hybridPlotWorld.MAIN_BLOCK.toPattern()); } } } 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 679a1b2df..c636fc6af 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -76,6 +76,9 @@ public class HybridPlotWorld extends ClassicPlotWorld { * The Y level at which schematic generation will start, lowest of either road or plot schematic generation. */ public int SCHEM_Y; + + private int plotY; + private int roadY; private Location SIGN_LOCATION; private File root = null; private int lastOverlayHeightError = Integer.MIN_VALUE; @@ -252,13 +255,13 @@ public class HybridPlotWorld extends ClassicPlotWorld { 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 + // 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; + 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; + roadY = minRoadWall - SCHEM_Y; int worldGenHeight = getMaxGenHeight() - getMinGenHeight() + 1; @@ -267,14 +270,15 @@ public class HybridPlotWorld extends ClassicPlotWorld { // SCHEM_Y should be normalised to the plot "start" height if (schematic3 != null) { - plotSchemHeight = maxSchematicHeight = schematic3.getClipboard().getDimensions().getY(); - if (maxSchematicHeight == worldGenHeight) { + plotSchemHeight = schematic3.getClipboard().getDimensions().getY(); + if (plotSchemHeight == worldGenHeight) { SCHEM_Y = getMinGenHeight(); plotY = 0; } else if (!Settings.Schematics.PASTE_ON_TOP) { SCHEM_Y = getMinBuildHeight(); plotY = 0; } + maxSchematicHeight = plotY + plotSchemHeight; } int roadSchemHeight; @@ -554,4 +558,24 @@ public class HybridPlotWorld extends ClassicPlotWorld { return this.root; } + /** + * Get the y value where the plot schematic should be pasted from. + * + * @return plot schematic y start value + * @since TODO + */ + public int getPlotYStart() { + return SCHEM_Y + plotY; + } + + /** + * Get the y value where the road schematic should be pasted from. + * + * @return road schematic y start value + * @since TODO + */ + public int getRoadYStart() { + return SCHEM_Y + roadY; + } + } 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 31523ba3b..f151c8ebd 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridUtils.java @@ -668,7 +668,7 @@ public class HybridUtils { } if (condition) { BaseBlock[] blocks = plotWorld.G_SCH.get(MathMan.pair(absX, absZ)); - int minY = Settings.Schematics.PASTE_ROAD_ON_TOP ? plotWorld.SCHEM_Y : area.getMinGenHeight() + 1; + int minY = plotWorld.getRoadYStart(); int maxDy = Math.max(extend, blocks.length); for (int dy = 0; dy < maxDy; dy++) { if (dy > blocks.length - 1) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java index e51e01eb3..0016ec71d 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java @@ -29,17 +29,17 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; @Singleton public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - private final Map plotWorlds = new HashMap<>(); + private final Map plotWorlds = new ConcurrentHashMap<>(); @Override public @NonNull PlotArea[] getAllPlotAreas() {