001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.generator; 020 021import com.google.inject.Inject; 022import com.plotsquared.core.PlotSquared; 023import com.plotsquared.core.configuration.Settings; 024import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; 025import com.plotsquared.core.location.Direction; 026import com.plotsquared.core.location.Location; 027import com.plotsquared.core.player.PlotPlayer; 028import com.plotsquared.core.plot.BlockBucket; 029import com.plotsquared.core.plot.Plot; 030import com.plotsquared.core.plot.PlotAreaTerrainType; 031import com.plotsquared.core.plot.PlotId; 032import com.plotsquared.core.queue.QueueCoordinator; 033import com.plotsquared.core.util.MathMan; 034import com.plotsquared.core.util.RegionManager; 035import com.plotsquared.core.util.task.TaskManager; 036import com.sk89q.worldedit.function.pattern.Pattern; 037import com.sk89q.worldedit.regions.CuboidRegion; 038import com.sk89q.worldedit.world.block.BlockTypes; 039import org.checkerframework.checker.nullness.qual.NonNull; 040import org.checkerframework.checker.nullness.qual.Nullable; 041 042import java.util.List; 043import java.util.Optional; 044 045/** 046 * A plot manager with square plots which tessellate on a square grid with the following sections: ROAD, WALL, BORDER (wall), PLOT, FLOOR (plot). 047 */ 048public class ClassicPlotManager extends SquarePlotManager { 049 050 private final ClassicPlotWorld classicPlotWorld; 051 private final RegionManager regionManager; 052 private final ProgressSubscriberFactory subscriberFactory; 053 054 @Inject 055 public ClassicPlotManager(final @NonNull ClassicPlotWorld classicPlotWorld, final @NonNull RegionManager regionManager) { 056 super(classicPlotWorld, regionManager); 057 this.classicPlotWorld = classicPlotWorld; 058 this.regionManager = regionManager; 059 this.subscriberFactory = PlotSquared.platform().injector().getInstance(ProgressSubscriberFactory.class); 060 } 061 062 @Override 063 public boolean setComponent( 064 @NonNull PlotId plotId, 065 @NonNull String component, 066 @NonNull Pattern blocks, 067 @Nullable PlotPlayer<?> actor, 068 @Nullable QueueCoordinator queue 069 ) { 070 final Optional<ClassicPlotManagerComponent> componentOptional = ClassicPlotManagerComponent.fromString(component); 071 return componentOptional.map(classicPlotManagerComponent -> switch (classicPlotManagerComponent) { 072 case FLOOR -> setFloor(plotId, blocks, actor, queue); 073 case WALL -> setWallFilling(plotId, blocks, actor, queue); 074 case AIR -> setAir(plotId, blocks, actor, queue); 075 case MAIN -> setMain(plotId, blocks, actor, queue); 076 case MIDDLE -> setMiddle(plotId, blocks, queue); 077 case OUTLINE -> setOutline(plotId, blocks, actor, queue); 078 case BORDER -> setWall(plotId, blocks, actor, queue); 079 case ALL -> setAll(plotId, blocks, actor, queue); 080 }).orElse(false); 081 } 082 083 @Override 084 public boolean unClaimPlot(@NonNull Plot plot, @Nullable Runnable whenDone, @Nullable QueueCoordinator queue) { 085 setWallFilling(plot.getId(), classicPlotWorld.WALL_FILLING.toPattern(), null, queue); 086 if (classicPlotWorld.PLACE_TOP_BLOCK && (!classicPlotWorld.WALL_BLOCK.isAir() || !classicPlotWorld.WALL_BLOCK 087 .equals(classicPlotWorld.CLAIMED_WALL_BLOCK))) { 088 setWall(plot.getId(), classicPlotWorld.WALL_BLOCK.toPattern(), null, queue); 089 } 090 TaskManager.runTask(whenDone); 091 return true; 092 } 093 094 /** 095 * Set the plot floor 096 * 097 * @param plotId id of plot to set floor of 098 * @param blocks pattern to set 099 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 100 * otherwise writes to the queue but does not enqueue. 101 * @return success or not 102 */ 103 public boolean setFloor( 104 @NonNull PlotId plotId, 105 @NonNull Pattern blocks, 106 @Nullable PlotPlayer<?> actor, 107 @Nullable QueueCoordinator queue 108 ) { 109 Plot plot = classicPlotWorld.getPlotAbs(plotId); 110 if (plot != null && plot.isBasePlot()) { 111 return this.regionManager 112 .setCuboids( 113 classicPlotWorld, 114 plot.getRegions(), 115 blocks, 116 classicPlotWorld.PLOT_HEIGHT, 117 classicPlotWorld.PLOT_HEIGHT, 118 actor, 119 queue 120 ); 121 } 122 return false; 123 } 124 125 /** 126 * Sets the plot main, floor and air areas. 127 * 128 * @param plotId id of plot to set all of 129 * @param blocks pattern to set 130 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 131 * otherwise writes to the queue but does not enqueue. 132 * @return success or not 133 */ 134 public boolean setAll( 135 @NonNull PlotId plotId, 136 @NonNull Pattern blocks, 137 @Nullable PlotPlayer<?> actor, 138 @Nullable QueueCoordinator queue 139 ) { 140 Plot plot = classicPlotWorld.getPlotAbs(plotId); 141 if (plot != null && plot.isBasePlot()) { 142 return this.regionManager.setCuboids( 143 classicPlotWorld, 144 plot.getRegions(), 145 blocks, 146 classicPlotWorld.getMinBuildHeight(), 147 classicPlotWorld.getMaxBuildHeight() - 1, 148 actor, 149 queue 150 ); 151 } 152 return false; 153 } 154 155 /** 156 * Sets the plot air region. 157 * 158 * @param plotId id of plot to set air of 159 * @param blocks pattern to set 160 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 161 * otherwise writes to the queue but does not enqueue. 162 * @return success or not 163 */ 164 public boolean setAir( 165 @NonNull PlotId plotId, 166 @NonNull Pattern blocks, 167 @Nullable PlotPlayer<?> actor, 168 @Nullable QueueCoordinator queue 169 ) { 170 Plot plot = classicPlotWorld.getPlotAbs(plotId); 171 if (plot != null && plot.isBasePlot()) { 172 return this.regionManager 173 .setCuboids( 174 classicPlotWorld, 175 plot.getRegions(), 176 blocks, 177 classicPlotWorld.PLOT_HEIGHT + 1, 178 classicPlotWorld.getMaxBuildHeight() - 1, 179 actor, 180 queue 181 ); 182 } 183 return false; 184 } 185 186 /** 187 * Sets the plot main blocks. 188 * 189 * @param plotId id of plot to set main of 190 * @param blocks pattern to set 191 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 192 * otherwise writes to the queue but does not enqueue. 193 * @return success or not 194 */ 195 public boolean setMain( 196 @NonNull PlotId plotId, 197 @NonNull Pattern blocks, 198 @Nullable PlotPlayer<?> actor, 199 @Nullable QueueCoordinator queue 200 ) { 201 Plot plot = classicPlotWorld.getPlotAbs(plotId); 202 if (plot == null || plot.isBasePlot()) { 203 return this.regionManager.setCuboids( 204 classicPlotWorld, 205 plot.getRegions(), 206 blocks, 207 classicPlotWorld.getMinBuildHeight(), 208 classicPlotWorld.PLOT_HEIGHT - 1, 209 actor, 210 queue 211 ); 212 } 213 return false; 214 } 215 216 /** 217 * Set the middle plot block to a Pattern 218 * 219 * @param plotId id of plot to set middle block of 220 * @param blocks pattern to set 221 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 222 * otherwise writes to the queue but does not enqueue. 223 * @return success or not 224 */ 225 public boolean setMiddle(@NonNull PlotId plotId, @NonNull Pattern blocks, @Nullable QueueCoordinator queue) { 226 Plot plot = classicPlotWorld.getPlotAbs(plotId); 227 if (plot == null || !plot.isBasePlot()) { 228 return false; 229 } 230 Location[] corners = plot.getCorners(); 231 232 boolean enqueue = false; 233 if (queue == null) { 234 queue = classicPlotWorld.getQueue(); 235 enqueue = true; 236 } 237 238 int x = MathMan.average(corners[0].getX(), corners[1].getX()); 239 int z = MathMan.average(corners[0].getZ(), corners[1].getZ()); 240 queue.setBlock(x, classicPlotWorld.PLOT_HEIGHT, z, blocks); 241 return !enqueue || queue.enqueue(); 242 } 243 244 /** 245 * Set a plot's outline 246 * 247 * @param plotId id of plot to set outline of 248 * @param blocks pattern to set 249 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 250 * otherwise writes to the queue but does not enqueue. 251 * @return success or not 252 */ 253 public boolean setOutline( 254 @NonNull PlotId plotId, 255 @NonNull Pattern blocks, 256 @Nullable PlotPlayer<?> actor, 257 @Nullable QueueCoordinator queue 258 ) { 259 if (classicPlotWorld.ROAD_WIDTH == 0) { 260 return false; 261 } 262 // When using full vanilla generation, don't generate the walls 263 if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) { 264 // Return true because the method actually did what it's intended to in this case, 265 // which is absolutely nothing 266 return true; 267 } 268 Plot plot = classicPlotWorld.getPlotAbs(plotId); 269 if (plot == null) { 270 return false; 271 } 272 Location bottom = plot.getBottomAbs(); 273 Location top = plot.getExtendedTopAbs(); 274 275 boolean enqueue = false; 276 if (queue == null) { 277 queue = classicPlotWorld.getQueue(); 278 enqueue = true; 279 if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { 280 queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); 281 } 282 } 283 284 int maxY = classicPlotWorld.getMaxBuildHeight() - 1; 285 if (!plot.isMerged(Direction.NORTH)) { 286 int z = bottom.getZ(); 287 for (int x = bottom.getX(); x <= top.getX(); x++) { 288 for (int y = classicPlotWorld.PLOT_HEIGHT; y <= maxY; y++) { 289 queue.setBlock(x, y, z, blocks); 290 } 291 } 292 } 293 if (!plot.isMerged(Direction.WEST)) { 294 int x = bottom.getX(); 295 for (int z = bottom.getZ(); z <= top.getZ(); z++) { 296 for (int y = classicPlotWorld.PLOT_HEIGHT; y <= maxY; y++) { 297 queue.setBlock(x, y, z, blocks); 298 } 299 } 300 } 301 302 if (!plot.isMerged(Direction.SOUTH)) { 303 int z = top.getZ(); 304 for (int x = bottom.getX(); x <= top.getX(); x++) { 305 for (int y = classicPlotWorld.PLOT_HEIGHT; y <= maxY; y++) { 306 queue.setBlock(x, y, z, blocks); 307 } 308 } 309 } 310 if (!plot.isMerged(Direction.EAST)) { 311 int x = top.getX(); 312 for (int z = bottom.getZ(); z <= top.getZ(); z++) { 313 for (int y = classicPlotWorld.PLOT_HEIGHT; y <= maxY; y++) { 314 queue.setBlock(x, y, z, blocks); 315 } 316 } 317 } 318 if (plot.isBasePlot()) { 319 for (CuboidRegion region : plot.getRegions()) { 320 Location pos1 = Location.at( 321 classicPlotWorld.getWorldName(), 322 region.getMinimumPoint().getX(), 323 maxY, 324 region.getMinimumPoint().getZ() 325 ); 326 Location pos2 = Location.at( 327 classicPlotWorld.getWorldName(), 328 region.getMaximumPoint().getX(), 329 maxY, 330 region.getMaximumPoint().getZ() 331 ); 332 queue.setCuboid(pos1, pos2, blocks); 333 } 334 } 335 return !enqueue || queue.enqueue(); 336 } 337 338 /** 339 * Set the wall filling for a plot 340 * 341 * @param plotId id of plot to set wall filling of 342 * @param blocks pattern to set 343 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 344 * otherwise writes to the queue but does not enqueue. 345 * @return success or not 346 */ 347 public boolean setWallFilling( 348 @NonNull PlotId plotId, 349 @NonNull Pattern blocks, 350 @Nullable PlotPlayer<?> actor, 351 @Nullable QueueCoordinator queue 352 ) { 353 if (classicPlotWorld.ROAD_WIDTH == 0) { 354 return false; 355 } 356 // When using full vanilla generation, don't generate the walls 357 if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) { 358 // Return true because the method actually did what it's intended to in this case, 359 // which is absolutely nothing 360 return true; 361 } 362 Plot plot = classicPlotWorld.getPlotAbs(plotId); 363 if (plot == null) { 364 return false; 365 } 366 Location bot = plot.getExtendedBottomAbs().subtract( 367 plot.isMerged(Direction.WEST) ? 0 : 1, 368 0, 369 plot.isMerged(Direction.NORTH) ? 0 : 1 370 ); 371 Location top = plot.getExtendedTopAbs().add(1, 0, 1); 372 373 boolean enqueue = false; 374 if (queue == null) { 375 queue = classicPlotWorld.getQueue(); 376 enqueue = true; 377 if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { 378 queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); 379 } 380 } 381 382 int yStart = classicPlotWorld.getMinBuildHeight() + (classicPlotWorld.PLOT_BEDROCK ? 1 : 0); 383 if (!plot.isMerged(Direction.NORTH)) { 384 int z = bot.getZ(); 385 for (int x = bot.getX(); x < top.getX(); x++) { 386 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { 387 queue.setBlock(x, y, z, blocks); 388 } 389 } 390 } 391 if (!plot.isMerged(Direction.WEST)) { 392 int x = bot.getX(); 393 for (int z = bot.getZ(); z < top.getZ(); z++) { 394 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { 395 queue.setBlock(x, y, z, blocks); 396 } 397 } 398 } 399 if (!plot.isMerged(Direction.SOUTH)) { 400 int z = top.getZ(); 401 for (int x = bot.getX(); x < top.getX() + (plot.isMerged(Direction.EAST) ? 0 : 1); x++) { 402 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { 403 queue.setBlock(x, y, z, blocks); 404 } 405 } 406 } 407 if (!plot.isMerged(Direction.EAST)) { 408 int x = top.getX(); 409 for (int z = bot.getZ(); z < top.getZ() + (plot.isMerged(Direction.SOUTH) ? 0 : 1); z++) { 410 for (int y = yStart; y <= classicPlotWorld.WALL_HEIGHT; y++) { 411 queue.setBlock(x, y, z, blocks); 412 } 413 } 414 } 415 return !enqueue || queue.enqueue(); 416 } 417 418 /** 419 * Set a plot's wall top block only 420 * 421 * @param plotId id of plot to set wall top block of 422 * @param blocks pattern to set 423 * @param queue Nullable {@link QueueCoordinator}. If null, creates own queue and enqueues, 424 * otherwise writes to the queue but does not enqueue. 425 * @return success or not 426 */ 427 public boolean setWall( 428 @NonNull PlotId plotId, 429 @NonNull Pattern blocks, 430 @Nullable PlotPlayer<?> actor, 431 @Nullable QueueCoordinator queue 432 ) { 433 if (classicPlotWorld.ROAD_WIDTH == 0) { 434 return false; 435 } 436 // When using full vanilla generation, don't generate the walls 437 if (classicPlotWorld.getTerrain() == PlotAreaTerrainType.ALL) { 438 // Return true because the method actually did what it's intended to in this case, 439 // which is absolutely nothing 440 return true; 441 } 442 Plot plot = classicPlotWorld.getPlotAbs(plotId); 443 if (plot == null) { 444 return false; 445 } 446 Location bot = plot.getExtendedBottomAbs().subtract( 447 plot.isMerged(Direction.WEST) ? 0 : 1, 448 0, 449 plot.isMerged(Direction.NORTH) ? 0 : 1 450 ); 451 Location top = plot.getExtendedTopAbs().add(1, 0, 1); 452 453 boolean enqueue = false; 454 if (queue == null) { 455 enqueue = true; 456 queue = classicPlotWorld.getQueue(); 457 if (actor != null && Settings.QUEUE.NOTIFY_PROGRESS) { 458 queue.addProgressSubscriber(subscriberFactory.createWithActor(actor)); 459 } 460 } 461 462 int y = classicPlotWorld.WALL_HEIGHT + 1; 463 if (!plot.isMerged(Direction.NORTH)) { 464 int z = bot.getZ(); 465 for (int x = bot.getX(); x < top.getX(); x++) { 466 queue.setBlock(x, y, z, blocks); 467 } 468 } 469 if (!plot.isMerged(Direction.WEST)) { 470 int x = bot.getX(); 471 for (int z = bot.getZ(); z < top.getZ(); z++) { 472 queue.setBlock(x, y, z, blocks); 473 } 474 } 475 if (!plot.isMerged(Direction.SOUTH)) { 476 int z = top.getZ(); 477 for (int x = bot.getX(); x < top.getX() + (plot.isMerged(Direction.EAST) ? 0 : 1); x++) { 478 queue.setBlock(x, y, z, blocks); 479 } 480 } 481 if (!plot.isMerged(Direction.EAST)) { 482 int x = top.getX(); 483 for (int z = bot.getZ(); z < top.getZ() + (plot.isMerged(Direction.SOUTH) ? 0 : 1); z++) { 484 queue.setBlock(x, y, z, blocks); 485 } 486 } 487 return !enqueue || queue.enqueue(); 488 } 489 490 @Override 491 public boolean createRoadEast(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 492 Location pos1 = getPlotBottomLocAbs(plot.getId()); 493 Location pos2 = getPlotTopLocAbs(plot.getId()); 494 int sx = pos2.getX() + 1; 495 int ex = sx + classicPlotWorld.ROAD_WIDTH - 1; 496 int sz = pos1.getZ() - 2; 497 int ez = pos2.getZ() + 2; 498 499 boolean enqueue = false; 500 if (queue == null) { 501 queue = classicPlotWorld.getQueue(); 502 enqueue = true; 503 } 504 505 int maxY = classicPlotWorld.getMaxGenHeight(); 506 queue.setCuboid( 507 Location.at( 508 classicPlotWorld.getWorldName(), 509 sx, 510 classicPlotWorld.schematicStartHeight() + 1, 511 sz + 1 512 ), 513 Location.at(classicPlotWorld.getWorldName(), ex, maxY, ez - 1), BlockTypes.AIR.getDefaultState() 514 ); 515 if (classicPlotWorld.PLOT_BEDROCK) { 516 queue.setCuboid( 517 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight(), sz + 1), 518 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMinGenHeight(), ez - 1), 519 BlockTypes.BEDROCK.getDefaultState() 520 ); 521 } 522 int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; 523 queue.setCuboid( 524 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), 525 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT, ez - 1), 526 classicPlotWorld.WALL_FILLING.toPattern() 527 ); 528 queue.setCuboid( 529 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), 530 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT, ez - 1), 531 classicPlotWorld.WALL_FILLING.toPattern() 532 ); 533 queue.setCuboid( 534 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), 535 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), 536 classicPlotWorld.ROAD_BLOCK.toPattern() 537 ); 538 539 if (classicPlotWorld.PLACE_TOP_BLOCK) { 540 queue.setCuboid( 541 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, sz + 1), 542 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), 543 classicPlotWorld.WALL_BLOCK.toPattern() 544 ); 545 queue.setCuboid( 546 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, sz + 1), 547 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.WALL_HEIGHT + 1, ez - 1), 548 classicPlotWorld.WALL_BLOCK.toPattern() 549 ); 550 } 551 return !enqueue || queue.enqueue(); 552 } 553 554 @Override 555 public boolean createRoadSouth(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 556 Location pos1 = getPlotBottomLocAbs(plot.getId()); 557 Location pos2 = getPlotTopLocAbs(plot.getId()); 558 int sz = pos2.getZ() + 1; 559 int ez = sz + classicPlotWorld.ROAD_WIDTH - 1; 560 int sx = pos1.getX() - 2; 561 int ex = pos2.getX() + 2; 562 563 boolean enqueue = false; 564 if (queue == null) { 565 queue = classicPlotWorld.getQueue(); 566 enqueue = true; 567 } 568 569 queue.setCuboid( 570 Location.at( 571 classicPlotWorld.getWorldName(), 572 sx + 1, 573 classicPlotWorld.schematicStartHeight() + 1, 574 sz 575 ), 576 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMaxGenHeight(), ez), 577 BlockTypes.AIR.getDefaultState() 578 ); 579 if (classicPlotWorld.PLOT_BEDROCK) { 580 queue.setCuboid( 581 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight(), sz), 582 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMinGenHeight(), ez), 583 BlockTypes.BEDROCK.getDefaultState() 584 ); 585 } 586 int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; 587 queue.setCuboid( 588 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz), 589 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, sz), 590 classicPlotWorld.WALL_FILLING.toPattern() 591 ); 592 queue.setCuboid( 593 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, ez), 594 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT, ez), 595 classicPlotWorld.WALL_FILLING.toPattern() 596 ); 597 queue.setCuboid( 598 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), 599 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), 600 classicPlotWorld.ROAD_BLOCK.toPattern() 601 ); 602 603 if (classicPlotWorld.PLACE_TOP_BLOCK) { 604 queue.setCuboid( 605 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, sz), 606 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, sz), 607 classicPlotWorld.WALL_BLOCK.toPattern() 608 ); 609 queue.setCuboid( 610 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.WALL_HEIGHT + 1, ez), 611 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.WALL_HEIGHT + 1, ez), 612 classicPlotWorld.WALL_BLOCK.toPattern() 613 ); 614 } 615 return !enqueue || queue.enqueue(); 616 } 617 618 619 @Override 620 public boolean createRoadSouthEast(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 621 Location pos2 = getPlotTopLocAbs(plot.getId()); 622 int sx = pos2.getX() + 1; 623 int ex = sx + classicPlotWorld.ROAD_WIDTH - 1; 624 int sz = pos2.getZ() + 1; 625 int ez = sz + classicPlotWorld.ROAD_WIDTH - 1; 626 627 boolean enqueue = false; 628 if (queue == null) { 629 queue = classicPlotWorld.getQueue(); 630 enqueue = true; 631 } 632 633 queue.setCuboid( 634 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.ROAD_HEIGHT + 1, sz + 1), 635 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMaxGenHeight(), ez - 1), 636 BlockTypes.AIR.getDefaultState() 637 ); 638 if (classicPlotWorld.PLOT_BEDROCK) { 639 queue.setCuboid( 640 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight(), sz + 1), 641 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.getMinGenHeight(), ez - 1), 642 BlockTypes.BEDROCK.getDefaultState() 643 ); 644 } 645 int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; 646 queue.setCuboid( 647 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), 648 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.ROAD_HEIGHT, ez - 1), 649 classicPlotWorld.ROAD_BLOCK.toPattern() 650 ); 651 return !enqueue || queue.enqueue(); 652 } 653 654 @Override 655 public boolean removeRoadEast(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 656 Location pos1 = getPlotBottomLocAbs(plot.getId()); 657 Location pos2 = getPlotTopLocAbs(plot.getId()); 658 int sx = pos2.getX() + 1; 659 int ex = sx + classicPlotWorld.ROAD_WIDTH - 1; 660 int sz = pos1.getZ() - 1; 661 int ez = pos2.getZ() + 1; 662 663 boolean enqueue = false; 664 if (queue == null) { 665 queue = classicPlotWorld.getQueue(); 666 enqueue = true; 667 } 668 669 queue 670 .setCuboid( 671 Location.at( 672 classicPlotWorld.getWorldName(), 673 sx, 674 classicPlotWorld.schematicStartHeight() + 1, 675 sz 676 ), 677 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez), 678 BlockTypes.AIR.getDefaultState() 679 ); 680 int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; 681 queue.setCuboid( 682 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz + 1), 683 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez - 1), 684 classicPlotWorld.MAIN_BLOCK.toPattern() 685 ); 686 queue.setCuboid( 687 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz + 1), 688 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez - 1), 689 classicPlotWorld.TOP_BLOCK.toPattern() 690 ); 691 692 return !enqueue || queue.enqueue(); 693 } 694 695 @Override 696 public boolean removeRoadSouth(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 697 Location pos1 = getPlotBottomLocAbs(plot.getId()); 698 Location pos2 = getPlotTopLocAbs(plot.getId()); 699 int sz = pos2.getZ() + 1; 700 int ez = sz + classicPlotWorld.ROAD_WIDTH - 1; 701 int sx = pos1.getX() - 1; 702 int ex = pos2.getX() + 1; 703 704 boolean enqueue = false; 705 if (queue == null) { 706 queue = classicPlotWorld.getQueue(); 707 enqueue = true; 708 } 709 710 queue 711 .setCuboid( 712 Location.at( 713 classicPlotWorld.getWorldName(), 714 sx, 715 classicPlotWorld.schematicStartHeight() + 1, 716 sz 717 ), 718 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez), 719 BlockTypes.AIR.getDefaultState() 720 ); 721 int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; 722 queue.setCuboid( 723 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.getMinGenHeight() + startYOffset, sz), 724 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT - 1, ez), 725 classicPlotWorld.MAIN_BLOCK.toPattern() 726 ); 727 queue.setCuboid( 728 Location.at(classicPlotWorld.getWorldName(), sx + 1, classicPlotWorld.PLOT_HEIGHT, sz), 729 Location.at(classicPlotWorld.getWorldName(), ex - 1, classicPlotWorld.PLOT_HEIGHT, ez), 730 classicPlotWorld.TOP_BLOCK.toPattern() 731 ); 732 733 return !enqueue || queue.enqueue(); 734 } 735 736 @Override 737 public boolean removeRoadSouthEast(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 738 Location location = getPlotTopLocAbs(plot.getId()); 739 int sx = location.getX() + 1; 740 int ex = sx + classicPlotWorld.ROAD_WIDTH - 1; 741 int sz = location.getZ() + 1; 742 int ez = sz + classicPlotWorld.ROAD_WIDTH - 1; 743 744 boolean enqueue = false; 745 if (queue == null) { 746 queue = classicPlotWorld.getQueue(); 747 enqueue = true; 748 } 749 750 queue 751 .setCuboid( 752 Location.at( 753 classicPlotWorld.getWorldName(), 754 sx, 755 classicPlotWorld.schematicStartHeight() + 1, 756 sz 757 ), 758 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.getMaxGenHeight(), ez), 759 BlockTypes.AIR.getDefaultState() 760 ); 761 int startYOffset = classicPlotWorld.PLOT_BEDROCK ? 1 : 0; 762 queue.setCuboid( 763 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.getMinGenHeight() + startYOffset, sz), 764 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez), 765 classicPlotWorld.MAIN_BLOCK.toPattern() 766 ); 767 queue.setCuboid( 768 Location.at(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz), 769 Location.at(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez), 770 classicPlotWorld.TOP_BLOCK.toPattern() 771 ); 772 773 return !enqueue || queue.enqueue(); 774 } 775 776 @Override 777 public boolean finishPlotMerge(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) { 778 final BlockBucket claim = classicPlotWorld.CLAIMED_WALL_BLOCK; 779 if (classicPlotWorld.PLACE_TOP_BLOCK && (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK))) { 780 for (PlotId plotId : plotIds) { 781 setWall(plotId, claim.toPattern(), null, queue); 782 } 783 } 784 if (Settings.General.MERGE_REPLACE_WALL) { 785 final BlockBucket wallBlock = classicPlotWorld.WALL_FILLING; 786 for (PlotId id : plotIds) { 787 setWallFilling(id, wallBlock.toPattern(), null, queue); 788 } 789 } 790 return true; 791 } 792 793 @Override 794 public boolean finishPlotUnlink(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) { 795 final BlockBucket claim = classicPlotWorld.CLAIMED_WALL_BLOCK; 796 if (classicPlotWorld.PLACE_TOP_BLOCK && (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK))) { 797 for (PlotId id : plotIds) { 798 setWall(id, claim.toPattern(), null, queue); 799 } 800 } 801 return true; // return false if unlink has been denied 802 } 803 804 @Override 805 public boolean startPlotMerge(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) { 806 return true; 807 } 808 809 @Override 810 public boolean startPlotUnlink(@NonNull List<PlotId> plotIds, @Nullable QueueCoordinator queue) { 811 return true; 812 } 813 814 @Override 815 public boolean claimPlot(@NonNull Plot plot, @Nullable QueueCoordinator queue) { 816 final BlockBucket claim = classicPlotWorld.CLAIMED_WALL_BLOCK; 817 if (classicPlotWorld.PLACE_TOP_BLOCK && (!claim.isAir() || !claim.equals(classicPlotWorld.WALL_BLOCK))) { 818 return setWall(plot.getId(), claim.toPattern(), null, queue); 819 } 820 return true; 821 } 822 823 @Override 824 public String[] getPlotComponents(@NonNull PlotId plotId) { 825 return ClassicPlotManagerComponent.stringValues(); 826 } 827 828 /** 829 * Retrieves the location of where a sign should be for a plot. 830 * 831 * @param plot The plot 832 * @return The location where a sign should be 833 */ 834 @Override 835 public Location getSignLoc(@NonNull Plot plot) { 836 plot = plot.getBasePlot(false); 837 final Location bot = plot.getBottomAbs(); 838 return Location.at(classicPlotWorld.getWorldName(), bot.getX() - 1, classicPlotWorld.ROAD_HEIGHT + 1, bot.getZ() - 2); 839 } 840 841}