mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-25 15:43:44 +02:00 
			
		
		
		
	Compare commits
	
		
			22 Commits
		
	
	
		
			renovate/c
			...
			refactor/v
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 676ca9fdf1 | ||
|   | efc2083798 | ||
|   | 3a6f845c01 | ||
|   | 7efd42ae45 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | f43f4cbf5d | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 104cc4b7a4 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 218be43143 | ||
|   | 308dba5601 | ||
|   | 5f233bb5d1 | ||
|   | 5e188d114f | ||
|   | 660e05d27f | ||
|   | 4c0ad148bf | ||
|   | 5c7bfb988c | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | b46f486680 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 05797d0c78 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 36ef2cf9ba | ||
|   | 26ec31a012 | ||
|   | fd4a542062 | ||
|   | dc13f2565f | ||
|   | 9f632af0ae | ||
|   | d698c6a1e5 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 40e1bd9897 | 
							
								
								
									
										1
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							| @@ -27,6 +27,7 @@ body: | ||||
|       description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. | ||||
|       multiple: false | ||||
|       options: | ||||
|         - '1.18.2' | ||||
|         - '1.18.1' | ||||
|         - '1.18' | ||||
|         - '1.17.1' | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ jobs: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Checkout Repository | ||||
|         uses: actions/checkout@v2.4.0 | ||||
|         uses: actions/checkout@v3.0.0 | ||||
|       - name: Validate Gradle Wrapper" | ||||
|         uses: gradle/wrapper-validation-action@v1.0.4 | ||||
|       - name: Setup Java | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,7 +23,7 @@ jobs: | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v2 | ||||
|         uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Initialize CodeQL | ||||
|         uses: github/codeql-action/init@v1 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/release-drafter.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/release-drafter.yml
									
									
									
									
										vendored
									
									
								
							| @@ -14,6 +14,6 @@ jobs: | ||||
|     if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: release-drafter/release-drafter@v5.18.1 | ||||
|       - uses: release-drafter/release-drafter@v5.19.0 | ||||
|         env: | ||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||
|   | ||||
| @@ -238,6 +238,16 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|         return this.version; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int versionMinHeight() { | ||||
|         return serverVersion()[1] >= 18 ? -64 : 0; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int versionMaxHeight() { | ||||
|         return serverVersion()[1] >= 18 ? 319 : 255; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull String serverImplementation() { | ||||
|         return Bukkit.getVersion(); | ||||
|   | ||||
| @@ -65,7 +65,10 @@ final class BlockStatePopulator extends BlockPopulator { | ||||
|             return; | ||||
|         } | ||||
|         final ChunkWrapper wrap = new ChunkWrapper(area.getWorldName(), source.getX(), source.getZ()); | ||||
|         final ScopedQueueCoordinator chunk = this.queue.getForChunk(wrap.x, wrap.z); | ||||
|         final ScopedQueueCoordinator chunk = this.queue.getForChunk(wrap.x, wrap.z, | ||||
|                 com.plotsquared.bukkit.util.BukkitWorld.getMinWorldHeight(world), | ||||
|                 com.plotsquared.bukkit.util.BukkitWorld.getMaxWorldHeight(world) - 1 | ||||
|         ); | ||||
|         if (this.plotGenerator.populateChunk(chunk, area)) { | ||||
|             this.queue.enqueue(); | ||||
|         } | ||||
|   | ||||
| @@ -27,6 +27,7 @@ package com.plotsquared.bukkit.generator; | ||||
|  | ||||
| import com.plotsquared.bukkit.queue.GenChunk; | ||||
| import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.plotsquared.bukkit.util.BukkitWorld; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.generator.GeneratorWrapper; | ||||
| import com.plotsquared.core.generator.IndependentPlotGenerator; | ||||
| @@ -159,12 +160,14 @@ public class BukkitPlotGenerator extends ChunkGenerator | ||||
|             @NonNull BiomeGrid biome | ||||
|     ) { | ||||
|  | ||||
|         GenChunk result = new GenChunk(); | ||||
|         int minY = BukkitWorld.getMinWorldHeight(world); | ||||
|         int maxY = BukkitWorld.getMaxWorldHeight(world); | ||||
|         GenChunk result = new GenChunk(minY, maxY); | ||||
|         if (this.getPlotGenerator() instanceof SingleWorldGenerator) { | ||||
|             if (result.getChunkData() != null) { | ||||
|                 for (int chunkX = 0; chunkX < 16; chunkX++) { | ||||
|                     for (int chunkZ = 0; chunkZ < 16; chunkZ++) { | ||||
|                         for (int y = 0; y < world.getMaxHeight(); y++) { | ||||
|                         for (int y = minY; y < maxY; y++) { | ||||
|                             biome.setBiome(chunkX, y, chunkZ, Biome.PLAINS); | ||||
|  | ||||
|                         } | ||||
|   | ||||
| @@ -354,7 +354,8 @@ public class BlockEventListener implements Listener { | ||||
|         Plot plot = area.getPlot(location); | ||||
|         if (plot != null) { | ||||
|             BukkitPlayer plotPlayer = BukkitUtil.adapt(player); | ||||
|             if (event.getBlock().getY() == 0) { | ||||
|             // == rather than <= as we only care about the "ground level" not being destroyed | ||||
|             if (event.getBlock().getY() == area.getMinGenHeight()) { | ||||
|                 if (!Permissions | ||||
|                         .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) { | ||||
|                     plotPlayer.sendMessage( | ||||
| @@ -649,7 +650,8 @@ public class BlockEventListener implements Listener { | ||||
|                     event.getBlock().breakNaturally(); | ||||
|                 } | ||||
|             } | ||||
|             if (location.getY() == 0) { | ||||
|             // == rather than <= as we only care about the "ground level" not being destroyed | ||||
|             if (location.getY() == area.getMinGenHeight()) { | ||||
|                 event.setCancelled(true); | ||||
|                 return; | ||||
|             } | ||||
|   | ||||
| @@ -76,7 +76,6 @@ import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.Permissions; | ||||
| import com.plotsquared.core.util.PremiumVerification; | ||||
| import com.plotsquared.core.util.RegExUtil; | ||||
| import com.plotsquared.core.util.entity.EntityCategories; | ||||
| import com.plotsquared.core.util.task.TaskManager; | ||||
| import com.plotsquared.core.util.task.TaskTime; | ||||
| @@ -223,10 +222,9 @@ public class PlayerEventListener extends PlotListener implements Listener { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @SuppressWarnings("StringSplitter") | ||||
|     @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) | ||||
|     public void playerCommand(PlayerCommandPreprocessEvent event) { | ||||
|         String msg = event.getMessage().toLowerCase().replaceAll("/", "").trim(); | ||||
|         String msg = event.getMessage().replace("/", "").toLowerCase(Locale.ROOT).trim(); | ||||
|         if (msg.isEmpty()) { | ||||
|             return; | ||||
|         } | ||||
| @@ -240,11 +238,9 @@ public class PlayerEventListener extends PlotListener implements Listener { | ||||
|         String[] parts = msg.split(" "); | ||||
|         Plot plot = plotPlayer.getCurrentPlot(); | ||||
|         // Check WorldEdit | ||||
|         switch (parts[0].toLowerCase()) { | ||||
|         switch (parts[0]) { | ||||
|             case "up": | ||||
|             case "/up": | ||||
|             case "worldedit:up": | ||||
|             case "worldedit:/up": | ||||
|                 if (plot == null || (!plot.isAdded(plotPlayer.getUUID()) && !Permissions | ||||
|                         .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_BUILD_OTHER, true))) { | ||||
|                     event.setCancelled(true); | ||||
| @@ -258,15 +254,40 @@ public class PlayerEventListener extends PlotListener implements Listener { | ||||
|         List<String> blockedCommands = plot != null ? | ||||
|                 plot.getFlag(BlockedCmdsFlag.class) : | ||||
|                 area.getFlag(BlockedCmdsFlag.class); | ||||
|         if (!blockedCommands.isEmpty() && !Permissions | ||||
|                 .hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { | ||||
|             String part = parts[0]; | ||||
|             if (parts[0].contains(":")) { | ||||
|                 part = parts[0].split(":")[1]; | ||||
|                 msg = msg.replace(parts[0].split(":")[0] + ':', ""); | ||||
|         if (blockedCommands.isEmpty()) { | ||||
|             return; | ||||
|         } | ||||
|         if (Permissions.hasPermission(plotPlayer, Permission.PERMISSION_ADMIN_INTERACT_BLOCKED_CMDS)) { | ||||
|             return; | ||||
|         } | ||||
|         // When using namespaced commands, we're not interested in the namespace | ||||
|         String part = parts[0]; | ||||
|         if (part.contains(":")) { | ||||
|             String[] namespaced = part.split(":"); | ||||
|             part = namespaced[1]; | ||||
|             msg = msg.substring(namespaced[0].length() + 1); | ||||
|         } | ||||
|         msg = replaceAliases(msg, part); | ||||
|         for (String blocked : blockedCommands) { | ||||
|             if (blocked.equalsIgnoreCase(msg)) { | ||||
|                 String perm; | ||||
|                 if (plot != null && plot.isAdded(plotPlayer.getUUID())) { | ||||
|                     perm = "plots.admin.command.blocked-cmds.shared"; | ||||
|                 } else { | ||||
|                     perm = "plots.admin.command.blocked-cmds.road"; | ||||
|                 } | ||||
|                 if (!Permissions.hasPermission(plotPlayer, perm)) { | ||||
|                     plotPlayer.sendMessage(TranslatableCaption.of("blockedcmds.command_blocked")); | ||||
|                     event.setCancelled(true); | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private String replaceAliases(String msg, String part) { | ||||
|         String s1 = part; | ||||
|             List<String> aliases = new ArrayList<>(); | ||||
|         Set<String> aliases = new HashSet<>(); | ||||
|         for (HelpTopic cmdLabel : Bukkit.getServer().getHelpMap().getHelpTopics()) { | ||||
|             if (part.equals(cmdLabel.getName())) { | ||||
|                 break; | ||||
| @@ -275,8 +296,8 @@ public class PlayerEventListener extends PlotListener implements Listener { | ||||
|             if (aliases.contains(label)) { | ||||
|                 continue; | ||||
|             } | ||||
|                 PluginCommand p; | ||||
|                 if ((p = Bukkit.getPluginCommand(label)) != null) { | ||||
|             PluginCommand p = Bukkit.getPluginCommand(label); | ||||
|             if (p != null) { | ||||
|                 for (String a : p.getAliases()) { | ||||
|                     if (aliases.contains(a)) { | ||||
|                         continue; | ||||
| @@ -293,28 +314,7 @@ public class PlayerEventListener extends PlotListener implements Listener { | ||||
|         if (!s1.equals(part)) { | ||||
|             msg = msg.replace(s1, part); | ||||
|         } | ||||
|             for (String s : blockedCommands) { | ||||
|                 Pattern pattern; | ||||
|                 if (!RegExUtil.compiledPatterns.containsKey(s)) { | ||||
|                     RegExUtil.compiledPatterns.put(s, pattern = Pattern.compile(s)); | ||||
|                 } else { | ||||
|                     pattern = RegExUtil.compiledPatterns.get(s); | ||||
|                 } | ||||
|                 if (pattern.matcher(msg).matches()) { | ||||
|                     String perm; | ||||
|                     if (plot != null && plot.isAdded(plotPlayer.getUUID())) { | ||||
|                         perm = "plots.admin.command.blocked-cmds.shared"; | ||||
|                     } else { | ||||
|                         perm = "plots.admin.command.blocked-cmds.road"; | ||||
|                     } | ||||
|                     if (!Permissions.hasPermission(plotPlayer, perm)) { | ||||
|                         plotPlayer.sendMessage(TranslatableCaption.of("blockedcmds.command_blocked")); | ||||
|                         event.setCancelled(true); | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return msg; | ||||
|     } | ||||
|  | ||||
|     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) | ||||
|   | ||||
| @@ -46,7 +46,7 @@ import static com.plotsquared.core.util.ReflectionUtils.getRefClass; | ||||
| public class SingleWorldListener implements Listener { | ||||
|  | ||||
|     private final Method methodGetHandleChunk; | ||||
|     private Field shouldSave; | ||||
|     private Field shouldSave = null; | ||||
|  | ||||
|     public SingleWorldListener() throws Exception { | ||||
|         ReflectionUtils.RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); | ||||
| @@ -59,9 +59,12 @@ public class SingleWorldListener implements Listener { | ||||
|                 } else { | ||||
|                     this.shouldSave = classChunk.getField("s").getRealField(); | ||||
|                 } | ||||
|             } else { | ||||
|             } else if (PlotSquared.platform().serverVersion()[1] == 17) { | ||||
|                 ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.Chunk"); | ||||
|                 this.shouldSave = classChunk.getField("r").getRealField(); | ||||
|             } else if (PlotSquared.platform().serverVersion()[1] == 18) { | ||||
|                 ReflectionUtils.RefClass classChunk = getRefClass("net.minecraft.world.level.chunk.IChunkAccess"); | ||||
|                 this.shouldSave = classChunk.getField("b").getRealField(); | ||||
|             } | ||||
|         } catch (NoSuchFieldException e) { | ||||
|             e.printStackTrace(); | ||||
|   | ||||
| @@ -74,8 +74,9 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator { | ||||
|     private final Consumer<Throwable> throwableConsumer; | ||||
|     private final boolean unloadAfter; | ||||
|     private final int totalSize; | ||||
|  | ||||
|     private final AtomicInteger expectedSize; | ||||
|     private final AtomicInteger loadingChunks = new AtomicInteger(); | ||||
|  | ||||
|     private int batchSize; | ||||
|     private PlotSquaredTask task; | ||||
|     private boolean shouldCancel; | ||||
| @@ -150,6 +151,13 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator { | ||||
|  | ||||
|         Chunk chunk = this.availableChunks.poll(); | ||||
|         if (chunk == null) { | ||||
|             if (this.availableChunks.isEmpty()) { | ||||
|                 if (this.requestedChunks.isEmpty() && loadingChunks.get() == 0) { | ||||
|                     finish(); | ||||
|                 } else { | ||||
|                     requestBatch(); | ||||
|                 } | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         long[] iterationTime = new long[2]; | ||||
| @@ -197,9 +205,11 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator { | ||||
|         BlockVector2 chunk; | ||||
|         for (int i = 0; i < this.batchSize && (chunk = this.requestedChunks.poll()) != null; i++) { | ||||
|             // This required PaperLib to be bumped to version 1.0.4 to mark the request as urgent | ||||
|             loadingChunks.incrementAndGet(); | ||||
|             PaperLib | ||||
|                     .getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), true, true) | ||||
|                     .whenComplete((chunkObject, throwable) -> { | ||||
|                         loadingChunks.decrementAndGet(); | ||||
|                         if (throwable != null) { | ||||
|                             throwable.printStackTrace(); | ||||
|                             // We want one less because this couldn't be processed | ||||
|   | ||||
| @@ -111,8 +111,8 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { | ||||
|     public boolean enqueue() { | ||||
|         final Clipboard regenClipboard; | ||||
|         if (isRegen()) { | ||||
|             BlockVector3 start = BlockVector3.at(getRegenStart()[0] << 4, 0, getRegenStart()[1] << 4); | ||||
|             BlockVector3 end = BlockVector3.at((getRegenEnd()[0] << 4) + 15, 255, (getRegenEnd()[1] << 4) + 15); | ||||
|             BlockVector3 start = BlockVector3.at(getRegenStart()[0] << 4, getMinY(), getRegenStart()[1] << 4); | ||||
|             BlockVector3 end = BlockVector3.at((getRegenEnd()[0] << 4) + 15, getMaxY(), (getRegenEnd()[1] << 4) + 15); | ||||
|             Region region = new CuboidRegion(start, end); | ||||
|             regenClipboard = new BlockArrayClipboard(region); | ||||
|             regenClipboard.setOrigin(start); | ||||
| @@ -134,7 +134,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { | ||||
|                 int sx = blockVector2.getX() << 4; | ||||
|                 int sz = blockVector2.getZ() << 4; | ||||
|                 if (isRegenChunk) { | ||||
|                     for (int layer = 0; layer < 16; layer++) { | ||||
|                     for (int layer = getMinLayer(); layer <= getMaxLayer(); layer++) { | ||||
|                         for (int y = 0; y < 16; y++) { | ||||
|                             for (int x = 0; x < 16; x++) { | ||||
|                                 for (int z = 0; z < 16; z++) { | ||||
| @@ -170,7 +170,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { | ||||
|                             int lx = ChunkUtil.getX(j); | ||||
|                             int lz = ChunkUtil.getZ(j); | ||||
|                             int x = sx + lx; | ||||
|                             int y = ChunkUtil.getY(layer, j); | ||||
|                             int y = ChunkUtil.getY(layer + localChunk.getMinSection(), j); | ||||
|                             int z = sz + lz; | ||||
|                             boolean edge = Settings.QUEUE.UPDATE_EDGES && isEdge(y >> 4, lx, y & 15, lz, blockVector2, | ||||
|                                     localChunk | ||||
| @@ -179,7 +179,7 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 for (int layer = 0; layer < localChunk.getBaseblocks().length; layer++) { | ||||
|                 for (int layer = 0; layer < localChunk.getBiomes().length; layer++) { | ||||
|                     BiomeType[] biomesLayer = localChunk.getBiomes()[layer]; | ||||
|                     if (biomesLayer == null) { | ||||
|                         continue; | ||||
| @@ -295,47 +295,48 @@ public class BukkitQueueCoordinator extends BasicQueueCoordinator { | ||||
|     } | ||||
|  | ||||
|     private boolean isEdge(int layer, int x, int y, int z, BlockVector2 blockVector2, LocalChunk localChunk) { | ||||
|         if (layer == 0 || layer == localChunk.getBaseblocks().length - 1) { | ||||
|         int layerIndex = (layer - localChunk.getMinSection()); | ||||
|         if (layer == localChunk.getMinSection() || layerIndex == localChunk.getBaseblocks().length - 1) { | ||||
|             return false; | ||||
|         } | ||||
|         if (x == 0) { | ||||
|             LocalChunk localChunkX = getBlockChunks().get(blockVector2.withX(blockVector2.getX() - 1)); | ||||
|             if (localChunkX == null || localChunkX.getBaseblocks()[layer] == null || | ||||
|                     localChunkX.getBaseblocks()[layer][ChunkUtil.getJ(15, y, z)] != null) { | ||||
|             if (localChunkX == null || localChunkX.getBaseblocks()[layerIndex] == null || | ||||
|                     localChunkX.getBaseblocks()[layerIndex][ChunkUtil.getJ(15, y, z)] != null) { | ||||
|                 return true; | ||||
|             } | ||||
|         } else if (x == 15) { | ||||
|             LocalChunk localChunkX = getBlockChunks().get(blockVector2.withX(blockVector2.getX() + 1)); | ||||
|             if (localChunkX == null || localChunkX.getBaseblocks()[layer] == null || | ||||
|                     localChunkX.getBaseblocks()[layer][ChunkUtil.getJ(0, y, z)] != null) { | ||||
|             if (localChunkX == null || localChunkX.getBaseblocks()[layerIndex] == null || | ||||
|                     localChunkX.getBaseblocks()[layerIndex][ChunkUtil.getJ(0, y, z)] != null) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         if (z == 0) { | ||||
|             LocalChunk localChunkZ = getBlockChunks().get(blockVector2.withZ(blockVector2.getZ() - 1)); | ||||
|             if (localChunkZ == null || localChunkZ.getBaseblocks()[layer] == null || | ||||
|                     localChunkZ.getBaseblocks()[layer][ChunkUtil.getJ(x, y, 15)] != null) { | ||||
|             if (localChunkZ == null || localChunkZ.getBaseblocks()[layerIndex] == null || | ||||
|                     localChunkZ.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, y, 15)] != null) { | ||||
|                 return true; | ||||
|             } | ||||
|         } else if (z == 15) { | ||||
|             LocalChunk localChunkZ = getBlockChunks().get(blockVector2.withZ(blockVector2.getZ() + 1)); | ||||
|             if (localChunkZ == null || localChunkZ.getBaseblocks()[layer] == null || | ||||
|                     localChunkZ.getBaseblocks()[layer][ChunkUtil.getJ(x, y, 0)] != null) { | ||||
|             if (localChunkZ == null || localChunkZ.getBaseblocks()[layerIndex] == null || | ||||
|                     localChunkZ.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, y, 0)] != null) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         if (y == 0) { | ||||
|             if (localChunk.getBaseblocks()[layer - 1] == null || | ||||
|                     localChunk.getBaseblocks()[layer][ChunkUtil.getJ(x, 15, z)] != null) { | ||||
|             if (localChunk.getBaseblocks()[layerIndex - 1] == null || | ||||
|                     localChunk.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, 15, z)] != null) { | ||||
|                 return true; | ||||
|             } | ||||
|         } else if (y == 15) { | ||||
|             if (localChunk.getBaseblocks()[layer + 1] == null || | ||||
|                     localChunk.getBaseblocks()[layer][ChunkUtil.getJ(x, 0, z)] != null) { | ||||
|             if (localChunk.getBaseblocks()[layerIndex + 1] == null || | ||||
|                     localChunk.getBaseblocks()[layerIndex][ChunkUtil.getJ(x, 0, z)] != null) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         BaseBlock[] baseBlocks = localChunk.getBaseblocks()[layer]; | ||||
|         BaseBlock[] baseBlocks = localChunk.getBaseblocks()[layerIndex]; | ||||
|         if (x > 0 && baseBlocks[ChunkUtil.getJ(x - 1, y, z)] == null) { | ||||
|             return true; | ||||
|         } | ||||
|   | ||||
| @@ -31,6 +31,7 @@ import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.plotsquared.core.location.ChunkWrapper; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.queue.ScopedQueueCoordinator; | ||||
| import com.plotsquared.core.util.AnnotationHelper; | ||||
| import com.plotsquared.core.util.ChunkUtil; | ||||
| import com.plotsquared.core.util.PatternUtil; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| @@ -50,6 +51,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import java.util.Arrays; | ||||
|  | ||||
| @AnnotationHelper.ApiDescription(info = "Internal use only. Subject to changes at any time.") | ||||
| public class GenChunk extends ScopedQueueCoordinator { | ||||
|  | ||||
|     public final Biome[] biomes; | ||||
| @@ -61,8 +63,14 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|     public int chunkZ; | ||||
|     private ChunkData chunkData = null; | ||||
|  | ||||
|     public GenChunk() { | ||||
|         super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15)); | ||||
|     /** | ||||
|      * @param minY minimum world Y, inclusive | ||||
|      * @param maxY maximum world Y, inclusive | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public GenChunk(int minY, int maxY) { | ||||
|         super(null, Location.at("", 0, minY, 0), Location.at("", 15, maxY, 15)); | ||||
|         this.biomes = Biome.values(); | ||||
|     } | ||||
|  | ||||
| @@ -117,7 +125,7 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|             return; | ||||
|         } | ||||
|         Biome biome = BukkitAdapter.adapt(biomeType); | ||||
|         for (int y = 0; y < 256; y++) { | ||||
|         for (int y = getMin().getY(); y <= getMax().getY(); y++) { | ||||
|             for (int x = 0; x < 16; x++) { | ||||
|                 for (int z = 0; z < 16; z++) { | ||||
|                     this.biomeGrid.setBiome(x, y, z, biome); | ||||
| @@ -130,7 +138,7 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|     public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BlockState block) { | ||||
|         if (result != null && pos1.getX() == 0 && pos1.getZ() == 0 && pos2.getX() == 15 && pos2.getZ() == 15) { | ||||
|             for (int y = pos1.getY(); y <= pos2.getY(); y++) { | ||||
|                 int layer = y >> 4; | ||||
|                 int layer = getLayerIndex(y); | ||||
|                 BlockState[] data = result[layer]; | ||||
|                 if (data == null) { | ||||
|                     result[layer] = data = new BlockState[4096]; | ||||
| @@ -164,7 +172,7 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|      */ | ||||
|     public boolean setBiome(int x, int z, @NonNull Biome biome) { | ||||
|         if (this.biomeGrid != null) { | ||||
|             for (int y = 0; y < 256; y++) { | ||||
|             for (int y = getMin().getY(); y <= getMax().getY(); y++) { | ||||
|                 this.setBiome(x, y, z, biome); | ||||
|             } | ||||
|             return true; | ||||
| @@ -197,7 +205,7 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|     } | ||||
|  | ||||
|     private void storeCache(final int x, final int y, final int z, final @NonNull BlockState id) { | ||||
|         int i = y >> 4; | ||||
|         int i = getLayerIndex(y); | ||||
|         BlockState[] v = this.result[i]; | ||||
|         if (v == null) { | ||||
|             this.result[i] = v = new BlockState[4096]; | ||||
| @@ -219,7 +227,7 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|  | ||||
|     @Override | ||||
|     public @Nullable BlockState getBlock(int x, int y, int z) { | ||||
|         int i = y >> 4; | ||||
|         int i = getLayerIndex(y); | ||||
|         if (result == null) { | ||||
|             return BukkitBlockUtil.get(chunkData.getType(x, y, z)); | ||||
|         } | ||||
| @@ -246,16 +254,16 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull Location getMax() { | ||||
|         return Location.at(getWorld().getName(), 15 + (getX() << 4), 255, 15 + (getZ() << 4)); | ||||
|         return Location.at(getWorld().getName(), 15 + (getX() << 4), super.getMax().getY(), 15 + (getZ() << 4)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull Location getMin() { | ||||
|         return Location.at(getWorld().getName(), getX() << 4, 0, getZ() << 4); | ||||
|         return Location.at(getWorld().getName(), getX() << 4, super.getMin().getY(), getZ() << 4); | ||||
|     } | ||||
|  | ||||
|     public @NonNull GenChunk clone() { | ||||
|         GenChunk toReturn = new GenChunk(); | ||||
|         GenChunk toReturn = new GenChunk(getMin().getY(), getMax().getY()); | ||||
|         if (this.result != null) { | ||||
|             for (int i = 0; i < this.result.length; i++) { | ||||
|                 BlockState[] matrix = this.result[i]; | ||||
| @@ -269,4 +277,8 @@ public class GenChunk extends ScopedQueueCoordinator { | ||||
|         return toReturn; | ||||
|     } | ||||
|  | ||||
|     private int getLayerIndex(int y) { | ||||
|         return (y - getMin().getY()) >> 4; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -40,7 +40,6 @@ import com.plotsquared.core.queue.QueueCoordinator; | ||||
| import com.plotsquared.core.queue.ScopedQueueCoordinator; | ||||
| import com.plotsquared.core.util.ChunkManager; | ||||
| import com.plotsquared.core.util.RegionManager; | ||||
| import com.plotsquared.core.util.RegionUtil; | ||||
| import com.plotsquared.core.util.WorldUtil; | ||||
| import com.plotsquared.core.util.entity.EntityCategories; | ||||
| import com.plotsquared.core.util.task.RunnableVal; | ||||
| @@ -261,7 +260,7 @@ public class BukkitRegionManager extends RegionManager { | ||||
|             if (checkX2 && checkZ2) { | ||||
|                 map.saveRegion(world, xxt2, xxt, zzt2, zzt); // | ||||
|             } | ||||
|             CuboidRegion currentPlotClear = RegionUtil.createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); | ||||
|             CuboidRegion currentPlotClear = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()); | ||||
|             map.saveEntitiesOut(Bukkit.getWorld(world.getName()).getChunkAt(x, z), currentPlotClear); | ||||
|             AugmentedUtils.bypass( | ||||
|                     ignoreAugment, | ||||
| @@ -276,7 +275,9 @@ public class BukkitRegionManager extends RegionManager { | ||||
|                                     PlotLoc plotLoc = new PlotLoc(bx + x1, bz + z1); | ||||
|                                     BaseBlock[] ids = map.allBlocks.get(plotLoc); | ||||
|                                     if (ids != null) { | ||||
|                                         for (int y = 0; y < Math.min(128, ids.length); y++) { | ||||
|                                         int minY = value.getMin().getY(); | ||||
|                                         for (int yIndex = 0; yIndex < ids.length; yIndex++) { | ||||
|                                             int y = yIndex + minY; | ||||
|                                             BaseBlock id = ids[y]; | ||||
|                                             if (id != null) { | ||||
|                                                 value.setBlock(x1, y, z1, id); | ||||
| @@ -284,12 +285,6 @@ public class BukkitRegionManager extends RegionManager { | ||||
|                                                 value.setBlock(x1, y, z1, BlockTypes.AIR.getDefaultState()); | ||||
|                                             } | ||||
|                                         } | ||||
|                                         for (int y = Math.min(128, ids.length); y < ids.length; y++) { | ||||
|                                             BaseBlock id = ids[y]; | ||||
|                                             if (id != null) { | ||||
|                                                 value.setBlock(x1, y, z1, id); | ||||
|                                             } | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
| @@ -297,7 +292,7 @@ public class BukkitRegionManager extends RegionManager { | ||||
|                     }, world.getName(), chunk) | ||||
|             ); | ||||
|             //map.restoreBlocks(worldObj, 0, 0); | ||||
|             map.restoreEntities(Bukkit.getWorld(world.getName()), 0, 0); | ||||
|             map.restoreEntities(Bukkit.getWorld(world.getName())); | ||||
|         }); | ||||
|         regenQueue.setCompleteTask(whenDone); | ||||
|         queue.setCompleteTask(regenQueue::enqueue); | ||||
|   | ||||
| @@ -44,7 +44,6 @@ import com.plotsquared.core.util.task.TaskManager; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| import com.sk89q.worldedit.bukkit.BukkitWorld; | ||||
| import com.sk89q.worldedit.math.BlockVector2; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import com.sk89q.worldedit.world.biome.BiomeType; | ||||
| import com.sk89q.worldedit.world.block.BlockCategories; | ||||
| import com.sk89q.worldedit.world.block.BlockState; | ||||
| @@ -61,7 +60,6 @@ import org.bukkit.Bukkit; | ||||
| import org.bukkit.Chunk; | ||||
| import org.bukkit.Material; | ||||
| import org.bukkit.World; | ||||
| import org.bukkit.block.Biome; | ||||
| import org.bukkit.block.Block; | ||||
| import org.bukkit.block.BlockFace; | ||||
| import org.bukkit.block.Sign; | ||||
| @@ -246,7 +244,9 @@ public class BukkitUtil extends WorldUtil { | ||||
|             final World bukkitWorld = Objects.requireNonNull(getWorld(world)); | ||||
|             // Skip top and bottom block | ||||
|             int air = 1; | ||||
|             for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) { | ||||
|             int maxY = com.plotsquared.bukkit.util.BukkitWorld.getMaxWorldHeight(bukkitWorld); | ||||
|             int minY = com.plotsquared.bukkit.util.BukkitWorld.getMinWorldHeight(bukkitWorld); | ||||
|             for (int y = maxY - 1; y >= minY; y--) { | ||||
|                 Block block = bukkitWorld.getBlockAt(x, y, z); | ||||
|                 Material type = block.getType(); | ||||
|                 if (type.isSolid()) { | ||||
| @@ -273,7 +273,9 @@ public class BukkitUtil extends WorldUtil { | ||||
|         final World bukkitWorld = Objects.requireNonNull(getWorld(world)); | ||||
|         // Skip top and bottom block | ||||
|         int air = 1; | ||||
|         for (int y = bukkitWorld.getMaxHeight() - 1; y >= 0; y--) { | ||||
|         int maxY = com.plotsquared.bukkit.util.BukkitWorld.getMaxWorldHeight(bukkitWorld); | ||||
|         int minY = com.plotsquared.bukkit.util.BukkitWorld.getMinWorldHeight(bukkitWorld); | ||||
|         for (int y = maxY - 1; y >= minY; y--) { | ||||
|             Block block = bukkitWorld.getBlockAt(x, y, z); | ||||
|             Material type = block.getType(); | ||||
|             if (type.isSolid()) { | ||||
| @@ -345,14 +347,16 @@ public class BukkitUtil extends WorldUtil { | ||||
|             final Block block = world.getBlockAt(location.getX(), location.getY(), location.getZ()); | ||||
|             final Material type = block.getType(); | ||||
|             if (type != Material.LEGACY_SIGN && type != Material.LEGACY_WALL_SIGN) { | ||||
|                 BlockFace facing = BlockFace.EAST; | ||||
|                 if (world.getBlockAt(location.getX(), location.getY(), location.getZ() + 1).getType().isSolid()) { | ||||
|                     facing = BlockFace.NORTH; | ||||
|                 BlockFace facing = BlockFace.NORTH; | ||||
|                 if (!world.getBlockAt(location.getX(), location.getY(), location.getZ() + 1).getType().isSolid()) { | ||||
|                     if (world.getBlockAt(location.getX() - 1, location.getY(), location.getZ()).getType().isSolid()) { | ||||
|                         facing = BlockFace.EAST; | ||||
|                     } else if (world.getBlockAt(location.getX() + 1, location.getY(), location.getZ()).getType().isSolid()) { | ||||
|                         facing = BlockFace.WEST; | ||||
|                     } else if (world.getBlockAt(location.getX(), location.getY(), location.getZ() - 1).getType().isSolid()) { | ||||
|                         facing = BlockFace.SOUTH; | ||||
|                     } | ||||
|                 } | ||||
|                 if (PlotSquared.platform().serverVersion()[1] == 13) { | ||||
|                     block.setType(Material.valueOf(area.legacySignMaterial()), false); | ||||
|                 } else { | ||||
| @@ -371,7 +375,7 @@ public class BukkitUtil extends WorldUtil { | ||||
|                     sign.setLine(i, LEGACY_COMPONENT_SERIALIZER | ||||
|                             .serialize(MINI_MESSAGE.parse(lines[i].getComponent(LocaleHolder.console()), replacements))); | ||||
|                 } | ||||
|                 sign.update(true); | ||||
|                 sign.update(true, false); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| @@ -382,27 +386,6 @@ public class BukkitUtil extends WorldUtil { | ||||
|         return new StringComparison<BlockState>().new ComparisonResult(1, state); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setBiomes( | ||||
|             final @NonNull String worldName, | ||||
|             final @NonNull CuboidRegion region, | ||||
|             final @NonNull BiomeType biomeType | ||||
|     ) { | ||||
|         final World world = getWorld(worldName); | ||||
|         if (world == null) { | ||||
|             LOGGER.warn("An error occurred while setting the biome because the world was null", new RuntimeException()); | ||||
|             return; | ||||
|         } | ||||
|         final Biome biome = BukkitAdapter.adapt(biomeType); | ||||
|         for (int x = region.getMinimumPoint().getX(); x <= region.getMaximumPoint().getX(); x++) { | ||||
|             for (int z = region.getMinimumPoint().getZ(); z <= region.getMaximumPoint().getZ(); z++) { | ||||
|                 if (world.getBiome(x, z) != biome) { | ||||
|                     world.setBiome(x, z, biome); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public com.sk89q.worldedit.world.@NonNull World getWeWorld(final @NonNull String world) { | ||||
|         return new BukkitWorld(Bukkit.getWorld(world)); | ||||
|   | ||||
| @@ -36,6 +36,18 @@ import java.util.Objects; | ||||
| public class BukkitWorld implements World<org.bukkit.World> { | ||||
|  | ||||
|     private static final Map<String, BukkitWorld> worldMap = Maps.newHashMap(); | ||||
|     private static final boolean HAS_MIN_Y; | ||||
|  | ||||
|     static { | ||||
|         boolean temp; | ||||
|         try { | ||||
|             org.bukkit.World.class.getMethod("getMinHeight"); | ||||
|             temp = true; | ||||
|         } catch (NoSuchMethodException e) { | ||||
|             temp = false; | ||||
|         } | ||||
|         HAS_MIN_Y = temp; | ||||
|     } | ||||
|  | ||||
|     private final org.bukkit.World world; | ||||
|  | ||||
| @@ -73,6 +85,24 @@ public class BukkitWorld implements World<org.bukkit.World> { | ||||
|         return bukkitWorld; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the min world height from a Bukkit {@link org.bukkit.World}. Inclusive | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public static int getMinWorldHeight(org.bukkit.World world) { | ||||
|         return HAS_MIN_Y ? world.getMinHeight() : 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the max world height from a Bukkit {@link org.bukkit.World}. Exclusive | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public static int getMaxWorldHeight(org.bukkit.World world) { | ||||
|         return HAS_MIN_Y ? world.getMaxHeight() : 256; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public org.bukkit.World getPlatformWorld() { | ||||
|         return this.world; | ||||
| @@ -83,6 +113,16 @@ public class BukkitWorld implements World<org.bukkit.World> { | ||||
|         return this.world.getName(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int getMinHeight() { | ||||
|         return getMinWorldHeight(world); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public int getMaxHeight() { | ||||
|         return getMaxWorldHeight(world) - 1; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean equals(final Object o) { | ||||
|         if (this == o) { | ||||
| @@ -103,7 +143,7 @@ public class BukkitWorld implements World<org.bukkit.World> { | ||||
|     /** | ||||
|      * @deprecated This method is not meant to be invoked or overridden, with no replacement. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     protected boolean canEqual(final Object other) { | ||||
|         return other instanceof BukkitWorld; | ||||
|     } | ||||
|   | ||||
| @@ -70,7 +70,7 @@ public class ContentMap { | ||||
|         } | ||||
|         for (int x = x1; x <= x2; x++) { | ||||
|             for (int z = z1; z <= z2; z++) { | ||||
|                 saveBlocks(world, 256, x, z, 0, 0); | ||||
|                 saveBlocks(world, x, z); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -92,14 +92,7 @@ public class ContentMap { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void saveEntitiesIn(Chunk chunk, CuboidRegion region) { | ||||
|         saveEntitiesIn(chunk, region, 0, 0, false); | ||||
|     } | ||||
|  | ||||
|     void saveEntitiesIn( | ||||
|             Chunk chunk, CuboidRegion region, int offsetX, int offsetZ, | ||||
|             boolean delete | ||||
|     ) { | ||||
|     void saveEntitiesIn(Chunk chunk, CuboidRegion region, boolean delete) { | ||||
|         for (Entity entity : chunk.getEntities()) { | ||||
|             Location location = BukkitUtil.adapt(entity.getLocation()); | ||||
|             int x = location.getX(); | ||||
| @@ -111,8 +104,6 @@ public class ContentMap { | ||||
|                 continue; | ||||
|             } | ||||
|             EntityWrapper wrap = new ReplicatingEntityWrapper(entity, (short) 2); | ||||
|             wrap.x += offsetX; | ||||
|             wrap.z += offsetZ; | ||||
|             wrap.saveEntity(); | ||||
|             this.entities.add(wrap); | ||||
|             if (delete) { | ||||
| @@ -123,10 +114,10 @@ public class ContentMap { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void restoreEntities(World world, int xOffset, int zOffset) { | ||||
|     void restoreEntities(World world) { | ||||
|         for (EntityWrapper entity : this.entities) { | ||||
|             try { | ||||
|                 entity.spawn(world, xOffset, zOffset); | ||||
|                 entity.spawn(world, 0, 0); | ||||
|             } catch (Exception e) { | ||||
|                 LOGGER.error("Failed to restore entity", e); | ||||
|             } | ||||
| @@ -134,15 +125,13 @@ public class ContentMap { | ||||
|         this.entities.clear(); | ||||
|     } | ||||
|  | ||||
|     //todo optimize maxY | ||||
|     void saveBlocks(BukkitWorld world, int maxY, int x, int z, int offsetX, int offsetZ) { | ||||
|         maxY = Math.min(255, maxY); | ||||
|         BaseBlock[] ids = new BaseBlock[maxY + 1]; | ||||
|         for (short y = 0; y <= maxY; y++) { | ||||
|             BaseBlock block = world.getFullBlock(BlockVector3.at(x, y, z)); | ||||
|             ids[y] = block; | ||||
|     private void saveBlocks(BukkitWorld world, int x, int z) { | ||||
|         BaseBlock[] ids = new BaseBlock[world.getMaxY() - world.getMinY() + 1]; | ||||
|         for (short yIndex = 0; yIndex <= world.getMaxY() - world.getMinY(); yIndex++) { | ||||
|             BaseBlock block = world.getFullBlock(BlockVector3.at(x, yIndex + world.getMinY(), z)); | ||||
|             ids[yIndex] = block; | ||||
|         } | ||||
|         PlotLoc loc = new PlotLoc(x + offsetX, z + offsetZ); | ||||
|         PlotLoc loc = new PlotLoc(x, z); | ||||
|         this.allBlocks.put(loc, ids); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -110,6 +110,11 @@ public class FaweRegionManager extends BukkitRegionManager { | ||||
|         delegate.setBiome(region, extendBiome, biome, world, whenDone); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, PlotArea area, Runnable whenDone) { | ||||
|         delegate.setBiome(region, extendBiome, biome, area.getWorldName(), whenDone); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean copyRegion( | ||||
|             final @NonNull Location pos1, | ||||
|   | ||||
| @@ -67,7 +67,7 @@ public class FaweSchematicHandler extends SchematicHandler { | ||||
|             final PlotPlayer<?> actor, | ||||
|             final RunnableVal<Boolean> whenDone | ||||
|     ) { | ||||
|         delegate.paste(schematic, plot, xOffset, yOffset, zOffset, autoHeight, whenDone); | ||||
|         delegate.paste(schematic, plot, xOffset, yOffset, zOffset, autoHeight, actor, whenDone); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -98,6 +98,22 @@ public interface PlotPlatform<P> extends LocaleHolder { | ||||
|      */ | ||||
|     int[] serverVersion(); | ||||
|  | ||||
|     /** | ||||
|      * Gets the default minimum world height for the version of Minecraft that the server is running. | ||||
|      * | ||||
|      * @return minimum world height | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     int versionMinHeight(); | ||||
|  | ||||
|     /** | ||||
|      * Gets the default maximum world height for the version of Minecraft that the server is running. | ||||
|      * | ||||
|      * @return maximum world height (inclusive) | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     int versionMaxHeight(); | ||||
|  | ||||
|     /** | ||||
|      * Gets the server implementation name and version | ||||
|      * | ||||
|   | ||||
| @@ -1020,8 +1020,8 @@ public class PlotSquared { | ||||
|             // save configuration | ||||
|  | ||||
|             final List<String> validArguments = Arrays | ||||
|                     .asList("s=", "size=", "g=", "gap=", "h=", "height=", "f=", "floor=", "m=", "main=", | ||||
|                             "w=", "wall=", "b=", "border=" | ||||
|                     .asList("s=", "size=", "g=", "gap=", "h=", "height=", "minh=", "minheight=", "maxh=", "maxheight=", | ||||
|                             "f=", "floor=", "m=", "main=", "w=", "wall=", "b=", "border=" | ||||
|                     ); | ||||
|  | ||||
|             // Calculate the number of expected arguments | ||||
| @@ -1100,6 +1100,14 @@ public class PlotSquared { | ||||
|                                     ConfigurationUtil.INTEGER.parseString(value).shortValue() | ||||
|                             ); | ||||
|                         } | ||||
|                         case "minh", "minheight" -> this.worldConfiguration.set( | ||||
|                                 base + "world.min_gen_height", | ||||
|                                 ConfigurationUtil.INTEGER.parseString(value).shortValue() | ||||
|                         ); | ||||
|                         case "maxh", "maxheight" -> this.worldConfiguration.set( | ||||
|                                 base + "world.max_gen_height", | ||||
|                                 ConfigurationUtil.INTEGER.parseString(value).shortValue() | ||||
|                         ); | ||||
|                         case "f", "floor" -> this.worldConfiguration.set( | ||||
|                                 base + "plot.floor", | ||||
|                                 ConfigurationUtil.BLOCK_BUCKET.parseString(value).toString() | ||||
|   | ||||
| @@ -75,6 +75,7 @@ import com.sk89q.worldedit.function.operation.Operations; | ||||
| import com.sk89q.worldedit.math.BlockVector3; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import com.sk89q.worldedit.regions.Region; | ||||
| import com.sk89q.worldedit.world.World; | ||||
| import net.kyori.adventure.text.minimessage.Template; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| @@ -191,11 +192,12 @@ public class Area extends SubCommand { | ||||
|                 final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint(); | ||||
|                 final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint(); | ||||
|                 // Create a new selection that spans the entire vertical range of the world | ||||
|                 World world = playerSelectedRegion.getWorld(); | ||||
|                 final CuboidRegion selectedRegion = | ||||
|                         new CuboidRegion( | ||||
|                                 playerSelectedRegion.getWorld(), | ||||
|                                 BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()), | ||||
|                                 BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ()) | ||||
|                                 BlockVector3.at(playerSelectionMin.getX(), world.getMinY(), playerSelectionMin.getZ()), | ||||
|                                 BlockVector3.at(playerSelectionMax.getX(), world.getMaxY(), playerSelectionMax.getZ()) | ||||
|                         ); | ||||
|                 // There's only one plot in the area... | ||||
|                 final PlotId plotId = PlotId.of(1, 1); | ||||
| @@ -278,9 +280,9 @@ public class Area extends SubCommand { | ||||
|                     if (offsetZ != 0) { | ||||
|                         this.worldConfiguration.set(path + ".road.offset.z", offsetZ); | ||||
|                     } | ||||
|                     final String world = this.setupUtils.setupWorld(singleBuilder); | ||||
|                     if (this.worldUtil.isWorld(world)) { | ||||
|                         PlotSquared.get().loadWorld(world, null); | ||||
|                     final String worldName = this.setupUtils.setupWorld(singleBuilder); | ||||
|                     if (this.worldUtil.isWorld(worldName)) { | ||||
|                         PlotSquared.get().loadWorld(worldName, null); | ||||
|                         player.sendMessage(TranslatableCaption.of("single.single_area_created")); | ||||
|                     } else { | ||||
|                         player.sendMessage( | ||||
| @@ -369,7 +371,8 @@ public class Area extends SubCommand { | ||||
|                                 int lower = (area.ROAD_WIDTH & 1) == 0 ? area.ROAD_WIDTH / 2 - 1 : area.ROAD_WIDTH / 2; | ||||
|                                 final int offsetX = bx - (area.ROAD_WIDTH == 0 ? 0 : lower); | ||||
|                                 final int offsetZ = bz - (area.ROAD_WIDTH == 0 ? 0 : lower); | ||||
|                                 final CuboidRegion region = RegionUtil.createRegion(bx, tx, bz, tz); | ||||
|                                 // Height doesn't matter for this region | ||||
|                                 final CuboidRegion region = RegionUtil.createRegion(bx, tx, 0, 0, bz, tz); | ||||
|                                 final Set<PlotArea> areas = this.plotAreaManager.getPlotAreasSet(area.getWorldName(), region); | ||||
|                                 if (!areas.isEmpty()) { | ||||
|                                     player.sendMessage( | ||||
|   | ||||
| @@ -49,6 +49,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collection; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
| import java.util.stream.Collectors; | ||||
| @@ -207,7 +208,7 @@ public class DebugExec extends SubCommand { | ||||
|                     } | ||||
|                     boolean result; | ||||
|                     if (HybridUtils.regions != null) { | ||||
|                         result = this.hybridUtils.scheduleRoadUpdate(area, HybridUtils.regions, 0, new HashSet<>()); | ||||
|                         result = this.hybridUtils.scheduleRoadUpdate(area, HybridUtils.regions, 0, new LinkedHashSet<>()); | ||||
|                     } else { | ||||
|                         result = this.hybridUtils.scheduleRoadUpdate(area, 0); | ||||
|                     } | ||||
|   | ||||
| @@ -104,8 +104,8 @@ public class Save extends SubCommand { | ||||
|                     TaskManager.runTaskAsync(() -> { | ||||
|                         String time = (System.currentTimeMillis() / 1000) + ""; | ||||
|                         Location[] corners = plot.getCorners(); | ||||
|                         corners[0] = corners[0].withY(0); | ||||
|                         corners[1] = corners[1].withY(255); | ||||
|                         corners[0] = corners[0].withY(plot.getArea().getMinBuildHeight()); | ||||
|                         corners[1] = corners[1].withY(plot.getArea().getMaxBuildHeight()); | ||||
|                         int size = (corners[1].getX() - corners[0].getX()) + 1; | ||||
|                         PlotId id = plot.getId(); | ||||
|                         String world1 = plot.getArea().toString().replaceAll(";", "-") | ||||
|   | ||||
| @@ -180,12 +180,12 @@ public class Trim extends SubCommand { | ||||
|                             int bx = cbx << 4; | ||||
|                             int bz = cbz << 4; | ||||
|                             CuboidRegion region = | ||||
|                                     RegionUtil.createRegion(bx, bx + 511, bz, bz + 511); | ||||
|                                     RegionUtil.createRegion(bx, bx + 511, 0, 0, bz, bz + 511); | ||||
|                             for (Plot plot : PlotQuery.newQuery().inWorld(world)) { | ||||
|                                 Location bot = plot.getBottomAbs(); | ||||
|                                 Location top = plot.getExtendedTopAbs(); | ||||
|                                 CuboidRegion plotReg = RegionUtil | ||||
|                                         .createRegion(bot.getX(), top.getX(), bot.getZ(), top.getZ()); | ||||
|                                         .createRegion(bot.getX(), top.getX(), 0, 0, bot.getZ(), top.getZ()); | ||||
|                                 if (!RegionUtil.intersects(region, plotReg)) { | ||||
|                                     continue; | ||||
|                                 } | ||||
|   | ||||
| @@ -70,7 +70,7 @@ public class AugmentedUtils { | ||||
|         final int blockZ = chunkZ << 4; | ||||
|         // Create a region that contains the | ||||
|         // entire chunk | ||||
|         CuboidRegion region = RegionUtil.createRegion(blockX, blockX + 15, blockZ, blockZ + 15); | ||||
|         CuboidRegion region = RegionUtil.createRegion(blockX, blockX + 15, 0, 0, blockZ, blockZ + 15); | ||||
|         // Query for plot areas in the chunk | ||||
|         final Set<PlotArea> areas = PlotSquared.get().getPlotAreaManager().getPlotAreasSet(world, region); | ||||
|         if (areas.isEmpty()) { | ||||
| @@ -122,6 +122,7 @@ public class AugmentedUtils { | ||||
|             } | ||||
|             QueueCoordinator secondaryMask; | ||||
|             BlockState air = BlockTypes.AIR.getDefaultState(); | ||||
|             int startYOffset = !(area instanceof ClassicPlotWorld) || ((ClassicPlotWorld) area).PLOT_BEDROCK ? 1 : 0; | ||||
|             if (area.getTerrain() == PlotAreaTerrainType.ROAD) { | ||||
|                 PlotManager manager = area.getPlotManager(); | ||||
|                 final boolean[][] canPlace = new boolean[16][16]; | ||||
| @@ -132,7 +133,7 @@ public class AugmentedUtils { | ||||
|                         int worldZ = z + blockZ; | ||||
|                         boolean can = manager.getPlotId(worldX, 0, worldZ) == null; | ||||
|                         if (can) { | ||||
|                             for (int y = 1; y < 128; y++) { | ||||
|                             for (int y = area.getMinGenHeight() + startYOffset; y <= area.getMaxGenHeight(); y++) { | ||||
|                                 queue.setBlock(worldX, y, worldZ, air); | ||||
|                             } | ||||
|                             canPlace[x][z] = true; | ||||
| @@ -149,7 +150,7 @@ public class AugmentedUtils { | ||||
|                 secondaryMask = primaryMask; | ||||
|                 for (int x = relativeBottomX; x <= relativeTopX; x++) { | ||||
|                     for (int z = relativeBottomZ; z <= relativeTopZ; z++) { | ||||
|                         for (int y = 1; y < 128; y++) { | ||||
|                         for (int y = area.getMinGenHeight() + startYOffset; y <= area.getMaxGenHeight(); y++) { | ||||
|                             queue.setBlock(blockX + x, y, blockZ + z, air); | ||||
|                         } | ||||
|                     } | ||||
| @@ -166,8 +167,8 @@ public class AugmentedUtils { | ||||
|             ScopedQueueCoordinator scoped = | ||||
|                     new ScopedQueueCoordinator( | ||||
|                             secondaryMask, | ||||
|                             Location.at(world, blockX, 0, blockZ), | ||||
|                             Location.at(world, blockX + 15, 255, blockZ + 15) | ||||
|                             Location.at(world, blockX, area.getMinGenHeight(), blockZ), | ||||
|                             Location.at(world, blockX + 15, area.getMaxGenHeight(), blockZ + 15) | ||||
|                     ); | ||||
|             generator.generateChunk(scoped, area); | ||||
|             generator.populateChunk(scoped, area); | ||||
|   | ||||
| @@ -37,7 +37,6 @@ import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.PlotAreaTerrainType; | ||||
| import com.plotsquared.core.plot.PlotId; | ||||
| import com.plotsquared.core.queue.QueueCoordinator; | ||||
| import com.plotsquared.core.util.BlockUtil; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.RegionManager; | ||||
| import com.plotsquared.core.util.task.TaskManager; | ||||
| @@ -147,7 +146,15 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|     ) { | ||||
|         Plot plot = classicPlotWorld.getPlotAbs(plotId); | ||||
|         if (plot != null && plot.isBasePlot()) { | ||||
|             return this.regionManager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, getWorldHeight(), actor, queue); | ||||
|             return this.regionManager.setCuboids( | ||||
|                     classicPlotWorld, | ||||
|                     plot.getRegions(), | ||||
|                     blocks, | ||||
|                     classicPlotWorld.getMinBuildHeight(), | ||||
|                     classicPlotWorld.getMaxBuildHeight(), | ||||
|                     actor, | ||||
|                     queue | ||||
|             ); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| @@ -175,7 +182,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                             plot.getRegions(), | ||||
|                             blocks, | ||||
|                             classicPlotWorld.PLOT_HEIGHT + 1, | ||||
|                             getWorldHeight(), | ||||
|                             classicPlotWorld.getMaxBuildHeight(), | ||||
|                             actor, | ||||
|                             queue | ||||
|                     ); | ||||
| @@ -204,7 +211,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                     classicPlotWorld, | ||||
|                     plot.getRegions(), | ||||
|                     blocks, | ||||
|                     1, | ||||
|                     classicPlotWorld.getMinBuildHeight(), | ||||
|                     classicPlotWorld.PLOT_HEIGHT - 1, | ||||
|                     actor, | ||||
|                     queue | ||||
| @@ -281,7 +288,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         int maxY = classicPlotWorld.getPlotManager().getWorldHeight(); | ||||
|         int maxY = classicPlotWorld.getMaxBuildHeight(); | ||||
|         if (!plot.isMerged(Direction.NORTH)) { | ||||
|             int z = bottom.getZ(); | ||||
|             for (int x = bottom.getX(); x <= top.getX(); x++) { | ||||
| @@ -382,7 +389,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.NORTH)) { | ||||
|             int z = bot.getZ(); | ||||
|             for (int x = bot.getX(); x < top.getX(); x++) { | ||||
|                 for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMaxBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -390,7 +397,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.WEST)) { | ||||
|             int x = bot.getX(); | ||||
|             for (int z = bot.getZ(); z < top.getZ(); z++) { | ||||
|                 for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -398,7 +405,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.SOUTH)) { | ||||
|             int z = top.getZ(); | ||||
|             for (int x = bot.getX(); x < top.getX() + (plot.isMerged(Direction.EAST) ? 0 : 1); x++) { | ||||
|                 for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -406,7 +413,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         if (!plot.isMerged(Direction.EAST)) { | ||||
|             int x = top.getX(); | ||||
|             for (int z = bot.getZ(); z < top.getZ() + (plot.isMerged(Direction.SOUTH) ? 0 : 1); z++) { | ||||
|                 for (int y = 1; y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                 for (int y = classicPlotWorld.getMinBuildHeight(); y <= classicPlotWorld.WALL_HEIGHT; y++) { | ||||
|                     queue.setBlock(x, y, z, blocks); | ||||
|                 } | ||||
|             } | ||||
| @@ -501,7 +508,7 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|             enqueue = true; | ||||
|         } | ||||
|  | ||||
|         int maxY = getWorldHeight(); | ||||
|         int maxY = classicPlotWorld.getMaxGenHeight(); | ||||
|         queue.setCuboid( | ||||
|                 Location.at( | ||||
|                         classicPlotWorld.getWorldName(), | ||||
| @@ -513,27 +520,27 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|         ); | ||||
|         if (classicPlotWorld.PLOT_BEDROCK) { | ||||
|             queue.setCuboid( | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, 0, sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex, 0, ez - 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight(), sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMinGenHeight(), ez - 1), | ||||
|                     BlockTypes.BEDROCK.getDefaultState() | ||||
|             ); | ||||
|             queue.setCuboid( | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1), | ||||
|                     classicPlotWorld.WALL_FILLING.toPattern() | ||||
|             ); | ||||
|         } else { | ||||
|             queue.setCuboid( | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, 0, sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1), | ||||
|                     classicPlotWorld.WALL_FILLING.toPattern() | ||||
|             ); | ||||
|         } | ||||
|         int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.WALL_FILLING.toPattern() | ||||
|         ); | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.WALL_FILLING.toPattern() | ||||
|         ); | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.ROAD_BLOCK.toPattern() | ||||
|         ); | ||||
|  | ||||
|         if (classicPlotWorld.PLACE_TOP_BLOCK) { | ||||
|             queue.setCuboid( | ||||
| @@ -541,24 +548,12 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), | ||||
|                     classicPlotWorld.WALL_BLOCK.toPattern() | ||||
|             ); | ||||
|         } | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex, 1, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.WALL_FILLING.toPattern() | ||||
|         ); | ||||
|         if (classicPlotWorld.PLACE_TOP_BLOCK) { | ||||
|             queue.setCuboid( | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), | ||||
|                     classicPlotWorld.WALL_BLOCK.toPattern() | ||||
|             ); | ||||
|         } | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.ROAD_BLOCK.toPattern() | ||||
|         ); | ||||
|         return !enqueue || queue.enqueue(); | ||||
|     } | ||||
|  | ||||
| @@ -584,19 +579,32 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                         classicPlotWorld.schematicStartHeight() + 1, | ||||
|                         sz | ||||
|                 ), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getPlotManager().getWorldHeight(), ez), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMaxGenHeight(), ez), | ||||
|                 BlockTypes.AIR.getDefaultState() | ||||
|         ); | ||||
|         if (classicPlotWorld.PLOT_BEDROCK) { | ||||
|             queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez), | ||||
|                 BlockUtil.get((short) 7, (byte) 0) | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight(), sz), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMinGenHeight(), ez), | ||||
|                     BlockTypes.BEDROCK.getDefaultState() | ||||
|             ); | ||||
|         } | ||||
|         int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, sz), | ||||
|                 classicPlotWorld.WALL_FILLING.toPattern() | ||||
|         ); | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, ez), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez), | ||||
|                 classicPlotWorld.WALL_FILLING.toPattern() | ||||
|         ); | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.ROAD_BLOCK.toPattern() | ||||
|         ); | ||||
|  | ||||
|         if (classicPlotWorld.PLACE_TOP_BLOCK) { | ||||
|             queue.setCuboid( | ||||
| @@ -604,24 +612,12 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, sz), | ||||
|                     classicPlotWorld.WALL_BLOCK.toPattern() | ||||
|             ); | ||||
|         } | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, ez), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez), | ||||
|                 classicPlotWorld.WALL_FILLING.toPattern() | ||||
|         ); | ||||
|         if (classicPlotWorld.PLACE_TOP_BLOCK) { | ||||
|             queue.setCuboid( | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, ez), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, ez), | ||||
|                     classicPlotWorld.WALL_BLOCK.toPattern() | ||||
|             ); | ||||
|         } | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.ROAD_BLOCK.toPattern() | ||||
|         ); | ||||
|         return !enqueue || queue.enqueue(); | ||||
|     } | ||||
|  | ||||
| @@ -642,14 +638,19 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|  | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.ROAD_HEIGHT + 1, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getPlotManager().getWorldHeight(), ez - 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMaxGenHeight(), ez - 1), | ||||
|                 BlockTypes.AIR.getDefaultState() | ||||
|         ); | ||||
|         queue.setCuboid(Location.at(classicPlotWorld.getWorldName(), sx + 1, 0, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, 0, ez - 1), BlockUtil.get((short) 7, (byte) 0) | ||||
|         ); | ||||
|         if (classicPlotWorld.PLOT_BEDROCK) { | ||||
|             queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight(), sz + 1), | ||||
|                     Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMinGenHeight(), ez - 1), | ||||
|                     BlockTypes.BEDROCK.getDefaultState() | ||||
|             ); | ||||
|         } | ||||
|         int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), | ||||
|                 classicPlotWorld.ROAD_BLOCK.toPattern() | ||||
|         ); | ||||
| @@ -679,11 +680,12 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                                 classicPlotWorld.schematicStartHeight() + 1, | ||||
|                                 sz | ||||
|                         ), | ||||
|                         Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez), | ||||
|                         Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez), | ||||
|                         BlockTypes.AIR.getDefaultState() | ||||
|                 ); | ||||
|         int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, 1, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez - 1), | ||||
|                 classicPlotWorld.MAIN_BLOCK.toPattern() | ||||
|         ); | ||||
| @@ -719,11 +721,12 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                                 classicPlotWorld.schematicStartHeight() + 1, | ||||
|                                 sz | ||||
|                         ), | ||||
|                         Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez), | ||||
|                         Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez), | ||||
|                         BlockTypes.AIR.getDefaultState() | ||||
|                 ); | ||||
|         int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, 1, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT - 1, ez), | ||||
|                 classicPlotWorld.MAIN_BLOCK.toPattern() | ||||
|         ); | ||||
| @@ -758,11 +761,12 @@ public class ClassicPlotManager extends SquarePlotManager { | ||||
|                                 classicPlotWorld.schematicStartHeight() + 1, | ||||
|                                 sz | ||||
|                         ), | ||||
|                         Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getPlotManager().getWorldHeight(), ez), | ||||
|                         Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez), | ||||
|                         BlockTypes.AIR.getDefaultState() | ||||
|                 ); | ||||
|         int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         queue.setCuboid( | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, 1, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz), | ||||
|                 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez), | ||||
|                 classicPlotWorld.MAIN_BLOCK.toPattern() | ||||
|         ); | ||||
|   | ||||
| @@ -127,16 +127,16 @@ public abstract class ClassicPlotWorld extends SquarePlotWorld { | ||||
|     public void loadConfiguration(ConfigurationSection config) { | ||||
|         super.loadConfiguration(config); | ||||
|         this.PLOT_BEDROCK = config.getBoolean("plot.bedrock"); | ||||
|         this.PLOT_HEIGHT = Math.min(255, config.getInt("plot.height")); | ||||
|         this.PLOT_HEIGHT = Math.min(getMaxGenHeight(), config.getInt("plot.height")); | ||||
|         this.MAIN_BLOCK = new BlockBucket(config.getString("plot.filling")); | ||||
|         this.TOP_BLOCK = new BlockBucket(config.getString("plot.floor")); | ||||
|         this.WALL_BLOCK = new BlockBucket(config.getString("wall.block")); | ||||
|         this.ROAD_HEIGHT = Math.min(255, config.getInt("road.height")); | ||||
|         this.ROAD_HEIGHT = Math.min(getMaxGenHeight(), config.getInt("road.height")); | ||||
|         this.ROAD_BLOCK = new BlockBucket(config.getString("road.block")); | ||||
|         this.WALL_FILLING = new BlockBucket(config.getString("wall.filling")); | ||||
|         this.WALL_HEIGHT = Math.min(254, config.getInt("wall.height")); | ||||
|         this.CLAIMED_WALL_BLOCK = new BlockBucket(config.getString("wall.block_claimed")); | ||||
|         this.PLACE_TOP_BLOCK = config.getBoolean("wall.place_top_block"); | ||||
|         this.WALL_HEIGHT = Math.min(getMaxGenHeight() - (PLACE_TOP_BLOCK ? 1 : 0), config.getInt("wall.height")); | ||||
|         this.CLAIMED_WALL_BLOCK = new BlockBucket(config.getString("wall.block_claimed")); | ||||
|     } | ||||
|  | ||||
|     int schematicStartHeight() { | ||||
|   | ||||
| @@ -91,7 +91,7 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|         if (hybridPlotWorld.PLOT_BEDROCK) { | ||||
|             for (short x = 0; x < 16; x++) { | ||||
|                 for (short z = 0; z < 16; z++) { | ||||
|                     result.setBlock(x, 0, z, BlockTypes.BEDROCK.getDefaultState()); | ||||
|                     result.setBlock(x, hybridPlotWorld.getMinGenHeight(), z, BlockTypes.BEDROCK.getDefaultState()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -156,7 +156,7 @@ public class HybridGen extends IndependentPlotGenerator { | ||||
|             } | ||||
|         } | ||||
|         // generation | ||||
|         int startY = hybridPlotWorld.PLOT_BEDROCK ? 1 : 0; | ||||
|         int startY = hybridPlotWorld.getMinGenHeight() + (hybridPlotWorld.PLOT_BEDROCK ? 1: 0); | ||||
|         for (short x = 0; x < 16; x++) { | ||||
|             if (insideRoadX[x]) { | ||||
|                 for (short z = 0; z < 16; z++) { | ||||
|   | ||||
| @@ -46,7 +46,6 @@ import com.sk89q.worldedit.function.pattern.Pattern; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import com.sk89q.worldedit.world.biome.BiomeType; | ||||
| import com.sk89q.worldedit.world.block.BaseBlock; | ||||
| import com.sk89q.worldedit.world.block.BlockState; | ||||
| import com.sk89q.worldedit.world.block.BlockTypes; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| @@ -107,22 +106,32 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|  | ||||
|     @Override | ||||
|     public boolean createRoadEast(final @NonNull Plot plot, @Nullable QueueCoordinator queue) { | ||||
|         boolean enqueue = false; | ||||
|         if (queue == null) { | ||||
|             queue = hybridPlotWorld.getQueue(); | ||||
|             enqueue = true; | ||||
|         } | ||||
|         super.createRoadEast(plot, queue); | ||||
|         PlotId id = plot.getId(); | ||||
|         PlotId id2 = PlotId.of(id.getX() + 1, id.getY()); | ||||
|         Location bot = getPlotBottomLocAbs(id2); | ||||
|         Location top = getPlotTopLocAbs(id); | ||||
|         Location pos1 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, 0, bot.getZ() - 1); | ||||
|         Location pos2 = Location.at(hybridPlotWorld.getWorldName(), bot.getX(), Math.min(getWorldHeight(), 255), top.getZ() + 1); | ||||
|         Location pos1 = Location.at( | ||||
|                 hybridPlotWorld.getWorldName(), | ||||
|                 top.getX() + 1, | ||||
|                 hybridPlotWorld.getMinGenHeight(), | ||||
|                 bot.getZ() - 1 | ||||
|         ); | ||||
|         Location pos2 = Location.at( | ||||
|                 hybridPlotWorld.getWorldName(), | ||||
|                 bot.getX(), | ||||
|                 hybridPlotWorld.getMaxGenHeight(), | ||||
|                 top.getZ() + 1 | ||||
|         ); | ||||
|         this.resetBiome(hybridPlotWorld, pos1, pos2); | ||||
|         if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|             return true; | ||||
|         } | ||||
|         boolean enqueue = false; | ||||
|         if (queue == null) { | ||||
|             queue = hybridPlotWorld.getQueue(); | ||||
|             enqueue = true; | ||||
|         } | ||||
|         createSchemAbs(queue, pos1, pos2, true); | ||||
|         return !enqueue || queue.enqueue(); | ||||
|     } | ||||
| @@ -139,7 +148,7 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|                         (pos1.getX() + pos2.getX()) / 2, | ||||
|                         (pos1.getZ() + pos2.getZ()) / 2 | ||||
|                 ), biome)) { | ||||
|             WorldUtil.setBiome(hybridPlotWorld.getWorldName(), pos1.getX(), pos1.getZ(), pos2.getX(), pos2.getZ(), biome); | ||||
|             WorldUtil.setBiome(hybridPlotWorld.getWorldName(), new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()), biome); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -190,38 +199,38 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|  | ||||
|     @Override | ||||
|     public boolean createRoadSouth(final @NonNull Plot plot, @Nullable QueueCoordinator queue) { | ||||
|         boolean enqueue = false; | ||||
|         if (queue == null) { | ||||
|             enqueue = true; | ||||
|             queue = hybridPlotWorld.getQueue(); | ||||
|         } | ||||
|         super.createRoadSouth(plot, queue); | ||||
|         PlotId id = plot.getId(); | ||||
|         PlotId id2 = PlotId.of(id.getX(), id.getY() + 1); | ||||
|         Location bot = getPlotBottomLocAbs(id2); | ||||
|         Location top = getPlotTopLocAbs(id); | ||||
|         Location pos1 = Location.at(hybridPlotWorld.getWorldName(), bot.getX() - 1, 0, top.getZ() + 1); | ||||
|         Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, Math.min(getWorldHeight(), 255), bot.getZ()); | ||||
|         Location pos1 = Location.at(hybridPlotWorld.getWorldName(), bot.getX() - 1, hybridPlotWorld.getMinGenHeight(), top.getZ() + 1); | ||||
|         Location pos2 = Location.at(hybridPlotWorld.getWorldName(), top.getX() + 1, hybridPlotWorld.getMaxGenHeight(), bot.getZ()); | ||||
|         this.resetBiome(hybridPlotWorld, pos1, pos2); | ||||
|         if (!hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|             return true; | ||||
|         } | ||||
|         boolean enqueue = false; | ||||
|         if (queue == null) { | ||||
|             enqueue = true; | ||||
|             queue = hybridPlotWorld.getQueue(); | ||||
|         } | ||||
|         createSchemAbs(queue, pos1, pos2, true); | ||||
|         return !enqueue || queue.enqueue(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean createRoadSouthEast(final @NonNull Plot plot, @Nullable QueueCoordinator queue) { | ||||
|         super.createRoadSouthEast(plot, queue); | ||||
|         PlotId id = plot.getId(); | ||||
|         PlotId id2 = PlotId.of(id.getX() + 1, id.getY() + 1); | ||||
|         Location pos1 = getPlotTopLocAbs(id).add(1, 0, 1).withY(0); | ||||
|         Location pos2 = getPlotBottomLocAbs(id2).withY(Math.min(getWorldHeight(), 255)); | ||||
|         boolean enqueue = false; | ||||
|         if (queue == null) { | ||||
|             enqueue = true; | ||||
|             queue = hybridPlotWorld.getQueue(); | ||||
|         } | ||||
|         super.createRoadSouthEast(plot, queue); | ||||
|         PlotId id = plot.getId(); | ||||
|         PlotId id2 = PlotId.of(id.getX() + 1, id.getY() + 1); | ||||
|         Location pos1 = getPlotTopLocAbs(id).add(1, 0, 1); | ||||
|         Location pos2 = getPlotBottomLocAbs(id2); | ||||
|         createSchemAbs(queue, pos1, pos2, true); | ||||
|         if (hybridPlotWorld.ROAD_SCHEMATIC_ENABLED) { | ||||
|             createSchemAbs(queue, pos1, pos2, true); | ||||
| @@ -271,11 +280,23 @@ public class HybridPlotManager extends ClassicPlotManager { | ||||
|             queue.setCompleteTask(whenDone); | ||||
|         } | ||||
|         if (!canRegen) { | ||||
|             queue.setCuboid(pos1.withY(0), pos2.withY(0), bedrock); | ||||
|             queue.setCuboid( | ||||
|                     pos1.withY(hybridPlotWorld.getMinGenHeight()), | ||||
|                     pos2.withY(hybridPlotWorld.getMinGenHeight()), | ||||
|                     hybridPlotWorld.PLOT_BEDROCK ? bedrock : filling | ||||
|             ); | ||||
|             // Each component has a different layer | ||||
|             queue.setCuboid(pos1.withY(1), pos2.withY(hybridPlotWorld.PLOT_HEIGHT - 1), filling); | ||||
|             queue.setCuboid( | ||||
|                     pos1.withY(hybridPlotWorld.getMinGenHeight() + 1), | ||||
|                     pos2.withY(hybridPlotWorld.PLOT_HEIGHT - 1), | ||||
|                     filling | ||||
|             ); | ||||
|             queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT), pos2.withY(hybridPlotWorld.PLOT_HEIGHT), plotfloor); | ||||
|             queue.setCuboid(pos1.withY(hybridPlotWorld.PLOT_HEIGHT + 1), pos2.withY(getWorldHeight()), BlockTypes.AIR.getDefaultState()); | ||||
|             queue.setCuboid( | ||||
|                     pos1.withY(hybridPlotWorld.PLOT_HEIGHT + 1), | ||||
|                     pos2.withY(hybridPlotWorld.getMaxGenHeight()), | ||||
|                     BlockTypes.AIR.getDefaultState() | ||||
|             ); | ||||
|             queue.setBiomeCuboid(pos1, pos2, biome); | ||||
|         } else { | ||||
|             queue.setRegenRegion(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3())); | ||||
|   | ||||
| @@ -79,6 +79,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|     public int SCHEM_Y; | ||||
|     private Location SIGN_LOCATION; | ||||
|     private File root = null; | ||||
|     private int lastOverlayHeightError = Integer.MIN_VALUE; | ||||
|  | ||||
|     @Inject | ||||
|     private SchematicHandler schematicHandler; | ||||
| @@ -171,9 +172,9 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|     public void loadConfiguration(ConfigurationSection config) { | ||||
|         super.loadConfiguration(config); | ||||
|         if ((this.ROAD_WIDTH & 1) == 0) { | ||||
|             this.PATH_WIDTH_LOWER = (short) (Math.floor(this.ROAD_WIDTH / 2) - 1); | ||||
|             this.PATH_WIDTH_LOWER = (short) (Math.floor(this.ROAD_WIDTH / 2f) - 1); | ||||
|         } else { | ||||
|             this.PATH_WIDTH_LOWER = (short) Math.floor(this.ROAD_WIDTH / 2); | ||||
|             this.PATH_WIDTH_LOWER = (short) Math.floor(this.ROAD_WIDTH / 2f); | ||||
|         } | ||||
|         if (this.ROAD_WIDTH == 0) { | ||||
|             this.PATH_WIDTH_UPPER = (short) (this.SIZE + 1); | ||||
| @@ -251,31 +252,34 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         Schematic schematic2 = this.schematicHandler.getSchematic(schematic2File); | ||||
|         Schematic schematic3 = this.schematicHandler.getSchematic(schematic3File); | ||||
|         int shift = this.ROAD_WIDTH / 2; | ||||
|         int oddshift = (this.ROAD_WIDTH & 1) == 0 ? 0 : 1; | ||||
|         int oddshift = (this.ROAD_WIDTH & 1); | ||||
|  | ||||
|         SCHEM_Y = schematicStartHeight(); | ||||
|         int plotY = PLOT_HEIGHT - SCHEM_Y; | ||||
|         int minRoadWall = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? Math.min(ROAD_HEIGHT, WALL_HEIGHT) : ROAD_HEIGHT; | ||||
|         int roadY = minRoadWall - SCHEM_Y; | ||||
|  | ||||
|         int worldHeight = getMaxGenHeight() - getMinGenHeight() + 1; | ||||
|  | ||||
|         // SCHEM_Y should be normalised to the plot "start" height | ||||
|         if (schematic3 != null) { | ||||
|             if (schematic3.getClipboard().getDimensions().getY() == 256) { | ||||
|             if (schematic3.getClipboard().getDimensions().getY() == worldHeight) { | ||||
|                 SCHEM_Y = plotY = 0; | ||||
|             } else if (!Settings.Schematics.PASTE_ON_TOP) { | ||||
|                 SCHEM_Y = plotY = getMinBuildHeight(); | ||||
|                 SCHEM_Y = plotY = getMinBuildHeight() - getMinGenHeight(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (schematic1 != null) { | ||||
|             if (schematic1.getClipboard().getDimensions().getY() == 256) { | ||||
|                 SCHEM_Y = roadY = 0; | ||||
|                 if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != 256 | ||||
|             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; | ||||
|                 } | ||||
|             } else if (!Settings.Schematics.PASTE_ROAD_ON_TOP) { | ||||
|                 SCHEM_Y = roadY = getMinBuildHeight(); | ||||
|                 if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != 256 | ||||
|                 if (schematic3 != null && schematic3.getClipboard().getDimensions().getY() != worldHeight | ||||
|                         && !Settings.Schematics.PASTE_ON_TOP) { | ||||
|                     plotY = PLOT_HEIGHT; | ||||
|                 } | ||||
| @@ -428,7 +432,10 @@ public class HybridPlotWorld extends ClassicPlotWorld { | ||||
|         int pair = MathMan.pair(x, z); | ||||
|         BaseBlock[] existing = this.G_SCH.computeIfAbsent(pair, k -> new BaseBlock[height]); | ||||
|         if (y >= height) { | ||||
|             LOGGER.error("Error adding overlay block. `y > height`"); | ||||
|             if (y != lastOverlayHeightError) { | ||||
|                 lastOverlayHeightError = y; | ||||
|                 LOGGER.error(String.format("Error adding overlay block. `y > height`. y=%s, height=%s", y, height)); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         existing[y] = id; | ||||
|   | ||||
| @@ -65,6 +65,7 @@ import com.sk89q.worldedit.world.block.BlockTypes; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import java.io.File; | ||||
| import java.util.ArrayDeque; | ||||
| @@ -73,6 +74,7 @@ import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
| @@ -85,7 +87,9 @@ public class HybridUtils { | ||||
|     public static HybridUtils manager; | ||||
|     public static Set<BlockVector2> regions; | ||||
|     public static int height; | ||||
|     public static Set<BlockVector2> chunks = new HashSet<>(); | ||||
|     // Use ordered for reasonable chunk loading order to reduce paper unloading neighbour chunks and then us attempting to load | ||||
|     // them again, causing errors | ||||
|     public static Set<BlockVector2> chunks = new LinkedHashSet<>(); | ||||
|     public static PlotArea area; | ||||
|     public static boolean UPDATE = false; | ||||
|  | ||||
| @@ -145,6 +149,8 @@ public class HybridUtils { | ||||
|             final int ctz = tz >> 4; | ||||
|             final int width = tx - bx + 1; | ||||
|             final int length = tz - bz + 1; | ||||
|             final int height = area.getMaxGenHeight() - area.getMinGenHeight() + 1; | ||||
|             final int minHeight = area.getMinGenHeight(); | ||||
|  | ||||
|             final PlotArea area = this.plotAreaManager.getPlotArea(world, null); | ||||
|  | ||||
| @@ -157,7 +163,7 @@ public class HybridUtils { | ||||
|  | ||||
|             final BlockState airBlock = BlockTypes.AIR.getDefaultState(); | ||||
|             final BlockState[][][] oldBlocks = chunk.getBlocks(); | ||||
|             final BlockState[][][] newBlocks = new BlockState[256][width][length]; | ||||
|             final BlockState[][][] newBlocks = new BlockState[height][width][length]; | ||||
|             for (final BlockState[][] newBlock : newBlocks) { | ||||
|                 for (final BlockState[] blockStates : newBlock) { | ||||
|                     Arrays.fill(blockStates, airBlock); | ||||
| @@ -211,11 +217,12 @@ public class HybridUtils { | ||||
|                     int xx = chunkBlockX + x; | ||||
|                     for (int z = minZ; z <= maxZ; z++) { | ||||
|                         int zz = chunkBlockZ + z; | ||||
|                         for (int y = 0; y < 256; y++) { | ||||
|                         for (int yIndex = 0; yIndex < height; yIndex++) { | ||||
|                             int y = yIndex + minHeight; | ||||
|                             BlockState block = queue.getBlock(xx, y, zz); | ||||
|                             int xr = xb + x; | ||||
|                             int zr = zb + z; | ||||
|                             newBlocks[y][xr][zr] = block; | ||||
|                             newBlocks[yIndex][xr][zr] = block; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| @@ -232,10 +239,10 @@ public class HybridUtils { | ||||
|                 for (int x = 0; x < width; x++) { | ||||
|                     for (int z = 0; z < length; z++) { | ||||
|                         Set<BlockType> types = new HashSet<>(); | ||||
|                         for (int y = 0; y < 256; y++) { | ||||
|                             BlockState old = oldBlocks[y][x][z]; | ||||
|                         for (int yIndex = 0; yIndex < height; yIndex++) { | ||||
|                             BlockState old = oldBlocks[yIndex][x][z]; | ||||
|                             try { | ||||
|                                 BlockState now = newBlocks[y][x][z]; | ||||
|                                 BlockState now = newBlocks[yIndex][x][z]; | ||||
|                                 if (!old.equals(now)) { | ||||
|                                     changes[i]++; | ||||
|                                 } | ||||
| @@ -244,23 +251,23 @@ public class HybridUtils { | ||||
|                                 } else { | ||||
|                                     // check vertices | ||||
|                                     // modifications_adjacent | ||||
|                                     if (x > 0 && z > 0 && y > 0 && x < width - 1 && z < length - 1 && y < 255) { | ||||
|                                         if (newBlocks[y - 1][x][z].getBlockType().getMaterial().isAir()) { | ||||
|                                     if (x > 0 && z > 0 && yIndex > 0 && x < width - 1 && z < length - 1 && yIndex < (height - 1)) { | ||||
|                                         if (newBlocks[yIndex - 1][x][z].getBlockType().getMaterial().isAir()) { | ||||
|                                             faces[i]++; | ||||
|                                         } | ||||
|                                         if (newBlocks[y][x - 1][z].getBlockType().getMaterial().isAir()) { | ||||
|                                         if (newBlocks[yIndex][x - 1][z].getBlockType().getMaterial().isAir()) { | ||||
|                                             faces[i]++; | ||||
|                                         } | ||||
|                                         if (newBlocks[y][x][z - 1].getBlockType().getMaterial().isAir()) { | ||||
|                                         if (newBlocks[yIndex][x][z - 1].getBlockType().getMaterial().isAir()) { | ||||
|                                             faces[i]++; | ||||
|                                         } | ||||
|                                         if (newBlocks[y + 1][x][z].getBlockType().getMaterial().isAir()) { | ||||
|                                         if (newBlocks[yIndex + 1][x][z].getBlockType().getMaterial().isAir()) { | ||||
|                                             faces[i]++; | ||||
|                                         } | ||||
|                                         if (newBlocks[y][x + 1][z].getBlockType().getMaterial().isAir()) { | ||||
|                                         if (newBlocks[yIndex][x + 1][z].getBlockType().getMaterial().isAir()) { | ||||
|                                             faces[i]++; | ||||
|                                         } | ||||
|                                         if (newBlocks[y][x][z + 1].getBlockType().getMaterial().isAir()) { | ||||
|                                         if (newBlocks[yIndex][x][z + 1].getBlockType().getMaterial().isAir()) { | ||||
|                                             faces[i]++; | ||||
|                                         } | ||||
|                                     } | ||||
| @@ -408,7 +415,7 @@ public class HybridUtils { | ||||
|         } | ||||
|         HybridUtils.UPDATE = true; | ||||
|         Set<BlockVector2> regions = this.worldUtil.getChunkChunks(area.getWorldName()); | ||||
|         return scheduleRoadUpdate(area, regions, extend, new HashSet<>()); | ||||
|         return scheduleRoadUpdate(area, regions, extend, new LinkedHashSet<>()); | ||||
|     } | ||||
|  | ||||
|     public boolean scheduleSingleRegionRoadUpdate(Plot plot, int extend) { | ||||
| @@ -418,7 +425,7 @@ public class HybridUtils { | ||||
|         HybridUtils.UPDATE = true; | ||||
|         Set<BlockVector2> regions = new HashSet<>(); | ||||
|         regions.add(RegionManager.getRegion(plot.getCenterSynchronous())); | ||||
|         return scheduleRoadUpdate(plot.getArea(), regions, extend, new HashSet<>()); | ||||
|         return scheduleRoadUpdate(plot.getArea(), regions, extend, new LinkedHashSet<>()); | ||||
|     } | ||||
|  | ||||
|     public boolean scheduleRoadUpdate( | ||||
| @@ -431,26 +438,29 @@ public class HybridUtils { | ||||
|         HybridUtils.area = area; | ||||
|         HybridUtils.height = extend; | ||||
|         HybridUtils.chunks = chunks; | ||||
|         final int initial = 1024 * regions.size() + chunks.size(); | ||||
|         final AtomicInteger count = new AtomicInteger(0); | ||||
|         TaskManager.runTask(new Runnable() { | ||||
|             @Override | ||||
|             public void run() { | ||||
|                 if (!UPDATE) { | ||||
|                     Iterator<BlockVector2> iter = chunks.iterator(); | ||||
|                     QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName())); | ||||
|                     while (iter.hasNext()) { | ||||
|                         BlockVector2 chunk = iter.next(); | ||||
|                         iter.remove(); | ||||
|                         boolean regenedRoad = regenerateRoad(area, chunk, extend); | ||||
|                         boolean regenedRoad = regenerateRoad(area, chunk, extend, queue); | ||||
|                         if (!regenedRoad) { | ||||
|                             LOGGER.info("Failed to regenerate roads"); | ||||
|                             LOGGER.info("Failed to regenerate roads in chunk {}", chunk); | ||||
|                         } | ||||
|                     } | ||||
|                     queue.enqueue(); | ||||
|                     LOGGER.info("Cancelled road task"); | ||||
|                     return; | ||||
|                 } | ||||
|                 count.incrementAndGet(); | ||||
|                 if (count.intValue() % 20 == 0) { | ||||
|                     LOGGER.info("Progress: {}%", 100 * (2048 - chunks.size()) / 2048); | ||||
|                 if (count.intValue() % 10 == 0) { | ||||
|                     LOGGER.info("Progress: {}%", 100 * (initial - (chunks.size() + 1024 * regions.size())) / initial); | ||||
|                 } | ||||
|                 if (HybridUtils.regions.isEmpty() && chunks.isEmpty()) { | ||||
|                     regeneratePlotWalls(area); | ||||
| @@ -462,7 +472,7 @@ public class HybridUtils { | ||||
|                     final Runnable task = this; | ||||
|                     TaskManager.runTaskAsync(() -> { | ||||
|                         try { | ||||
|                             if (chunks.size() < 1024) { | ||||
|                             if (chunks.size() < 64) { | ||||
|                                 if (!HybridUtils.regions.isEmpty()) { | ||||
|                                     Iterator<BlockVector2> iterator = HybridUtils.regions.iterator(); | ||||
|                                     BlockVector2 loc = iterator.next(); | ||||
| @@ -475,18 +485,35 @@ public class HybridUtils { | ||||
|                             } | ||||
|                             if (!chunks.isEmpty()) { | ||||
|                                 TaskManager.getPlatformImplementation().sync(() -> { | ||||
|                                     long start = System.currentTimeMillis(); | ||||
|                                     Iterator<BlockVector2> iterator = chunks.iterator(); | ||||
|                                     while (System.currentTimeMillis() - start < 20 && !chunks.isEmpty()) { | ||||
|                                     if (chunks.size() >= 32) { | ||||
|                                         QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName())); | ||||
|                                         for (int i = 0; i < 32; i++) { | ||||
|                                             final BlockVector2 chunk = iterator.next(); | ||||
|                                             iterator.remove(); | ||||
|                                         boolean regenedRoads = regenerateRoad(area, chunk, extend); | ||||
|                                             boolean regenedRoads = regenerateRoad(area, chunk, extend, queue); | ||||
|                                             if (!regenedRoads) { | ||||
|                                             LOGGER.info("Failed to regenerate road"); | ||||
|                                                 LOGGER.info("Failed to regenerate the road in chunk {}", chunk); | ||||
|                                             } | ||||
|                                         } | ||||
|                                         queue.setCompleteTask(task); | ||||
|                                         queue.enqueue(); | ||||
|                                         return null; | ||||
|                                     } | ||||
|                                     QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName())); | ||||
|                                     while (!chunks.isEmpty()) { | ||||
|                                         final BlockVector2 chunk = iterator.next(); | ||||
|                                         iterator.remove(); | ||||
|                                         boolean regenedRoads = regenerateRoad(area, chunk, extend, queue); | ||||
|                                         if (!regenedRoads) { | ||||
|                                             LOGGER.info("Failed to regenerate road in chunk {}", chunk); | ||||
|                                         } | ||||
|                                     } | ||||
|                                     queue.setCompleteTask(task); | ||||
|                                     queue.enqueue(); | ||||
|                                     return null; | ||||
|                                 }); | ||||
|                                 return; | ||||
|                             } | ||||
|                         } catch (Exception e) { | ||||
|                             e.printStackTrace(); | ||||
| @@ -514,7 +541,6 @@ public class HybridUtils { | ||||
|         Location bot = plot.getBottomAbs().subtract(1, 0, 1); | ||||
|         Location top = plot.getTopAbs(); | ||||
|         final HybridPlotWorld plotworld = (HybridPlotWorld) plot.getArea(); | ||||
|         PlotManager plotManager = plotworld.getPlotManager(); | ||||
|         // Do not use plotworld#schematicStartHeight() here as we want to restore the pre 6.1.4 way of doing it if | ||||
|         //  USE_WALL_IN_ROAD_SCHEM_HEIGHT is false | ||||
|         int schemY = Settings.Schematics.USE_WALL_IN_ROAD_SCHEM_HEIGHT ? | ||||
| @@ -524,10 +550,10 @@ public class HybridUtils { | ||||
|         int sy = Settings.Schematics.PASTE_ROAD_ON_TOP ? schemY : plot.getArea().getMinBuildHeight(); | ||||
|         int ex = bot.getX(); | ||||
|         int ez = top.getZ(); | ||||
|         int ey = get_ey(plotManager, queue, sx, ex, sz, ez, sy); | ||||
|         int ey = get_ey(plotworld, queue, sx, ex, sz, ez, sy); | ||||
|         int bz = sz - plotworld.ROAD_WIDTH; | ||||
|         int tz = sz - 1; | ||||
|         int ty = get_ey(plotManager, queue, sx, ex, bz, tz, sy); | ||||
|         int ty = get_ey(plotworld, queue, sx, ex, bz, tz, sy); | ||||
|  | ||||
|         final Set<CuboidRegion> sideRoad = Collections.singleton(RegionUtil.createRegion(sx, ex, sy, ey, sz, ez)); | ||||
|         final Set<CuboidRegion> intersection = Collections.singleton(RegionUtil.createRegion(sx, ex, sy, ty, bz, tz)); | ||||
| @@ -553,11 +579,11 @@ public class HybridUtils { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public int get_ey(final PlotManager pm, QueueCoordinator queue, int sx, int ex, int sz, int ez, int sy) { | ||||
|     private int get_ey(final HybridPlotWorld hpw, QueueCoordinator queue, int sx, int ex, int sz, int ez, int sy) { | ||||
|         int ey = sy; | ||||
|         for (int x = sx; x <= ex; x++) { | ||||
|             for (int z = sz; z <= ez; z++) { | ||||
|                 for (int y = sy; y <= pm.getWorldHeight(); y++) { | ||||
|                 for (int y = sy; y <= hpw.getMaxGenHeight(); y++) { | ||||
|                     if (y > ey) { | ||||
|                         BlockState block = queue.getBlock(x, y, z); | ||||
|                         if (!block.getBlockType().getMaterial().isAir()) { | ||||
| @@ -570,7 +596,36 @@ public class HybridUtils { | ||||
|         return ey; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Regenerate the road in a chunk in a plot area. | ||||
|      * | ||||
|      * @param area   Plot area to regenerate road for | ||||
|      * @param chunk  Chunk location to regenerate | ||||
|      * @param extend How far to extend setting air above the road | ||||
|      * @return if successful | ||||
|      * @deprecated use {@link HybridUtils#regenerateRoad(PlotArea, BlockVector2, int, QueueCoordinator)} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     public boolean regenerateRoad(final PlotArea area, final BlockVector2 chunk, int extend) { | ||||
|         return regenerateRoad(area, chunk, extend, null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Regenerate the road in a chunk in a plot area. | ||||
|      * | ||||
|      * @param area             Plot area to regenerate road for | ||||
|      * @param chunk            Chunk location to regenerate | ||||
|      * @param extend           How far to extend setting air above the road | ||||
|      * @param queueCoordinator {@link QueueCoordinator} to use to set the blocks. Null if one should be created and enqueued | ||||
|      * @return if successful | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public boolean regenerateRoad( | ||||
|             final PlotArea area, | ||||
|             final BlockVector2 chunk, | ||||
|             int extend, | ||||
|             @Nullable QueueCoordinator queueCoordinator | ||||
|     ) { | ||||
|         int x = chunk.getX() << 4; | ||||
|         int z = chunk.getZ() << 4; | ||||
|         int ex = x + 15; | ||||
| @@ -596,9 +651,16 @@ public class HybridUtils { | ||||
|         z -= plotWorld.ROAD_OFFSET_Z; | ||||
|         final int finalX = x; | ||||
|         final int finalZ = z; | ||||
|         QueueCoordinator queue = this.blockQueue.getNewQueue(worldUtil.getWeWorld(plotWorld.getWorldName())); | ||||
|         final boolean enqueue; | ||||
|         final QueueCoordinator queue; | ||||
|         if (queueCoordinator == null) { | ||||
|             queue = this.blockQueue.getNewQueue(worldUtil.getWeWorld(plotWorld.getWorldName())); | ||||
|             enqueue = true; | ||||
|         } else { | ||||
|             queue = queueCoordinator; | ||||
|             enqueue = false; | ||||
|         } | ||||
|         if (id1 == null || id2 == null || id1 != id2) { | ||||
|             this.chunkManager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> { | ||||
|             if (id1 != null) { | ||||
|                 Plot p1 = area.getPlotAbs(id1); | ||||
|                 if (p1 != null && p1.hasOwner() && p1.isMerged()) { | ||||
| @@ -611,7 +673,7 @@ public class HybridUtils { | ||||
|                     toCheck.set(true); | ||||
|                 } | ||||
|             } | ||||
|                 int size = plotWorld.SIZE; | ||||
|             short size = plotWorld.SIZE; | ||||
|             for (int X = 0; X < 16; X++) { | ||||
|                 short absX = (short) ((finalX + X) % size); | ||||
|                 for (int Z = 0; Z < 16; Z++) { | ||||
| @@ -638,29 +700,29 @@ 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 : 1; | ||||
|                             int maxY = Math.max(extend, blocks.length); | ||||
|                             for (int y = 0; y < maxY; y++) { | ||||
|                                 if (y > blocks.length - 1) { | ||||
|                         int minY = Settings.Schematics.PASTE_ROAD_ON_TOP ? plotWorld.SCHEM_Y : area.getMinGenHeight() + 1; | ||||
|                         int maxDy = Math.max(extend, blocks.length); | ||||
|                         for (int dy = 0; dy < maxDy; dy++) { | ||||
|                             if (dy > blocks.length - 1) { | ||||
|                                 queue.setBlock( | ||||
|                                         finalX + X + plotWorld.ROAD_OFFSET_X, | ||||
|                                             minY + y, | ||||
|                                         minY + dy, | ||||
|                                         finalZ + Z + plotWorld.ROAD_OFFSET_Z, | ||||
|                                         WEExtent.AIRBASE | ||||
|                                 ); | ||||
|                             } else { | ||||
|                                     BaseBlock block = blocks[y]; | ||||
|                                 BaseBlock block = blocks[dy]; | ||||
|                                 if (block != null) { | ||||
|                                     queue.setBlock( | ||||
|                                             finalX + X + plotWorld.ROAD_OFFSET_X, | ||||
|                                                 minY + y, | ||||
|                                             minY + dy, | ||||
|                                             finalZ + Z + plotWorld.ROAD_OFFSET_Z, | ||||
|                                             block | ||||
|                                     ); | ||||
|                                 } else { | ||||
|                                     queue.setBlock( | ||||
|                                             finalX + X + plotWorld.ROAD_OFFSET_X, | ||||
|                                                 minY + y, | ||||
|                                             minY + dy, | ||||
|                                             finalZ + Z + plotWorld.ROAD_OFFSET_Z, | ||||
|                                             WEExtent.AIRBASE | ||||
|                                     ); | ||||
| @@ -680,8 +742,9 @@ public class HybridUtils { | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (enqueue) { | ||||
|                 queue.enqueue(); | ||||
|             }); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         return false; | ||||
|   | ||||
| @@ -96,7 +96,7 @@ public abstract class SquarePlotManager extends GridPlotManager { | ||||
|                 .floor(squarePlotWorld.ROAD_WIDTH / 2) - 1; | ||||
|         int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - (int) Math | ||||
|                 .floor(squarePlotWorld.ROAD_WIDTH / 2) - 1; | ||||
|         return Location.at(squarePlotWorld.getWorldName(), x, Math.min(getWorldHeight(), 255), z); | ||||
|         return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMaxGenHeight(), z); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -260,7 +260,7 @@ public abstract class SquarePlotManager extends GridPlotManager { | ||||
|                 - (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2); | ||||
|         int z = (squarePlotWorld.ROAD_OFFSET_Z + (pz * (squarePlotWorld.ROAD_WIDTH + squarePlotWorld.PLOT_WIDTH))) - squarePlotWorld.PLOT_WIDTH | ||||
|                 - (int) Math.floor(squarePlotWorld.ROAD_WIDTH / 2); | ||||
|         return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMinBuildHeight(), z); | ||||
|         return Location.at(squarePlotWorld.getWorldName(), x, squarePlotWorld.getMinGenHeight(), z); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -35,6 +35,7 @@ import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.util.Permissions; | ||||
| import com.plotsquared.core.util.WEManager; | ||||
| import com.plotsquared.core.util.WorldUtil; | ||||
| import com.sk89q.worldedit.EditSession; | ||||
| import com.sk89q.worldedit.WorldEdit; | ||||
| import com.sk89q.worldedit.entity.Player; | ||||
| import com.sk89q.worldedit.event.extent.EditSessionEvent; | ||||
| @@ -67,6 +68,9 @@ public class WESubscriber { | ||||
|             WorldEdit.getInstance().getEventBus().unregister(this); | ||||
|             return; | ||||
|         } | ||||
|         if (event.getStage() != EditSession.Stage.BEFORE_HISTORY) { | ||||
|             return; | ||||
|         } | ||||
|         World worldObj = event.getWorld(); | ||||
|         if (worldObj == null) { | ||||
|             return; | ||||
|   | ||||
| @@ -58,6 +58,21 @@ public interface World<T> { | ||||
|      */ | ||||
|     @NonNull String getName(); | ||||
|  | ||||
|     /** | ||||
|      * Get the min world height. Inclusive. | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     int getMinHeight(); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Get the max world height. Inclusive. | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     int getMaxHeight(); | ||||
|  | ||||
|     class NullWorld<T> implements World<T> { | ||||
|  | ||||
|         private NullWorld() { | ||||
| @@ -74,6 +89,16 @@ public interface World<T> { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public int getMinHeight() { | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public int getMaxHeight() { | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean equals(final Object obj) { | ||||
|             return obj instanceof NullWorld; | ||||
|   | ||||
| @@ -122,7 +122,7 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE; | ||||
|  */ | ||||
| public class Plot { | ||||
|  | ||||
|  | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     public static final int MAX_HEIGHT = 256; | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Plot.class.getSimpleName()); | ||||
| @@ -1371,7 +1371,7 @@ public class Plot { | ||||
|         int z = largest.getMinimumPoint().getZ() - 1; | ||||
|         PlotManager manager = getManager(); | ||||
|         int y = isLoaded() ? this.worldUtil.getHighestBlockSynchronous(getWorldName(), x, z) : 62; | ||||
|         if (area.allowSigns() && (y <= 0 || y >= 255)) { | ||||
|         if (area.allowSigns() && (y <= area.getMinGenHeight() || y >= area.getMaxGenHeight())) { | ||||
|             y = Math.max(y, manager.getSignLoc(this).getY() - 1); | ||||
|         } | ||||
|         return Location.at(getWorldName(), x, y + 1, z); | ||||
| @@ -1387,7 +1387,7 @@ public class Plot { | ||||
|         if (isLoaded()) { | ||||
|             this.worldUtil.getHighestBlock(getWorldName(), x, z, y -> { | ||||
|                 int height = y; | ||||
|                 if (area.allowSigns() && (y <= 0 || y >= 255)) { | ||||
|                 if (area.allowSigns() && (y <= area.getMinGenHeight() || y >= area.getMaxGenHeight())) { | ||||
|                     height = Math.max(y, manager.getSignLoc(this).getY() - 1); | ||||
|                 } | ||||
|                 result.accept(Location.at(getWorldName(), x, height + 1, z)); | ||||
| @@ -1619,8 +1619,8 @@ public class Plot { | ||||
|     public double getVolume() { | ||||
|         double count = 0; | ||||
|         for (CuboidRegion region : getRegions()) { | ||||
|             count += (region.getMaximumPoint().getX() - (double) region.getMinimumPoint().getX() + 1) * ( | ||||
|                     region.getMaximumPoint().getZ() - (double) region.getMinimumPoint().getZ() + 1) * MAX_HEIGHT; | ||||
|             // CuboidRegion#getArea is deprecated and we want to ensure use of correct height | ||||
|             count += region.getLength() * region.getWidth() * (area.getMaxGenHeight() - area.getMinGenHeight() + 1); | ||||
|         } | ||||
|         return count; | ||||
|     } | ||||
| @@ -1738,7 +1738,6 @@ public class Plot { | ||||
|             area.addPlot(this); | ||||
|             updateWorldBorder(); | ||||
|         } | ||||
|         this.getPlotModificationManager().setSign(player.getName()); | ||||
|         player.sendMessage(TranslatableCaption.of("working.claimed"), Template.of("plot", this.getId().toString())); | ||||
|         if (teleport) { | ||||
|             if (!auto && Settings.Teleport.ON_CLAIM) { | ||||
| @@ -1786,6 +1785,7 @@ public class Plot { | ||||
|             ); | ||||
|         } | ||||
|         plotworld.getPlotManager().claimPlot(this, null); | ||||
|         this.getPlotModificationManager().setSign(player.getName()); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -2438,8 +2438,8 @@ public class Plot { | ||||
|             return regions_cache; | ||||
|         } | ||||
|         if (!this.isMerged()) { | ||||
|             Location pos1 = this.getBottomAbs(); | ||||
|             Location pos2 = this.getTopAbs(); | ||||
|             Location pos1 = this.getBottomAbs().withY(getArea().getMinBuildHeight()); | ||||
|             Location pos2 = this.getTopAbs().withY(getArea().getMaxBuildHeight()); | ||||
|             connected_cache = Sets.newHashSet(this); | ||||
|             CuboidRegion rg = new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()); | ||||
|             regions_cache = Collections.singleton(rg); | ||||
|   | ||||
| @@ -34,8 +34,6 @@ import com.plotsquared.core.configuration.ConfigurationNode; | ||||
| import com.plotsquared.core.configuration.ConfigurationSection; | ||||
| import com.plotsquared.core.configuration.ConfigurationUtil; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.CaptionUtility; | ||||
| import com.plotsquared.core.configuration.caption.LocaleHolder; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.configuration.file.YamlConfiguration; | ||||
| import com.plotsquared.core.generator.GridPlotWorld; | ||||
| @@ -54,7 +52,6 @@ import com.plotsquared.core.plot.flag.FlagParseException; | ||||
| import com.plotsquared.core.plot.flag.GlobalFlagContainer; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DoneFlag; | ||||
| import com.plotsquared.core.plot.flag.types.DoubleFlag; | ||||
| import com.plotsquared.core.queue.GlobalBlockQueue; | ||||
| import com.plotsquared.core.queue.QueueCoordinator; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| @@ -144,8 +141,10 @@ public abstract class PlotArea { | ||||
|     private boolean homeAllowNonmember = false; | ||||
|     private BlockLoc nonmemberHome; | ||||
|     private BlockLoc defaultHome; | ||||
|     private int maxBuildHeight = 256; | ||||
|     private int minBuildHeight = 1; | ||||
|     private int maxBuildHeight = PlotSquared.platform().versionMaxHeight() + 1; // Exclusive | ||||
|     private int minBuildHeight = PlotSquared.platform().versionMinHeight() + 1; // Inclusive | ||||
|     private int maxGenHeight = PlotSquared.platform().versionMaxHeight(); // Inclusive | ||||
|     private int minGenHeight = PlotSquared.platform().versionMinHeight(); // Inclusive | ||||
|     private GameMode gameMode = GameModes.CREATIVE; | ||||
|     private Map<String, PlotExpression> prices = new HashMap<>(); | ||||
|     private List<String> schematics = new ArrayList<>(); | ||||
| @@ -361,6 +360,8 @@ public abstract class PlotArea { | ||||
|         this.worldBorder = config.getBoolean("world.border"); | ||||
|         this.maxBuildHeight = config.getInt("world.max_height"); | ||||
|         this.minBuildHeight = config.getInt("world.min_height"); | ||||
|         this.minGenHeight = config.getInt("world.min_gen_height"); | ||||
|         this.maxGenHeight = config.getInt("world.max_gen_height"); | ||||
|  | ||||
|         switch (config.getString("world.gamemode").toLowerCase()) { | ||||
|             case "creative", "c", "1" -> this.gameMode = GameModes.CREATIVE; | ||||
| @@ -484,6 +485,8 @@ public abstract class PlotArea { | ||||
|         options.put("home.nonmembers", position); | ||||
|         options.put("world.max_height", this.getMaxBuildHeight()); | ||||
|         options.put("world.min_height", this.getMinBuildHeight()); | ||||
|         options.put("world.min_gen_height", this.getMinGenHeight()); | ||||
|         options.put("world.max_gen_height", this.getMaxGenHeight()); | ||||
|         options.put("world.gamemode", this.getGameMode().getName().toLowerCase()); | ||||
|         options.put("road.flags.default", null); | ||||
|  | ||||
| @@ -1078,8 +1081,8 @@ public abstract class PlotArea { | ||||
|                     BlockVector2 pos1 = BlockVector2.at(value.getP1().getX(), value.getP1().getY()); | ||||
|                     BlockVector2 pos2 = BlockVector2.at(value.getP2().getX(), value.getP2().getY()); | ||||
|                     return new CuboidRegion( | ||||
|                             pos1.toBlockVector3(), | ||||
|                             pos2.toBlockVector3(Plot.MAX_HEIGHT - 1) | ||||
|                             pos1.toBlockVector3(getMinGenHeight()), | ||||
|                             pos2.toBlockVector3(getMaxGenHeight()) | ||||
|                     ); | ||||
|                 } | ||||
|             }; | ||||
| @@ -1361,14 +1364,38 @@ public abstract class PlotArea { | ||||
|         this.defaultHome = defaultHome; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the maximum height players may build in. Exclusive. | ||||
|      */ | ||||
|     public int getMaxBuildHeight() { | ||||
|         return this.maxBuildHeight; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the minimum height players may build in. Inclusive. | ||||
|      */ | ||||
|     public int getMinBuildHeight() { | ||||
|         return this.minBuildHeight; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the min height from which P2 will generate blocks. Inclusive. | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public int getMinGenHeight() { | ||||
|         return this.minGenHeight; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the max height to which P2 will generate blocks. Inclusive. | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public int getMaxGenHeight() { | ||||
|         return this.maxGenHeight; | ||||
|     } | ||||
|  | ||||
|     public GameMode getGameMode() { | ||||
|         return this.gameMode; | ||||
|     } | ||||
|   | ||||
| @@ -89,11 +89,17 @@ public class PlotCluster { | ||||
|     } | ||||
|  | ||||
|     private void setRegion() { | ||||
|         this.region = RegionUtil.createRegion(this.pos1.getX(), this.pos2.getX(), | ||||
|         this.region = RegionUtil.createRegion(this.pos1.getX(), this.pos2.getX(), 0, 0, | ||||
|                 this.pos1.getY(), this.pos2.getY() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a region of PlotIDs | ||||
|      * | ||||
|      * @deprecated - returns region of IDs, not of actual blocks. | ||||
|      */ | ||||
|     @Deprecated | ||||
|     public CuboidRegion getRegion() { | ||||
|         return this.region; | ||||
|     } | ||||
| @@ -165,7 +171,7 @@ public class PlotCluster { | ||||
|         Consumer<Location> locationConsumer = toReturn -> | ||||
|                 PlotSquared.platform().worldUtil().getHighestBlock(this.area.getWorldName(), toReturn.getX(), toReturn.getZ(), | ||||
|                         highest -> { | ||||
|                             if (highest == 0) { | ||||
|                             if (highest <= area.getMinBuildHeight()) { | ||||
|                                 highest = 63; | ||||
|                             } | ||||
|                             if (highest > toReturn.getY()) { | ||||
| @@ -175,12 +181,12 @@ public class PlotCluster { | ||||
|                             } | ||||
|                         } | ||||
|                 ); | ||||
|         if (home.getY() == 0) { | ||||
|         if (home.getY() == Integer.MIN_VALUE) { | ||||
|             // default pos | ||||
|             Plot center = getCenterPlot(); | ||||
|             center.getHome(location -> { | ||||
|                 Location toReturn = location; | ||||
|                 if (toReturn.getY() == 0) { | ||||
|                 if (toReturn.getY() <= area.getMinBuildHeight()) { | ||||
|                     PlotManager manager = this.area.getPlotManager(); | ||||
|                     Location locationSign = manager.getSignLoc(center); | ||||
|                     toReturn = toReturn.withY(locationSign.getY()); | ||||
|   | ||||
| @@ -69,8 +69,6 @@ import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| import static com.plotsquared.core.plot.Plot.MAX_HEIGHT; | ||||
|  | ||||
| /** | ||||
|  * Manager that handles {@link Plot} modifications | ||||
|  */ | ||||
| @@ -311,7 +309,7 @@ public final class PlotModificationManager { | ||||
|                     return; | ||||
|                 } | ||||
|                 CuboidRegion region = regions.poll(); | ||||
|                 PlotSquared.platform().regionManager().setBiome(region, extendBiome, biome, plot.getWorldName(), this); | ||||
|                 PlotSquared.platform().regionManager().setBiome(region, extendBiome, biome, plot.getArea(), this); | ||||
|             } | ||||
|         }; | ||||
|         run.run(); | ||||
| @@ -527,28 +525,6 @@ public final class PlotModificationManager { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the south road section of a plot<br> | ||||
|      * - Used when a plot is merged<br> | ||||
|      * | ||||
|      * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, | ||||
|      *              otherwise writes to the queue but does not enqueue. | ||||
|      */ | ||||
|     public void removeRoadSouth(final @Nullable QueueCoordinator queue) { | ||||
|         if (this.plot.getArea().getType() != PlotAreaType.NORMAL && this.plot | ||||
|                 .getArea() | ||||
|                 .getTerrain() == PlotAreaTerrainType.ROAD) { | ||||
|             Plot other = this.plot.getRelative(Direction.SOUTH); | ||||
|             Location bot = other.getBottomAbs(); | ||||
|             Location top = this.plot.getTopAbs(); | ||||
|             Location pos1 = Location.at(this.plot.getWorldName(), bot.getX(), 0, top.getZ()); | ||||
|             Location pos2 = Location.at(this.plot.getWorldName(), top.getX(), MAX_HEIGHT, bot.getZ()); | ||||
|             PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null); | ||||
|         } else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove | ||||
|             this.plot.getManager().removeRoadSouth(this.plot, queue); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Auto merge a plot in a specific direction. | ||||
|      * | ||||
| @@ -915,6 +891,28 @@ public final class PlotModificationManager { | ||||
|         return this.setComponent(component, parsed.toPattern(), actor, queue); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the south road section of a plot<br> | ||||
|      * - Used when a plot is merged<br> | ||||
|      * | ||||
|      * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, | ||||
|      *              otherwise writes to the queue but does not enqueue. | ||||
|      */ | ||||
|     public void removeRoadSouth(final @Nullable QueueCoordinator queue) { | ||||
|         if (this.plot.getArea().getType() != PlotAreaType.NORMAL && this.plot | ||||
|                 .getArea() | ||||
|                 .getTerrain() == PlotAreaTerrainType.ROAD) { | ||||
|             Plot other = this.plot.getRelative(Direction.SOUTH); | ||||
|             Location bot = other.getBottomAbs(); | ||||
|             Location top = this.plot.getTopAbs(); | ||||
|             Location pos1 = Location.at(this.plot.getWorldName(), bot.getX(), plot.getArea().getMinGenHeight(), top.getZ()); | ||||
|             Location pos2 = Location.at(this.plot.getWorldName(), top.getX(), plot.getArea().getMaxGenHeight(), bot.getZ()); | ||||
|             PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null); | ||||
|         } else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove | ||||
|             this.plot.getManager().removeRoadSouth(this.plot, queue); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the east road section of a plot<br> | ||||
|      * - Used when a plot is merged<br> | ||||
| @@ -929,8 +927,8 @@ public final class PlotModificationManager { | ||||
|             Plot other = this.plot.getRelative(Direction.EAST); | ||||
|             Location bot = other.getBottomAbs(); | ||||
|             Location top = this.plot.getTopAbs(); | ||||
|             Location pos1 = Location.at(this.plot.getWorldName(), top.getX(), 0, bot.getZ()); | ||||
|             Location pos2 = Location.at(this.plot.getWorldName(), bot.getX(), MAX_HEIGHT, top.getZ()); | ||||
|             Location pos1 = Location.at(this.plot.getWorldName(), top.getX(), plot.getArea().getMinGenHeight(), bot.getZ()); | ||||
|             Location pos2 = Location.at(this.plot.getWorldName(), bot.getX(), plot.getArea().getMaxGenHeight(), top.getZ()); | ||||
|             PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null); | ||||
|         } else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove | ||||
|             this.plot.getArea().getPlotManager().removeRoadEast(this.plot, queue); | ||||
| @@ -948,8 +946,8 @@ public final class PlotModificationManager { | ||||
|                 .getArea() | ||||
|                 .getTerrain() == PlotAreaTerrainType.ROAD) { | ||||
|             Plot other = this.plot.getRelative(1, 1); | ||||
|             Location pos1 = this.plot.getTopAbs().add(1, 0, 1).withY(0); | ||||
|             Location pos2 = other.getBottomAbs().subtract(1, 0, 1).withY(MAX_HEIGHT); | ||||
|             Location pos1 = this.plot.getTopAbs().add(1, 0, 1); | ||||
|             Location pos2 = other.getBottomAbs().subtract(1, 0, 1); | ||||
|             PlotSquared.platform().regionManager().regenerateRegion(pos1, pos2, true, null); | ||||
|         } else if (this.plot.getArea().getTerrain() != PlotAreaTerrainType.ALL) { // no road generated => no road to remove | ||||
|             this.plot.getArea().getPlotManager().removeRoadSouthEast(this.plot, queue); | ||||
|   | ||||
| @@ -125,7 +125,7 @@ public abstract class PlotWorld { | ||||
|     /** | ||||
|      * @deprecated This method is not meant to be invoked or overridden, with no replacement. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     protected boolean canEqual(final Object other) { | ||||
|         return other instanceof PlotWorld; | ||||
|     } | ||||
|   | ||||
| @@ -391,7 +391,7 @@ public class FlagContainer { | ||||
|     /** | ||||
|      * @deprecated This method is not meant to be invoked or overridden, with no replacement. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     protected boolean canEqual(final Object other) { | ||||
|         return other instanceof FlagContainer; | ||||
|     } | ||||
|   | ||||
| @@ -221,7 +221,7 @@ public abstract class PlotFlag<T, F extends PlotFlag<T, F>> { | ||||
|     /** | ||||
|      * @deprecated This method is not meant to be invoked or overridden, with no replacement. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     protected boolean canEqual(final Object other) { | ||||
|         return other instanceof PlotFlag; | ||||
|     } | ||||
|   | ||||
| @@ -101,7 +101,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator { | ||||
|  | ||||
|     @Override | ||||
|     public boolean setBlock(int x, int y, int z, @NonNull BaseBlock id) { | ||||
|         if ((y > 255) || (y < 0)) { | ||||
|         if ((y > world.getMaxY()) || (y < world.getMinY())) { | ||||
|             return false; | ||||
|         } | ||||
|         LocalChunk chunk = getChunk(x >> 4, z >> 4); | ||||
| @@ -121,7 +121,7 @@ public abstract class BasicQueueCoordinator extends QueueCoordinator { | ||||
|     @Override | ||||
|     public boolean setBiome(int x, int z, @NonNull BiomeType biomeType) { | ||||
|         LocalChunk chunk = getChunk(x >> 4, z >> 4); | ||||
|         for (int y = 0; y < 256; y++) { | ||||
|         for (int y = world.getMinY(); y <= world.getMaxY(); y++) { | ||||
|             chunk.setBiome(x & 15, y, z & 15, biomeType); | ||||
|         } | ||||
|         settingBiomes = true; | ||||
|   | ||||
| @@ -54,12 +54,12 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator { | ||||
|             @NonNull BlockVector3 top, | ||||
|             boolean biomes | ||||
|     ) { | ||||
|         super(null, Location.at("", 0, 0, 0), Location.at("", 15, 255, 15)); | ||||
|         super(null, Location.at("", 0, weWorld.getMinY(), 0), Location.at("", 15, weWorld.getMaxY(), 15)); | ||||
|         this.weWorld = weWorld; | ||||
|         this.width = top.getX() - bot.getX() + 1; | ||||
|         this.length = top.getZ() - bot.getZ() + 1; | ||||
|         this.result = new BlockState[256][width][length]; | ||||
|         this.biomeResult = biomes ? new BiomeType[256][width][length] : null; | ||||
|         this.result = new BlockState[weWorld.getMaxY() - weWorld.getMinY() + 1][width][length]; | ||||
|         this.biomeResult = biomes ? new BiomeType[weWorld.getMaxY() - weWorld.getMinY() + 1][width][length] : null; | ||||
|         this.bot = bot; | ||||
|         this.top = top; | ||||
|     } | ||||
| @@ -71,7 +71,7 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator { | ||||
|     @Override | ||||
|     public boolean setBiome(int x, int z, @NonNull BiomeType biomeType) { | ||||
|         if (this.biomeResult != null) { | ||||
|             for (int y = 0; y < 256; y++) { | ||||
|             for (int y = weWorld.getMinY(); y <= weWorld.getMaxY(); y++) { | ||||
|                 this.storeCacheBiome(x, y, z, biomeType); | ||||
|             } | ||||
|             return true; | ||||
| @@ -101,9 +101,10 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator { | ||||
|     } | ||||
|  | ||||
|     private void storeCache(final int x, final int y, final int z, final @NonNull BlockState id) { | ||||
|         BlockState[][] resultY = result[y]; | ||||
|         int yIndex = getYIndex(y); | ||||
|         BlockState[][] resultY = result[yIndex]; | ||||
|         if (resultY == null) { | ||||
|             result[y] = resultY = new BlockState[length][]; | ||||
|             result[yIndex] = resultY = new BlockState[length][]; | ||||
|         } | ||||
|         BlockState[] resultYZ = resultY[z]; | ||||
|         if (resultYZ == null) { | ||||
| @@ -113,9 +114,10 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator { | ||||
|     } | ||||
|  | ||||
|     private void storeCacheBiome(final int x, final int y, final int z, final @NonNull BiomeType id) { | ||||
|         BiomeType[][] resultY = biomeResult[y]; | ||||
|         int yIndex = getYIndex(y); | ||||
|         BiomeType[][] resultY = biomeResult[yIndex]; | ||||
|         if (resultY == null) { | ||||
|             biomeResult[y] = resultY = new BiomeType[length][]; | ||||
|             biomeResult[yIndex] = resultY = new BiomeType[length][]; | ||||
|         } | ||||
|         BiomeType[] resultYZ = resultY[z]; | ||||
|         if (resultYZ == null) { | ||||
| @@ -132,7 +134,7 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator { | ||||
|  | ||||
|     @Override | ||||
|     public @Nullable BlockState getBlock(int x, int y, int z) { | ||||
|         BlockState[][] blocksY = result[y]; | ||||
|         BlockState[][] blocksY = result[getYIndex(y)]; | ||||
|         if (blocksY != null) { | ||||
|             BlockState[] blocksYZ = blocksY[z]; | ||||
|             if (blocksYZ != null) { | ||||
| @@ -157,4 +159,8 @@ public class ChunkQueueCoordinator extends ScopedQueueCoordinator { | ||||
|         return Location.at(getWorld().getName(), bot.getX(), bot.getY(), bot.getZ()); | ||||
|     } | ||||
|  | ||||
|     private int getYIndex(int y) { | ||||
|         return y - weWorld.getMinY(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -42,6 +42,7 @@ public class LocalChunk { | ||||
|     private final QueueCoordinator parent; | ||||
|     private final int x; | ||||
|     private final int z; | ||||
|     private final int minSection; | ||||
|  | ||||
|     private final BaseBlock[][] baseblocks; | ||||
|     private final BiomeType[][] biomes; | ||||
| @@ -52,8 +53,10 @@ public class LocalChunk { | ||||
|         this.parent = parent; | ||||
|         this.x = x; | ||||
|         this.z = z; | ||||
|         baseblocks = new BaseBlock[16][]; | ||||
|         biomes = new BiomeType[16][]; | ||||
|         this.minSection = parent.getMinLayer(); | ||||
|         int sections = parent.getMaxLayer() - parent.getMinLayer() + 1; | ||||
|         baseblocks = new BaseBlock[sections][]; | ||||
|         biomes = new BiomeType[sections][]; | ||||
|     } | ||||
|  | ||||
|     public @NonNull QueueCoordinator getParent() { | ||||
| @@ -68,6 +71,15 @@ public class LocalChunk { | ||||
|         return this.z; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the minimum layer position stored (usually -4 or 0). | ||||
|      * | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public int getMinSection() { | ||||
|         return this.minSection; | ||||
|     } | ||||
|  | ||||
|     public @NonNull BaseBlock[][] getBaseblocks() { | ||||
|         return this.baseblocks; | ||||
|     } | ||||
| @@ -81,7 +93,7 @@ public class LocalChunk { | ||||
|     } | ||||
|  | ||||
|     public void setBiome(final int x, final int y, final int z, final @NonNull BiomeType biomeType) { | ||||
|         final int i = y >> 4; | ||||
|         final int i = getLayerIndex(y); | ||||
|         final int j = ChunkUtil.getJ(x, y, z); | ||||
|         BiomeType[] array = this.biomes[i]; | ||||
|         if (array == null) { | ||||
| @@ -96,7 +108,7 @@ public class LocalChunk { | ||||
|     } | ||||
|  | ||||
|     public void setBlock(final int x, final int y, final int z, final @NonNull BaseBlock baseBlock) { | ||||
|         final int i = y >> 4; | ||||
|         final int i = getLayerIndex(y); | ||||
|         final int j = ChunkUtil.getJ(x, y, z); | ||||
|         BaseBlock[] array = baseblocks[i]; | ||||
|         if (array == null) { | ||||
| @@ -117,4 +129,8 @@ public class LocalChunk { | ||||
|         return this.entities; | ||||
|     } | ||||
|  | ||||
|     private int getLayerIndex(final int y) { | ||||
|         return (y >> 4) - minSection; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -87,11 +87,14 @@ public class LocationOffsetDelegateQueueCoordinator extends DelegateQueueCoordin | ||||
|  | ||||
|     @Override | ||||
|     public boolean setBiome(int x, int z, @NonNull BiomeType biome) { | ||||
|         boolean result = true; | ||||
|         for (int y = 0; y < 256; y++) { | ||||
|             result &= this.setBiome(x, y, z, biome); | ||||
|         try { | ||||
|             if (canPlace[x - blockX][z - blockZ]) { | ||||
|                 return super.setBiome(x, z, biome); | ||||
|             } | ||||
|         return result; | ||||
|         } catch (final Exception e) { | ||||
|             throw e; | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|   | ||||
| @@ -75,12 +75,29 @@ public abstract class QueueCoordinator { | ||||
|      * @param x chunk x coordinate | ||||
|      * @param z chunk z coordinate | ||||
|      * @return a new {@link ScopedQueueCoordinator} | ||||
|      * @deprecated Use {@link ScopedQueueCoordinator#getForChunk(int, int, int, int)} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     public ScopedQueueCoordinator getForChunk(int x, int z) { | ||||
|         if (getWorld() == null) { | ||||
|             return getForChunk(x, z, PlotSquared.platform().versionMinHeight(), PlotSquared.platform().versionMaxHeight()); | ||||
|         } | ||||
|         return getForChunk(x, z, getWorld().getMinY(), getWorld().getMaxY()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a {@link ScopedQueueCoordinator} limited to the chunk at the specific chunk Coordinates | ||||
|      * | ||||
|      * @param x chunk x coordinate | ||||
|      * @param z chunk z coordinate | ||||
|      * @return a new {@link ScopedQueueCoordinator} | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public ScopedQueueCoordinator getForChunk(int x, int z, int minY, int maxY) { | ||||
|         int bx = x << 4; | ||||
|         int bz = z << 4; | ||||
|         return new ScopedQueueCoordinator(this, Location.at(getWorld().getName(), bx, 0, bz), | ||||
|                 Location.at(getWorld().getName(), bx + 15, 255, bz + 255) | ||||
|         return new ScopedQueueCoordinator(this, Location.at(getWorld().getName(), bx, minY, bz), | ||||
|                 Location.at(getWorld().getName(), bx + 15, maxY, bz + 15) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| @@ -404,7 +421,7 @@ public abstract class QueueCoordinator { | ||||
|      */ | ||||
|     public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BlockState block) { | ||||
|         int yMin = Math.min(pos1.getY(), pos2.getY()); | ||||
|         int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); | ||||
|         int yMax = Math.max(pos1.getY(), pos2.getY()); | ||||
|         int xMin = Math.min(pos1.getX(), pos2.getX()); | ||||
|         int xMax = Math.max(pos1.getX(), pos2.getX()); | ||||
|         int zMin = Math.min(pos1.getZ(), pos2.getZ()); | ||||
| @@ -427,7 +444,7 @@ public abstract class QueueCoordinator { | ||||
|      */ | ||||
|     public void setCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull Pattern blocks) { | ||||
|         int yMin = Math.min(pos1.getY(), pos2.getY()); | ||||
|         int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); | ||||
|         int yMax = Math.max(pos1.getY(), pos2.getY()); | ||||
|         int xMin = Math.min(pos1.getX(), pos2.getX()); | ||||
|         int xMax = Math.max(pos1.getX(), pos2.getX()); | ||||
|         int zMin = Math.min(pos1.getZ(), pos2.getZ()); | ||||
| @@ -450,7 +467,7 @@ public abstract class QueueCoordinator { | ||||
|      */ | ||||
|     public void setBiomeCuboid(@NonNull Location pos1, @NonNull Location pos2, @NonNull BiomeType biome) { | ||||
|         int yMin = Math.min(pos1.getY(), pos2.getY()); | ||||
|         int yMax = Math.min(255, Math.max(pos1.getY(), pos2.getY())); | ||||
|         int yMax = Math.max(pos1.getY(), pos2.getY()); | ||||
|         int xMin = Math.min(pos1.getX(), pos2.getX()); | ||||
|         int xMax = Math.max(pos1.getX(), pos2.getX()); | ||||
|         int zMin = Math.min(pos1.getZ(), pos2.getZ()); | ||||
| @@ -464,4 +481,32 @@ public abstract class QueueCoordinator { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the min Y limit associated with the queue | ||||
|      */ | ||||
|     protected int getMinY() { | ||||
|         return getWorld() != null ? getWorld().getMinY() : PlotSquared.platform().versionMinHeight(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the max Y limit associated with the queue | ||||
|      */ | ||||
|     protected int getMaxY() { | ||||
|         return getWorld() != null ? getWorld().getMinY() : PlotSquared.platform().versionMaxHeight(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the min chunk layer associated with the queue. Usually 0 or -4; | ||||
|      */ | ||||
|     protected int getMinLayer() { | ||||
|         return (getWorld() != null ? getWorld().getMinY() : PlotSquared.platform().versionMinHeight()) >> 4; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the max chunk layer associated with the queue. Usually 15 or 19 | ||||
|      */ | ||||
|     protected int getMaxLayer() { | ||||
|         return (getWorld() != null ? getWorld().getMaxY() : PlotSquared.platform().versionMaxHeight()) >> 4; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,8 @@ import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  */ | ||||
| public class ScopedQueueCoordinator extends DelegateQueueCoordinator { | ||||
|  | ||||
|     private final Location min; | ||||
|     private final Location max; | ||||
|     private final int minX; | ||||
|     private final int minY; | ||||
|     private final int minZ; | ||||
| @@ -51,8 +53,13 @@ public class ScopedQueueCoordinator extends DelegateQueueCoordinator { | ||||
|     private final int dy; | ||||
|     private final int dz; | ||||
|  | ||||
|     /** | ||||
|      * Create a new ScopedQueueCoordinator instance that delegates to a given QueueCoordinator. Locations are inclusive. | ||||
|      */ | ||||
|     public ScopedQueueCoordinator(@Nullable QueueCoordinator parent, @NonNull Location min, @NonNull Location max) { | ||||
|         super(parent); | ||||
|         this.min = min; | ||||
|         this.max = max; | ||||
|         this.minX = min.getX(); | ||||
|         this.minY = min.getY(); | ||||
|         this.minZ = min.getZ(); | ||||
| @@ -112,11 +119,11 @@ public class ScopedQueueCoordinator extends DelegateQueueCoordinator { | ||||
|     } | ||||
|  | ||||
|     public @NonNull Location getMin() { | ||||
|         return Location.at(this.getWorld().getName(), this.minX, this.minY, this.minZ); | ||||
|         return min; | ||||
|     } | ||||
|  | ||||
|     public @NonNull Location getMax() { | ||||
|         return Location.at(this.getWorld().getName(), this.maxX, this.maxY, this.maxZ); | ||||
|         return max; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -31,6 +31,7 @@ import com.plotsquared.core.queue.QueueCoordinator; | ||||
| import com.plotsquared.core.queue.ScopedQueueCoordinator; | ||||
| import com.plotsquared.core.util.task.RunnableVal; | ||||
| import com.sk89q.worldedit.math.BlockVector2; | ||||
| import com.sk89q.worldedit.world.World; | ||||
|  | ||||
| import java.util.Map; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| @@ -47,18 +48,16 @@ public abstract class ChunkManager { | ||||
|             String world, | ||||
|             BlockVector2 loc | ||||
|     ) { | ||||
|         QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(PlotSquared | ||||
|                 .platform() | ||||
|                 .worldUtil() | ||||
|                 .getWeWorld(world)); | ||||
|         World weWorld = PlotSquared.platform().worldUtil().getWeWorld(world); | ||||
|         QueueCoordinator queue = PlotSquared.platform().globalBlockQueue().getNewQueue(weWorld); | ||||
|         if (PlotSquared.get().getPlotAreaManager().isAugmented(world) && PlotSquared.get().isNonStandardGeneration(world, loc)) { | ||||
|             int blockX = loc.getX() << 4; | ||||
|             int blockZ = loc.getZ() << 4; | ||||
|             ScopedQueueCoordinator scoped = | ||||
|                     new ScopedQueueCoordinator( | ||||
|                             queue, | ||||
|                             Location.at(world, blockX, 0, blockZ), | ||||
|                             Location.at(world, blockX + 15, 255, blockZ + 15) | ||||
|                             Location.at(world, blockX, weWorld.getMinY(), blockZ), | ||||
|                             Location.at(world, blockX + 15, weWorld.getMaxY(), blockZ + 15) | ||||
|                     ); | ||||
|             if (force != null) { | ||||
|                 force.run(scoped); | ||||
|   | ||||
| @@ -39,30 +39,27 @@ public class ChunkUtil { | ||||
|      * - Used for efficient world generation<br> | ||||
|      */ | ||||
|     private static final short[] x_loc; | ||||
|     private static final short[][] y_loc; | ||||
|     private static final short[] y_loc; | ||||
|     private static final short[] z_loc; | ||||
|     private static final short[][][] CACHE_J; | ||||
|  | ||||
|     static { | ||||
|         x_loc = new short[4096]; | ||||
|         y_loc = new short[16][4096]; | ||||
|         y_loc = new short[4096]; | ||||
|         z_loc = new short[4096]; | ||||
|         for (int i = 0; i < 16; i++) { | ||||
|             int i4 = i << 4; | ||||
|         for (int j = 0; j < 4096; j++) { | ||||
|                 int y = i4 + (j >> 8); | ||||
|             int y = j >> 8; | ||||
|             int a = j - ((y & 0xF) << 8); | ||||
|             int z1 = a >> 4; | ||||
|             int x1 = a - (z1 << 4); | ||||
|             x_loc[j] = (short) x1; | ||||
|                 y_loc[i][j] = (short) y; | ||||
|             y_loc[j] = (short) y; | ||||
|             z_loc[j] = (short) z1; | ||||
|         } | ||||
|         } | ||||
|         CACHE_J = new short[256][16][16]; | ||||
|         CACHE_J = new short[16][16][16]; | ||||
|         for (int x = 0; x < 16; x++) { | ||||
|             for (int z = 0; z < 16; z++) { | ||||
|                 for (int y = 0; y < 256; y++) { | ||||
|                 for (int y = 0; y < 16; y++) { | ||||
|                     short j = (short) ((y & 0xF) << 8 | z << 4 | x); | ||||
|                     CACHE_J[y][x][z] = j; | ||||
|                 } | ||||
| @@ -83,7 +80,7 @@ public class ChunkUtil { | ||||
|      * @return J value for xyz position in Array[4096]. | ||||
|      */ | ||||
|     public static int getJ(int x, int y, int z) { | ||||
|         return CACHE_J[y][x][z]; | ||||
|         return CACHE_J[y & 15][x & 15][z & 15]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -97,14 +94,14 @@ public class ChunkUtil { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the y coordinate for specific I and J values for a Chunk 16x16x16x16 layerxyz Array[16][4096]. | ||||
|      * Gets the y coordinate for specific I and J values for a Chunk Nx16x16x16 layerxyz Array[N][4096]. | ||||
|      * | ||||
|      * @param i Relative layer of the position in the layerxyz Array[16][4096]. | ||||
|      * @param i Relative layer of the position in the layerxyz Array[16][4096]. May be negative. | ||||
|      * @param j Position in the xyz Array[4096]. | ||||
|      * @return x coordinate within the chunk | ||||
|      */ | ||||
|     public static int getY(int i, int j) { | ||||
|         return y_loc[i][j]; | ||||
|         return (i << 4) + y_loc[j]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -37,15 +37,21 @@ public class MainUtil { | ||||
|      * Cache of mapping x,y,z coordinates to the chunk array<br> | ||||
|      * - Used for efficient world generation<br> | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "6.0.0") | ||||
|     public static short[][] x_loc; | ||||
|     @Deprecated(forRemoval = true, since = "6.0.0") | ||||
|     public static short[][] y_loc; | ||||
|     @Deprecated(forRemoval = true, since = "6.0.0") | ||||
|     public static short[][] z_loc; | ||||
|     @Deprecated(forRemoval = true, since = "6.0.0") | ||||
|     public static short[][][] CACHE_I = null; | ||||
|     @Deprecated(forRemoval = true, since = "6.0.0") | ||||
|     public static short[][][] CACHE_J = null; | ||||
|  | ||||
|     /** | ||||
|      * This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "6.0.0") | ||||
|     public static void initCache() { | ||||
|         if (x_loc == null) { | ||||
|             x_loc = new short[16][4096]; | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.regex.Pattern; | ||||
|  | ||||
| @Deprecated(since = "TODO", forRemoval = true) | ||||
| public class RegExUtil { | ||||
|  | ||||
|     public static Map<String, Pattern> compiledPatterns; | ||||
|   | ||||
| @@ -279,7 +279,10 @@ public abstract class RegionManager { | ||||
|         fromQueue1.addReadChunks(new CuboidRegion(pos1.getBlockVector3(), pos2.getBlockVector3()).getChunks()); | ||||
|         fromQueue2.addReadChunks(new CuboidRegion( | ||||
|                 swapPos.getBlockVector3(), | ||||
|                 BlockVector3.at(swapPos.getX() + pos2.getX() - pos1.getX(), 0, swapPos.getZ() + pos2.getZ() - pos1.getZ()) | ||||
|                 BlockVector3.at(swapPos.getX() + pos2.getX() - pos1.getX(), | ||||
|                         pos1.getY(), | ||||
|                         swapPos.getZ() + pos2.getZ() - pos1.getZ() | ||||
|                 ) | ||||
|         ).getChunks()); | ||||
|         QueueCoordinator toQueue1 = blockQueue.getNewQueue(world1); | ||||
|         QueueCoordinator toQueue2 = blockQueue.getNewQueue(world2); | ||||
| @@ -352,7 +355,7 @@ public abstract class RegionManager { | ||||
|             int bz = Math.max(pos1.getZ(), cbz) & 15; | ||||
|             int tx = Math.min(pos2.getX(), cbx + 15) & 15; | ||||
|             int tz = Math.min(pos2.getZ(), cbz + 15) & 15; | ||||
|             for (int y = 0; y < 256; y++) { | ||||
|             for (int y = world1.getMinY(); y <= world1.getMaxY(); y++) { | ||||
|                 for (int x = bx; x <= tx; x++) { | ||||
|                     for (int z = bz; z <= tz; z++) { | ||||
|                         int rx = cbx + x; | ||||
| @@ -363,7 +366,10 @@ public abstract class RegionManager { | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             Region region = new CuboidRegion(BlockVector3.at(cbx + bx, 0, cbz + bz), BlockVector3.at(cbx + tx, 255, cbz + tz)); | ||||
|             Region region = new CuboidRegion( | ||||
|                     BlockVector3.at(cbx + bx, world1.getMinY(), cbz + bz), | ||||
|                     BlockVector3.at(cbx + tx, world1.getMaxY(), cbz + tz) | ||||
|             ); | ||||
|             toQueue.addEntities(world1.getEntities(region)); | ||||
|             if (removeEntities) { | ||||
|                 for (Entity entity : world1.getEntities(region)) { | ||||
| @@ -373,6 +379,7 @@ public abstract class RegionManager { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     public void setBiome( | ||||
|             final CuboidRegion region, | ||||
|             final int extendBiome, | ||||
| @@ -380,39 +387,35 @@ public abstract class RegionManager { | ||||
|             final String world, | ||||
|             final Runnable whenDone | ||||
|     ) { | ||||
|         Location pos1 = Location | ||||
|                 .at( | ||||
|                         world, | ||||
|                         region.getMinimumPoint().getX() - extendBiome, | ||||
|                         region.getMinimumPoint().getY(), | ||||
|                         region.getMinimumPoint().getZ() - extendBiome | ||||
|                 ); | ||||
|         Location pos2 = Location | ||||
|                 .at( | ||||
|                         world, | ||||
|                         region.getMaximumPoint().getX() + extendBiome, | ||||
|                         region.getMaximumPoint().getY(), | ||||
|                         region.getMaximumPoint().getZ() + extendBiome | ||||
|                 ); | ||||
|         final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(world)); | ||||
|         setBiome(region, extendBiome, biome, PlotSquared.get().getPlotAreaManager().getPlotAreas(world, region)[0], whenDone); | ||||
|     } | ||||
|  | ||||
|         final int minX = pos1.getX(); | ||||
|         final int minZ = pos1.getZ(); | ||||
|         final int maxX = pos2.getX(); | ||||
|         final int maxZ = pos2.getZ(); | ||||
|     /** | ||||
|      * Set a region to a biome type. | ||||
|      * | ||||
|      * @param region      region to set | ||||
|      * @param extendBiome how far outside the region to extent setting the biome too account for 3D biomes being 4x4 | ||||
|      * @param biome       biome to set | ||||
|      * @param area        {@link PlotArea} in which the biome is being set | ||||
|      * @param whenDone    task to run when complete | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public void setBiome( | ||||
|             final CuboidRegion region, | ||||
|             final int extendBiome, | ||||
|             final BiomeType biome, | ||||
|             final PlotArea area, | ||||
|             final Runnable whenDone | ||||
|     ) { | ||||
|         final QueueCoordinator queue = blockQueue.getNewQueue(worldUtil.getWeWorld(area.getWorldName())); | ||||
|         queue.addReadChunks(region.getChunks()); | ||||
|         queue.setChunkConsumer(blockVector2 -> { | ||||
|             final int cx = blockVector2.getX() << 4; | ||||
|             final int cz = blockVector2.getZ() << 4; | ||||
|             WorldUtil.setBiome( | ||||
|                     world, | ||||
|                     Math.max(minX, cx), | ||||
|                     Math.max(minZ, cz), | ||||
|                     Math.min(maxX, cx + 15), | ||||
|                     Math.min(maxZ, cz + 15), | ||||
|                     area.getWorldName(), | ||||
|                     region, | ||||
|                     biome | ||||
|             ); | ||||
|             worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), world); | ||||
|             worldUtil.refreshChunk(blockVector2.getBlockX(), blockVector2.getBlockZ(), area.getWorldName()); | ||||
|         }); | ||||
|         queue.setCompleteTask(whenDone); | ||||
|         queue.enqueue(); | ||||
|   | ||||
| @@ -76,8 +76,9 @@ public class RegionUtil { | ||||
|         return new CuboidRegion(min, max); | ||||
|     } | ||||
|  | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) { | ||||
|         return createRegion(pos1x, pos2x, 0, Plot.MAX_HEIGHT - 1, pos1z, pos2z); | ||||
|         return createRegion(pos1x, pos2x, 0, 255, pos1z, pos2z); | ||||
|     } | ||||
|  | ||||
|     public static CuboidRegion createRegion( | ||||
|   | ||||
| @@ -305,12 +305,13 @@ public abstract class SchematicHandler { | ||||
|             final int WIDTH = dimension.getX(); | ||||
|             final int LENGTH = dimension.getZ(); | ||||
|             final int HEIGHT = dimension.getY(); | ||||
|             final int worldHeight = plot.getArea().getMaxGenHeight() - plot.getArea().getMinGenHeight() + 1; | ||||
|             // Validate dimensions | ||||
|             CuboidRegion region = plot.getLargestRegion(); | ||||
|             boolean sizeMismatch = | ||||
|                     ((region.getMaximumPoint().getX() - region.getMinimumPoint().getX() + xOffset + 1) < WIDTH) || ( | ||||
|                             (region.getMaximumPoint().getZ() - region.getMinimumPoint().getZ() + zOffset + 1) < LENGTH) || (HEIGHT | ||||
|                             > 256); | ||||
|                             > worldHeight); | ||||
|             if (!Settings.Schematics.PASTE_MISMATCHES && sizeMismatch) { | ||||
|                 actor.sendMessage(TranslatableCaption.of("schematics.schematic_size_mismatch")); | ||||
|                 TaskManager.runTask(whenDone); | ||||
| @@ -321,14 +322,14 @@ public abstract class SchematicHandler { | ||||
|             // Calculate the optimal height to paste the schematic at | ||||
|             final int y_offset_actual; | ||||
|             if (autoHeight) { | ||||
|                 if (HEIGHT >= 256) { | ||||
|                 if (HEIGHT >= worldHeight) { | ||||
|                     y_offset_actual = yOffset; | ||||
|                 } else { | ||||
|                     PlotArea pw = plot.getArea(); | ||||
|                     if (pw instanceof ClassicPlotWorld) { | ||||
|                         y_offset_actual = yOffset + pw.getMinBuildHeight() + ((ClassicPlotWorld) pw).PLOT_HEIGHT; | ||||
|                     } else { | ||||
|                         y_offset_actual = yOffset + 1 + this.worldUtil | ||||
|                         y_offset_actual = yOffset + pw.getMinBuildHeight() + this.worldUtil | ||||
|                                 .getHighestBlockSynchronous(plot.getWorldName(), region.getMinimumPoint().getX() + 1, | ||||
|                                         region.getMinimumPoint().getZ() + 1 | ||||
|                                 ); | ||||
| @@ -360,9 +361,9 @@ public abstract class SchematicHandler { | ||||
|             // Paste schematic here | ||||
|             final QueueCoordinator queue = plot.getArea().getQueue(); | ||||
|  | ||||
|             for (int ry = 0; ry < Math.min(256, HEIGHT); ry++) { | ||||
|             for (int ry = 0; ry < Math.min(worldHeight, HEIGHT); ry++) { | ||||
|                 int yy = y_offset_actual + ry; | ||||
|                 if (yy > 255 || yy < 0) { | ||||
|                 if (yy > plot.getArea().getMaxGenHeight() || yy < plot.getArea().getMinGenHeight()) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 for (int rz = 0; rz < blockArrayClipboard.getDimensions().getZ(); rz++) { | ||||
| @@ -379,18 +380,18 @@ public abstract class SchematicHandler { | ||||
|                         BlockVector3 loc = BlockVector3.at(rx, ry, rz); | ||||
|                         BaseBlock id = blockArrayClipboard.getFullBlock(loc); | ||||
|                         queue.setBlock(xx, yy, zz, id); | ||||
|                         if (ry == 0) { | ||||
|                         BiomeType biome = blockArrayClipboard.getBiome(loc); | ||||
|                         queue.setBiome(xx, yy, zz, biome); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             } | ||||
|             if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { | ||||
|                 queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); | ||||
|             } | ||||
|             if (whenDone != null) { | ||||
|                 whenDone.value = true; | ||||
|                 queue.setCompleteTask(whenDone); | ||||
|             } | ||||
|             queue.enqueue(); | ||||
|         } catch (Exception e) { | ||||
|             e.printStackTrace(); | ||||
|   | ||||
| @@ -44,6 +44,9 @@ import java.util.UUID; | ||||
|  | ||||
| public class WEManager { | ||||
|  | ||||
|     private static final BlockVector3 MIN = BlockVector3.at(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); | ||||
|     private static final BlockVector3 MAX = BlockVector3.at(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); | ||||
|  | ||||
|     public static boolean maskContains(Set<CuboidRegion> mask, int x, int y, int z) { | ||||
|         for (CuboidRegion region : mask) { | ||||
|             if (RegionUtil.contains(region, x, y, z)) { | ||||
| @@ -91,10 +94,7 @@ public class WEManager { | ||||
|         Location location = player.getLocation(); | ||||
|         String world = location.getWorldName(); | ||||
|         if (!PlotSquared.get().getPlotAreaManager().hasPlotArea(world)) { | ||||
|             regions.add(RegionUtil | ||||
|                     .createRegion(Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, | ||||
|                             Integer.MAX_VALUE | ||||
|                     )); | ||||
|             regions.add(new CuboidRegion(MIN, MAX)); | ||||
|             return regions; | ||||
|         } | ||||
|         PlotArea area = player.getApplicablePlotArea(); | ||||
|   | ||||
| @@ -39,6 +39,7 @@ import com.sk89q.jnbt.Tag; | ||||
| import com.sk89q.worldedit.math.BlockVector2; | ||||
| import com.sk89q.worldedit.math.BlockVector3; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import com.sk89q.worldedit.world.World; | ||||
| import com.sk89q.worldedit.world.biome.BiomeType; | ||||
| import com.sk89q.worldedit.world.block.BlockState; | ||||
| import com.sk89q.worldedit.world.block.BlockType; | ||||
| @@ -78,14 +79,29 @@ public abstract class WorldUtil { | ||||
|      * @param p2x   Max X | ||||
|      * @param p2z   Max Z | ||||
|      * @param biome Biome | ||||
|      * @deprecated use {@link WorldUtil#setBiome(String, CuboidRegion, BiomeType)} | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true) | ||||
|     public static void setBiome(String world, int p1x, int p1z, int p2x, int p2z, BiomeType biome) { | ||||
|         BlockVector3 pos1 = BlockVector2.at(p1x, p1z).toBlockVector3(); | ||||
|         BlockVector3 pos2 = BlockVector2.at(p2x, p2z).toBlockVector3(Plot.MAX_HEIGHT - 1); | ||||
|         World weWorld = PlotSquared.platform().worldUtil().getWeWorld(world); | ||||
|         BlockVector3 pos1 = BlockVector2.at(p1x, p1z).toBlockVector3(weWorld.getMinY()); | ||||
|         BlockVector3 pos2 = BlockVector2.at(p2x, p2z).toBlockVector3(weWorld.getMaxY()); | ||||
|         CuboidRegion region = new CuboidRegion(pos1, pos2); | ||||
|         PlotSquared.platform().worldUtil().setBiomes(world, region, biome); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the biome in a region | ||||
|      * | ||||
|      * @param world  World name | ||||
|      * @param region Region | ||||
|      * @param biome  Biome | ||||
|      * @since 6.6.0 | ||||
|      */ | ||||
|     public static void setBiome(String world, final CuboidRegion region, BiomeType biome) { | ||||
|         PlotSquared.platform().worldUtil().setBiomes(world, region, biome); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if a given world name corresponds to a real world | ||||
|      * | ||||
| @@ -217,11 +233,14 @@ public abstract class WorldUtil { | ||||
|     /** | ||||
|      * Set the biome in a region | ||||
|      * | ||||
|      * @param world  World name | ||||
|      * @param worldName World name | ||||
|      * @param region    Region | ||||
|      * @param biome     New biome | ||||
|      */ | ||||
|     public abstract void setBiomes(@NonNull String world, @NonNull CuboidRegion region, @NonNull BiomeType biome); | ||||
|     public void setBiomes(@NonNull String worldName, @NonNull CuboidRegion region, @NonNull BiomeType biome) { | ||||
|         final World world = getWeWorld(worldName); | ||||
|         region.forEach(bv -> world.setBiome(bv, biome)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the WorldEdit {@link com.sk89q.worldedit.world.World} corresponding to a world name | ||||
|   | ||||
| @@ -71,7 +71,7 @@ public class UUIDMapping { | ||||
|     /** | ||||
|      * @deprecated This method is not meant to be invoked or overridden, with no replacement. | ||||
|      */ | ||||
|     @Deprecated(forRemoval = true, since = "TODO") | ||||
|     @Deprecated(forRemoval = true, since = "6.6.0") | ||||
|     protected boolean canEqual(final Object other) { | ||||
|         return other instanceof UUIDMapping; | ||||
|     } | ||||
|   | ||||
| @@ -161,8 +161,9 @@ | ||||
|   "setup.road_width": "<gold>Road width</gold>", | ||||
|   "setup.road_height": "<gold>Road height</gold>", | ||||
|   "setup.road_block": "<gold>Road block</gold>", | ||||
|   "setup.wall_filling_block": "<gold>Wall filling block</gold><gray> (Block(s) been put under the plot border down to Y1)</gray>", | ||||
|   "setup.wall_filling_block": "<gold>Wall filling block</gold><gray> (Block(s) been put under the plot border down to min gen height + 1)</gray>", | ||||
|   "setup.wall_height": "<gold>Wall height</gold>", | ||||
|   "setup.min_gen_height": "<gold>Minimum height from which to generate (for 1.18+ can be negative).</gold>", | ||||
|   "setup.bedrock_boolean": "<gold>Whether a bedrock layer under the plot should be generated or not</gold>", | ||||
|   "setup.singleplotarea_void_world": "<gold>Void world</gold>", | ||||
|   "plotareatype.plot_area_type_normal": "<gray>Standard plot generation</gray>", | ||||
|   | ||||
| @@ -18,7 +18,7 @@ plugins { | ||||
|     idea | ||||
| } | ||||
|  | ||||
| version = "6.5.2-SNAPSHOT" | ||||
| version = "6.6.2-SNAPSHOT" | ||||
|  | ||||
| allprojects { | ||||
|     group = "com.plotsquared" | ||||
|   | ||||
| @@ -6,7 +6,7 @@ guava = "31.0.1-jre" # Version set by Minecraft | ||||
|  | ||||
| # Platform expectations | ||||
| paper = "1.18.1-R0.1-SNAPSHOT" | ||||
| checker-qual = "3.21.2" | ||||
| checker-qual = "3.21.3" | ||||
| guice = "5.1.0" | ||||
| findbugs = "3.0.1" | ||||
| snakeyaml = "1.30" # Version set by Bukkit | ||||
| @@ -18,17 +18,17 @@ adventure-platform-bukkit = "4.0.1" | ||||
|  | ||||
| # Plugins | ||||
| worldedit = "7.2.9" | ||||
| fawe = "2.0.1" | ||||
| fawe = "2.1.0" | ||||
| vault = "1.7.1" | ||||
| placeholderapi = "2.11.1" | ||||
| luckperms = "5.4" | ||||
| essentialsx = "2.19.2" | ||||
| essentialsx = "2.19.4" | ||||
| mvdwapi = "3.1.1" | ||||
|  | ||||
| # Third party | ||||
| prtree = "2.0.0" | ||||
| aopalliance = "1.0" | ||||
| cloud-services = "1.6.1" | ||||
| cloud-services = "1.6.2" | ||||
| arkitektonika = "2.1.1" | ||||
| paster = "1.1.4" | ||||
| bstats = "3.0.0" | ||||
|   | ||||
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| zipStorePath=wrapper/dists | ||||
|   | ||||
| @@ -8,7 +8,8 @@ | ||||
|     "com.google.guava:guava", | ||||
|     "com.google.code.gson:gson", | ||||
|     "gson", | ||||
|     "snakeyaml" | ||||
|     "snakeyaml", | ||||
|     "net.kyori" | ||||
|   ], | ||||
|   "timezone": "Europe/Berlin", | ||||
|   "schedule": [ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user