mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-31 17:43:44 +01:00 
			
		
		
		
	Features/v5/move swap fixes + some other important commits (comments, etc) (#2699)
* Use generics instead of the raw class
* Add Gradle wrapper verification
* Fix biome setting in versions prior to 1.15
* Fixes #2654
* Document area getters in PlotAreaManager, and replace y-value with z in the area contains check.
* Remove update notifications
* Remove unused dependencies
* Do not kick plot owners on "/p deny *"
* Do not kick any added players on /p deny *
* Allow redstone to be used in server plot with `redstone.disable-offline` enabled.
Potentially fixes #2613
* Disallow swapping ,erged plots
* Fix legacy converter.
* Fix blockbucket pattern generation
* Prevent pasting schematics onto merged plots.
* Cancel claim event correctly
* Revert "Cancel claim event correctly"
This reverts commit 0f786155
Further investigation required
* Fix plot swapping messing up owners. Fixes #2282
* Fix plot move
* Prevent plot swapping form changing the database unless the swap was successful.
* Update signs after swap.
* Only send move success message if the move was successful.
Co-authored-by: Matt <4009945+MattBDev@users.noreply.github.com>
Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: Daniel <admin@hywse.eu>
Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
			
			
This commit is contained in:
		 Alexander Söderberg
					Alexander Söderberg
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							30b83faab6
						
					
				
				
					commit
					05626c2c8f
				
			
							
								
								
									
										2
									
								
								.github/workflows/gradle.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/gradle.yml
									
									
									
									
										vendored
									
									
								
							| @@ -22,5 +22,7 @@ jobs: | ||||
|       uses: actions/setup-java@v1 | ||||
|       with: | ||||
|         java-version: 1.8 | ||||
|     - name: Gradle Wrapper Validation | ||||
|       uses: gradle/wrapper-validation-action@v1 | ||||
|     - name: Test with Gradle | ||||
|       run: ./gradlew clean build | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import com.github.intellectualsites.plotsquared.bukkit.util.UpdateUtility; | ||||
| import com.github.intellectualsites.plotsquared.plot.PlotSquared; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Captions; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Settings; | ||||
| import com.github.intellectualsites.plotsquared.plot.database.DBFunc; | ||||
| import com.github.intellectualsites.plotsquared.plot.flags.implementations.AnimalAttackFlag; | ||||
| import com.github.intellectualsites.plotsquared.plot.flags.implementations.AnimalCapFlag; | ||||
| import com.github.intellectualsites.plotsquared.plot.flags.implementations.AnimalInteractFlag; | ||||
| @@ -485,17 +486,19 @@ import java.util.regex.Pattern; | ||||
|             return; | ||||
|         } | ||||
|         if (Settings.Redstone.DISABLE_OFFLINE) { | ||||
|             boolean disable; | ||||
|             if (plot.isMerged()) { | ||||
|                 disable = true; | ||||
|                 for (UUID owner : plot.getOwners()) { | ||||
|                     if (UUIDHandler.getPlayer(owner) != null) { | ||||
|                         disable = false; | ||||
|                         break; | ||||
|             boolean disable = false; | ||||
|             if (!plot.getOwner().equals(DBFunc.SERVER)) { | ||||
|                 if (plot.isMerged()) { | ||||
|                     disable = true; | ||||
|                     for (UUID owner : plot.getOwners()) { | ||||
|                         if (UUIDHandler.getPlayer(owner) != null) { | ||||
|                             disable = false; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                 } else { | ||||
|                     disable = UUIDHandler.getPlayer(plot.guessOwner()) == null; | ||||
|                 } | ||||
|             } else { | ||||
|                 disable = UUIDHandler.getPlayer(plot.guessOwner()) == null; | ||||
|             } | ||||
|             if (disable) { | ||||
|                 for (UUID trusted : plot.getTrusted()) { | ||||
|   | ||||
| @@ -39,6 +39,7 @@ import org.bukkit.inventory.ItemStack; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
| import org.jetbrains.annotations.Nullable; | ||||
|  | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashSet; | ||||
| import java.util.List; | ||||
| @@ -46,6 +47,14 @@ import java.util.Set; | ||||
|  | ||||
| @SuppressWarnings({"unused", "WeakerAccess"}) public class BukkitUtil extends WorldUtil { | ||||
|  | ||||
|     private static Method biomeSetter; | ||||
|     static { | ||||
|         try { | ||||
|             biomeSetter = World.class.getMethod("setBiome", Integer.class, Integer.class, Biome.class); | ||||
|         } catch (final Exception ignored) { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static String lastString = null; | ||||
|     private static World lastWorld = null; | ||||
|  | ||||
| @@ -425,7 +434,16 @@ import java.util.Set; | ||||
|         for (int x = region.getMinimumPoint().getX(); x <= region.getMaximumPoint().getX(); x++) { | ||||
|             for (int z = region.getMinimumPoint().getZ(); z <= region.getMaximumPoint().getZ(); z++) { | ||||
|                 for (int y = 0; y < world.getMaxHeight(); y++) { | ||||
|                     world.setBiome(x, y, z, biome); | ||||
|                     try { | ||||
|                         if (biomeSetter != null) { | ||||
|                             biomeSetter.invoke(world, x, z, biome); | ||||
|                         } else { | ||||
|                             world.setBiome(x, y, z, biome); | ||||
|                         } | ||||
|                     } catch (final Exception e) { | ||||
|                         PlotSquared.log("An error occurred setting the biome:"); | ||||
|                         e.printStackTrace(); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import com.github.intellectualsites.plotsquared.plot.object.Location; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.MainUtil; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.block.ScopedLocalBlockQueue; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.world.PatternUtil; | ||||
| import com.google.common.base.Preconditions; | ||||
| import com.sk89q.worldedit.bukkit.BukkitAdapter; | ||||
| import com.sk89q.worldedit.function.pattern.Pattern; | ||||
| import com.sk89q.worldedit.world.biome.BiomeType; | ||||
| @@ -20,9 +21,9 @@ import org.bukkit.World; | ||||
| import org.bukkit.block.Biome; | ||||
| import org.bukkit.generator.ChunkGenerator.BiomeGrid; | ||||
| import org.bukkit.generator.ChunkGenerator.ChunkData; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public class GenChunk extends ScopedLocalBlockQueue { | ||||
|  | ||||
| @@ -109,7 +110,7 @@ public class GenChunk extends ScopedLocalBlockQueue { | ||||
|     } | ||||
|  | ||||
|     @Override public boolean setBlock(int x, int y, int z, @NotNull Pattern pattern) { | ||||
|         return setBlock(x, y, z, PatternUtil.apply(pattern, x, y, z)); | ||||
|         return setBlock(x, y, z, PatternUtil.apply(Preconditions.checkNotNull(pattern, "Pattern may not be null"), x, y, z)); | ||||
|     } | ||||
|  | ||||
|     @Override public boolean setBlock(int x, int y, int z, BlockState id) { | ||||
|   | ||||
| @@ -2,9 +2,7 @@ package com.github.intellectualsites.plotsquared.plot.commands; | ||||
|  | ||||
| import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Captions; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.Location; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.Plot; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotId; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.comment.CommentInbox; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.comment.PlotComment; | ||||
| @@ -14,6 +12,7 @@ import com.github.intellectualsites.plotsquared.plot.util.StringMan; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.UUIDHandler; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.Locale; | ||||
| import java.util.Map.Entry; | ||||
|  | ||||
| @CommandDeclaration(command = "comment", | ||||
| @@ -30,40 +29,41 @@ public class Comment extends SubCommand { | ||||
|                 StringMan.join(CommentManager.inboxes.keySet(), "|")); | ||||
|             return false; | ||||
|         } | ||||
|         CommentInbox inbox = CommentManager.inboxes.get(args[0].toLowerCase()); | ||||
|         if (inbox == null) { | ||||
|             sendMessage(player, Captions.COMMENT_SYNTAX, | ||||
|                 StringMan.join(CommentManager.inboxes.keySet(), "|")); | ||||
|             return false; | ||||
|  | ||||
|         // Attempt to extract a plot out of the first argument | ||||
|         Plot plot = null; | ||||
|         if (!CommentManager.inboxes.containsKey(args[0].toLowerCase(Locale.ENGLISH))) { | ||||
|             plot = MainUtil.getPlotFromString(player, args[0], false); | ||||
|         } | ||||
|         Location location = player.getLocation(); | ||||
|         PlotId id; | ||||
|         try { | ||||
|             id = PlotId.fromString(args[1]); | ||||
|         } catch (IllegalArgumentException ignored) { | ||||
|             MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); | ||||
|             return false; | ||||
|         } | ||||
|         Plot plot = MainUtil.getPlotFromString(player, args[1], false); | ||||
|  | ||||
|         int index; | ||||
|         if (plot == null) { | ||||
|             index = 1; | ||||
|             plot = location.getPlotAbs(); | ||||
|             plot = player.getLocation().getPlotAbs(); | ||||
|         } else { | ||||
|             if (args.length < 4) { | ||||
|             if (args.length < 3) { | ||||
|                 sendMessage(player, Captions.COMMENT_SYNTAX, | ||||
|                     StringMan.join(CommentManager.inboxes.keySet(), "|")); | ||||
|                 return false; | ||||
|             } | ||||
|             index = 2; | ||||
|         } | ||||
|  | ||||
|         CommentInbox inbox = CommentManager.inboxes.get(args[index - 1].toLowerCase()); | ||||
|         if (inbox == null) { | ||||
|             sendMessage(player, Captions.COMMENT_SYNTAX, | ||||
|                 StringMan.join(CommentManager.inboxes.keySet(), "|")); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!inbox.canWrite(plot, player)) { | ||||
|             sendMessage(player, Captions.NO_PERM_INBOX, ""); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         String message = StringMan.join(Arrays.copyOfRange(args, index, args.length), " "); | ||||
|         PlotComment comment = | ||||
|             new PlotComment(location.getWorld(), id, message, player.getName(), inbox.toString(), | ||||
|             new PlotComment(player.getLocation().getWorld(), plot.getId(), message, player.getName(), inbox.toString(), | ||||
|                 System.currentTimeMillis()); | ||||
|         boolean result = inbox.addComment(plot, comment); | ||||
|         if (!result) { | ||||
|   | ||||
| @@ -17,6 +17,7 @@ import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.concurrent.ExecutionException; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
|  | ||||
| @CommandDeclaration(command = "condense", | ||||
| @@ -135,13 +136,17 @@ public class Condense extends SubCommand { | ||||
|                             } | ||||
|                             i++; | ||||
|                             final AtomicBoolean result = new AtomicBoolean(false); | ||||
|                             result.set(origin.move(possible, () -> { | ||||
|                                 if (result.get()) { | ||||
|                                     MainUtil.sendMessage(player, | ||||
|                                         "Moving: " + origin + " -> " + possible); | ||||
|                                     TaskManager.runTaskLater(task, 1); | ||||
|                                 } | ||||
|                             }, false)); | ||||
|                             try { | ||||
|                                 result.set(origin.move(possible, () -> { | ||||
|                                     if (result.get()) { | ||||
|                                         MainUtil.sendMessage(player, | ||||
|                                             "Moving: " + origin + " -> " + possible); | ||||
|                                         TaskManager.runTaskLater(task, 1); | ||||
|                                     } | ||||
|                                 }, false).get()); | ||||
|                             } catch (InterruptedException | ExecutionException e) { | ||||
|                                 e.printStackTrace(); | ||||
|                             } | ||||
|                             if (result.get()) { | ||||
|                                 break; | ||||
|                             } | ||||
|   | ||||
| @@ -77,6 +77,10 @@ public class Deny extends SubCommand { | ||||
|                 handleKick(UUIDHandler.getPlayer(uuid), plot); | ||||
|             } else { | ||||
|                 for (PlotPlayer plotPlayer : plot.getPlayersInPlot()) { | ||||
|                     // Ignore plot-owners | ||||
|                     if (plot.isAdded(plotPlayer.getUUID())) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     handleKick(plotPlayer, plot); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| package com.github.intellectualsites.plotsquared.plot.commands; | ||||
|  | ||||
| import com.github.intellectualsites.plotsquared.commands.Command; | ||||
| import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; | ||||
| import com.github.intellectualsites.plotsquared.plot.PlotSquared; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Captions; | ||||
| @@ -7,9 +8,13 @@ import com.github.intellectualsites.plotsquared.plot.object.Location; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.Plot; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotArea; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.MainUtil; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.Permissions; | ||||
|  | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| @CommandDeclaration(usage = "/plot move <X;Z>", | ||||
|     command = "move", | ||||
|     description = "Move a plot", | ||||
| @@ -18,16 +23,19 @@ import com.github.intellectualsites.plotsquared.plot.util.Permissions; | ||||
|     requiredType = RequiredType.PLAYER) | ||||
| public class Move extends SubCommand { | ||||
|  | ||||
|     @Override public boolean onCommand(final PlotPlayer player, String[] args) { | ||||
|     @Override public CompletableFuture<Boolean> execute(PlotPlayer player, String[] args, | ||||
|         RunnableVal3<Command, Runnable, Runnable> confirm, | ||||
|         RunnableVal2<Command, CommandResult> whenDone) { | ||||
|         Location location = player.getLocation(); | ||||
|         Plot plot1 = location.getPlotAbs(); | ||||
|         if (plot1 == null) { | ||||
|             return !MainUtil.sendMessage(player, Captions.NOT_IN_PLOT); | ||||
|             return CompletableFuture | ||||
|                 .completedFuture(!MainUtil.sendMessage(player, Captions.NOT_IN_PLOT)); | ||||
|         } | ||||
|         if (!plot1.isOwner(player.getUUID()) && !Permissions | ||||
|             .hasPermission(player, Captions.PERMISSION_ADMIN.getTranslated())) { | ||||
|             MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         boolean override = false; | ||||
|         if (args.length == 2 && args[1].equalsIgnoreCase("-f")) { | ||||
| @@ -36,14 +44,14 @@ public class Move extends SubCommand { | ||||
|         } | ||||
|         if (args.length != 1) { | ||||
|             Captions.COMMAND_SYNTAX.send(player, getUsage()); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]); | ||||
|         Plot plot2; | ||||
|         if (area == null) { | ||||
|             plot2 = MainUtil.getPlotFromString(player, args[0], true); | ||||
|             if (plot2 == null) { | ||||
|                 return false; | ||||
|                 return CompletableFuture.completedFuture(false); | ||||
|             } | ||||
|         } else { | ||||
|             plot2 = area.getPlotAbs(plot1.getId()); | ||||
| @@ -51,19 +59,32 @@ public class Move extends SubCommand { | ||||
|         if (plot1.equals(plot2)) { | ||||
|             MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); | ||||
|             MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot copy <X;Z>"); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (!plot1.getArea().isCompatible(plot2.getArea()) && (!override || !Permissions | ||||
|             .hasPermission(player, Captions.PERMISSION_ADMIN.getTranslated()))) { | ||||
|             Captions.PLOTWORLD_INCOMPATIBLE.send(player); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (plot1.move(plot2, () -> MainUtil.sendMessage(player, Captions.MOVE_SUCCESS), false)) { | ||||
|             return true; | ||||
|         } else { | ||||
|             MainUtil.sendMessage(player, Captions.REQUIRES_UNOWNED); | ||||
|             return false; | ||||
|         if (plot1.isMerged() || plot2.isMerged()) { | ||||
|             Captions.MOVE_MERGED.send(player); | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|  | ||||
|         return plot1.move(plot2, () -> {}, false) | ||||
|             .thenApply(result -> { | ||||
|                 if (result) { | ||||
|                     MainUtil.sendMessage(player, Captions.MOVE_SUCCESS); | ||||
|                     return true; | ||||
|                 } else { | ||||
|                     MainUtil.sendMessage(player, Captions.REQUIRES_UNOWNED); | ||||
|                     return false; | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     @Override public boolean onCommand(final PlotPlayer player, String[] args) { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -68,6 +68,10 @@ public class SchematicCmd extends SubCommand { | ||||
|                     MainUtil.sendMessage(player, Captions.TASK_IN_PROCESS); | ||||
|                     return false; | ||||
|                 } | ||||
|                 if (plot.isMerged()) { | ||||
|                     MainUtil.sendMessage(player, Captions.SCHEMATIC_PASTE_MERGED); | ||||
|                     return false; | ||||
|                 } | ||||
|                 final String location = args[1]; | ||||
|                 this.running = true; | ||||
|                 TaskManager.runTaskAsync(() -> { | ||||
|   | ||||
| @@ -1,13 +1,18 @@ | ||||
| package com.github.intellectualsites.plotsquared.plot.commands; | ||||
|  | ||||
| import com.github.intellectualsites.plotsquared.commands.Command; | ||||
| import com.github.intellectualsites.plotsquared.commands.CommandDeclaration; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Captions; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.Location; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.Plot; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.RunnableVal2; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.RunnableVal3; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.MainUtil; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.Permissions; | ||||
|  | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| @CommandDeclaration(usage = "/plot swap <X;Z>", | ||||
|     command = "swap", | ||||
|     description = "Swap two plots", | ||||
| @@ -16,43 +21,54 @@ import com.github.intellectualsites.plotsquared.plot.util.Permissions; | ||||
|     requiredType = RequiredType.PLAYER) | ||||
| public class Swap extends SubCommand { | ||||
|  | ||||
|     @Override public boolean onCommand(final PlotPlayer player, String[] args) { | ||||
|     @Override public CompletableFuture<Boolean> execute(PlotPlayer player, String[] args, | ||||
|         RunnableVal3<Command, Runnable, Runnable> confirm, | ||||
|         RunnableVal2<Command, CommandResult> whenDone) { | ||||
|         Location location = player.getLocation(); | ||||
|         Plot plot1 = location.getPlotAbs(); | ||||
|         if (plot1 == null) { | ||||
|             return !MainUtil.sendMessage(player, Captions.NOT_IN_PLOT); | ||||
|             return CompletableFuture.completedFuture(!MainUtil.sendMessage(player, Captions.NOT_IN_PLOT)); | ||||
|         } | ||||
|         if (!plot1.isOwner(player.getUUID()) && !Permissions | ||||
|             .hasPermission(player, Captions.PERMISSION_ADMIN.getTranslated())) { | ||||
|             MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (args.length != 1) { | ||||
|             Captions.COMMAND_SYNTAX.send(player, getUsage()); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         Plot plot2 = MainUtil.getPlotFromString(player, args[0], true); | ||||
|         if (plot2 == null) { | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (plot1.equals(plot2)) { | ||||
|             MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); | ||||
|             MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot copy <X;Z>"); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (!plot1.getArea().isCompatible(plot2.getArea())) { | ||||
|             Captions.PLOTWORLD_INCOMPATIBLE.send(player); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (plot1.move(plot2, new Runnable() { | ||||
|             @Override public void run() { | ||||
|                 MainUtil.sendMessage(player, Captions.SWAP_SUCCESS); | ||||
|             } | ||||
|         }, true)) { | ||||
|             return true; | ||||
|         } else { | ||||
|             MainUtil.sendMessage(player, Captions.SWAP_OVERLAP); | ||||
|             return false; | ||||
|         if (plot1.isMerged() || plot2.isMerged()) { | ||||
|             Captions.SWAP_MERGED.send(player); | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|  | ||||
|         return plot1.move(plot2, () -> {}, true) | ||||
|             .thenApply(result -> { | ||||
|                 if (result) { | ||||
|                     MainUtil.sendMessage(player, Captions.SWAP_SUCCESS); | ||||
|                     return true; | ||||
|                 } else { | ||||
|                     MainUtil.sendMessage(player, Captions.SWAP_OVERLAP); | ||||
|                     return false; | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     @Override public boolean onCommand(final PlotPlayer player, String[] args) { | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -174,6 +174,7 @@ public enum Captions implements Caption { | ||||
|     //</editor-fold> | ||||
|     //<editor-fold desc="Move"> | ||||
|     MOVE_SUCCESS("$4Successfully moved plot.", "Move"), | ||||
|     MOVE_MERGED("$2Merged plots may not be moved. Please unmerge the plot before performing the move.", "Move"), | ||||
|     COPY_SUCCESS("$4Successfully copied plot.", "Move"), | ||||
|     REQUIRES_UNOWNED("$2The location specified is already occupied.", "Move"), | ||||
|     //</editor-fold> | ||||
| @@ -234,6 +235,7 @@ public enum Captions implements Caption { | ||||
|     SWAP_DIMENSIONS("$2The proposed areas must have comparable dimensions", "Swap"), | ||||
|     SWAP_SYNTAX("$2/plot swap <id>", "Swap"), | ||||
|     SWAP_SUCCESS("$4Successfully swapped plots", "Swap"), | ||||
|     SWAP_MERGED("$2Merged plots may not be swapped. Please unmerge the plot before performing the swap.", "Swap"), | ||||
|     //</editor-fold> | ||||
|     //<editor-fold desc="Comments"> | ||||
|     INBOX_NOTIFICATION("%s unread messages. Use /plot inbox", "Comment"), | ||||
| @@ -318,6 +320,7 @@ public enum Captions implements Caption { | ||||
|     SCHEMATIC_MISSING_ARG("$2You need to specify an argument. Possible values: $1save$2, $1paste $2, $1exportall$2, $1list", "Schematics"), | ||||
|     SCHEMATIC_INVALID("$2That is not a valid schematic. Reason: $2%s", "Schematics"), | ||||
|     SCHEMATIC_VALID("$2That is a valid schematic", "Schematics"), | ||||
|     SCHEMATIC_PASTE_MERGED("$2Schematics cannot be pasted onto merged plots. Please unmerge the plot before performing the paste.", "Schematics"), | ||||
|     SCHEMATIC_PASTE_FAILED("$2Failed to paste the schematic", "Schematics"), | ||||
|     SCHEMATIC_PASTE_SUCCESS("$4The schematic pasted successfully", "Schematics"), | ||||
|     SCHEMATIC_LIST("$4Saved Schematics: $1%s", "Schematics"), | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package com.github.intellectualsites.plotsquared.plot.config; | ||||
| import com.github.intellectualsites.plotsquared.configuration.MemorySection; | ||||
| import com.github.intellectualsites.plotsquared.configuration.file.YamlConfiguration; | ||||
| import com.github.intellectualsites.plotsquared.plot.PlotSquared; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Settings.Enabled_Components; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.StringMan; | ||||
|  | ||||
| import java.io.File; | ||||
| @@ -30,7 +31,7 @@ public class Config { | ||||
|      * @param <T> | ||||
|      * @return | ||||
|      */ | ||||
|     public static <T> T get(String key, Class root) { | ||||
|     public static <T> T get(String key, Class<?> root) { | ||||
|         String[] split = key.split("\\."); | ||||
|         Object instance = getInstance(split, root); | ||||
|         if (instance != null) { | ||||
| @@ -55,7 +56,7 @@ public class Config { | ||||
|      * @param value value | ||||
|      * @param root | ||||
|      */ | ||||
|     public static void set(String key, Object value, Class root) { | ||||
|     public static void set(String key, Object value, Class<? extends Config> root) { | ||||
|         String[] split = key.split("\\."); | ||||
|         Object instance = getInstance(split, root); | ||||
|         if (instance != null) { | ||||
| @@ -81,7 +82,7 @@ public class Config { | ||||
|         PlotSquared.debug("Failed to set config option: " + key + ": " + value + " | " + instance); | ||||
|     } | ||||
|  | ||||
|     public static boolean load(File file, Class root) { | ||||
|     public static boolean load(File file, Class<? extends Config> root) { | ||||
|         if (!file.exists()) { | ||||
|             return false; | ||||
|         } | ||||
| @@ -102,7 +103,7 @@ public class Config { | ||||
|      * @param file | ||||
|      * @param root | ||||
|      */ | ||||
|     public static void save(File file, Class root) { | ||||
|     public static void save(File file, Class<? extends Config> root) { | ||||
|         try { | ||||
|             if (!file.exists()) { | ||||
|                 file.getParentFile().mkdirs(); | ||||
| @@ -123,7 +124,7 @@ public class Config { | ||||
|      * @param clazz | ||||
|      * @return | ||||
|      */ | ||||
|     public static Map<String, Object> getFields(Class clazz) { | ||||
|     public static Map<String, Object> getFields(Class<Enabled_Components> clazz) { | ||||
|         HashMap<String, Object> map = new HashMap<>(); | ||||
|         for (Field field : clazz.getFields()) { | ||||
|             if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { | ||||
| @@ -242,7 +243,7 @@ public class Config { | ||||
|      * @param root | ||||
|      * @return | ||||
|      */ | ||||
|     private static Field getField(String[] split, Class root) { | ||||
|     private static Field getField(String[] split, Class<?> root) { | ||||
|         Object instance = getInstance(split, root); | ||||
|         if (instance == null) { | ||||
|             return null; | ||||
| @@ -278,7 +279,7 @@ public class Config { | ||||
|      * @param root | ||||
|      * @return The instance or null | ||||
|      */ | ||||
|     private static Object getInstance(String[] split, Class root) { | ||||
|     private static Object getInstance(String[] split, Class<?> root) { | ||||
|         try { | ||||
|             Class<?> clazz = root == null ? MethodHandles.lookup().lookupClass() : root; | ||||
|             Object instance = clazz.newInstance(); | ||||
| @@ -286,9 +287,9 @@ public class Config { | ||||
|                 if (split.length == 1) { | ||||
|                     return instance; | ||||
|                 } | ||||
|                 Class found = null; | ||||
|                 Class<?> found = null; | ||||
|                 Class<?>[] classes = clazz.getDeclaredClasses(); | ||||
|                 for (Class current : classes) { | ||||
|                 for (Class<?> current : classes) { | ||||
|                     if (current.getSimpleName().equalsIgnoreCase(toFieldName(split[0]))) { | ||||
|                         found = current; | ||||
|                         break; | ||||
| @@ -361,8 +362,6 @@ public class Config { | ||||
|      * Set some field to be accessible. | ||||
|      * | ||||
|      * @param field | ||||
|      * @throws NoSuchFieldException | ||||
|      * @throws IllegalAccessException | ||||
|      */ | ||||
|     private static void setAccessible(Field field) { | ||||
|         field.setAccessible(true); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| public interface AbstractDB { | ||||
|  | ||||
| @@ -144,7 +145,7 @@ public interface AbstractDB { | ||||
|      * @param plot1 Plot1 | ||||
|      * @param plot2 Plot2 | ||||
|      */ | ||||
|     void swapPlots(Plot plot1, Plot plot2); | ||||
|     CompletableFuture<Boolean> swapPlots(Plot plot1, Plot plot2); | ||||
|  | ||||
|     /** | ||||
|      * Sets plot flag. | ||||
|   | ||||
| @@ -16,6 +16,7 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| /** | ||||
|  * Database Functions | ||||
| @@ -58,10 +59,11 @@ public class DBFunc { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static void swapPlots(Plot plot1, Plot plot2) { | ||||
|     public static CompletableFuture<Boolean> swapPlots(Plot plot1, Plot plot2) { | ||||
|         if (dbManager != null) { | ||||
|             dbManager.swapPlots(plot1, plot2); | ||||
|             return dbManager.swapPlots(plot1, plot2); | ||||
|         } | ||||
|         return CompletableFuture.completedFuture(false); | ||||
|     } | ||||
|  | ||||
|     public static boolean deleteTables() { | ||||
|   | ||||
| @@ -44,6 +44,7 @@ import java.util.Map.Entry; | ||||
| import java.util.Queue; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
| import java.util.concurrent.ConcurrentLinkedQueue; | ||||
| import java.util.concurrent.atomic.AtomicInteger; | ||||
| @@ -2028,37 +2029,32 @@ import java.util.concurrent.atomic.AtomicInteger; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     @Override public void swapPlots(Plot plot1, Plot plot2) { | ||||
|         final int id1 = getId(plot1); | ||||
|         final int id2 = getId(plot2); | ||||
|         final PlotId pos1 = plot1.getId(); | ||||
|         final PlotId pos2 = plot2.getId(); | ||||
|         addPlotTask(plot1, new UniqueStatement("swapPlots") { | ||||
|             @Override public void set(PreparedStatement statement) throws SQLException { | ||||
|                 statement.setInt(1, pos2.x); | ||||
|                 statement.setInt(2, pos2.y); | ||||
|                 statement.setInt(3, id1); | ||||
|             } | ||||
|  | ||||
|             @Override public PreparedStatement get() throws SQLException { | ||||
|                 return SQLManager.this.connection.prepareStatement( | ||||
|                     "UPDATE `" + SQLManager.this.prefix | ||||
|                         + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?"); | ||||
|             } | ||||
|         }); | ||||
|         addPlotTask(plot2, new UniqueStatement("swapPlots") { | ||||
|             @Override public void set(PreparedStatement statement) throws SQLException { | ||||
|                 statement.setInt(1, pos1.x); | ||||
|                 statement.setInt(2, pos1.y); | ||||
|                 statement.setInt(3, id2); | ||||
|             } | ||||
|  | ||||
|             @Override public PreparedStatement get() throws SQLException { | ||||
|                 return SQLManager.this.connection.prepareStatement( | ||||
|                     "UPDATE `" + SQLManager.this.prefix | ||||
|                         + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?"); | ||||
|     @Override public CompletableFuture<Boolean> swapPlots(Plot plot1, Plot plot2) { | ||||
|         final CompletableFuture<Boolean> future = new CompletableFuture<>(); | ||||
|         TaskManager.runTaskAsync(() -> { | ||||
|             final int id1 = getId(plot1); | ||||
|             final int id2 = getId(plot2); | ||||
|             final PlotId pos1 = plot1.getId(); | ||||
|             final PlotId pos2 = plot2.getId(); | ||||
|             try (final PreparedStatement preparedStatement = this.connection.prepareStatement("UPDATE `" + SQLManager.this.prefix | ||||
|                 + "plot` SET `plot_id_x` = ?, `plot_id_z` = ? WHERE `id` = ?")) { | ||||
|                 preparedStatement.setInt(1, pos1.getX()); | ||||
|                 preparedStatement.setInt(2, pos1.getY()); | ||||
|                 preparedStatement.setInt(3, id1); | ||||
|                 preparedStatement.execute(); | ||||
|                 preparedStatement.setInt(1, pos2.getX()); | ||||
|                 preparedStatement.setInt(2, pos2.getY()); | ||||
|                 preparedStatement.setInt(3, id2); | ||||
|                 preparedStatement.execute(); | ||||
|             } catch (final Exception e) { | ||||
|                 PlotSquared.log(Captions.PREFIX.getTranslated() + "Failed to persist swap of " + plot1 + " and " + plot2 + "!"); | ||||
|                 e.printStackTrace(); | ||||
|                 future.complete(false); | ||||
|                 return; | ||||
|             } | ||||
|             future.complete(true); | ||||
|         }); | ||||
|         return future; | ||||
|     } | ||||
|  | ||||
|     @Override public void movePlot(final Plot original, final Plot newPlot) { | ||||
|   | ||||
| @@ -80,7 +80,7 @@ public final class BlockBucket implements ConfigurationSerializable { | ||||
|         if (chance == -1) | ||||
|             chance = 1; | ||||
|         String prefix = input.length() == 0 ? "" : ","; | ||||
|         input.append(prefix).append(chance).append("%").append(prefix); | ||||
|         input.append(prefix).append(block.toString()).append(":").append(chance); | ||||
|         this.compiled = false; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -54,13 +54,16 @@ import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.HashSet; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.ConcurrentHashMap; | ||||
| import java.util.concurrent.TimeUnit; | ||||
| import java.util.concurrent.atomic.AtomicBoolean; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| /** | ||||
| @@ -1742,26 +1745,19 @@ public class Plot { | ||||
|      * Swaps the settings for two plots. | ||||
|      * | ||||
|      * @param plot     the plot to swap data with | ||||
|      * @param whenDone the task to run at the end of this method. | ||||
|      * @return | ||||
|      * @return Future containing the result | ||||
|      */ | ||||
|     public boolean swapData(Plot plot, Runnable whenDone) { | ||||
|     public CompletableFuture<Boolean> swapData(Plot plot) { | ||||
|         if (this.owner == null) { | ||||
|             if (plot == null) { | ||||
|                 return false; | ||||
|             if (plot != null && plot.hasOwner()) { | ||||
|                 plot.moveData(this, null); | ||||
|                 return CompletableFuture.completedFuture(true); | ||||
|             } | ||||
|             if (plot.hasOwner()) { | ||||
|                 plot.moveData(this, whenDone); | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         if (plot == null) { | ||||
|             this.moveData(plot, whenDone); | ||||
|             return true; | ||||
|         } else if (plot.getOwner() == null) { | ||||
|             this.moveData(plot, whenDone); | ||||
|             return true; | ||||
|         if (plot == null || plot.getOwner() == null) { | ||||
|             this.moveData(plot, null); | ||||
|             return CompletableFuture.completedFuture(true); | ||||
|         } | ||||
|         // Swap cached | ||||
|         PlotId temp = new PlotId(this.getId().x, this.getId().y); | ||||
| @@ -1776,9 +1772,7 @@ public class Plot { | ||||
|         this.area.addPlotAbs(this); | ||||
|         plot.area.addPlotAbs(plot); | ||||
|         // Swap database | ||||
|         DBFunc.swapPlots(plot, this); | ||||
|         TaskManager.runTaskLater(whenDone, 1); | ||||
|         return true; | ||||
|         return DBFunc.swapPlots(plot, this); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -1911,10 +1905,10 @@ public class Plot { | ||||
|      * @param whenDone    A task to run when finished, or null | ||||
|      * @return boolean if swap was successful | ||||
|      * @see ChunkManager#swap(Location, Location, Location, Location, Runnable) to swap terrain | ||||
|      * @see this#swapData(Plot, Runnable) to swap plot settings | ||||
|      * @see this#swapData(Plot, Runnable) | ||||
|      * @see this#swapData(Plot) to swap plot settings | ||||
|      * @see this#swapData(Plot) | ||||
|      */ | ||||
|     public boolean swap(Plot destination, Runnable whenDone) { | ||||
|     public CompletableFuture<Boolean> swap(Plot destination, Runnable whenDone) { | ||||
|         return this.move(destination, whenDone, true); | ||||
|     } | ||||
|  | ||||
| @@ -1926,7 +1920,7 @@ public class Plot { | ||||
|      * @param whenDone    A task to run when done, or null | ||||
|      * @return if the move was successful | ||||
|      */ | ||||
|     public boolean move(Plot destination, Runnable whenDone) { | ||||
|     public CompletableFuture<Boolean> move(Plot destination, Runnable whenDone) { | ||||
|         return this.move(destination, whenDone, false); | ||||
|     } | ||||
|  | ||||
| @@ -3067,7 +3061,7 @@ public class Plot { | ||||
|      * @param allowSwap   whether to swap plots | ||||
|      * @return success | ||||
|      */ | ||||
|     public boolean move(final Plot destination, final Runnable whenDone, boolean allowSwap) { | ||||
|     public CompletableFuture<Boolean> move(final Plot destination, final Runnable whenDone, boolean allowSwap) { | ||||
|         final PlotId offset = new PlotId(destination.getId().x - this.getId().x, | ||||
|             destination.getId().y - this.getId().y); | ||||
|         Location db = destination.getBottomAbs(); | ||||
| @@ -3076,18 +3070,18 @@ public class Plot { | ||||
|         final int offsetZ = db.getZ() - ob.getZ(); | ||||
|         if (this.owner == null) { | ||||
|             TaskManager.runTaskLater(whenDone, 1); | ||||
|             return false; | ||||
|             return CompletableFuture.completedFuture(false); | ||||
|         } | ||||
|         boolean occupied = false; | ||||
|         AtomicBoolean occupied = new AtomicBoolean(false); | ||||
|         Set<Plot> plots = this.getConnectedPlots(); | ||||
|         for (Plot plot : plots) { | ||||
|             Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); | ||||
|             if (other.hasOwner()) { | ||||
|                 if (!allowSwap) { | ||||
|                     TaskManager.runTaskLater(whenDone, 1); | ||||
|                     return false; | ||||
|                     return CompletableFuture.completedFuture(false); | ||||
|                 } | ||||
|                 occupied = true; | ||||
|                 occupied.set(true); | ||||
|             } else { | ||||
|                 plot.removeSign(); | ||||
|             } | ||||
| @@ -3097,59 +3091,85 @@ public class Plot { | ||||
|         final ArrayDeque<CuboidRegion> regions = new ArrayDeque<>(this.getRegions()); | ||||
|         // move / swap data | ||||
|         final PlotArea originArea = getArea(); | ||||
|         for (Plot plot : plots) { | ||||
|             Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); | ||||
|             plot.swapData(other, null); | ||||
|         } | ||||
|         // copy terrain | ||||
|         if (occupied) { | ||||
|             Runnable swap = new Runnable() { | ||||
|                 @Override public void run() { | ||||
|                     if (regions.isEmpty()) { | ||||
|                         TaskManager.runTask(whenDone); | ||||
|                         return; | ||||
|                     } | ||||
|                     CuboidRegion region = regions.poll(); | ||||
|                     Location[] corners = MainUtil.getCorners(getWorldName(), region); | ||||
|                     Location pos1 = corners[0]; | ||||
|                     Location pos2 = corners[1]; | ||||
|                     Location pos3 = pos1.clone().add(offsetX, 0, offsetZ); | ||||
|                     Location pos4 = pos2.clone().add(offsetX, 0, offsetZ); | ||||
|                     pos3.setWorld(destination.getWorldName()); | ||||
|                     pos4.setWorld(destination.getWorldName()); | ||||
|                     ChunkManager.manager.swap(pos1, pos2, pos3, pos4, this); | ||||
|  | ||||
|         final Iterator<Plot> plotIterator = plots.iterator(); | ||||
|  | ||||
|         CompletableFuture<Boolean> future = null; | ||||
|         if (plotIterator.hasNext()) { | ||||
|             while (plotIterator.hasNext()) { | ||||
|                 final Plot plot = plotIterator.next(); | ||||
|                 final Plot other = plot.getRelative(destination.getArea(), offset.x, offset.y); | ||||
|                 final CompletableFuture<Boolean> swapResult = plot.swapData(other); | ||||
|                 if (future == null) { | ||||
|                     future = swapResult; | ||||
|                 } else { | ||||
|                     future = future.thenCombine(swapResult, (fn, th) -> fn); | ||||
|                 } | ||||
|             }; | ||||
|             swap.run(); | ||||
|             } | ||||
|         } else { | ||||
|             Runnable move = new Runnable() { | ||||
|                 @Override public void run() { | ||||
|                     if (regions.isEmpty()) { | ||||
|                         Plot plot = destination.getRelative(0, 0); | ||||
|                         for (Plot current : plot.getConnectedPlots()) { | ||||
|                             getManager().claimPlot(current); | ||||
|                             Plot originPlot = originArea.getPlotAbs( | ||||
|                                 new PlotId(current.id.x - offset.x, current.id.y - offset.y)); | ||||
|                             originPlot.getManager().unClaimPlot(originPlot, null); | ||||
|                         } | ||||
|                         plot.setSign(); | ||||
|                         TaskManager.runTask(whenDone); | ||||
|                         return; | ||||
|                     } | ||||
|                     final Runnable task = this; | ||||
|                     CuboidRegion region = regions.poll(); | ||||
|                     Location[] corners = MainUtil.getCorners(getWorldName(), region); | ||||
|                     final Location pos1 = corners[0]; | ||||
|                     final Location pos2 = corners[1]; | ||||
|                     Location newPos = pos1.clone().add(offsetX, 0, offsetZ); | ||||
|                     newPos.setWorld(destination.getWorldName()); | ||||
|                     ChunkManager.manager.copyRegion(pos1, pos2, newPos, | ||||
|                         () -> ChunkManager.manager.regenerateRegion(pos1, pos2, false, task)); | ||||
|                 } | ||||
|             }; | ||||
|             move.run(); | ||||
|             future = CompletableFuture.completedFuture(true); | ||||
|         } | ||||
|         return true; | ||||
|  | ||||
|         return future.thenApply(result -> { | ||||
|             if (!result) { | ||||
|                 return false; | ||||
|             } | ||||
|             // copy terrain | ||||
|             if (occupied.get()) { | ||||
|                 new Runnable() { | ||||
|                     @Override public void run() { | ||||
|                         if (regions.isEmpty()) { | ||||
|                             // Update signs | ||||
|                             destination.setSign(); | ||||
|                             Plot.this.setSign(); | ||||
|                             // Run final tasks | ||||
|                             TaskManager.runTask(whenDone); | ||||
|                         } else { | ||||
|                             CuboidRegion region = regions.poll(); | ||||
|                             Location[] corners = MainUtil.getCorners(getWorldName(), region); | ||||
|                             Location pos1 = corners[0]; | ||||
|                             Location pos2 = corners[1]; | ||||
|                             Location pos3 = pos1.clone().add(offsetX, 0, offsetZ); | ||||
|                             Location pos4 = pos2.clone().add(offsetX, 0, offsetZ); | ||||
|                             pos3.setWorld(destination.getWorldName()); | ||||
|                             pos4.setWorld(destination.getWorldName()); | ||||
|                             ChunkManager.manager.swap(pos1, pos2, pos3, pos4, this); | ||||
|                         } | ||||
|                     } | ||||
|                 }.run(); | ||||
|             } else { | ||||
|                 new Runnable() { | ||||
|                     @Override public void run() { | ||||
|                         if (regions.isEmpty()) { | ||||
|                             Plot plot = destination.getRelative(0, 0); | ||||
|                             Plot originPlot = originArea.getPlotAbs(new PlotId(plot.id.x - offset.x, plot.id.y - offset.y)); | ||||
|                             final Runnable clearDone = () -> { | ||||
|                                 for (final Plot current : plot.getConnectedPlots()) { | ||||
|                                     getManager().claimPlot(current); | ||||
|                                 } | ||||
|                                 plot.setSign(); | ||||
|                                 TaskManager.runTask(whenDone); | ||||
|                             }; | ||||
|                             if (originPlot != null) { | ||||
|                                 originPlot.clear(false, true, clearDone); | ||||
|                             } else { | ||||
|                                 clearDone.run(); | ||||
|                             } | ||||
|                             return; | ||||
|                         } | ||||
|                         final Runnable task = this; | ||||
|                         CuboidRegion region = regions.poll(); | ||||
|                         Location[] corners = MainUtil.getCorners(getWorldName(), region); | ||||
|                         final Location pos1 = corners[0]; | ||||
|                         final Location pos2 = corners[1]; | ||||
|                         Location newPos = pos1.clone().add(offsetX, 0, offsetZ); | ||||
|                         newPos.setWorld(destination.getWorldName()); | ||||
|                         ChunkManager.manager.copyRegion(pos1, pos2, newPos, task); | ||||
|                     } | ||||
|                 }.run(); | ||||
|             } | ||||
|             return true; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotArea; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.StringMan; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.area.QuadMap; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| @@ -61,7 +62,7 @@ public class DefaultPlotAreaManager implements PlotAreaManager { | ||||
|                 if (areas == null) { | ||||
|                     return null; | ||||
|                 } | ||||
|                 int y; | ||||
|                 int z; | ||||
|                 int x; | ||||
|                 switch (areas.length) { | ||||
|                     case 1: | ||||
| @@ -74,9 +75,9 @@ public class DefaultPlotAreaManager implements PlotAreaManager { | ||||
|                     case 7: | ||||
|                     case 8: | ||||
|                         x = location.getX(); | ||||
|                         y = location.getY(); | ||||
|                         z = location.getZ(); | ||||
|                         for (PlotArea area : areas) { | ||||
|                             if (area.contains(x, y)) { | ||||
|                             if (area.contains(x, z)) { | ||||
|                                 return area; | ||||
|                             } | ||||
|                         } | ||||
| @@ -139,7 +140,7 @@ public class DefaultPlotAreaManager implements PlotAreaManager { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override public PlotArea getPlotArea(Location location) { | ||||
|     @Override public PlotArea getPlotArea(@NotNull Location location) { | ||||
|         switch (this.plotAreas.length) { | ||||
|             case 0: | ||||
|                 return null; | ||||
| @@ -174,7 +175,7 @@ public class DefaultPlotAreaManager implements PlotAreaManager { | ||||
|                     return null; | ||||
|                 } | ||||
|                 int x; | ||||
|                 int y; | ||||
|                 int z; | ||||
|                 switch (areas.length) { | ||||
|                     case 0: | ||||
|                         PlotArea a = areas[0]; | ||||
| @@ -187,9 +188,9 @@ public class DefaultPlotAreaManager implements PlotAreaManager { | ||||
|                     case 7: | ||||
|                     case 8: | ||||
|                         x = location.getX(); | ||||
|                         y = location.getY(); | ||||
|                         z = location.getZ(); | ||||
|                         for (PlotArea area : areas) { | ||||
|                             if (area.contains(x, y)) { | ||||
|                             if (area.contains(x, z)) { | ||||
|                                 return area; | ||||
|                             } | ||||
|                         } | ||||
|   | ||||
| @@ -3,11 +3,33 @@ package com.github.intellectualsites.plotsquared.plot.object.worlds; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.Location; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotArea; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public interface PlotAreaManager { | ||||
|  | ||||
|     /** | ||||
|      * Get the plot area for a particular location. This | ||||
|      * method assumes that the caller already knows that | ||||
|      * the location belongs to a plot area, in which | ||||
|      * case it will return the appropriate plot area. | ||||
|      * | ||||
|      * If the location does not belong to a plot area, | ||||
|      * it may still return an area. | ||||
|      * | ||||
|      * @param location The location | ||||
|      * @return An applicable area, or null | ||||
|      */ | ||||
|     PlotArea getApplicablePlotArea(Location location); | ||||
|  | ||||
|     PlotArea getPlotArea(Location location); | ||||
|     /** | ||||
|      * Get the plot area, if there is any, for the given | ||||
|      * location. This may return null, if given location | ||||
|      * does not belong to a plot area. | ||||
|      * | ||||
|      * @param location The location | ||||
|      * @return The area, if found | ||||
|      */ | ||||
|     PlotArea getPlotArea(@NotNull Location location); | ||||
|  | ||||
|     PlotArea getPlotArea(String world, String id); | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import com.github.intellectualsites.plotsquared.plot.object.PlotArea; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.ArrayUtil; | ||||
| import com.github.intellectualsites.plotsquared.plot.util.SetupUtils; | ||||
| import com.sk89q.worldedit.regions.CuboidRegion; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public class SinglePlotAreaManager extends DefaultPlotAreaManager { | ||||
|     private final SinglePlotArea[] array; | ||||
| @@ -82,7 +83,7 @@ public class SinglePlotAreaManager extends DefaultPlotAreaManager { | ||||
|         return isWorld(world) || world.equals("*") ? area : super.getPlotArea(world, id); | ||||
|     } | ||||
|  | ||||
|     @Override public PlotArea getPlotArea(Location location) { | ||||
|     @Override public PlotArea getPlotArea(@NotNull Location location) { | ||||
|         PlotArea found = super.getPlotArea(location); | ||||
|         if (found != null) { | ||||
|             return found; | ||||
|   | ||||
| @@ -52,7 +52,9 @@ public abstract class ChunkManager { | ||||
|             } | ||||
|             queue.flush(); | ||||
|         } else { | ||||
|             forceChunks.put(loc, force); | ||||
|             if (force != null) { | ||||
|                 forceChunks.put(loc, force); | ||||
|             } | ||||
|             addChunks.put(loc, add); | ||||
|             queue.regenChunk(loc.getX(), loc.getZ()); | ||||
|             forceChunks.remove(loc); | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package com.github.intellectualsites.plotsquared.plot.util.world; | ||||
| import com.github.intellectualsites.plotsquared.commands.Command; | ||||
| import com.github.intellectualsites.plotsquared.plot.config.Captions; | ||||
| import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; | ||||
| import com.google.common.base.Preconditions; | ||||
| import com.sk89q.worldedit.WorldEdit; | ||||
| import com.sk89q.worldedit.entity.Player; | ||||
| import com.sk89q.worldedit.extension.input.InputParseException; | ||||
| @@ -18,7 +19,9 @@ import com.sk89q.worldedit.world.block.BlockType; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| public class PatternUtil { | ||||
|  | ||||
|     public static BaseBlock apply(@NotNull Pattern pattern, int x, int y, int z) { | ||||
|         Preconditions.checkNotNull(pattern, "Pattern may not be null"); | ||||
|         if (pattern instanceof BlockPattern | ||||
|             || pattern instanceof RandomPattern | ||||
|             || pattern instanceof BlockState | ||||
|   | ||||
| @@ -14,6 +14,7 @@ import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
|  | ||||
| public class AbstractDBTest implements AbstractDB { | ||||
|  | ||||
| @@ -91,7 +92,8 @@ public class AbstractDBTest implements AbstractDB { | ||||
|     @Override public void setMerged(Plot plot, boolean[] merged) { | ||||
|     } | ||||
|  | ||||
|     @Override public void swapPlots(Plot plot1, Plot plot2) { | ||||
|     @Override public CompletableFuture<Boolean> swapPlots(Plot plot1, Plot plot2) { | ||||
|         return CompletableFuture.completedFuture(true); | ||||
|     } | ||||
|  | ||||
|     @Override public void setFlag(Plot plot, PlotFlag<?, ?> flag) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user