mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-29 08:33:43 +01:00 
			
		
		
		
	Compare commits
	
		
			38 Commits
		
	
	
		
			feat/chore
			...
			fix/4595
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 519b8453be | ||
|   | aa44078018 | ||
|   | bfbf406418 | ||
|   | 2accedf264 | ||
|   | 6ef0d58480 | ||
|   | fbf4a638b4 | ||
|   | 9abfa21078 | ||
|   | b84599b4b3 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 058983cdd5 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 6ba3694121 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 8e8e31b80e | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | da2e66c1f8 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | d5d6fcb859 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 96f73331f9 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 020947d90c | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 7dbd0bcff8 | ||
|   | 9626302f04 | ||
|   | 1b4a347e8b | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 19e6ed4b9b | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 6b1b0f2d6a | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | e499bc02ec | ||
|   | 62084fffdd | ||
|   | d012f79349 | ||
|   | 139d6efc70 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 6f5cb917f2 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 9bf66f1b7c | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 92875ebe7f | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 25a4545f14 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 3fdeed019b | ||
|   | f3400df811 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | beb7cb40f4 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 2c0bb03e5c | ||
|   | e8c170686c | ||
|   | ff8676cde3 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 817effb735 | ||
|   | a0a3d8828a | ||
|   | 8741bfcf88 | ||
|   | 6a6c113e5b | 
							
								
								
									
										12
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -29,18 +29,18 @@ jobs: | |||||||
|           fi |           fi | ||||||
|       - name: Publish Release |       - name: Publish Release | ||||||
|         if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} |         if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} | ||||||
|         run: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository |         run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache | ||||||
|         env: |         env: | ||||||
|           ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} |           ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.CENTRAL_USERNAME }} | ||||||
|           ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} |           ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.CENTRAL_PASSWORD }} | ||||||
|           ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} |           ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }} | ||||||
|           ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} |           ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }} | ||||||
|       - name: Publish Snapshot |       - name: Publish Snapshot | ||||||
|         if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main' }} |         if: ${{ runner.os == 'Linux' && env.STATUS != 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main' }} | ||||||
|         run: ./gradlew publishToSonatype |         run: ./gradlew publishAllPublicationsToMavenCentralRepository | ||||||
|         env: |         env: | ||||||
|           ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }} |           ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.CENTRAL_USERNAME }} | ||||||
|           ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }} |           ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.CENTRAL_PASSWORD }} | ||||||
|       - name: Publish core javadoc |       - name: Publish core javadoc | ||||||
|         if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} |         if: ${{ runner.os == 'Linux' && env.STATUS == 'release' && github.event_name == 'push' && github.ref == 'refs/heads/main'}} | ||||||
|         uses: cpina/github-action-push-to-another-repository@main |         uses: cpina/github-action-push-to-another-repository@main | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar | |||||||
| repositories { | repositories { | ||||||
|     maven { |     maven { | ||||||
|         name = "PlaceholderAPI" |         name = "PlaceholderAPI" | ||||||
|         url = uri("https://repo.extendedclip.com/content/repositories/placeholderapi/") |         url = uri("https://repo.extendedclip.com/releases/") | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     maven { |     maven { | ||||||
|   | |||||||
| @@ -252,6 +252,11 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | |||||||
|         return Bukkit.getVersion(); |         return Bukkit.getVersion(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public @NonNull String serverBrand() { | ||||||
|  |         return Bukkit.getName(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @SuppressWarnings("deprecation") // Paper deprecation |     @SuppressWarnings("deprecation") // Paper deprecation | ||||||
|     public void onEnable() { |     public void onEnable() { | ||||||
|   | |||||||
| @@ -28,7 +28,6 @@ import com.plotsquared.core.plot.flag.implementations.CopperOxideFlag; | |||||||
| import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag; | import com.plotsquared.core.plot.flag.implementations.MiscInteractFlag; | ||||||
| import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag; | import com.plotsquared.core.plot.flag.implementations.SculkSensorInteractFlag; | ||||||
| import com.plotsquared.core.util.PlotFlagUtil; | import com.plotsquared.core.util.PlotFlagUtil; | ||||||
| import org.bukkit.Material; |  | ||||||
| import org.bukkit.block.Block; | import org.bukkit.block.Block; | ||||||
| import org.bukkit.entity.Entity; | import org.bukkit.entity.Entity; | ||||||
| import org.bukkit.entity.Item; | import org.bukkit.entity.Item; | ||||||
| @@ -42,31 +41,11 @@ import org.bukkit.event.block.BlockReceiveGameEvent; | |||||||
|  |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Objects; | import java.util.Objects; | ||||||
| import java.util.Set; |  | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
| @SuppressWarnings("unused") | @SuppressWarnings("unused") | ||||||
| public class BlockEventListener117 implements Listener { | public class BlockEventListener117 implements Listener { | ||||||
|  |  | ||||||
|     private static final Set<Material> COPPER_OXIDIZING = Set.of( |  | ||||||
|             Material.COPPER_BLOCK, |  | ||||||
|             Material.EXPOSED_COPPER, |  | ||||||
|             Material.WEATHERED_COPPER, |  | ||||||
|             Material.OXIDIZED_COPPER, |  | ||||||
|             Material.CUT_COPPER, |  | ||||||
|             Material.EXPOSED_CUT_COPPER, |  | ||||||
|             Material.WEATHERED_CUT_COPPER, |  | ||||||
|             Material.OXIDIZED_CUT_COPPER, |  | ||||||
|             Material.CUT_COPPER_STAIRS, |  | ||||||
|             Material.EXPOSED_CUT_COPPER_STAIRS, |  | ||||||
|             Material.WEATHERED_CUT_COPPER_STAIRS, |  | ||||||
|             Material.OXIDIZED_CUT_COPPER_STAIRS, |  | ||||||
|             Material.CUT_COPPER_SLAB, |  | ||||||
|             Material.EXPOSED_CUT_COPPER_SLAB, |  | ||||||
|             Material.WEATHERED_CUT_COPPER_SLAB, |  | ||||||
|             Material.OXIDIZED_CUT_COPPER_SLAB |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     @Inject |     @Inject | ||||||
|     public BlockEventListener117() { |     public BlockEventListener117() { | ||||||
|     } |     } | ||||||
| @@ -134,7 +113,7 @@ public class BlockEventListener117 implements Listener { | |||||||
|     public void onBlockFertilize(BlockFertilizeEvent event) { |     public void onBlockFertilize(BlockFertilizeEvent event) { | ||||||
|         Block block = event.getBlock(); |         Block block = event.getBlock(); | ||||||
|         List<org.bukkit.block.BlockState> blocks = event.getBlocks(); |         List<org.bukkit.block.BlockState> blocks = event.getBlocks(); | ||||||
|         Location location = BukkitUtil.adapt(blocks.get(0).getLocation()); |         Location location = BukkitUtil.adapt(block.getLocation()); | ||||||
|  |  | ||||||
|         PlotArea area = location.getPlotArea(); |         PlotArea area = location.getPlotArea(); | ||||||
|         if (area == null) { |         if (area == null) { | ||||||
| @@ -184,7 +163,7 @@ public class BlockEventListener117 implements Listener { | |||||||
|         if (plot == null) { |         if (plot == null) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         if (COPPER_OXIDIZING.contains(event.getNewState().getType())) { |         if (event.getNewState().getType().name().contains("COPPER")) { | ||||||
|             if (!plot.getFlag(CopperOxideFlag.class)) { |             if (!plot.getFlag(CopperOxideFlag.class)) { | ||||||
|                 plot.debug("Copper could not oxide because copper-oxide = false"); |                 plot.debug("Copper could not oxide because copper-oxide = false"); | ||||||
|                 event.setCancelled(true); |                 event.setCancelled(true); | ||||||
|   | |||||||
| @@ -88,10 +88,8 @@ import org.bukkit.Bukkit; | |||||||
| import org.bukkit.FluidCollisionMode; | import org.bukkit.FluidCollisionMode; | ||||||
| import org.bukkit.Material; | import org.bukkit.Material; | ||||||
| import org.bukkit.block.Block; | import org.bukkit.block.Block; | ||||||
| import org.bukkit.block.BlockFace; |  | ||||||
| import org.bukkit.block.BlockState; | import org.bukkit.block.BlockState; | ||||||
| import org.bukkit.block.Sign; | import org.bukkit.block.Sign; | ||||||
| import org.bukkit.block.data.Waterlogged; |  | ||||||
| import org.bukkit.command.PluginCommand; | import org.bukkit.command.PluginCommand; | ||||||
| import org.bukkit.entity.ArmorStand; | import org.bukkit.entity.ArmorStand; | ||||||
| import org.bukkit.entity.Boat; | import org.bukkit.entity.Boat; | ||||||
| @@ -593,14 +591,18 @@ public class PlayerEventListener implements Listener { | |||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|                 Plot plot = area.getPlot(location); |                 Plot plot = area.getPlot(location); | ||||||
|                 if (plot != null) { |                 if (plot != null && !plot.equals(lastPlot)) { | ||||||
|                     final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot); |                     final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot); | ||||||
|                     // there is one possibility to still allow teleportation: |                     // there is one possibility to still allow teleportation: | ||||||
|                     // to is identical to the plot's home location, and untrusted-visit is true |                     // to is identical to the plot's home location, and untrusted-visit is true | ||||||
|                     // i.e. untrusted-visit can override deny-teleport |                     // i.e. untrusted-visit can override deny-teleport | ||||||
|                     // this is acceptable, because otherwise it wouldn't make sense to have both flags set |                     // this is acceptable, because otherwise it wouldn't make sense to have both flags set | ||||||
|                     if (result || (plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous().equals(BukkitUtil.adaptComplete(to)))) { |                     if (result || (plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous().equals(BukkitUtil.adaptComplete(to)))) { | ||||||
|                         plotListener.plotEntry(pp, plot); |                         // returns false if the player is not allowed to enter the plot (if they are denied, for example) | ||||||
|  |                         // don't let the move event cancel the entry after teleport, but rather catch and cancel early (#4647) | ||||||
|  |                         if (!plotListener.plotEntry(pp, plot)) { | ||||||
|  |                             event.setCancelled(true); | ||||||
|  |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         pp.sendMessage( |                         pp.sendMessage( | ||||||
|                                 TranslatableCaption.of("deny.no_enter"), |                                 TranslatableCaption.of("deny.no_enter"), | ||||||
| @@ -1370,22 +1372,7 @@ public class PlayerEventListener implements Listener { | |||||||
|  |  | ||||||
|     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) |     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) | ||||||
|     public void onBucketEmpty(PlayerBucketEmptyEvent event) { |     public void onBucketEmpty(PlayerBucketEmptyEvent event) { | ||||||
|         BlockFace bf = event.getBlockFace(); |         final Block block = event.getBlock(); | ||||||
|         // Note: a month after Bukkit 1.14.4 released, they added the API method |  | ||||||
|         // PlayerBucketEmptyEvent#getBlock(), which returns the block the |  | ||||||
|         // bucket contents is going to be placed at. Currently we determine this |  | ||||||
|         // block ourselves to retain compatibility with 1.13. |  | ||||||
|         final Block block; |  | ||||||
|         // if the block can be waterlogged, the event might waterlog the block |  | ||||||
|         // sometimes |  | ||||||
|         if (event.getBlockClicked().getBlockData() instanceof Waterlogged waterlogged |  | ||||||
|                 && !waterlogged.isWaterlogged() && event.getBucket() != Material.LAVA_BUCKET) { |  | ||||||
|             block = event.getBlockClicked(); |  | ||||||
|         } else { |  | ||||||
|             block = event.getBlockClicked().getLocation() |  | ||||||
|                     .add(bf.getModX(), bf.getModY(), bf.getModZ()) |  | ||||||
|                     .getBlock(); |  | ||||||
|         } |  | ||||||
|         Location location = BukkitUtil.adapt(block.getLocation()); |         Location location = BukkitUtil.adapt(block.getLocation()); | ||||||
|         PlotArea area = location.getPlotArea(); |         PlotArea area = location.getPlotArea(); | ||||||
|         if (area == null) { |         if (area == null) { | ||||||
|   | |||||||
| @@ -44,6 +44,7 @@ import java.util.List; | |||||||
| import java.util.Queue; | import java.util.Queue; | ||||||
| import java.util.concurrent.LinkedBlockingQueue; | import java.util.concurrent.LinkedBlockingQueue; | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  | import java.util.concurrent.TimeoutException; | ||||||
| import java.util.concurrent.atomic.AtomicInteger; | import java.util.concurrent.atomic.AtomicInteger; | ||||||
| import java.util.function.Consumer; | import java.util.function.Consumer; | ||||||
|  |  | ||||||
| @@ -226,16 +227,22 @@ public final class BukkitChunkCoordinator extends ChunkCoordinator { | |||||||
|             loadingChunks.incrementAndGet(); |             loadingChunks.incrementAndGet(); | ||||||
|             PaperLib |             PaperLib | ||||||
|                     .getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), shouldGen, true) |                     .getChunkAtAsync(this.bukkitWorld, chunk.getX(), chunk.getZ(), shouldGen, true) | ||||||
|                     .completeOnTimeout(null, 10L, TimeUnit.SECONDS) |                     .orTimeout(10L, TimeUnit.SECONDS) | ||||||
|                     .whenComplete((chunkObject, throwable) -> { |                     .whenComplete((chunkObject, throwable) -> { | ||||||
|                         loadingChunks.decrementAndGet(); |                         loadingChunks.decrementAndGet(); | ||||||
|                         if (throwable != null) { |                         if (throwable != null) { | ||||||
|  |                             if (throwable instanceof TimeoutException) { | ||||||
|  |                                 LOGGER.warn("Timed out awaiting chunk load {}", chunk); | ||||||
|  |                                 this.requestedChunks.offer(chunk); | ||||||
|  |                             } else { | ||||||
|                                 LOGGER.error("Failed to load chunk {}", chunk, throwable); |                                 LOGGER.error("Failed to load chunk {}", chunk, throwable); | ||||||
|                                 // We want one less because this couldn't be processed |                                 // We want one less because this couldn't be processed | ||||||
|                                 this.expectedSize.decrementAndGet(); |                                 this.expectedSize.decrementAndGet(); | ||||||
|  |                             } | ||||||
|                         } else if (chunkObject == null) { |                         } else if (chunkObject == null) { | ||||||
|                             LOGGER.warn("Timed out awaiting chunk load {}", chunk); |                             if (shouldGen) { | ||||||
|                             this.requestedChunks.offer(chunk); |                                 LOGGER.error("Null chunk returned for chunk at {}", chunk); | ||||||
|  |                             } | ||||||
|                         } else if (PlotSquared.get().isMainThread(Thread.currentThread())) { |                         } else if (PlotSquared.get().isMainThread(Thread.currentThread())) { | ||||||
|                             this.processChunk(chunkObject); |                             this.processChunk(chunkObject); | ||||||
|                         } else { |                         } else { | ||||||
|   | |||||||
| @@ -120,6 +120,14 @@ public interface PlotPlatform<P> extends LocaleHolder { | |||||||
|      */ |      */ | ||||||
|     @NonNull String serverImplementation(); |     @NonNull String serverImplementation(); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Gets the server brand name | ||||||
|  |      * | ||||||
|  |      * @return server brand | ||||||
|  |      * @since 7.5.3 | ||||||
|  |      */ | ||||||
|  |     @NonNull String serverBrand(); | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Gets the native server code package prefix. |      * Gets the native server code package prefix. | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -713,6 +713,8 @@ public class PlotSquared { | |||||||
|                 case CREATION_DATE_TIMESTAMP -> toReturn.addAll(sortPlotsByTimestamp(map.get(area))); |                 case CREATION_DATE_TIMESTAMP -> toReturn.addAll(sortPlotsByTimestamp(map.get(area))); | ||||||
|                 case DISTANCE_FROM_ORIGIN -> toReturn.addAll(sortPlotsByHash(map.get(area))); |                 case DISTANCE_FROM_ORIGIN -> toReturn.addAll(sortPlotsByHash(map.get(area))); | ||||||
|                 case LAST_MODIFIED -> toReturn.addAll(sortPlotsByModified(map.get(area))); |                 case LAST_MODIFIED -> toReturn.addAll(sortPlotsByModified(map.get(area))); | ||||||
|  |                 default -> { | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return toReturn; |         return toReturn; | ||||||
|   | |||||||
| @@ -144,6 +144,7 @@ public class Buy extends Command { | |||||||
|             plot.getPlotModificationManager().setSign(player.getName()); |             plot.getPlotModificationManager().setSign(player.getName()); | ||||||
|             player.sendMessage( |             player.sendMessage( | ||||||
|                     TranslatableCaption.of("working.claimed"), |                     TranslatableCaption.of("working.claimed"), | ||||||
|  |                     TagResolver.resolver("world", Tag.inserting(Component.text(plot.getArea().getWorldName()))), | ||||||
|                     TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) |                     TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) | ||||||
|             ); |             ); | ||||||
|             this.eventDispatcher.callPostPlayerBuyPlot(player, previousOwner, plot, price); |             this.eventDispatcher.callPostPlayerBuyPlot(player, previousOwner, plot, price); | ||||||
|   | |||||||
| @@ -131,6 +131,7 @@ public class Clear extends Command { | |||||||
|                     player.sendMessage( |                     player.sendMessage( | ||||||
|                             TranslatableCaption.of("working.clearing_done"), |                             TranslatableCaption.of("working.clearing_done"), | ||||||
|                             TagResolver.builder() |                             TagResolver.builder() | ||||||
|  |                                     .tag("world", Tag.inserting(Component.text(plot.getArea().getWorldName()))) | ||||||
|                                     .tag("amount", Tag.inserting(Component.text(System.currentTimeMillis() - start))) |                                     .tag("amount", Tag.inserting(Component.text(System.currentTimeMillis() - start))) | ||||||
|                                     .tag("plot", Tag.inserting(Component.text(plot.getId().toString()))) |                                     .tag("plot", Tag.inserting(Component.text(plot.getId().toString()))) | ||||||
|                                     .build() |                                     .build() | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ import com.plotsquared.core.configuration.caption.TranslatableCaption; | |||||||
| import com.plotsquared.core.player.PlotPlayer; | import com.plotsquared.core.player.PlotPlayer; | ||||||
| import net.kyori.adventure.text.Component; | import net.kyori.adventure.text.Component; | ||||||
| import net.kyori.adventure.text.minimessage.MiniMessage; | import net.kyori.adventure.text.minimessage.MiniMessage; | ||||||
|  | import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
| @@ -98,6 +99,14 @@ public enum CommandCategory implements Caption { | |||||||
|         return MiniMessage.miniMessage().deserialize(getComponent(localeHolder)); |         return MiniMessage.miniMessage().deserialize(getComponent(localeHolder)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public @NonNull Component toComponent( | ||||||
|  |             @NonNull final LocaleHolder localeHolder, | ||||||
|  |             final @NonNull TagResolver @NonNull ... tagResolvers | ||||||
|  |     ) { | ||||||
|  |         return MiniMessage.miniMessage().deserialize(getComponent(localeHolder)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Checks if a player has access to this command category |      * Checks if a player has access to this command category | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -86,7 +86,8 @@ public class DebugPaste extends SubCommand { | |||||||
|                 b.append("# WorldEdit implementation:\n"); |                 b.append("# WorldEdit implementation:\n"); | ||||||
|                 b.append(PlotSquared.platform().worldEditImplementations()).append("\n\n"); |                 b.append(PlotSquared.platform().worldEditImplementations()).append("\n\n"); | ||||||
|                 b.append("# Server Information\n"); |                 b.append("# Server Information\n"); | ||||||
|                 b.append("Server Version: ").append(PlotSquared.platform().serverImplementation()) |                 b.append("Server Version: ").append(PlotSquared.platform().serverBrand()).append(": ") | ||||||
|  |                         .append(PlotSquared.platform().serverImplementation()).append("\n") | ||||||
|                         .append("\n"); |                         .append("\n"); | ||||||
|                 b.append("online_mode: ").append(!Settings.UUID.OFFLINE).append(';') |                 b.append("online_mode: ").append(!Settings.UUID.OFFLINE).append(';') | ||||||
|                         .append(!Settings.UUID.OFFLINE).append('\n'); |                         .append(!Settings.UUID.OFFLINE).append('\n'); | ||||||
|   | |||||||
| @@ -124,6 +124,7 @@ public class Delete extends SubCommand { | |||||||
|                                 "amount", |                                 "amount", | ||||||
|                                 Tag.inserting(Component.text(String.valueOf(System.currentTimeMillis() - start))) |                                 Tag.inserting(Component.text(String.valueOf(System.currentTimeMillis() - start))) | ||||||
|                         ), |                         ), | ||||||
|  |                         TagResolver.resolver("world", Tag.inserting(Component.text(plotArea.getWorldName()))), | ||||||
|                         TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) |                         TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) | ||||||
|                 ); |                 ); | ||||||
|                 eventDispatcher.callPostDelete(plot); |                 eventDispatcher.callPostDelete(plot); | ||||||
|   | |||||||
| @@ -113,38 +113,34 @@ public class Help extends Command { | |||||||
|             } |             } | ||||||
|             if (cat == null && page == 0) { |             if (cat == null && page == 0) { | ||||||
|                 TextComponent.Builder builder = Component.text(); |                 TextComponent.Builder builder = Component.text(); | ||||||
|                 builder.append(MINI_MESSAGE.deserialize(TranslatableCaption.of("help.help_header").getComponent(player))); |                 builder.append(TranslatableCaption.of("help.help_header").toComponent(player)); | ||||||
|                 for (CommandCategory c : CommandCategory.values()) { |                 for (CommandCategory c : CommandCategory.values()) { | ||||||
|                     if (!c.canAccess(player)) { |                     if (!c.canAccess(player)) { | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|                     builder.append(Component.newline()).append(MINI_MESSAGE |                     builder.append(Component.newline()); | ||||||
|                             .deserialize( |                     builder.append(TranslatableCaption.of("help.help_info_item").toComponent( | ||||||
|                                     TranslatableCaption.of("help.help_info_item").getComponent(player), |                             player, TagResolver.builder() | ||||||
|                                     TagResolver.builder() |  | ||||||
|                                     .tag("command", Tag.inserting(Component.text("/plot help"))) |                                     .tag("command", Tag.inserting(Component.text("/plot help"))) | ||||||
|                                     .tag("category", Tag.inserting(Component.text(c.name().toLowerCase()))) |                                     .tag("category", Tag.inserting(Component.text(c.name().toLowerCase()))) | ||||||
|                                     .tag("category_desc", Tag.inserting(c.toComponent(player))) |                                     .tag("category_desc", Tag.inserting(c.toComponent(player))) | ||||||
|                                     .build() |                                     .build() | ||||||
|                     )); |                     )); | ||||||
|                 } |                 } | ||||||
|                 builder.append(Component.newline()).append(MINI_MESSAGE |                 builder.append(Component.newline()); | ||||||
|                         .deserialize( |                 builder.append(TranslatableCaption.of("help.help_info_item").toComponent( | ||||||
|                                 TranslatableCaption.of("help.help_info_item").getComponent(player), |                         player, TagResolver.builder() | ||||||
|                                 TagResolver.builder() |  | ||||||
|                                 .tag("command", Tag.inserting(Component.text("/plot help"))) |                                 .tag("command", Tag.inserting(Component.text("/plot help"))) | ||||||
|                                 .tag("category", Tag.inserting(Component.text("all"))) |                                 .tag("category", Tag.inserting(Component.text("all"))) | ||||||
|                                 .tag( |                                 .tag( | ||||||
|                                                 "category_desc", |                                         "category_desc", Tag.inserting(TranslatableCaption | ||||||
|                                                 Tag.inserting(TranslatableCaption |  | ||||||
|                                                 .of("help.help_display_all_commands") |                                                 .of("help.help_display_all_commands") | ||||||
|                                                 .toComponent(player)) |                                                 .toComponent(player)) | ||||||
|                                 ) |                                 ) | ||||||
|                                 .build() |                                 .build() | ||||||
|                 )); |                 )); | ||||||
|                 builder.append(Component.newline()).append(MINI_MESSAGE.deserialize(TranslatableCaption |                 builder.append(Component.newline()); | ||||||
|                         .of("help.help_footer") |                 builder.append(TranslatableCaption.of("help.help_footer").toComponent(player)); | ||||||
|                         .getComponent(player))); |  | ||||||
|                 player.sendMessage(StaticCaption.of(MINI_MESSAGE.serialize(builder.asComponent()))); |                 player.sendMessage(StaticCaption.of(MINI_MESSAGE.serialize(builder.asComponent()))); | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -44,8 +44,13 @@ import org.apache.logging.log4j.Logger; | |||||||
| import java.util.Arrays; | import java.util.Arrays; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Objects; | ||||||
|  | import java.util.Optional; | ||||||
| import java.util.concurrent.CompletableFuture; | import java.util.concurrent.CompletableFuture; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  | import javax.annotation.Nullable; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * PlotSquared command class. |  * PlotSquared command class. | ||||||
|  */ |  */ | ||||||
| @@ -147,8 +152,7 @@ public class MainCommand extends Command { | |||||||
|                 try { |                 try { | ||||||
|                     injector.getInstance(command); |                     injector.getInstance(command); | ||||||
|                 } catch (final Exception e) { |                 } catch (final Exception e) { | ||||||
|                     LOGGER.error("Failed to register command {}", command.getCanonicalName()); |                     LOGGER.error("Failed to register command {}", command.getCanonicalName(), e); | ||||||
|                     e.printStackTrace(); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -236,110 +240,170 @@ public class MainCommand extends Command { | |||||||
|             RunnableVal3<Command, Runnable, Runnable> confirm, |             RunnableVal3<Command, Runnable, Runnable> confirm, | ||||||
|             RunnableVal2<Command, CommandResult> whenDone |             RunnableVal2<Command, CommandResult> whenDone | ||||||
|     ) { |     ) { | ||||||
|         // Optional command scope // |         prepareArguments(new CommandExecutionData(player, args, confirm, whenDone, null)) | ||||||
|         Location location = null; |                 .thenCompose(executionData -> { | ||||||
|         Plot plot = null; |                     if (executionData.isEmpty()) { | ||||||
|         boolean tp = false; |  | ||||||
|         if (args.length >= 2) { |  | ||||||
|             PlotArea area = player.getApplicablePlotArea(); |  | ||||||
|             Plot newPlot = Plot.fromString(area, args[0]); |  | ||||||
|             if (newPlot != null && (player instanceof ConsolePlayer || newPlot.getArea() |  | ||||||
|                     .equals(area) || player.hasPermission(Permission.PERMISSION_ADMIN) |  | ||||||
|                     || player.hasPermission(Permission.PERMISSION_ADMIN_AREA_SUDO)) |  | ||||||
|                     && !newPlot.isDenied(player.getUUID())) { |  | ||||||
|                 final Location newLoc; |  | ||||||
|                 if (newPlot.getArea() instanceof SinglePlotArea) { |  | ||||||
|                     newLoc = newPlot.isLoaded() ? newPlot.getCenterSynchronous() : Location.at("", 0, 0, 0); |  | ||||||
|                 } else { |  | ||||||
|                     newLoc = newPlot.getCenterSynchronous(); |  | ||||||
|                 } |  | ||||||
|                 if (player.canTeleport(newLoc)) { |  | ||||||
|                     // Save meta |  | ||||||
|                     try (final MetaDataAccess<Location> locationMetaDataAccess |  | ||||||
|                                  = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { |  | ||||||
|                         location = locationMetaDataAccess.get().orElse(null); |  | ||||||
|                         locationMetaDataAccess.set(newLoc); |  | ||||||
|                     } |  | ||||||
|                     try (final MetaDataAccess<Plot> plotMetaDataAccess |  | ||||||
|                                  = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { |  | ||||||
|                         plot = plotMetaDataAccess.get().orElse(null); |  | ||||||
|                         plotMetaDataAccess.set(newPlot); |  | ||||||
|                     } |  | ||||||
|                     tp = true; |  | ||||||
|                 } else { |  | ||||||
|                     player.sendMessage(TranslatableCaption.of("border.denied")); |  | ||||||
|                         return CompletableFuture.completedFuture(false); |                         return CompletableFuture.completedFuture(false); | ||||||
|                     } |                     } | ||||||
|                 // Trim command |                     var data = executionData.get(); | ||||||
|                 args = Arrays.copyOfRange(args, 1, args.length); |                     try { | ||||||
|  |                         return super.execute(data.player(), data.args(), data.confirm(), data.whenDone()); | ||||||
|  |                     } catch (CommandException e) { | ||||||
|  |                         throw e; | ||||||
|  |                     } catch (Throwable e) { | ||||||
|  |                         LOGGER.error("A error occurred while executing plot command", e); | ||||||
|  |                         String message = e.getMessage(); | ||||||
|  |                         if (message != null) { | ||||||
|  |                             data.player().sendMessage( | ||||||
|  |                                     TranslatableCaption.of("errors.error"), | ||||||
|  |                                     TagResolver.resolver("value", Tag.inserting(Component.text(message))) | ||||||
|  |                             ); | ||||||
|  |                         } else { | ||||||
|  |                             data.player().sendMessage( | ||||||
|  |                                     TranslatableCaption.of("errors.error_console")); | ||||||
|                         } |                         } | ||||||
|             if (args.length >= 2 && !args[0].isEmpty() && args[0].charAt(0) == '-') { |                     } finally { | ||||||
|                 if ("f".equals(args[0].substring(1))) { |                         if (data.postCommandData() != null) { | ||||||
|                     confirm = new RunnableVal3<>() { |                             resetCommandScope(data.player(), data.postCommandData()); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     return CompletableFuture.completedFuture(true); | ||||||
|  |                 }); | ||||||
|  |         return CompletableFuture.completedFuture(true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private CompletableFuture<Optional<CommandExecutionData>> prepareArguments(CommandExecutionData data) { | ||||||
|  |         if (data.args().length >= 2) { | ||||||
|  |             PlotArea area = data.player().getApplicablePlotArea(); | ||||||
|  |             Plot newPlot = Plot.fromString(area, data.args()[0]); | ||||||
|  |             return preparePlotArgument(newPlot, data, area) | ||||||
|  |                     .thenApply(d -> d.flatMap(x -> prepareFlagArgument(x, area))); | ||||||
|  |         } else { | ||||||
|  |             return CompletableFuture.completedFuture(Optional.of(data)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private CompletableFuture<Optional<CommandExecutionData>> preparePlotArgument(@Nullable Plot newPlot, | ||||||
|  |                                                                         @Nonnull CommandExecutionData data, | ||||||
|  |                                                                                   @Nullable PlotArea area) { | ||||||
|  |         if (newPlot != null && (data.player() instanceof ConsolePlayer | ||||||
|  |                 || (area != null && area.equals(newPlot.getArea())) | ||||||
|  |                 || data.player().hasPermission(Permission.PERMISSION_ADMIN) | ||||||
|  |                 || data.player().hasPermission(Permission.PERMISSION_ADMIN_AREA_SUDO)) | ||||||
|  |                 && !newPlot.isDenied(data.player().getUUID())) { | ||||||
|  |             return fetchPlotCenterLocation(newPlot) | ||||||
|  |                     .thenApply(newLoc -> { | ||||||
|  |                         if (!data.player().canTeleport(newLoc)) { | ||||||
|  |                             data.player().sendMessage(TranslatableCaption.of("border.denied")); | ||||||
|  |                             return Optional.empty(); | ||||||
|  |                         } | ||||||
|  |                         // Save meta | ||||||
|  |                         var originalCommandMeta = setCommandScope(data.player(), new TemporaryCommandMeta(newLoc, newPlot)); | ||||||
|  |                         return Optional.of(new CommandExecutionData( | ||||||
|  |                                 data.player(), | ||||||
|  |                                 Arrays.copyOfRange(data.args(), 1, data.args().length), // Trimmed command | ||||||
|  |                                 data.confirm(), | ||||||
|  |                                 data.whenDone(), | ||||||
|  |                                 originalCommandMeta | ||||||
|  |                         )); | ||||||
|  |                     }); | ||||||
|  |         } | ||||||
|  |         return CompletableFuture.completedFuture(Optional.of(data)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private Optional<CommandExecutionData> prepareFlagArgument(@Nonnull CommandExecutionData data, @Nonnull PlotArea area) { | ||||||
|  |         if (data.args().length >= 2 && !data.args()[0].isEmpty() && data.args()[0].charAt(0) == '-') { | ||||||
|  |             if ("f".equals(data.args()[0].substring(1))) { | ||||||
|  |                 return Optional.of(new CommandExecutionData( | ||||||
|  |                         data.player(), | ||||||
|  |                         Arrays.copyOfRange(data.args(), 1, data.args().length), // Trimmed command | ||||||
|  |                         createForcedConfirmation(data.player(), area), | ||||||
|  |                         data.whenDone(), | ||||||
|  |                         data.postCommandData() | ||||||
|  |                 )); | ||||||
|  |             } else { | ||||||
|  |                 data.player().sendMessage(TranslatableCaption.of("errors.invalid_command_flag")); | ||||||
|  |                 return Optional.empty(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return Optional.of(data); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private CompletableFuture<Location> fetchPlotCenterLocation(Plot plot) { | ||||||
|  |         if (plot.getArea() instanceof SinglePlotArea && !plot.isLoaded()) { | ||||||
|  |             return CompletableFuture.completedFuture(Location.at("", 0, 0, 0)); | ||||||
|  |         } | ||||||
|  |         CompletableFuture<Location> future = new CompletableFuture<>(); | ||||||
|  |         plot.getCenter(future::complete); | ||||||
|  |         return future; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private @Nonnull RunnableVal3<Command, Runnable, Runnable> createForcedConfirmation(@Nonnull PlotPlayer<?> player, | ||||||
|  |                                                                                         @Nullable PlotArea area) { | ||||||
|  |         return new RunnableVal3<>() { | ||||||
|             @Override |             @Override | ||||||
|             public void run(Command cmd, Runnable success, Runnable failure) { |             public void run(Command cmd, Runnable success, Runnable failure) { | ||||||
|                             if (area != null && PlotSquared.platform().econHandler().isEnabled(area)) { |                 if (area != null && PlotSquared.platform().econHandler().isEnabled(area) | ||||||
|                                 PlotExpression priceEval = |                         && Optional.of(area.getPrices().get(cmd.getFullId())) | ||||||
|                                         area.getPrices().get(cmd.getFullId()); |                         .map(priceEval -> priceEval.evaluate(0d)) | ||||||
|                                 double price = priceEval != null ? priceEval.evaluate(0d) : 0d; |                         .filter(price -> price != 0d) | ||||||
|                                 if (price != 0d |                         .filter(price -> PlotSquared.platform().econHandler().getMoney(player) < price) | ||||||
|                                         && PlotSquared.platform().econHandler().getMoney(player) < price) { |                         .isPresent()) { | ||||||
|                     if (failure != null) { |                     if (failure != null) { | ||||||
|                         failure.run(); |                         failure.run(); | ||||||
|                     } |                     } | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|                             } |  | ||||||
|                 if (success != null) { |                 if (success != null) { | ||||||
|                     success.run(); |                     success.run(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|                     args = Arrays.copyOfRange(args, 1, args.length); |  | ||||||
|                 } else { |  | ||||||
|                     player.sendMessage(TranslatableCaption.of("errors.invalid_command_flag")); |  | ||||||
|                     return CompletableFuture.completedFuture(false); |  | ||||||
|     } |     } | ||||||
|             } |  | ||||||
|         } |     private @Nonnull TemporaryCommandMeta setCommandScope(@Nonnull PlotPlayer<?> player, @Nonnull TemporaryCommandMeta commandMeta) { | ||||||
|         try { |         Objects.requireNonNull(commandMeta.location()); | ||||||
|             super.execute(player, args, confirm, whenDone); |         Objects.requireNonNull(commandMeta.plot()); | ||||||
|         } catch (CommandException e) { |         Location location; | ||||||
|             throw e; |         Plot plot; | ||||||
|         } catch (Throwable e) { |  | ||||||
|             e.printStackTrace(); |  | ||||||
|             String message = e.getMessage(); |  | ||||||
|             if (message != null) { |  | ||||||
|                 player.sendMessage( |  | ||||||
|                         TranslatableCaption.of("errors.error"), |  | ||||||
|                         TagResolver.resolver("value", Tag.inserting(Component.text(message))) |  | ||||||
|                 ); |  | ||||||
|             } else { |  | ||||||
|                 player.sendMessage( |  | ||||||
|                         TranslatableCaption.of("errors.error_console")); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         // Reset command scope // |  | ||||||
|         if (tp && !(player instanceof ConsolePlayer)) { |  | ||||||
|         try (final MetaDataAccess<Location> locationMetaDataAccess |         try (final MetaDataAccess<Location> locationMetaDataAccess | ||||||
|                      = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { |                      = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { | ||||||
|                 if (location == null) { |             location = locationMetaDataAccess.get().orElse(null); | ||||||
|  |             locationMetaDataAccess.set(commandMeta.location()); | ||||||
|  |         } | ||||||
|  |         try (final MetaDataAccess<Plot> plotMetaDataAccess | ||||||
|  |                      = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { | ||||||
|  |             plot = plotMetaDataAccess.get().orElse(null); | ||||||
|  |             plotMetaDataAccess.set(commandMeta.plot()); | ||||||
|  |         } | ||||||
|  |         return new TemporaryCommandMeta(location, plot); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private void resetCommandScope(@Nonnull PlotPlayer<?> player, @Nonnull TemporaryCommandMeta commandMeta) { | ||||||
|  |         try (final MetaDataAccess<Location> locationMetaDataAccess | ||||||
|  |                      = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { | ||||||
|  |             if (commandMeta.location() == null) { | ||||||
|                 locationMetaDataAccess.remove(); |                 locationMetaDataAccess.remove(); | ||||||
|             } else { |             } else { | ||||||
|                     locationMetaDataAccess.set(location); |                 locationMetaDataAccess.set(commandMeta.location()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         try (final MetaDataAccess<Plot> plotMetaDataAccess |         try (final MetaDataAccess<Plot> plotMetaDataAccess | ||||||
|                      = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { |                      = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { | ||||||
|                 if (plot == null) { |             if (commandMeta.plot() == null) { | ||||||
|                 plotMetaDataAccess.remove(); |                 plotMetaDataAccess.remove(); | ||||||
|             } else { |             } else { | ||||||
|                     plotMetaDataAccess.set(plot); |                 plotMetaDataAccess.set(commandMeta.plot()); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|         return CompletableFuture.completedFuture(true); |  | ||||||
|     } |     private record CommandExecutionData(@Nonnull PlotPlayer<?> player, @Nonnull String[] args, | ||||||
|  |                     @Nonnull RunnableVal3<Command, Runnable, Runnable> confirm, | ||||||
|  |                     @Nonnull RunnableVal2<Command, CommandResult> whenDone, | ||||||
|  |                     @Nullable TemporaryCommandMeta postCommandData) {} | ||||||
|  |  | ||||||
|  |     private record TemporaryCommandMeta(@Nullable Location location, @Nullable Plot plot) {} | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean canExecute(PlotPlayer<?> player, boolean message) { |     public boolean canExecute(PlotPlayer<?> player, boolean message) { | ||||||
|   | |||||||
| @@ -67,10 +67,13 @@ public class Visit extends Command { | |||||||
|  |  | ||||||
|     private void visit( |     private void visit( | ||||||
|             final @NonNull PlotPlayer<?> player, final @NonNull PlotQuery query, final PlotArea sortByArea, |             final @NonNull PlotPlayer<?> player, final @NonNull PlotQuery query, final PlotArea sortByArea, | ||||||
|             final RunnableVal3<Command, Runnable, Runnable> confirm, final RunnableVal2<Command, CommandResult> whenDone, |             final RunnableVal3<Command, Runnable, Runnable> confirm, final RunnableVal2<Command, CommandResult> whenDone, int page | ||||||
|             int page, final boolean isQueryingBasePlot |  | ||||||
|     ) { |     ) { | ||||||
|         if (!isQueryingBasePlot && query.hasMinimumMatches(2)) { |         // We get the query once, | ||||||
|  |         // then we get it another time further on | ||||||
|  |         final List<Plot> unsorted = query.asList(); | ||||||
|  |  | ||||||
|  |         if (unsorted.size() > 1) { | ||||||
|             query.whereBasePlot(); |             query.whereBasePlot(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -234,8 +237,7 @@ public class Visit extends Command { | |||||||
|                                     finalSortByArea, |                                     finalSortByArea, | ||||||
|                                     confirm, |                                     confirm, | ||||||
|                                     whenDone, |                                     whenDone, | ||||||
|                                     finalPage1, |                                     finalPage1 | ||||||
|                                     true |  | ||||||
|                             ); |                             ); | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
| @@ -259,9 +261,12 @@ public class Visit extends Command { | |||||||
|                         if (throwable instanceof TimeoutException) { |                         if (throwable instanceof TimeoutException) { | ||||||
|                             // The request timed out |                             // The request timed out | ||||||
|                             player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); |                             player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||||
|                             return; |                         } else if (uuid != null && (Settings.Teleport.VISIT_MERGED_OWNERS | ||||||
|                         } |                                 ? !PlotQuery.newQuery().ownersInclude(uuid).anyMatch() | ||||||
|                         if (uuid == null){ |                                 : !PlotQuery.newQuery().ownedBy(uuid).anyMatch())) { | ||||||
|  |                             // It was a valid UUID but the player has no plots | ||||||
|  |                             player.sendMessage(TranslatableCaption.of("errors.player_no_plots")); | ||||||
|  |                         } else if (uuid == null) { | ||||||
|                             // player not found, so we assume it's an alias if no page was provided |                             // player not found, so we assume it's an alias if no page was provided | ||||||
|                             if (finalPage == Integer.MIN_VALUE) { |                             if (finalPage == Integer.MIN_VALUE) { | ||||||
|                                 this.visit( |                                 this.visit( | ||||||
| @@ -270,8 +275,7 @@ public class Visit extends Command { | |||||||
|                                         player.getApplicablePlotArea(), |                                         player.getApplicablePlotArea(), | ||||||
|                                         confirm, |                                         confirm, | ||||||
|                                         whenDone, |                                         whenDone, | ||||||
|                                         1, |                                         1 | ||||||
|                                         false |  | ||||||
|                                 ); |                                 ); | ||||||
|                             } else { |                             } else { | ||||||
|                                 player.sendMessage( |                                 player.sendMessage( | ||||||
| @@ -279,23 +283,24 @@ public class Visit extends Command { | |||||||
|                                         TagResolver.resolver("value", Tag.inserting(Component.text(finalArgs[0]))) |                                         TagResolver.resolver("value", Tag.inserting(Component.text(finalArgs[0]))) | ||||||
|                                 ); |                                 ); | ||||||
|                             } |                             } | ||||||
|                             return; |                         } else { | ||||||
|  |                             this.visit( | ||||||
|  |                                     player, | ||||||
|  |                                     Settings.Teleport.VISIT_MERGED_OWNERS | ||||||
|  |                                             ? PlotQuery.newQuery().ownersInclude(uuid).whereBasePlot() | ||||||
|  |                                             : PlotQuery.newQuery().ownedBy(uuid).whereBasePlot(), | ||||||
|  |                                     null, | ||||||
|  |                                     confirm, | ||||||
|  |                                     whenDone, | ||||||
|  |                                     finalPage | ||||||
|  |                             ); | ||||||
|                         } |                         } | ||||||
|                         final PlotQuery query = Settings.Teleport.VISIT_MERGED_OWNERS |  | ||||||
|                                 ? PlotQuery.newQuery().ownersInclude(uuid) |  | ||||||
|                                 : PlotQuery.newQuery().ownedBy(uuid); |  | ||||||
|                         if (!query.anyMatch()) { |  | ||||||
|                             // It was a valid UUID but the player has no plots |  | ||||||
|                             player.sendMessage(TranslatableCaption.of("errors.player_no_plots")); |  | ||||||
|                             return; |  | ||||||
|                         } |  | ||||||
|                         this.visit(player, query.whereBasePlot(), null, confirm, whenDone, finalPage, true); |  | ||||||
|                     }); |                     }); | ||||||
|                 } else { |                 } else { | ||||||
|                     // Try to parse a plot |                     // Try to parse a plot | ||||||
|                     final Plot plot = Plot.getPlotFromString(player, finalArgs[0], true); |                     final Plot plot = Plot.getPlotFromString(player, finalArgs[0], true); | ||||||
|                     if (plot != null) { |                     if (plot != null) { | ||||||
|                         this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1, false); |                         this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ package com.plotsquared.core.configuration.caption; | |||||||
|  |  | ||||||
| import net.kyori.adventure.text.Component; | import net.kyori.adventure.text.Component; | ||||||
| import net.kyori.adventure.text.ComponentLike; | import net.kyori.adventure.text.ComponentLike; | ||||||
|  | import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -44,6 +45,16 @@ public interface Caption { | |||||||
|      */ |      */ | ||||||
|     @NonNull Component toComponent(@NonNull LocaleHolder localeHolder); |     @NonNull Component toComponent(@NonNull LocaleHolder localeHolder); | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Get the Adventure {@link ComponentLike} for this caption while applying custom {@link TagResolver} | ||||||
|  |      * (apart from the default {@code core.prefix}) | ||||||
|  |      * @param localeHolder Local holder | ||||||
|  |      * @param tagResolvers custom tag resolvers to replace placeholders / parameters | ||||||
|  |      * @return {@link ComponentLike} | ||||||
|  |      * @since TODO | ||||||
|  |      */ | ||||||
|  |     @NonNull Component toComponent(@NonNull LocaleHolder localeHolder, @NonNull TagResolver @NonNull... tagResolvers); | ||||||
|  |  | ||||||
|     @NonNull String toString(); |     @NonNull String toString(); | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ package com.plotsquared.core.configuration.caption; | |||||||
| import com.google.common.base.Preconditions; | import com.google.common.base.Preconditions; | ||||||
| import net.kyori.adventure.text.Component; | import net.kyori.adventure.text.Component; | ||||||
| import net.kyori.adventure.text.minimessage.MiniMessage; | import net.kyori.adventure.text.minimessage.MiniMessage; | ||||||
|  | import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  |  | ||||||
| public final class StaticCaption implements Caption { | public final class StaticCaption implements Caption { | ||||||
| @@ -51,6 +52,14 @@ public final class StaticCaption implements Caption { | |||||||
|         return MiniMessage.miniMessage().deserialize(this.value); |         return MiniMessage.miniMessage().deserialize(this.value); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public @NonNull Component toComponent( | ||||||
|  |             @NonNull final LocaleHolder localeHolder, | ||||||
|  |             final @NonNull TagResolver @NonNull ... tagResolvers | ||||||
|  |     ) { | ||||||
|  |         return MiniMessage.miniMessage().deserialize(this.value, tagResolvers); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public @NonNull String toString() { |     public @NonNull String toString() { | ||||||
|         return "StaticCaption(" + value + ")"; |         return "StaticCaption(" + value + ")"; | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | |||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
|  | import java.util.Arrays; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.regex.Pattern; | import java.util.regex.Pattern; | ||||||
|  |  | ||||||
| @@ -96,13 +97,23 @@ public final class TranslatableCaption implements NamespacedCaption { | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public @NonNull Component toComponent(@NonNull final LocaleHolder localeHolder) { |     public @NonNull Component toComponent(@NonNull final LocaleHolder localeHolder) { | ||||||
|  |         return this.toComponent(localeHolder, new TagResolver[0]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public @NonNull Component toComponent( | ||||||
|  |             @NonNull final LocaleHolder localeHolder, | ||||||
|  |             final @NonNull TagResolver @NonNull ... tagResolvers | ||||||
|  |     ) { | ||||||
|         if (getKey().equals("core.prefix")) { |         if (getKey().equals("core.prefix")) { | ||||||
|             return MiniMessage.miniMessage().deserialize(getComponent(localeHolder)); |             return MiniMessage.miniMessage().deserialize(getComponent(localeHolder)); | ||||||
|         } |         } | ||||||
|         return MiniMessage.miniMessage().deserialize(getComponent(localeHolder), TagResolver.resolver( |         TagResolver[] finalResolvers = Arrays.copyOf(tagResolvers, tagResolvers.length + 1); | ||||||
|  |         finalResolvers[finalResolvers.length - 1] = TagResolver.resolver( | ||||||
|                 "prefix", |                 "prefix", | ||||||
|                 Tag.inserting(TranslatableCaption.of("core.prefix").toComponent(localeHolder)) |                 Tag.inserting(TranslatableCaption.of("core.prefix").toComponent(localeHolder)) | ||||||
|         )); |         ); | ||||||
|  |         return MiniMessage.miniMessage().deserialize(getComponent(localeHolder), finalResolvers); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|   | |||||||
| @@ -444,7 +444,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer, | |||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Get this player's UUID. |      * Get this player's UUID. | ||||||
|      * === !IMPORTANT ===<br> |      * <p>=== !IMPORTANT ===</p> | ||||||
|      * The UUID is dependent on the mode chosen in the settings.yml and may not be the same as Bukkit has |      * The UUID is dependent on the mode chosen in the settings.yml and may not be the same as Bukkit has | ||||||
|      * (especially if using an old version of Bukkit that does not support UUIDs) |      * (especially if using an old version of Bukkit that does not support UUIDs) | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -1717,6 +1717,7 @@ public class Plot { | |||||||
|         } |         } | ||||||
|         player.sendMessage( |         player.sendMessage( | ||||||
|                 TranslatableCaption.of("working.claimed"), |                 TranslatableCaption.of("working.claimed"), | ||||||
|  |                 TagResolver.resolver("world", Tag.inserting(Component.text(this.getWorldName()))), | ||||||
|                 TagResolver.resolver("plot", Tag.inserting(Component.text(this.getId().toString()))) |                 TagResolver.resolver("plot", Tag.inserting(Component.text(this.getId().toString()))) | ||||||
|         ); |         ); | ||||||
|         if (teleport) { |         if (teleport) { | ||||||
|   | |||||||
| @@ -1,50 +0,0 @@ | |||||||
| /* |  | ||||||
|  * PlotSquared, a land and world management plugin for Minecraft. |  | ||||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> |  | ||||||
|  * Copyright (C) IntellectualSites team and contributors |  | ||||||
|  * |  | ||||||
|  * This program is free software: you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
| package com.plotsquared.core.util.comparator; |  | ||||||
|  |  | ||||||
| import com.plotsquared.core.plot.Plot; |  | ||||||
|  |  | ||||||
| import java.util.Comparator; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Sort plots by {@link Plot#temp} (being the auto increment id in database) in natural order for {@code temp > 0}. |  | ||||||
|  * For {@code temp < 1} sort by {@link Plot#hashCode()} |  | ||||||
|  */ |  | ||||||
| public class PlotByCreationDateComparator implements Comparator<Plot> { |  | ||||||
|  |  | ||||||
|     public static final Comparator<Plot> INSTANCE = new PlotByCreationDateComparator(); |  | ||||||
|  |  | ||||||
|     private PlotByCreationDateComparator() { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     @SuppressWarnings("deprecation") // Plot#temp |  | ||||||
|     public int compare(final Plot first, final Plot second) { |  | ||||||
|         if (first.temp > 0 && second.temp > 0) { |  | ||||||
|             return Integer.compare(first.temp, second.temp); |  | ||||||
|         } |  | ||||||
|         // second is implicitly `< 1` (due to previous condition) |  | ||||||
|         if (first.temp > 0) { |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|         // sort dangling plots (temp < 1) by their hashcode |  | ||||||
|         return Integer.compare(first.hashCode(), second.hashCode()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,52 +0,0 @@ | |||||||
| /* |  | ||||||
|  * PlotSquared, a land and world management plugin for Minecraft. |  | ||||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> |  | ||||||
|  * Copyright (C) IntellectualSites team and contributors |  | ||||||
|  * |  | ||||||
|  * This program is free software: you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
| package com.plotsquared.core.util.comparator; |  | ||||||
|  |  | ||||||
| import com.plotsquared.core.plot.Plot; |  | ||||||
| import com.plotsquared.core.plot.flag.implementations.DoneFlag; |  | ||||||
| import com.plotsquared.core.util.MathMan; |  | ||||||
|  |  | ||||||
| import java.util.Comparator; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Sort plots by their {@link DoneFlag} in reverse numeric natural order. (more recent "finished plots" first) |  | ||||||
|  * <br> |  | ||||||
|  * Non-finished plots last, unsorted. |  | ||||||
|  */ |  | ||||||
| public class PlotByDoneComparator implements Comparator<Plot> { |  | ||||||
|  |  | ||||||
|     public static final PlotByDoneComparator INSTANCE = new PlotByDoneComparator(); |  | ||||||
|  |  | ||||||
|     private PlotByDoneComparator() { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int compare(final Plot first, final Plot second) { |  | ||||||
|         String firstDone = first.getFlag(DoneFlag.class); |  | ||||||
|         String lastDone = second.getFlag(DoneFlag.class); |  | ||||||
|         if (MathMan.isInteger(firstDone)) { |  | ||||||
|             if (MathMan.isInteger(lastDone)) { |  | ||||||
|                 return Integer.parseInt(lastDone) - Integer.parseInt(firstDone); |  | ||||||
|             } |  | ||||||
|             return -1; // only "first" is finished, so sort "second" after "first" |  | ||||||
|         } |  | ||||||
|         return 0; // neither is finished |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,61 +0,0 @@ | |||||||
| /* |  | ||||||
|  * PlotSquared, a land and world management plugin for Minecraft. |  | ||||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> |  | ||||||
|  * Copyright (C) IntellectualSites team and contributors |  | ||||||
|  * |  | ||||||
|  * This program is free software: you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
| package com.plotsquared.core.util.comparator; |  | ||||||
|  |  | ||||||
| import com.plotsquared.core.plot.Plot; |  | ||||||
| import com.plotsquared.core.plot.Rating; |  | ||||||
|  |  | ||||||
| import java.util.Comparator; |  | ||||||
| import java.util.Map; |  | ||||||
| import java.util.UUID; |  | ||||||
|  |  | ||||||
| public class PlotByRatingComparator implements Comparator<Plot> { |  | ||||||
|  |  | ||||||
|     public static final PlotByRatingComparator INSTANCE = new PlotByRatingComparator(); |  | ||||||
|  |  | ||||||
|     PlotByRatingComparator() { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int compare(final Plot p1, final Plot p2) { |  | ||||||
|         double v1 = 0; |  | ||||||
|         int p1s = p1.getSettings().getRatings().size(); |  | ||||||
|         int p2s = p2.getRatings().size(); |  | ||||||
|         if (!p1.getSettings().getRatings().isEmpty()) { |  | ||||||
|             v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) |  | ||||||
|                     .map(av -> av * av).sum(); |  | ||||||
|             v1 /= p1s; |  | ||||||
|             v1 += p1s; |  | ||||||
|         } |  | ||||||
|         double v2 = 0; |  | ||||||
|         if (!p2.getSettings().getRatings().isEmpty()) { |  | ||||||
|             for (Map.Entry<UUID, Rating> entry : p2.getRatings().entrySet()) { |  | ||||||
|                 double av = entry.getValue().getAverageRating(); |  | ||||||
|                 v2 += av * av; |  | ||||||
|             } |  | ||||||
|             v2 /= p2s; |  | ||||||
|             v2 += p2s; |  | ||||||
|         } |  | ||||||
|         if (v2 == v1 && v2 != 0) { |  | ||||||
|             return p2s - p1s; |  | ||||||
|         } |  | ||||||
|         return (int) Math.signum(v2 - v1); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -1,49 +0,0 @@ | |||||||
| /* |  | ||||||
|  * PlotSquared, a land and world management plugin for Minecraft. |  | ||||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> |  | ||||||
|  * Copyright (C) IntellectualSites team and contributors |  | ||||||
|  * |  | ||||||
|  * This program is free software: you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation, either version 3 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
| package com.plotsquared.core.util.comparator; |  | ||||||
|  |  | ||||||
| import com.plotsquared.core.plot.Plot; |  | ||||||
| import com.plotsquared.core.plot.PlotArea; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nullable; |  | ||||||
| import java.util.Comparator; |  | ||||||
|  |  | ||||||
| public class PlotInPrioritizedAreaComparator implements Comparator<Plot> { |  | ||||||
|  |  | ||||||
|     private final PlotArea priorityArea; |  | ||||||
|  |  | ||||||
|     public PlotInPrioritizedAreaComparator(@Nullable final PlotArea area) { |  | ||||||
|         this.priorityArea = area; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public int compare(final Plot first, final Plot second) { |  | ||||||
|         if (this.priorityArea == null) { |  | ||||||
|             return 0; // no defined priority? don't sort |  | ||||||
|         } |  | ||||||
|         if (this.priorityArea.equals(first.getArea())) { |  | ||||||
|             return -1; |  | ||||||
|         } |  | ||||||
|         if (this.priorityArea.equals(second.getArea())) { |  | ||||||
|             return 1; |  | ||||||
|         } |  | ||||||
|         return 0; // same area, don't sort |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -25,21 +25,16 @@ import com.plotsquared.core.player.PlotPlayer; | |||||||
| import com.plotsquared.core.util.StringMan; | import com.plotsquared.core.util.StringMan; | ||||||
| import net.kyori.adventure.text.Component; | import net.kyori.adventure.text.Component; | ||||||
| import net.kyori.adventure.text.ComponentLike; | import net.kyori.adventure.text.ComponentLike; | ||||||
| import net.kyori.adventure.text.minimessage.MiniMessage; |  | ||||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | import net.kyori.adventure.text.minimessage.tag.Tag; | ||||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
| public class HelpObject implements ComponentLike { | public class HelpObject implements ComponentLike { | ||||||
|  |  | ||||||
|     static final MiniMessage MINI_MESSAGE = MiniMessage.miniMessage(); |  | ||||||
|  |  | ||||||
|     private final Component rendered; |     private final Component rendered; | ||||||
|  |  | ||||||
|     public HelpObject(final Command command, final String label, final PlotPlayer<?> audience) { |     public HelpObject(final Command command, final String label, final PlotPlayer<?> audience) { | ||||||
|         rendered = MINI_MESSAGE.deserialize( |         this.rendered = TranslatableCaption.of("help.help_item").toComponent(audience, TagResolver.builder() | ||||||
|                 TranslatableCaption.of("help.help_item").getComponent(audience), |  | ||||||
|                 TagResolver.builder() |  | ||||||
|                 .tag("usage", Tag.inserting(Component.text(command.getUsage().replace("{label}", label)))) |                 .tag("usage", Tag.inserting(Component.text(command.getUsage().replace("{label}", label)))) | ||||||
|                 .tag("alias", Tag.inserting(Component.text( |                 .tag("alias", Tag.inserting(Component.text( | ||||||
|                         command.getAliases().isEmpty() ? "" : StringMan.join(command.getAliases(), " | ") |                         command.getAliases().isEmpty() ? "" : StringMan.join(command.getAliases(), " | ") | ||||||
| @@ -47,8 +42,7 @@ public class HelpObject implements ComponentLike { | |||||||
|                 .tag("desc", Tag.inserting(command.getDescription().toComponent(audience))) |                 .tag("desc", Tag.inserting(command.getDescription().toComponent(audience))) | ||||||
|                 .tag("arguments", Tag.inserting(Component.text(buildArgumentList(command.getRequiredArguments())))) |                 .tag("arguments", Tag.inserting(Component.text(buildArgumentList(command.getRequiredArguments())))) | ||||||
|                 .tag("label", Tag.inserting(Component.text(label))) |                 .tag("label", Tag.inserting(Component.text(label))) | ||||||
|                         .build() |                 .build()); | ||||||
|         ); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private String buildArgumentList(final Argument<?>[] arguments) { |     private String buildArgumentList(final Argument<?>[] arguments) { | ||||||
|   | |||||||
| @@ -24,7 +24,6 @@ import com.plotsquared.core.plot.PlotArea; | |||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.stream.Stream; |  | ||||||
|  |  | ||||||
| class AreaLimitedPlotProvider implements PlotProvider { | class AreaLimitedPlotProvider implements PlotProvider { | ||||||
|  |  | ||||||
| @@ -43,9 +42,4 @@ class AreaLimitedPlotProvider implements PlotProvider { | |||||||
|         return plots; |         return plots; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public Stream<Plot> streamPlots() { |  | ||||||
|         return streamPlotsInPlotAreas(this.areas.toArray(PlotArea[]::new)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ import com.plotsquared.core.PlotSquared; | |||||||
| import com.plotsquared.core.plot.Plot; | import com.plotsquared.core.plot.Plot; | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.stream.Stream; |  | ||||||
|  |  | ||||||
| class ExpiredPlotProvider implements PlotProvider { | class ExpiredPlotProvider implements PlotProvider { | ||||||
|  |  | ||||||
| @@ -31,9 +30,4 @@ class ExpiredPlotProvider implements PlotProvider { | |||||||
|         return PlotSquared.platform().expireManager().getPendingExpired(); |         return PlotSquared.platform().expireManager().getPendingExpired(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public Stream<Plot> streamPlots() { |  | ||||||
|         return getPlots().stream(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; | |||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.stream.Stream; |  | ||||||
|  |  | ||||||
| class FixedPlotProvider implements PlotProvider { | class FixedPlotProvider implements PlotProvider { | ||||||
|  |  | ||||||
| @@ -38,9 +37,4 @@ class FixedPlotProvider implements PlotProvider { | |||||||
|         return Collections.singleton(plot); |         return Collections.singleton(plot); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public Stream<Plot> streamPlots() { |  | ||||||
|         return Stream.of(plot); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,7 +26,6 @@ import org.checkerframework.checker.nullness.qual.NonNull; | |||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.stream.Stream; |  | ||||||
|  |  | ||||||
| class GlobalPlotProvider implements PlotProvider { | class GlobalPlotProvider implements PlotProvider { | ||||||
|  |  | ||||||
| @@ -45,9 +44,4 @@ class GlobalPlotProvider implements PlotProvider { | |||||||
|         return plots; |         return plots; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public Stream<Plot> streamPlots() { |  | ||||||
|         return streamPlotsInPlotAreas(this.plotAreaManager.getAllPlotAreas()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ import com.plotsquared.core.plot.Plot; | |||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.stream.Stream; |  | ||||||
|  |  | ||||||
| class NullProvider implements PlotProvider { | class NullProvider implements PlotProvider { | ||||||
|  |  | ||||||
| @@ -31,9 +30,4 @@ class NullProvider implements PlotProvider { | |||||||
|         return Collections.emptyList(); |         return Collections.emptyList(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public Stream<Plot> streamPlots() { |  | ||||||
|         return Stream.empty(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,11 +23,17 @@ import org.checkerframework.checker.nullness.qual.NonNull; | |||||||
|  |  | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
|  |  | ||||||
| record OwnersIncludeFilter(UUID owner) implements PlotFilter { | class OwnersIncludeFilter implements PlotFilter { | ||||||
|  |  | ||||||
|  |     private final UUID owner; | ||||||
|  |  | ||||||
|  |     OwnersIncludeFilter(final @NonNull UUID owner) { | ||||||
|  |         this.owner = owner; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public boolean accepts(final @NonNull Plot plot) { |     public boolean accepts(final @NonNull Plot plot) { | ||||||
|         return plot.isBasePlot() && plot.isOwner(owner); |         return plot.isBasePlot() && plot.getOwners().size() > 0 && plot.getOwners().contains(owner); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,44 +19,12 @@ | |||||||
| package com.plotsquared.core.util.query; | package com.plotsquared.core.util.query; | ||||||
|  |  | ||||||
| import com.plotsquared.core.plot.Plot; | import com.plotsquared.core.plot.Plot; | ||||||
| import com.plotsquared.core.plot.PlotArea; |  | ||||||
|  |  | ||||||
| import java.util.Collection; | import java.util.Collection; | ||||||
| import java.util.Iterator; |  | ||||||
| import java.util.Spliterator; |  | ||||||
| import java.util.Spliterators; |  | ||||||
| import java.util.stream.Stream; |  | ||||||
| import java.util.stream.StreamSupport; |  | ||||||
|  |  | ||||||
|  | @FunctionalInterface | ||||||
| interface PlotProvider { | interface PlotProvider { | ||||||
|  |  | ||||||
|     Collection<Plot> getPlots(); |     Collection<Plot> getPlots(); | ||||||
|  |  | ||||||
|     Stream<Plot> streamPlots(); |  | ||||||
|  |  | ||||||
|     default Stream<Plot> streamPlotsInPlotAreas(PlotArea[] areas) { |  | ||||||
|         if (areas == null || areas.length == 0) { |  | ||||||
|             return Stream.of(); |  | ||||||
|         } |  | ||||||
|         return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<>() { |  | ||||||
|             private int areaIndex = -1; |  | ||||||
|             private Iterator<Plot> currentAreaPlots; |  | ||||||
|             @Override |  | ||||||
|             public boolean hasNext() { |  | ||||||
|                 if (currentAreaPlots == null || !currentAreaPlots.hasNext()) { |  | ||||||
|                     if (areaIndex >= areas.length - 1) { |  | ||||||
|                         return false; |  | ||||||
|                     } |  | ||||||
|                     currentAreaPlots = areas[++areaIndex].getPlots().iterator(); |  | ||||||
|                 } |  | ||||||
|                 return true; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             @Override |  | ||||||
|             public Plot next() { |  | ||||||
|                 return currentAreaPlots.next(); |  | ||||||
|             } |  | ||||||
|         }, Spliterator.IMMUTABLE), false); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,11 +23,10 @@ import com.plotsquared.core.PlotSquared; | |||||||
| import com.plotsquared.core.player.PlotPlayer; | import com.plotsquared.core.player.PlotPlayer; | ||||||
| import com.plotsquared.core.plot.Plot; | import com.plotsquared.core.plot.Plot; | ||||||
| import com.plotsquared.core.plot.PlotArea; | import com.plotsquared.core.plot.PlotArea; | ||||||
|  | import com.plotsquared.core.plot.Rating; | ||||||
|  | import com.plotsquared.core.plot.flag.implementations.DoneFlag; | ||||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | import com.plotsquared.core.plot.world.PlotAreaManager; | ||||||
| import com.plotsquared.core.util.comparator.PlotByDoneComparator; | import com.plotsquared.core.util.MathMan; | ||||||
| import com.plotsquared.core.util.comparator.PlotByRatingComparator; |  | ||||||
| import com.plotsquared.core.util.comparator.PlotByCreationDateComparator; |  | ||||||
| import com.plotsquared.core.util.comparator.PlotInPrioritizedAreaComparator; |  | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  |  | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| @@ -38,6 +37,7 @@ import java.util.HashSet; | |||||||
| import java.util.Iterator; | import java.util.Iterator; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
| import java.util.function.Predicate; | import java.util.function.Predicate; | ||||||
| @@ -229,7 +229,6 @@ public final class PlotQuery implements Iterable<Plot> { | |||||||
|     public @NonNull PlotQuery hasOwner() { |     public @NonNull PlotQuery hasOwner() { | ||||||
|         return this.addFilter(new HasOwnerFilter()); |         return this.addFilter(new HasOwnerFilter()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Query for plots with a specific alias |      * Query for plots with a specific alias | ||||||
|      * |      * | ||||||
| @@ -308,15 +307,7 @@ public final class PlotQuery implements Iterable<Plot> { | |||||||
|      * @return Matching plots |      * @return Matching plots | ||||||
|      */ |      */ | ||||||
|     public @NonNull Stream<Plot> asStream() { |     public @NonNull Stream<Plot> asStream() { | ||||||
|         Stream<Plot> stream = this.plotProvider.streamPlots().filter(testPlotAgainstFilters()); |         return this.asList().stream(); | ||||||
|         if (this.sortingStrategy == SortingStrategy.NO_SORTING) { |  | ||||||
|             return stream; |  | ||||||
|         } |  | ||||||
|         stream = stream.sorted(getConfiguredComparator()); |  | ||||||
|         if (this.priorityArea != null) { |  | ||||||
|             stream = stream.sorted(new PlotInPrioritizedAreaComparator(this.priorityArea)); |  | ||||||
|         } |  | ||||||
|         return stream; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -343,10 +334,49 @@ public final class PlotQuery implements Iterable<Plot> { | |||||||
|         } |         } | ||||||
|         if (this.sortingStrategy == SortingStrategy.NO_SORTING) { |         if (this.sortingStrategy == SortingStrategy.NO_SORTING) { | ||||||
|             return result; |             return result; | ||||||
|  |         } else if (this.sortingStrategy == SortingStrategy.SORT_BY_TEMP) { | ||||||
|  |             return PlotSquared.get().sortPlotsByTemp(result); | ||||||
|  |         } else if (this.sortingStrategy == SortingStrategy.SORT_BY_DONE) { | ||||||
|  |             result.sort((a, b) -> { | ||||||
|  |                 String va = a.getFlag(DoneFlag.class); | ||||||
|  |                 String vb = b.getFlag(DoneFlag.class); | ||||||
|  |                 if (MathMan.isInteger(va)) { | ||||||
|  |                     if (MathMan.isInteger(vb)) { | ||||||
|  |                         return Integer.parseInt(vb) - Integer.parseInt(va); | ||||||
|                     } |                     } | ||||||
|         result.sort(getConfiguredComparator()); |                     return -1; | ||||||
|         if (this.priorityArea != null) { |                 } | ||||||
|             result.sort(new PlotInPrioritizedAreaComparator(this.priorityArea)); |                 return 1; | ||||||
|  |             }); | ||||||
|  |         } else if (this.sortingStrategy == SortingStrategy.SORT_BY_RATING) { | ||||||
|  |             result.sort((p1, p2) -> { | ||||||
|  |                 double v1 = 0; | ||||||
|  |                 int p1s = p1.getSettings().getRatings().size(); | ||||||
|  |                 int p2s = p2.getRatings().size(); | ||||||
|  |                 if (!p1.getSettings().getRatings().isEmpty()) { | ||||||
|  |                     v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) | ||||||
|  |                             .map(av -> av * av).sum(); | ||||||
|  |                     v1 /= p1s; | ||||||
|  |                     v1 += p1s; | ||||||
|  |                 } | ||||||
|  |                 double v2 = 0; | ||||||
|  |                 if (!p2.getSettings().getRatings().isEmpty()) { | ||||||
|  |                     for (Map.Entry<UUID, Rating> entry : p2.getRatings().entrySet()) { | ||||||
|  |                         double av = entry.getValue().getAverageRating(); | ||||||
|  |                         v2 += av * av; | ||||||
|  |                     } | ||||||
|  |                     v2 /= p2s; | ||||||
|  |                     v2 += p2s; | ||||||
|  |                 } | ||||||
|  |                 if (v2 == v1 && v2 != 0) { | ||||||
|  |                     return p2s - p1s; | ||||||
|  |                 } | ||||||
|  |                 return (int) Math.signum(v2 - v1); | ||||||
|  |             }); | ||||||
|  |         } else if (this.sortingStrategy == SortingStrategy.SORT_BY_CREATION) { | ||||||
|  |             return PlotSquared.get().sortPlots(result, PlotSquared.SortType.CREATION_DATE, this.priorityArea); | ||||||
|  |         } else if (this.sortingStrategy == SortingStrategy.COMPARATOR) { | ||||||
|  |             result.sort(this.plotComparator); | ||||||
|         } |         } | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| @@ -397,28 +427,22 @@ public final class PlotQuery implements Iterable<Plot> { | |||||||
|      * @return {@code true} if any provided plot matches the filters. |      * @return {@code true} if any provided plot matches the filters. | ||||||
|      */ |      */ | ||||||
|     public boolean anyMatch() { |     public boolean anyMatch() { | ||||||
|         return hasMinimumMatches(1); |         if (this.filters.isEmpty()) { | ||||||
|  |             return !this.plotProvider.getPlots().isEmpty(); | ||||||
|  |         } else { | ||||||
|  |             final Collection<Plot> plots = this.plotProvider.getPlots(); | ||||||
|  |             outer: | ||||||
|  |             for (final Plot plot : plots) { | ||||||
|  |                 // a plot must pass all filters to match the criteria | ||||||
|  |                 for (final PlotFilter filter : this.filters) { | ||||||
|  |                     if (!filter.accepts(plot)) { | ||||||
|  |                         continue outer; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Get whether this query matches at least {@code minimum} plots. |  | ||||||
|      * <br /> |  | ||||||
|      * Should be prioritized over {@link #count()}, if possible. |  | ||||||
|      * This method only queries as many plots and areas as required without applying sorting. (short-circuiting on the stream) |  | ||||||
|      * |  | ||||||
|      * @param minimum the minimum amount of matches plots expected (inclusive) |  | ||||||
|      * @return {@code true} if this query's result contains at least {@code minimum} plots (after optional filters). |  | ||||||
|      * |  | ||||||
|      * @since TODO |  | ||||||
|      */ |  | ||||||
|     public boolean hasMinimumMatches(int minimum) { |  | ||||||
|         return this.plotProvider.streamPlots().filter(testPlotAgainstFilters()).limit(minimum).count() == minimum; |  | ||||||
|                 } |                 } | ||||||
|  |                 return true; // a plot passed all filters, so we have a match | ||||||
|     @NonNull |             } | ||||||
|     @Override |             return false; | ||||||
|     public Iterator<Plot> iterator() { |         } | ||||||
|         return this.asCollection().iterator(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @NonNull |     @NonNull | ||||||
| @@ -427,28 +451,10 @@ public final class PlotQuery implements Iterable<Plot> { | |||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Comparator<Plot> getConfiguredComparator() { |     @NonNull | ||||||
|         return switch (sortingStrategy) { |     @Override | ||||||
|             case NO_SORTING -> (p1, p2) -> 0; |     public Iterator<Plot> iterator() { | ||||||
|             case SORT_BY_TEMP, SORT_BY_CREATION -> PlotByCreationDateComparator.INSTANCE; |         return this.asCollection().iterator(); | ||||||
|             case SORT_BY_DONE -> PlotByDoneComparator.INSTANCE; |  | ||||||
|             case SORT_BY_RATING -> PlotByRatingComparator.INSTANCE; |  | ||||||
|             case COMPARATOR -> plotComparator; |  | ||||||
|         }; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private Predicate<Plot> testPlotAgainstFilters() { |  | ||||||
|         if (this.filters.isEmpty()) { |  | ||||||
|             return plot -> true; |  | ||||||
|         } |  | ||||||
|         return plot -> { |  | ||||||
|             for (final PlotFilter filter : filters) { |  | ||||||
|                 if (!filter.accepts(plot)) { |  | ||||||
|                     return false; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             return true; |  | ||||||
|         }; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -31,7 +31,6 @@ import java.util.List; | |||||||
| import java.util.UUID; | import java.util.UUID; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
| import java.util.stream.IntStream; | import java.util.stream.IntStream; | ||||||
| import java.util.stream.Stream; |  | ||||||
|  |  | ||||||
| class SearchPlotProvider implements PlotProvider { | class SearchPlotProvider implements PlotProvider { | ||||||
|  |  | ||||||
| @@ -116,9 +115,4 @@ class SearchPlotProvider implements PlotProvider { | |||||||
|         return getPlotsBySearch(this.searchTerm); |         return getPlotsBySearch(this.searchTerm); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public Stream<Plot> streamPlots() { |  | ||||||
|         return getPlots().stream(); // TODO: look into potentially optimizations here? |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -390,11 +390,11 @@ | |||||||
|   "info.area_list_tooltip": "<gold>Claimed=</gold><gray><claimed></gray>\n<gold>Usage=</gold><gray><usage></gray>\n<gold>Clusters=</gold><gray><clusters></gray>\n<gold>Region=</gold><gray><region></gray>\n<gold>Generator=</gold><gray><generator></gray>", |   "info.area_list_tooltip": "<gold>Claimed=</gold><gray><claimed></gray>\n<gold>Usage=</gold><gray><usage></gray>\n<gold>Clusters=</gold><gray><clusters></gray>\n<gold>Region=</gold><gray><region></gray>\n<gold>Generator=</gold><gray><generator></gray>", | ||||||
|   "info.area_list_item": "<click:run_command:'<command_tp>'><hover:show_text:'<command_tp>'><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:'<command_info>'><hover:show_text:'<hover_info>'><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>", |   "info.area_list_item": "<click:run_command:'<command_tp>'><hover:show_text:'<command_tp>'><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:'<command_info>'><hover:show_text:'<hover_info>'><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>", | ||||||
|   "working.generating_component": "<prefix><gold>Started generating component from your settings.</gold>", |   "working.generating_component": "<prefix><gold>Started generating component from your settings.</gold>", | ||||||
|   "working.clearing_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><plot></gold><dark_aqua> has been cleared! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>", |   "working.clearing_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><world>;<plot></gold><dark_aqua> has been cleared! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>", | ||||||
|   "working.deleting_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><plot></gold><dark_aqua> has been deleted! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>", |   "working.deleting_done": "<prefix><dark_aqua>Plot </dark_aqua><gold><world>;<plot></gold><dark_aqua> has been deleted! Took </dark_aqua><gold><amount>ms</gold><dark_aqua>.</dark_aqua>", | ||||||
|   "working.plot_not_claimed": "<prefix><gray>Plot not claimed.</gray>", |   "working.plot_not_claimed": "<prefix><gray>Plot not claimed.</gray>", | ||||||
|   "working.plot_is_claimed": "<prefix><gray>This plot is already claimed.</gray>", |   "working.plot_is_claimed": "<prefix><gray>This plot is already claimed.</gray>", | ||||||
|   "working.claimed": "<prefix><dark_aqua>You successfully claimed the plot </dark_aqua><gold><plot></gold><dark_aqua>.</dark_aqua>", |   "working.claimed": "<prefix><dark_aqua>You successfully claimed the plot </dark_aqua><gold><world>;<plot></gold><dark_aqua>.</dark_aqua>", | ||||||
|   "working.progress": "<prefix><gray>Current progress: </gray><gold><progress></gold><gray>%</gray>", |   "working.progress": "<prefix><gray>Current progress: </gray><gold><progress></gold><gray>%</gray>", | ||||||
|   "working.component_complete": "<prefix><gold>Component generation has finished for plot <plot>.</gold>", |   "working.component_complete": "<prefix><gold>Component generation has finished for plot <plot>.</gold>", | ||||||
|   "list.comment_list_header_paged": "<gray>(Page </gray><gold><cur></gold><gray>/</gray><gold><max></gold><gray>) </gray><gold>List of <amount> comment(s):</gold>", |   "list.comment_list_header_paged": "<gray>(Page </gray><gold><cur></gold><gray>/</gray><gold><max></gold><gray>) </gray><gold>List of <amount> comment(s):</gold>", | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import com.diffplug.gradle.spotless.SpotlessPlugin | import com.diffplug.gradle.spotless.SpotlessPlugin | ||||||
| import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin | import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin | ||||||
|  | import com.vanniktech.maven.publish.SonatypeHost | ||||||
| import groovy.json.JsonSlurper | import groovy.json.JsonSlurper | ||||||
| import xyz.jpenilla.runpaper.task.RunServer | import xyz.jpenilla.runpaper.task.RunServer | ||||||
| import java.net.URI | import java.net.URI | ||||||
| @@ -7,13 +8,12 @@ import java.net.URI | |||||||
| plugins { | plugins { | ||||||
|     java |     java | ||||||
|     `java-library` |     `java-library` | ||||||
|     `maven-publish` |  | ||||||
|     signing |     signing | ||||||
|  |  | ||||||
|     alias(libs.plugins.shadow) |     alias(libs.plugins.shadow) | ||||||
|     alias(libs.plugins.spotless) |     alias(libs.plugins.spotless) | ||||||
|     alias(libs.plugins.grgit) |     alias(libs.plugins.grgit) | ||||||
|     alias(libs.plugins.nexus) |     alias(libs.plugins.publish) | ||||||
|  |  | ||||||
|     eclipse |     eclipse | ||||||
|     idea |     idea | ||||||
| @@ -22,7 +22,7 @@ plugins { | |||||||
| } | } | ||||||
|  |  | ||||||
| group = "com.intellectualsites.plotsquared" | group = "com.intellectualsites.plotsquared" | ||||||
| version = "7.5.1-SNAPSHOT" | version = "7.5.4-SNAPSHOT" | ||||||
|  |  | ||||||
| if (!File("$rootDir/.git").exists()) { | if (!File("$rootDir/.git").exists()) { | ||||||
|     logger.lifecycle(""" |     logger.lifecycle(""" | ||||||
| @@ -41,16 +41,6 @@ subprojects { | |||||||
|     repositories { |     repositories { | ||||||
|         mavenCentral() |         mavenCentral() | ||||||
|  |  | ||||||
|         maven { |  | ||||||
|             name = "Sonatype OSS" |  | ||||||
|             url = uri("https://oss.sonatype.org/content/repositories/snapshots/") |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         maven { |  | ||||||
|             name = "Sonatype OSS (S01)" |  | ||||||
|             url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/") |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         maven { |         maven { | ||||||
|             name = "Jitpack" |             name = "Jitpack" | ||||||
|             url = uri("https://jitpack.io") |             url = uri("https://jitpack.io") | ||||||
| @@ -68,7 +58,7 @@ subprojects { | |||||||
|     apply { |     apply { | ||||||
|         plugin<JavaPlugin>() |         plugin<JavaPlugin>() | ||||||
|         plugin<JavaLibraryPlugin>() |         plugin<JavaLibraryPlugin>() | ||||||
|         plugin<MavenPublishPlugin>() |         plugin<com.vanniktech.maven.publish.MavenPublishPlugin>() | ||||||
|         plugin<ShadowPlugin>() |         plugin<ShadowPlugin>() | ||||||
|         plugin<SpotlessPlugin>() |         plugin<SpotlessPlugin>() | ||||||
|         plugin<SigningPlugin>() |         plugin<SigningPlugin>() | ||||||
| @@ -79,8 +69,8 @@ subprojects { | |||||||
|  |  | ||||||
|     dependencies { |     dependencies { | ||||||
|         // Tests |         // Tests | ||||||
|         testImplementation("org.junit.jupiter:junit-jupiter:5.12.0") |         testImplementation("org.junit.jupiter:junit-jupiter:5.12.2") | ||||||
|         testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.12.0") |         testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.12.2") | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     plugins.withId("java") { |     plugins.withId("java") { | ||||||
| @@ -107,11 +97,6 @@ subprojects { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     java { |  | ||||||
|         withSourcesJar() |  | ||||||
|         withJavadocJar() |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     val javaComponent = components["java"] as AdhocComponentWithVariants |     val javaComponent = components["java"] as AdhocComponentWithVariants | ||||||
|     javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { |     javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) { | ||||||
|         skip() |         skip() | ||||||
| @@ -127,14 +112,15 @@ subprojects { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     publishing { |     mavenPublishing { | ||||||
|         publications { |         coordinates( | ||||||
|             create<MavenPublication>("maven") { |             groupId = "$group", | ||||||
|                 from(components["java"]) |             artifactId = project.name, | ||||||
|  |             version = "${project.version}", | ||||||
|  |         ) | ||||||
|  |  | ||||||
|         pom { |         pom { | ||||||
|  |             name.set(project.name) | ||||||
|                     name.set(project.name + " " + project.version) |  | ||||||
|             description.set("PlotSquared, a land and world management plugin for Minecraft.") |             description.set("PlotSquared, a land and world management plugin for Minecraft.") | ||||||
|             url.set("https://github.com/IntellectualSites/PlotSquared") |             url.set("https://github.com/IntellectualSites/PlotSquared") | ||||||
|  |  | ||||||
| @@ -185,8 +171,8 @@ subprojects { | |||||||
|                 system.set("GitHub") |                 system.set("GitHub") | ||||||
|                 url.set("https://github.com/IntellectualSites/PlotSquared/issues") |                 url.set("https://github.com/IntellectualSites/PlotSquared/issues") | ||||||
|             } |             } | ||||||
|                 } |  | ||||||
|             } |             publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -194,7 +180,6 @@ subprojects { | |||||||
|  |  | ||||||
|         compileJava { |         compileJava { | ||||||
|             options.compilerArgs.add("-parameters") |             options.compilerArgs.add("-parameters") | ||||||
|             options.isDeprecation = true |  | ||||||
|             options.encoding = "UTF-8" |             options.encoding = "UTF-8" | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -217,27 +202,18 @@ subprojects { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| nexusPublishing { |  | ||||||
|     this.repositories { |  | ||||||
|         sonatype { |  | ||||||
|             nexusUrl.set(URI.create("https://s01.oss.sonatype.org/service/local/")) |  | ||||||
|             snapshotRepositoryUrl.set(URI.create("https://s01.oss.sonatype.org/content/repositories/snapshots/")) |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| tasks.getByName<Jar>("jar") { | tasks.getByName<Jar>("jar") { | ||||||
|     enabled = false |     enabled = false | ||||||
| } | } | ||||||
|  |  | ||||||
| val supportedVersions = listOf("1.19.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4") | val supportedVersions = listOf("1.19.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4", "1.21.5") | ||||||
| tasks { | tasks { | ||||||
|     register("cacheLatestFaweArtifact") { |     register("cacheLatestFaweArtifact") { | ||||||
|         val lastSuccessfulBuildUrl = uri("https://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/api/json").toURL() |         val lastSuccessfulBuildUrl = uri("https://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/api/json").toURL() | ||||||
|         val artifact = ((JsonSlurper().parse(lastSuccessfulBuildUrl) as Map<*, *>)["artifacts"] as List<*>) |         val artifact = ((JsonSlurper().parse(lastSuccessfulBuildUrl) as Map<*, *>)["artifacts"] as List<*>) | ||||||
|                 .map { it as Map<*, *> } |                 .map { it as Map<*, *> } | ||||||
|                 .map { it["fileName"] as String } |                 .map { it["fileName"] as String } | ||||||
|                 .first { it -> it.contains("Bukkit") } |                 .first { it -> it.contains("Paper") } | ||||||
|         project.ext["faweArtifact"] = artifact |         project.ext["faweArtifact"] = artifact | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,13 +2,13 @@ | |||||||
| # Platform expectations | # Platform expectations | ||||||
| paper = "1.20.4-R0.1-SNAPSHOT" | paper = "1.20.4-R0.1-SNAPSHOT" | ||||||
| guice = "7.0.0" | guice = "7.0.0" | ||||||
| spotbugs = "4.9.1" | spotbugs = "4.9.3" | ||||||
| checkerqual = "3.49.0" | checkerqual = "3.49.3" | ||||||
| gson = "2.10" | gson = "2.10" | ||||||
| guava = "31.1-jre" | guava = "31.1-jre" | ||||||
| snakeyaml = "2.0" | snakeyaml = "2.0" | ||||||
| adventure = "4.19.0" | adventure = "4.21.0" | ||||||
| adventure-bukkit = "4.3.4" | adventure-bukkit = "4.4.0" | ||||||
| log4j = "2.19.0" | log4j = "2.19.0" | ||||||
|  |  | ||||||
| # Plugins | # Plugins | ||||||
| @@ -16,27 +16,27 @@ worldedit = "7.2.20" | |||||||
| fawe = "2.13.0" | fawe = "2.13.0" | ||||||
| placeholderapi = "2.11.6" | placeholderapi = "2.11.6" | ||||||
| luckperms = "5.4" | luckperms = "5.4" | ||||||
| essentialsx = "2.20.1" | essentialsx = "2.21.0" | ||||||
| mvdwapi = "3.1.1" | mvdwapi = "3.1.1" | ||||||
|  |  | ||||||
| # Third party | # Third party | ||||||
| prtree = "2.0.1" | prtree = "2.0.1" | ||||||
| aopalliance = "1.0" | aopalliance = "1.0" | ||||||
| cloud-services = "1.8.4" | cloud-services = "1.8.4" | ||||||
| arkitektonika = "2.1.3" | arkitektonika = "2.1.4" | ||||||
| squirrelid = "0.3.2" | squirrelid = "0.3.2" | ||||||
| paster = "1.1.6" | paster = "1.1.7" | ||||||
| bstats = "3.1.0" | bstats = "3.1.0" | ||||||
| paperlib = "1.0.8" | paperlib = "1.0.8" | ||||||
| informative-annotations = "1.5" | informative-annotations = "1.6" | ||||||
| vault = "1.7.1" | vault = "1.7.1" | ||||||
| serverlib = "2.3.6" | serverlib = "2.3.7" | ||||||
|  |  | ||||||
| # Gradle plugins | # Gradle plugins | ||||||
| shadow = "8.3.6" | shadow = "8.3.6" | ||||||
| grgit = "4.1.1" | grgit = "4.1.1" | ||||||
| spotless = "7.0.2" | spotless = "7.0.3" | ||||||
| nexus = "2.0.0" | publish = "0.32.0" | ||||||
| runPaper = "2.3.1" | runPaper = "2.3.1" | ||||||
|  |  | ||||||
| [libraries] | [libraries] | ||||||
| @@ -81,5 +81,5 @@ serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.re | |||||||
| shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } | shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } | ||||||
| grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" } | grgit = { id = "org.ajoberstar.grgit", version.ref = "grgit" } | ||||||
| spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } | spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } | ||||||
| nexus = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" } | publish = { id = "com.vanniktech.maven.publish", version.ref = "publish" } | ||||||
| runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" } | runPaper = { id = "xyz.jpenilla.run-paper", version.ref = "runPaper" } | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| distributionBase=GRADLE_USER_HOME | distributionBase=GRADLE_USER_HOME | ||||||
| distributionPath=wrapper/dists | distributionPath=wrapper/dists | ||||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip | ||||||
| networkTimeout=10000 | networkTimeout=10000 | ||||||
| validateDistributionUrl=true | validateDistributionUrl=true | ||||||
| zipStoreBase=GRADLE_USER_HOME | zipStoreBase=GRADLE_USER_HOME | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								gradlew
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								gradlew
									
									
									
									
										vendored
									
									
								
							| @@ -114,7 +114,7 @@ case "$( uname )" in                #( | |||||||
|   NONSTOP* )        nonstop=true ;; |   NONSTOP* )        nonstop=true ;; | ||||||
| esac | esac | ||||||
|  |  | ||||||
| CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar | CLASSPATH="\\\"\\\"" | ||||||
|  |  | ||||||
|  |  | ||||||
| # Determine the Java command to use to start the JVM. | # Determine the Java command to use to start the JVM. | ||||||
| @@ -205,7 +205,7 @@ fi | |||||||
| DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | ||||||
|  |  | ||||||
| # Collect all arguments for the java command: | # Collect all arguments for the java command: | ||||||
| #   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | #   * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, | ||||||
| #     and any embedded shellness will be escaped. | #     and any embedded shellness will be escaped. | ||||||
| #   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be | #   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be | ||||||
| #     treated as '${Hostname}' itself on the command line. | #     treated as '${Hostname}' itself on the command line. | ||||||
| @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' | |||||||
| set -- \ | set -- \ | ||||||
|         "-Dorg.gradle.appname=$APP_BASE_NAME" \ |         "-Dorg.gradle.appname=$APP_BASE_NAME" \ | ||||||
|         -classpath "$CLASSPATH" \ |         -classpath "$CLASSPATH" \ | ||||||
|         org.gradle.wrapper.GradleWrapperMain \ |         -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ | ||||||
|         "$@" |         "$@" | ||||||
|  |  | ||||||
| # Stop when "xargs" is not available. | # Stop when "xargs" is not available. | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								gradlew.bat
									
									
									
									
										vendored
									
									
								
							| @@ -70,11 +70,11 @@ goto fail | |||||||
| :execute | :execute | ||||||
| @rem Setup the command line | @rem Setup the command line | ||||||
|  |  | ||||||
| set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar | set CLASSPATH= | ||||||
|  |  | ||||||
|  |  | ||||||
| @rem Execute Gradle | @rem Execute Gradle | ||||||
| "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* | ||||||
|  |  | ||||||
| :end | :end | ||||||
| @rem End local scope for the variables with windows NT shell | @rem End local scope for the variables with windows NT shell | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user