mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-24 23:23:44 +02:00 
			
		
		
		
	Compare commits
	
		
			60 Commits
		
	
	
		
			7.2.0
			...
			feature/cl
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | c8e5cf163f | ||
|   | 628c520c1b | ||
|   | e0c7c58aaa | ||
|   | a659832613 | ||
|   | 2a0ad92a97 | ||
|   | 780c65e68c | ||
|   | 92a00ef60a | ||
|   | 3a1b373c8e | ||
|   | 1a277bbbeb | ||
|   | 24d7fe626d | ||
|   | b62a237dab | ||
|   | 2ac2f6648e | ||
|   | 6088dd8409 | ||
|   | e4613cfc62 | ||
|   | 8c44b2d2d2 | ||
|   | 449af2f3a4 | ||
|   | ead7acdd76 | ||
|   | 1991142d48 | ||
|   | 63ae11b3d3 | ||
|   | 86fe3c6846 | ||
|   | a90e179338 | ||
|   | a6ae287908 | ||
|   | 1a33997099 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 6edd4b8220 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 9b0d1e484c | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 6971fa4c10 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 3c818f3e33 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 31be2e5eb3 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 945a8ad306 | ||
|   | c6b0b99cd6 | ||
|   | dbfc43e3cd | ||
|   | c8b4a2fa39 | ||
|   | d851e27aed | ||
|   | 4a45729c9e | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 7931c0864e | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 1456b29d93 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 761477b76d | ||
|   | e61bcf905f | ||
|   | 85bec710df | ||
|   | d130794453 | ||
|   | f5f875eb11 | ||
|   | 89511f07f9 | ||
|   | 1a18adcd95 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 65858c5f3e | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 5c7520b5f5 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | f3b9cd5ded | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 8a3eb25805 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 48bbd3c018 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | bf85013f70 | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | d36a2d236b | ||
| ![renovate[bot]](/assets/img/avatar_default.png)  | 79f111ec0a | ||
|   | 31ae62b62c | ||
|   | cdb44d4884 | ||
|   | eb63e4351d | ||
|   | ba7880241b | ||
|   | be6838f29e | ||
|   | dc73116401 | ||
|   | b6a87df072 | ||
|   | 8195afaa2f | ||
|   | 561eac2fbd | 
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/bug_report.yml
									
									
									
									
										vendored
									
									
								
							| @@ -27,7 +27,7 @@ body: | ||||
|       description: Which server version version you using? If your server version is not listed, it is not supported. Update to a supported version first. | ||||
|       multiple: false | ||||
|       options: | ||||
|         - '1.20.2' | ||||
|         - '1.20.4' | ||||
|         - '1.20' | ||||
|         - '1.19.4' | ||||
|         - '1.19.3' | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/renovate.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/renovate.json
									
									
									
									
										vendored
									
									
								
							| @@ -14,6 +14,6 @@ | ||||
|     "com.google.code.gson:gson", | ||||
|     "com.google.guava:guava", | ||||
|     "org.yaml:snakeyaml", | ||||
|     "org.apache.logging.log4j:log4j-api", | ||||
|     "org.apache.logging.log4j:log4j-api" | ||||
|   ] | ||||
| } | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/build-pr.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-pr.yml
									
									
									
									
										vendored
									
									
								
							| @@ -13,7 +13,7 @@ jobs: | ||||
|       - name: Validate Gradle Wrapper | ||||
|         uses: gradle/wrapper-validation-action@v1 | ||||
|       - name: Setup Java | ||||
|         uses: actions/setup-java@v3 | ||||
|         uses: actions/setup-java@v4 | ||||
|         with: | ||||
|           distribution: temurin | ||||
|           java-version: 17 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @@ -13,7 +13,7 @@ jobs: | ||||
|       - name: Validate Gradle Wrapper | ||||
|         uses: gradle/wrapper-validation-action@v1 | ||||
|       - name: Setup Java | ||||
|         uses: actions/setup-java@v3 | ||||
|         uses: actions/setup-java@v4 | ||||
|         with: | ||||
|           distribution: temurin | ||||
|           java-version: 17 | ||||
|   | ||||
							
								
								
									
										8
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							| @@ -22,15 +22,15 @@ jobs: | ||||
|       - name: Checkout repository | ||||
|         uses: actions/checkout@v4 | ||||
|       - name: Setup Java | ||||
|         uses: actions/setup-java@v3 | ||||
|         uses: actions/setup-java@v4 | ||||
|         with: | ||||
|           distribution: temurin | ||||
|           java-version: 17 | ||||
|       - name: Initialize CodeQL | ||||
|         uses: github/codeql-action/init@v2 | ||||
|         uses: github/codeql-action/init@v3 | ||||
|         with: | ||||
|           languages: ${{ matrix.language }} | ||||
|       - name: Autobuild | ||||
|         uses: github/codeql-action/autobuild@v2 | ||||
|         uses: github/codeql-action/autobuild@v3 | ||||
|       - name: Perform CodeQL Analysis | ||||
|         uses: github/codeql-action/analyze@v2 | ||||
|         uses: github/codeql-action/analyze@v3 | ||||
|   | ||||
| @@ -53,6 +53,9 @@ dependencies { | ||||
|  | ||||
|     // Adventure | ||||
|     implementation(libs.adventureBukkit) | ||||
|  | ||||
|     // Cloud | ||||
|     implementation(libs.cloudPaper) | ||||
| } | ||||
|  | ||||
| tasks.processResources { | ||||
| @@ -67,6 +70,7 @@ tasks.named<ShadowJar>("shadowJar") { | ||||
|         exclude(dependency("org.checkerframework:")) | ||||
|     } | ||||
|  | ||||
|     relocate("net.kyori.option", "com.plotsquared.core.configuration.option") | ||||
|     relocate("net.kyori.adventure", "com.plotsquared.core.configuration.adventure") | ||||
|     relocate("net.kyori.examination", "com.plotsquared.core.configuration.examination") | ||||
|     relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") | ||||
| @@ -76,6 +80,7 @@ tasks.named<ShadowJar>("shadowJar") { | ||||
|     relocate("com.google.inject", "com.plotsquared.google") | ||||
|     relocate("org.aopalliance", "com.plotsquared.core.aopalliance") | ||||
|     relocate("cloud.commandframework.services", "com.plotsquared.core.services") | ||||
|     relocate("cloud.commandframework", "com.plotsquared.commands") | ||||
|     relocate("io.leangen.geantyref", "com.plotsquared.core.geantyref") | ||||
|     relocate("com.intellectualsites.arkitektonika", "com.plotsquared.core.arkitektonika") | ||||
|     relocate("com.intellectualsites.http", "com.plotsquared.core.http") | ||||
| @@ -105,7 +110,7 @@ tasks { | ||||
|         opt.links("https://intellectualsites.github.io/plotsquared-javadocs/core/") | ||||
|         opt.links("https://jd.advntr.dev/api/4.14.0/") | ||||
|         opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/") | ||||
|         opt.links("https://checkerframework.org/api/") | ||||
|     //    opt.links("https://checkerframework.org/api/") | ||||
|         opt.isLinkSource = true | ||||
|         opt.bottom(File("$rootDir/javadocfooter.html").readText()) | ||||
|         opt.isUse = true | ||||
|   | ||||
| @@ -28,6 +28,7 @@ import com.google.inject.TypeLiteral; | ||||
| import com.plotsquared.bukkit.generator.BukkitPlotGenerator; | ||||
| import com.plotsquared.bukkit.inject.BackupModule; | ||||
| import com.plotsquared.bukkit.inject.BukkitModule; | ||||
| import com.plotsquared.bukkit.inject.CloudModule; | ||||
| import com.plotsquared.bukkit.inject.PermissionModule; | ||||
| import com.plotsquared.bukkit.inject.WorldManagerModule; | ||||
| import com.plotsquared.bukkit.listener.BlockEventListener; | ||||
| @@ -37,6 +38,7 @@ import com.plotsquared.bukkit.listener.EntityEventListener; | ||||
| import com.plotsquared.bukkit.listener.EntitySpawnListener; | ||||
| import com.plotsquared.bukkit.listener.PaperListener; | ||||
| import com.plotsquared.bukkit.listener.PlayerEventListener; | ||||
| import com.plotsquared.bukkit.listener.PlayerEventListener1201; | ||||
| import com.plotsquared.bukkit.listener.ProjectileEventListener; | ||||
| import com.plotsquared.bukkit.listener.ServerListener; | ||||
| import com.plotsquared.bukkit.listener.SingleWorldListener; | ||||
| @@ -63,6 +65,7 @@ import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; | ||||
| import com.plotsquared.core.PlotPlatform; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.backup.BackupManager; | ||||
| import com.plotsquared.core.commands.PlotSquaredCommandManager; | ||||
| import com.plotsquared.core.components.ComponentPresetManager; | ||||
| import com.plotsquared.core.configuration.ConfigurationNode; | ||||
| import com.plotsquared.core.configuration.ConfigurationSection; | ||||
| @@ -82,6 +85,7 @@ import com.plotsquared.core.inject.annotations.DefaultGenerator; | ||||
| import com.plotsquared.core.inject.annotations.ImpromptuPipeline; | ||||
| import com.plotsquared.core.inject.annotations.WorldConfig; | ||||
| import com.plotsquared.core.inject.annotations.WorldFile; | ||||
| import com.plotsquared.core.inject.modules.CommandModule; | ||||
| import com.plotsquared.core.inject.modules.PlotSquaredModule; | ||||
| import com.plotsquared.core.listener.PlotListener; | ||||
| import com.plotsquared.core.listener.WESubscriber; | ||||
| @@ -292,6 +296,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|                         new PermissionModule(), | ||||
|                         new WorldManagerModule(), | ||||
|                         new PlotSquaredModule(), | ||||
|                         new CommandModule(), | ||||
|                         new CloudModule(this), | ||||
|                         new BukkitModule(this), | ||||
|                         new BackupModule() | ||||
|                 ); | ||||
| @@ -359,6 +365,9 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|  | ||||
|         if (Settings.Enabled_Components.EVENTS) { | ||||
|             getServer().getPluginManager().registerEvents(injector().getInstance(PlayerEventListener.class), this); | ||||
|             if ((serverVersion()[1] == 20 && serverVersion()[2] >= 1) || serverVersion()[1] > 20) { | ||||
|                 getServer().getPluginManager().registerEvents(injector().getInstance(PlayerEventListener1201.class), this); | ||||
|             } | ||||
|             getServer().getPluginManager().registerEvents(injector().getInstance(BlockEventListener.class), this); | ||||
|             if (serverVersion()[1] >= 17) { | ||||
|                 getServer().getPluginManager().registerEvents(injector().getInstance(BlockEventListener117.class), this); | ||||
| @@ -384,6 +393,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|         // Commands | ||||
|         if (Settings.Enabled_Components.COMMANDS) { | ||||
|             this.registerCommands(); | ||||
|             // Register the commands. | ||||
|             this.injector().getInstance(PlotSquaredCommandManager.class).registerDefaultCommands(); | ||||
|         } | ||||
|  | ||||
|         // Permissions | ||||
| @@ -814,6 +825,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|                         case "MINECART_MOB_SPAWNER": | ||||
|                         case "ENDER_CRYSTAL": | ||||
|                         case "MINECART_TNT": | ||||
|                         case "CHEST_BOAT": | ||||
|                         case "BOAT": | ||||
|                             if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { | ||||
|                                 com.plotsquared.core.location.Location location = BukkitUtil.adapt(entity.getLocation()); | ||||
|   | ||||
| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|  * 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.bukkit.commands; | ||||
|  | ||||
| import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.plotsquared.core.player.ConsolePlayer; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.SenderMapper; | ||||
|  | ||||
| /** | ||||
|  * Mapper between {@link CommandSender} and {@link PlotPlayer}. | ||||
|  */ | ||||
| public final class BukkitSenderMapper implements SenderMapper<CommandSender, PlotPlayer<?>> { | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull PlotPlayer<?> map(final @NonNull CommandSender base) { | ||||
|         if (base instanceof Player player) { | ||||
|             return BukkitUtil.adapt(player); | ||||
|         } | ||||
|         return ConsolePlayer.getConsole(); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull CommandSender reverse(final @NonNull PlotPlayer<?> mapped) { | ||||
|         if (mapped instanceof ConsolePlayer) { | ||||
|             return Bukkit.getConsoleSender(); | ||||
|         } | ||||
|         return (Player) mapped.getPlatformPlayer(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,99 @@ | ||||
| /* | ||||
|  * 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.bukkit.inject; | ||||
|  | ||||
| import com.google.inject.AbstractModule; | ||||
| import com.google.inject.Key; | ||||
| import com.google.inject.TypeLiteral; | ||||
| import com.plotsquared.bukkit.BukkitPlatform; | ||||
| import com.plotsquared.bukkit.commands.BukkitSenderMapper; | ||||
| import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.plotsquared.core.commands.CommandRequirement; | ||||
| import com.plotsquared.core.commands.PlotSquaredCaptionProvider; | ||||
| import com.plotsquared.core.commands.PlotSquaredRequirementFailureHandler; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.ConsolePlayer; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.CommandManager; | ||||
| import org.incendo.cloud.bukkit.CloudBukkitCapabilities; | ||||
| import org.incendo.cloud.execution.ExecutionCoordinator; | ||||
| import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler; | ||||
| import org.incendo.cloud.paper.PaperCommandManager; | ||||
| import org.incendo.cloud.processors.requirements.RequirementPostprocessor; | ||||
|  | ||||
| public class CloudModule extends AbstractModule { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + CloudModule.class.getSimpleName()); | ||||
|  | ||||
|     private static @NonNull CommandSender convert(final @NonNull PlotPlayer<?> player) { | ||||
|         if (player instanceof ConsolePlayer) { | ||||
|             return Bukkit.getConsoleSender(); | ||||
|         } | ||||
|         return (Player) player.getPlatformPlayer(); | ||||
|     } | ||||
|  | ||||
|     private static @NonNull PlotPlayer<?> convert (final @NonNull CommandSender sender) { | ||||
|         if (sender instanceof Player player) { | ||||
|             return BukkitUtil.adapt(player); | ||||
|         } | ||||
|         return ConsolePlayer.getConsole(); | ||||
|     } | ||||
|  | ||||
|     private final BukkitPlatform bukkitPlatform; | ||||
|  | ||||
|     public CloudModule(final @NonNull BukkitPlatform bukkitPlatform) { | ||||
|         this.bukkitPlatform = bukkitPlatform; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void configure() { | ||||
|         final PaperCommandManager<PlotPlayer<?>> commandManager = new PaperCommandManager<PlotPlayer<?>>( | ||||
|                 this.bukkitPlatform, | ||||
|                 ExecutionCoordinator.asyncCoordinator(), | ||||
|                 new BukkitSenderMapper() | ||||
|         ); | ||||
|         commandManager.captionRegistry().registerProvider(new PlotSquaredCaptionProvider()); | ||||
|  | ||||
|         if (commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) { | ||||
|             commandManager.registerBrigadier(); | ||||
|         } else if (commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) { | ||||
|             commandManager.registerAsynchronousCompletions(); | ||||
|         } | ||||
|  | ||||
|         final RequirementPostprocessor<PlotPlayer<?>, CommandRequirement> requirementPostprocessor = | ||||
|                 RequirementPostprocessor.of(CommandRequirement.REQUIREMENTS_KEY, new PlotSquaredRequirementFailureHandler()); | ||||
|         commandManager.registerCommandPostProcessor(requirementPostprocessor); | ||||
|  | ||||
|         // TODO(City): Override parsing errors using MM parsing. | ||||
|         MinecraftExceptionHandler.<PlotPlayer<?>>create(PlotPlayer::getAudience) | ||||
|                 .defaultHandlers() | ||||
|                 .decorator((ctx, component) -> TranslatableCaption.of("core.prefix"). | ||||
|                         toComponent(ctx.context().sender()) | ||||
|                         .append(component)) | ||||
|                 .registerTo(commandManager); | ||||
|  | ||||
|         bind(Key.get(new TypeLiteral<CommandManager<PlotPlayer<?>>>() {})).toInstance(commandManager); | ||||
|     } | ||||
| } | ||||
| @@ -261,7 +261,10 @@ public class BlockEventListener implements Listener { | ||||
|                 final BlockFace facing = piston.getFacing(); | ||||
|                 location = location.add(facing.getModX(), facing.getModY(), facing.getModZ()); | ||||
|                 Plot newPlot = area.getOwnedPlotAbs(location); | ||||
|                 if (!plot.equals(newPlot)) { | ||||
|                 if (plot.equals(newPlot)) { | ||||
|                     return; | ||||
|                 } | ||||
|                 if (!plot.isMerged() || !plot.getConnectedPlots().contains(newPlot)) { | ||||
|                     event.setCancelled(true); | ||||
|                     plot.debug("Prevented piston update because of invalid edge piston detection"); | ||||
|                 } | ||||
|   | ||||
| @@ -35,6 +35,7 @@ import com.plotsquared.core.plot.flag.implementations.DisablePhysicsFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.EntityChangeBlockFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.ExplosionFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.InvincibleFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.ProjectileChangeBlockFlag; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| @@ -143,6 +144,10 @@ public class EntityEventListener implements Listener { | ||||
|         if (area == null) { | ||||
|             return; | ||||
|         } | ||||
|         // Armour-stands are handled elsewhere and should not be handled by area-wide entity-spawn options | ||||
|         if (entity.getType() == EntityType.ARMOR_STAND) { | ||||
|             return; | ||||
|         } | ||||
|         CreatureSpawnEvent.SpawnReason reason = event.getSpawnReason(); | ||||
|         switch (reason.toString()) { | ||||
|             case "DISPENSE_EGG", "EGG", "OCELOT_BABY", "SPAWNER_EGG" -> { | ||||
| @@ -153,7 +158,7 @@ public class EntityEventListener implements Listener { | ||||
|             } | ||||
|             case "REINFORCEMENTS", "NATURAL", "MOUNT", "PATROL", "RAID", "SHEARED", "SILVERFISH_BLOCK", "ENDER_PEARL", | ||||
|                     "TRAP", "VILLAGE_DEFENSE", "VILLAGE_INVASION", "BEEHIVE", "CHUNK_GEN", "NETHER_PORTAL", | ||||
|                     "DUPLICATION", "FROZEN", "SPELL" -> { | ||||
|                     "DUPLICATION", "FROZEN", "SPELL", "DEFAULT" -> { | ||||
|                 if (!area.isMobSpawning()) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
| @@ -166,7 +171,7 @@ public class EntityEventListener implements Listener { | ||||
|                 } | ||||
|             } | ||||
|             case "BUILD_IRONGOLEM", "BUILD_SNOWMAN", "BUILD_WITHER", "CUSTOM" -> { | ||||
|                 if (!area.isSpawnCustom() && entity.getType() != EntityType.ARMOR_STAND) { | ||||
|                 if (!area.isSpawnCustom()) { | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|                 } | ||||
| @@ -354,13 +359,13 @@ public class EntityEventListener implements Listener { | ||||
|             if (shooter instanceof Player) { | ||||
|                 PlotPlayer<?> pp = BukkitUtil.adapt((Player) shooter); | ||||
|                 if (plot == null) { | ||||
|                     if (!pp.hasPermission(Permission.PERMISSION_ADMIN_PROJECTILE_UNOWNED)) { | ||||
|                     if (area.isRoadFlags() && !area.getRoadFlag(ProjectileChangeBlockFlag.class) && !pp.hasPermission(Permission.PERMISSION_ADMIN_PROJECTILE_UNOWNED)) { | ||||
|                         entity.remove(); | ||||
|                         event.setCancelled(true); | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
|                 if (plot.isAdded(pp.getUUID()) || pp.hasPermission(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) { | ||||
|                 if (plot.isAdded(pp.getUUID()) || plot.getFlag(ProjectileChangeBlockFlag.class) || pp.hasPermission(Permission.PERMISSION_ADMIN_PROJECTILE_OTHER)) { | ||||
|                     return; | ||||
|                 } | ||||
|                 entity.remove(); | ||||
|   | ||||
| @@ -124,7 +124,7 @@ public class PaperListener implements Listener { | ||||
|         } | ||||
|         Slime slime = event.getEntity(); | ||||
|  | ||||
|         Block b = slime.getTargetBlock(4); | ||||
|         Block b = slime.getTargetBlockExact(4); | ||||
|         if (b == null) { | ||||
|             return; | ||||
|         } | ||||
| @@ -166,12 +166,16 @@ public class PaperListener implements Listener { | ||||
|         } | ||||
|         Location location = BukkitUtil.adapt(event.getSpawnLocation()); | ||||
|         PlotArea area = location.getPlotArea(); | ||||
|         if (!location.isPlotArea()) { | ||||
|         if (area == null) { | ||||
|             return; | ||||
|         } | ||||
|         //If entities are spawning... the chunk should be loaded? | ||||
|         // Armour-stands are handled elsewhere and should not be handled by area-wide entity-spawn options | ||||
|         if (event.getType() == EntityType.ARMOR_STAND) { | ||||
|             return; | ||||
|         } | ||||
|         // If entities are spawning... the chunk should be loaded? | ||||
|         Entity[] entities = event.getSpawnLocation().getChunk().getEntities(); | ||||
|         if (entities.length > Settings.Chunk_Processor.MAX_ENTITIES) { | ||||
|         if (entities.length >= Settings.Chunk_Processor.MAX_ENTITIES) { | ||||
|             event.setShouldAbortSpawn(true); | ||||
|             event.setCancelled(true); | ||||
|             return; | ||||
| @@ -200,7 +204,7 @@ public class PaperListener implements Listener { | ||||
|                 } | ||||
|             } | ||||
|             case "BUILD_IRONGOLEM", "BUILD_SNOWMAN", "BUILD_WITHER", "CUSTOM" -> { | ||||
|                 if (!area.isSpawnCustom() && event.getType() != EntityType.ARMOR_STAND) { | ||||
|                 if (!area.isSpawnCustom()) { | ||||
|                     event.setShouldAbortSpawn(true); | ||||
|                     event.setCancelled(true); | ||||
|                     return; | ||||
|   | ||||
| @@ -50,6 +50,7 @@ import com.plotsquared.core.plot.flag.implementations.DenyPortalsFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DenyTeleportFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DoneFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DropProtectionFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.EditSignFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.HangingBreakFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.HangingPlaceFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.HostileInteractFlag; | ||||
| @@ -87,6 +88,7 @@ import org.bukkit.Material; | ||||
| import org.bukkit.block.Block; | ||||
| import org.bukkit.block.BlockFace; | ||||
| import org.bukkit.block.BlockState; | ||||
| import org.bukkit.block.Sign; | ||||
| import org.bukkit.block.data.Waterlogged; | ||||
| import org.bukkit.command.PluginCommand; | ||||
| import org.bukkit.entity.ArmorStand; | ||||
| @@ -175,6 +177,33 @@ public class PlayerEventListener implements Listener { | ||||
|             Material.WRITABLE_BOOK, | ||||
|             Material.WRITTEN_BOOK | ||||
|     ); | ||||
|     private static final Set<String> DYES; | ||||
|     static { | ||||
|         Set<String> mutableDyes = new HashSet<>(Set.of( | ||||
|                 "WHITE_DYE", | ||||
|                 "LIGHT_GRAY_DYE", | ||||
|                 "GRAY_DYE", | ||||
|                 "BLACK_DYE", | ||||
|                 "BROWN_DYE", | ||||
|                 "RED_DYE", | ||||
|                 "ORANGE_DYE", | ||||
|                 "YELLOW_DYE", | ||||
|                 "LIME_DYE", | ||||
|                 "GREEN_DYE", | ||||
|                 "CYAN_DYE", | ||||
|                 "LIGHT_BLUE_DYE", | ||||
|                 "BLUE_DYE", | ||||
|                 "PURPLE_DYE", | ||||
|                 "MAGENTA_DYE", | ||||
|                 "PINK_DYE", | ||||
|                 "GLOW_INK_SAC" | ||||
|         )); | ||||
|         int[] version = PlotSquared.platform().serverVersion(); | ||||
|         if (version[1] >= 20 && version[2] >= 1) { | ||||
|             mutableDyes.add("HONEYCOMB"); | ||||
|         } | ||||
|         DYES = Set.copyOf(mutableDyes); | ||||
|     } | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|     private final WorldEdit worldEdit; | ||||
|     private final PlotAreaManager plotAreaManager; | ||||
| @@ -207,6 +236,40 @@ public class PlayerEventListener implements Listener { | ||||
|         this.plotListener = plotListener; | ||||
|     } | ||||
|  | ||||
|     @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) | ||||
|     public void onPlayerDyeSign(PlayerInteractEvent event) { | ||||
|         ItemStack itemStack = event.getItem(); | ||||
|         if (itemStack == null) { | ||||
|             return; | ||||
|         } | ||||
|         Block block = event.getClickedBlock(); | ||||
|         if (block != null && block.getState() instanceof Sign) { | ||||
|             if (DYES.contains(itemStack.getType().toString())) { | ||||
|                 Location location = BukkitUtil.adapt(block.getLocation()); | ||||
|                 PlotArea area = location.getPlotArea(); | ||||
|                 if (area == null) { | ||||
|                     return; | ||||
|                 } | ||||
|                 Plot plot = location.getOwnedPlot(); | ||||
|                 if (plot == null) { | ||||
|                     if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, EditSignFlag.class, false) | ||||
|                             && !event.getPlayer().hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString())) { | ||||
|                         event.setCancelled(true); | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
|                 if (plot.isAdded(event.getPlayer().getUniqueId())) { | ||||
|                     return; // allow for added players | ||||
|                 } | ||||
|                 if (!plot.getFlag(EditSignFlag.class) | ||||
|                         && !event.getPlayer().hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString())) { | ||||
|                     plot.debug(event.getPlayer().getName() + " could not color the sign because of edit-sign = false"); | ||||
|                     event.setCancelled(true); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @EventHandler(ignoreCancelled = true) | ||||
|     public void onEffect(@NonNull EntityPotionEffectEvent event) { | ||||
|         if (Settings.Enabled_Components.DISABLE_BEACON_EFFECT_OVERFLOW || | ||||
|   | ||||
| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  * 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.bukkit.listener; | ||||
|  | ||||
| import com.plotsquared.bukkit.util.BukkitUtil; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
| import com.plotsquared.core.plot.flag.implementations.EditSignFlag; | ||||
| import com.plotsquared.core.util.PlotFlagUtil; | ||||
| import org.bukkit.block.Sign; | ||||
| import org.bukkit.event.EventHandler; | ||||
| import org.bukkit.event.Listener; | ||||
| import org.bukkit.event.player.PlayerSignOpenEvent; | ||||
|  | ||||
| /** | ||||
|  * For events since 1.20.1 | ||||
|  * @since 7.2.1 | ||||
|  */ | ||||
| public class PlayerEventListener1201 implements Listener { | ||||
|  | ||||
|     @EventHandler(ignoreCancelled = true) | ||||
|     @SuppressWarnings({"removal", "UnstableApiUsage"}) // thanks Paper, thanks Spigot | ||||
|     public void onPlayerSignOpenEvent(PlayerSignOpenEvent event) { | ||||
|         Sign sign = event.getSign(); | ||||
|         Location location = BukkitUtil.adapt(sign.getLocation()); | ||||
|         PlotArea area = location.getPlotArea(); | ||||
|         if (area == null) { | ||||
|             return; | ||||
|         } | ||||
|         Plot plot = location.getOwnedPlot(); | ||||
|         if (plot == null) { | ||||
|             if (PlotFlagUtil.isAreaRoadFlagsAndFlagEquals(area, EditSignFlag.class, false) | ||||
|                     && !event.getPlayer().hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString())) { | ||||
|                 event.setCancelled(true); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         if (plot.isAdded(event.getPlayer().getUniqueId())) { | ||||
|             return; // allow for added players | ||||
|         } | ||||
|         if (!plot.getFlag(EditSignFlag.class) | ||||
|                 && !event.getPlayer().hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString())) { | ||||
|             plot.debug(event.getPlayer().getName() + " could not edit the sign because of edit-sign = false"); | ||||
|             event.setCancelled(true); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -158,6 +158,7 @@ public class BukkitPlayer extends PlotPlayer<Player> { | ||||
|         } | ||||
|         final String[] nodes = stub.split("\\."); | ||||
|         final StringBuilder n = new StringBuilder(); | ||||
|         // Wildcard check from less specific permission to more specific permission | ||||
|         for (int i = 0; i < (nodes.length - 1); i++) { | ||||
|             n.append(nodes[i]).append("."); | ||||
|             if (!stub.equals(n + Permission.PERMISSION_STAR.toString())) { | ||||
| @@ -166,9 +167,11 @@ public class BukkitPlayer extends PlotPlayer<Player> { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // Wildcard check for the full permission | ||||
|         if (hasPermission(stub + ".*")) { | ||||
|             return Integer.MAX_VALUE; | ||||
|         } | ||||
|         // Permission value cache for iterative check | ||||
|         int max = 0; | ||||
|         if (CHECK_EFFECTIVE) { | ||||
|             boolean hasAny = false; | ||||
|   | ||||
| @@ -47,7 +47,21 @@ public class TranslationUpdateManager { | ||||
|         String usedGrants = "usedGrants"; | ||||
|         String usedGrantsReplacement = "used_grants"; | ||||
|         String remainingGrants = "remainingGrants"; | ||||
|         String rremainingGrantsReplacement = "remaining_grants"; | ||||
|         String remainingGrantsReplacement = "remaining_grants"; | ||||
|         String minimumRadius = "minimumRadius"; | ||||
|         String minimumRadiusReplacement = "minimum_radius"; | ||||
|         String maximumMoves = "maximumMoves"; | ||||
|         String maximumMovesReplacement = "maximum_moves"; | ||||
|         String userMove = "userMove"; | ||||
|         String userMoveReplacement = "user_move"; | ||||
|  | ||||
|         // tag opening / closing characters are important, as the locale keys exist as well, which should not be replaced | ||||
|         String listInfoUnknown = "<info.unknown>"; | ||||
|         String listInfoUnknownReplacement = "<unknown>"; | ||||
|         String listInfoServer = "<info.server>"; | ||||
|         String listInfoServerReplacement = "<server>"; | ||||
|         String listInfoEveryone = "<info.everyone>"; | ||||
|         String listInfoEveryoneReplacement = "<everyone>"; | ||||
|  | ||||
|         try (Stream<Path> paths = Files.walk(Paths.get(PlotSquared.platform().getDirectory().toPath().resolve("lang").toUri()))) { | ||||
|             paths | ||||
| @@ -58,7 +72,13 @@ public class TranslationUpdateManager { | ||||
|                         replaceInFile(p, minHeight, minheightReplacement); | ||||
|                         replaceInFile(p, maxHeight, maxheightReplacement); | ||||
|                         replaceInFile(p, usedGrants, usedGrantsReplacement); | ||||
|                         replaceInFile(p, remainingGrants, rremainingGrantsReplacement); | ||||
|                         replaceInFile(p, remainingGrants, remainingGrantsReplacement); | ||||
|                         replaceInFile(p, minimumRadius, minimumRadiusReplacement); | ||||
|                         replaceInFile(p, maximumMoves, maximumMovesReplacement); | ||||
|                         replaceInFile(p, userMove, userMoveReplacement); | ||||
|                         replaceInFile(p, listInfoUnknown, listInfoUnknownReplacement); | ||||
|                         replaceInFile(p, listInfoServer, listInfoServerReplacement); | ||||
|                         replaceInFile(p, listInfoEveryone, listInfoEveryoneReplacement); | ||||
|                     }); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -15,6 +15,11 @@ dependencies { | ||||
|     api(libs.adventureApi) | ||||
|     api(libs.adventureMiniMessage) | ||||
|  | ||||
|     // Cloud | ||||
|     api(libs.cloud) | ||||
|     api(libs.cloudMinecraftExtras) | ||||
|     api(libs.cloudRequirements) | ||||
|  | ||||
|     // Guice | ||||
|     api(libs.guice) { | ||||
|         exclude(group = "com.google.guava") | ||||
| @@ -71,7 +76,7 @@ tasks { | ||||
|         opt.links("https://jd.advntr.dev/api/4.14.0/") | ||||
|         opt.links("https://jd.advntr.dev/text-minimessage/4.14.0/") | ||||
|         opt.links("https://google.github.io/guice/api-docs/" + libs.guice.get().versionConstraint.toString() + "/javadoc/") | ||||
|         opt.links("https://checkerframework.org/api/") | ||||
|       //  opt.links("https://checkerframework.org/api/") | ||||
|         opt.isLinkSource = true | ||||
|         opt.bottom(File("$rootDir/javadocfooter.html").readText()) | ||||
|         opt.isUse = true | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core; | ||||
|  | ||||
| import cloud.commandframework.services.ServicePipeline; | ||||
| import com.google.inject.Injector; | ||||
| import com.google.inject.Key; | ||||
| import com.google.inject.TypeLiteral; | ||||
| @@ -47,6 +46,7 @@ import net.kyori.adventure.audience.Audience; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import org.incendo.cloud.services.ServicePipeline; | ||||
|  | ||||
| import java.io.File; | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.command; | ||||
|  | ||||
| import cloud.commandframework.services.ServicePipeline; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| @@ -49,6 +48,7 @@ import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import org.incendo.cloud.services.ServicePipeline; | ||||
|  | ||||
| import java.util.Collections; | ||||
| import java.util.Iterator; | ||||
| @@ -332,7 +332,7 @@ public class Auto extends SubCommand { | ||||
|         List<Plot> plots = this.servicePipeline | ||||
|                 .pump(new AutoQuery(player, null, sizeX, sizeZ, plotarea)) | ||||
|                 .through(AutoService.class) | ||||
|                 .getResult(); | ||||
|                 .complete(); | ||||
|  | ||||
|         plots = this.eventDispatcher.callAutoPlotsChosen(player, plots).getPlots(); | ||||
|  | ||||
|   | ||||
| @@ -256,11 +256,11 @@ public class Condense extends SubCommand { | ||||
|                 player.sendMessage(TranslatableCaption.of("condense.default_eval")); | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("condense.minimum_radius"), | ||||
|                         TagResolver.resolver("minimumRadius", Tag.inserting(Component.text(minimumRadius))) | ||||
|                         TagResolver.resolver("minimum_radius", Tag.inserting(Component.text(minimumRadius))) | ||||
|                 ); | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("condense.maximum_moved"), | ||||
|                         TagResolver.resolver("maxMove", Tag.inserting(Component.text(maxMove))) | ||||
|                         TagResolver.resolver("maximum_moves", Tag.inserting(Component.text(maxMove))) | ||||
|                 ); | ||||
|                 player.sendMessage(TranslatableCaption.of("condense.input_eval")); | ||||
|                 player.sendMessage( | ||||
| @@ -269,7 +269,7 @@ public class Condense extends SubCommand { | ||||
|                 ); | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("condense.estimated_moves"), | ||||
|                         TagResolver.resolver("userMove", Tag.inserting(Component.text(userMove))) | ||||
|                         TagResolver.resolver("user_move", Tag.inserting(Component.text(userMove))) | ||||
|                 ); | ||||
|                 player.sendMessage(TranslatableCaption.of("condense.eta")); | ||||
|                 player.sendMessage(TranslatableCaption.of("condense.radius_measured")); | ||||
|   | ||||
| @@ -94,7 +94,7 @@ public class Done extends SubCommand { | ||||
|                 TagResolver.resolver("plot", Tag.inserting(Component.text(plot.getId().toString()))) | ||||
|         ); | ||||
|         final Settings.Auto_Clear doneRequirements = Settings.AUTO_CLEAR.get("done"); | ||||
|         if (PlotSquared.platform().expireManager() == null || doneRequirements == null) { | ||||
|         if (PlotSquared.platform().expireManager() == null || doneRequirements == null || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_DONE)) { | ||||
|             finish(plot, player, true); | ||||
|             plot.removeRunning(); | ||||
|         } else { | ||||
|   | ||||
| @@ -136,7 +136,9 @@ public class Download extends SubCommand { | ||||
|                     } | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("web.generation_link_success_legacy_world"), | ||||
|                             TagResolver.resolver("url", Tag.inserting(Component.text(url.toString()))) | ||||
|                             TagResolver.builder() | ||||
|                                     .tag("url", Tag.preProcessParsed(url.toString())) | ||||
|                                     .build() | ||||
|                     ); | ||||
|                 } | ||||
|             }); | ||||
|   | ||||
| @@ -103,9 +103,10 @@ public final class FlagCommand extends Command { | ||||
|         if (flag instanceof IntegerFlag && MathMan.isInteger(value)) { | ||||
|             try { | ||||
|                 int numeric = Integer.parseInt(value); | ||||
|                 // Getting full permission without ".<amount>" at the end | ||||
|                 perm = perm.substring(0, perm.length() - value.length() - 1); | ||||
|                 boolean result = false; | ||||
|                 if (numeric > 0) { | ||||
|                 if (numeric >= 0) { | ||||
|                     int checkRange = PlotSquared.get().getPlatform().equalsIgnoreCase("bukkit") ? | ||||
|                             numeric : | ||||
|                             Settings.Limit.MAX_PLOTS; | ||||
|   | ||||
| @@ -465,7 +465,7 @@ public class ListCmd extends SubCommand { | ||||
|                 TextComponent.Builder builder = Component.text(); | ||||
|                 if (plot.getFlag(ServerPlotFlag.class)) { | ||||
|                     TagResolver serverResolver = TagResolver.resolver( | ||||
|                             "info.server", | ||||
|                             "server", | ||||
|                             Tag.inserting(TranslatableCaption.of("info.server").toComponent(player)) | ||||
|                     ); | ||||
|                     builder.append(MINI_MESSAGE.deserialize(server, serverResolver)); | ||||
| @@ -483,13 +483,13 @@ public class ListCmd extends SubCommand { | ||||
|                                 builder.append(MINI_MESSAGE.deserialize(online, resolver)); | ||||
|                             } else if (uuidMapping.username().equalsIgnoreCase("unknown")) { | ||||
|                                 TagResolver unknownResolver = TagResolver.resolver( | ||||
|                                         "info.unknown", | ||||
|                                         "unknown", | ||||
|                                         Tag.inserting(TranslatableCaption.of("info.unknown").toComponent(player)) | ||||
|                                 ); | ||||
|                                 builder.append(MINI_MESSAGE.deserialize(unknown, unknownResolver)); | ||||
|                             } else if (uuidMapping.uuid().equals(DBFunc.EVERYONE)) { | ||||
|                                 TagResolver everyoneResolver = TagResolver.resolver( | ||||
|                                         "info.everyone", | ||||
|                                         "everyone", | ||||
|                                         Tag.inserting(TranslatableCaption.of("info.everyone").toComponent(player)) | ||||
|                                 ); | ||||
|                                 builder.append(MINI_MESSAGE.deserialize(everyone, everyoneResolver)); | ||||
|   | ||||
| @@ -100,15 +100,17 @@ public class Remove extends SubCommand { | ||||
|                             count++; | ||||
|                         } | ||||
|                     } else if (uuid == DBFunc.EVERYONE) { | ||||
|                         count += plot.getTrusted().size(); | ||||
|                         if (plot.removeTrusted(uuid)) { | ||||
|                             this.eventDispatcher.callTrusted(player, plot, uuid, false); | ||||
|                             count++; | ||||
|                         } else if (plot.removeMember(uuid)) { | ||||
|                         } | ||||
|                         count += plot.getMembers().size(); | ||||
|                         if (plot.removeMember(uuid)) { | ||||
|                             this.eventDispatcher.callMember(player, plot, uuid, false); | ||||
|                             count++; | ||||
|                         } else if (plot.removeDenied(uuid)) { | ||||
|                         } | ||||
|                         count += plot.getDenied().size(); | ||||
|                         if (plot.removeDenied(uuid)) { | ||||
|                             this.eventDispatcher.callDenied(player, plot, uuid, false); | ||||
|                             count++; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -0,0 +1,98 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
| import org.incendo.cloud.processors.requirements.Requirement; | ||||
| import org.incendo.cloud.processors.requirements.Requirements; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * Something that is required for a command to be executed. | ||||
|  */ | ||||
| public interface CommandRequirement extends Requirement<PlotPlayer<?>, CommandRequirement> { | ||||
|  | ||||
|     /** | ||||
|      * The key used to store the requirements in the {@link org.incendo.cloud.meta.CommandMeta}. | ||||
|      */ | ||||
|     CloudKey<Requirements<PlotPlayer<?>, CommandRequirement>> REQUIREMENTS_KEY = CloudKey.of( | ||||
|             "requirements", | ||||
|             new TypeToken<Requirements<PlotPlayer<?>, CommandRequirement>>() { | ||||
|             } | ||||
|     ); | ||||
|  | ||||
|     /** | ||||
|      * Returns the caption sent when the requirement is not met. | ||||
|      * | ||||
|      * @return the caption | ||||
|      */ | ||||
|     @NonNull TranslatableCaption failureCaption(); | ||||
|  | ||||
|     /** | ||||
|      * Returns the placeholder values. | ||||
|      * | ||||
|      * @return placeholder values | ||||
|      */ | ||||
|     default @NonNull TagResolver @NonNull[] tagResolvers() { | ||||
|         return new TagResolver[0]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a requirement that evaluates to {@code true} if the sender has the given {@code permission} or if | ||||
|      * this requirement evaluates to {@code true}. | ||||
|      * | ||||
|      * @param permission the override permission | ||||
|      * @return the new requirement | ||||
|      */ | ||||
|     default @NonNull CommandRequirement withPermissionOverride(final @NonNull Permission permission) { | ||||
|         final CommandRequirement thisRequirement = this; | ||||
|         return new CommandRequirement() { | ||||
|             @Override | ||||
|             public @NonNull TranslatableCaption failureCaption() { | ||||
|                 return TranslatableCaption.of("permission.no_permission"); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public @NonNull TagResolver @NonNull [] tagResolvers() { | ||||
|                 return new TagResolver[] { | ||||
|                         TagResolver.resolver("node", Tag.inserting(Permission.PERMISSION_SET_FLAG_OTHER)) | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public @NonNull List<@NonNull CommandRequirement> parents() { | ||||
|                 return thisRequirement.parents(); | ||||
|             } | ||||
|  | ||||
|             @Override | ||||
|             public boolean evaluateRequirement(final @NonNull CommandContext<PlotPlayer<?>> context) { | ||||
|                 return context.sender().hasPermission(permission) || thisRequirement.evaluateRequirement(context); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,81 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
| import java.util.function.Predicate; | ||||
|  | ||||
| /** | ||||
|  * Common {@link CommandRequirement command requirements}. | ||||
|  */ | ||||
| public enum CommonCommandRequirement implements CommandRequirement { | ||||
|     /** | ||||
|      * Requires that the command sender is currently in a plot. | ||||
|      */ | ||||
|     REQUIRES_PLOT(TranslatableCaption.of("errors.not_in_plot"), ctx -> ctx.sender().getCurrentPlot() != null), | ||||
|     /** | ||||
|      * Requires that the command sender is in a claimed plot. | ||||
|      */ | ||||
|     REQUIRES_OWNER(TranslatableCaption.of("working.plot_not_claimed"), | ||||
|             ctx -> ctx.sender().getCurrentPlot().hasOwner(), | ||||
|             REQUIRES_PLOT | ||||
|     ), | ||||
|     /** | ||||
|      * Requires that the command sender is the plot owner. | ||||
|      */ | ||||
|     IS_OWNER(TranslatableCaption.of("permission.no_plot_perms"), | ||||
|             ctx -> ctx.sender().getCurrentPlot().isOwner(ctx.sender().getUUID()), | ||||
|             REQUIRES_OWNER | ||||
|     ) | ||||
|     ; | ||||
|  | ||||
|     private final TranslatableCaption failureCaption; | ||||
|     private final Predicate<CommandContext<PlotPlayer<?>>> predicate; | ||||
|     private final List<@NonNull CommandRequirement> parents; | ||||
|  | ||||
|     CommonCommandRequirement( | ||||
|             final @NonNull TranslatableCaption failureCaption, | ||||
|             final @NonNull Predicate<CommandContext<PlotPlayer<?>>> predicate, | ||||
|             final @NonNull CommandRequirement @NonNull... parents | ||||
|     ) { | ||||
|         this.failureCaption = failureCaption; | ||||
|         this.predicate = predicate; | ||||
|         this.parents = Arrays.asList(parents); | ||||
|     } | ||||
|  | ||||
|     public @NonNull TranslatableCaption failureCaption() { | ||||
|         return this.failureCaption; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull List<@NonNull CommandRequirement> parents() { | ||||
|         return this.parents; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean evaluateRequirement(final @NonNull CommandContext<PlotPlayer<?>> context) { | ||||
|         return this.predicate.test(context); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,50 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.configuration.caption.CaptionMap; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import org.incendo.cloud.caption.Caption; | ||||
| import org.incendo.cloud.caption.CaptionProvider; | ||||
|  | ||||
| /** | ||||
|  * {@link CaptionProvider} that retrieves caption values from the {@link CaptionMap caption map}. | ||||
|  */ | ||||
| public final class PlotSquaredCaptionProvider implements CaptionProvider<PlotPlayer<?>> { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + PlotSquaredCaptionProvider.class.getSimpleName()); | ||||
|  | ||||
|     @Override | ||||
|     public @Nullable String provide(final @NonNull Caption caption, final @NonNull PlotPlayer<?> recipient) { | ||||
|         try { | ||||
|             return PlotSquared.get() | ||||
|                     .getCaptionMap(TranslatableCaption.DEFAULT_NAMESPACE) | ||||
|                     .getMessage(TranslatableCaption.of(caption.key()), recipient); | ||||
|         } catch (final CaptionMap.NoSuchCaptionException ignored) { | ||||
|             LOGGER.warn("Missing caption '{}', will attempt to fall back on Cloud defaults", caption.key()); | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,78 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.plotsquared.core.command.CommandCategory; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
| import org.incendo.cloud.bean.CommandBean; | ||||
| import org.incendo.cloud.bean.CommandProperties; | ||||
| import org.incendo.cloud.processors.requirements.RequirementApplicable; | ||||
| import org.incendo.cloud.processors.requirements.Requirements; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public abstract class PlotSquaredCommandBean extends CommandBean<PlotPlayer<?>> { | ||||
|  | ||||
|     private final RequirementApplicable.RequirementApplicableFactory<PlotPlayer<?>, CommandRequirement> | ||||
|             requirementApplicableFactory = RequirementApplicable.factory(CommandRequirement.REQUIREMENTS_KEY); | ||||
|  | ||||
|     /** | ||||
|      * Returns the category of the command. | ||||
|      * | ||||
|      * @return the category | ||||
|      */ | ||||
|     public abstract @NonNull CommandCategory category(); | ||||
|  | ||||
|     /** | ||||
|      * Returns the requirements for the command to be executable. | ||||
|      * | ||||
|      * @return the requirements | ||||
|      */ | ||||
|     public abstract @NonNull List<@NonNull CommandRequirement> requirements(); | ||||
|  | ||||
|     /** | ||||
|      * Prepares the given {@code builder}. | ||||
|      * | ||||
|      * <p>This should be implemented by abstract classes that extend {@link PlotSquaredCommandBean} to offer shared behavior | ||||
|      * for a subset of plot commands.</p> | ||||
|      * | ||||
|      * @param builder the builder | ||||
|      * @return the prepared builder | ||||
|      */ | ||||
|     protected Command.@NonNull Builder<PlotPlayer<?>> prepare(final Command.@NonNull Builder<PlotPlayer<?>> builder) { | ||||
|         return builder; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected final @NonNull CommandProperties properties() { | ||||
|         return CommandProperties.of("platsquared", "plat"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected final Command.@NonNull Builder<PlotPlayer<?>> configure(final Command.@NonNull Builder<PlotPlayer<?>> builder) { | ||||
|         return this.configurePlotCommand(this.prepare(builder.meta(PlotSquaredCommandMeta.META_CATEGORY, this.category()))) | ||||
|                 .apply(this.requirementApplicableFactory.create(Requirements.of(this.requirements()))); | ||||
|     } | ||||
|  | ||||
|     protected abstract Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( | ||||
|             Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ); | ||||
| } | ||||
| @@ -0,0 +1,74 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Injector; | ||||
| import com.google.inject.Key; | ||||
| import com.google.inject.Singleton; | ||||
| import com.google.inject.TypeLiteral; | ||||
| import com.plotsquared.core.commands.injection.PlotInjector; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.CommandManager; | ||||
| import org.incendo.cloud.injection.GuiceInjectionService; | ||||
|  | ||||
| import java.util.Set; | ||||
|  | ||||
| @Singleton | ||||
| public final class PlotSquaredCommandManager { | ||||
|  | ||||
|     private final CommandManager<PlotPlayer<?>> commandManager; | ||||
|     private final Injector injector; | ||||
|  | ||||
|     @Inject | ||||
|     public PlotSquaredCommandManager( | ||||
|             final @NonNull CommandManager<PlotPlayer<?>> commandManager, | ||||
|             final @NonNull Injector injector | ||||
|     ) { | ||||
|         this.commandManager = commandManager; | ||||
|         this.injector = injector; | ||||
|         this.registerInjectors(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Registers the commands that are shipped with PlotSquared. | ||||
|      */ | ||||
|     public void registerDefaultCommands() { | ||||
|         final Set<PlotSquaredCommandBean> commands = | ||||
|                 this.injector.getInstance(Key.get(new TypeLiteral<Set<PlotSquaredCommandBean>>() {})); | ||||
|         commands.forEach(command -> this.commandManager().command(command)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the command manager. | ||||
|      * | ||||
|      * @return the command manager | ||||
|      */ | ||||
|     public @NonNull CommandManager<PlotPlayer<?>> commandManager() { | ||||
|         return this.commandManager; | ||||
|     } | ||||
|  | ||||
|     private void registerInjectors() { | ||||
|         this.commandManager.parameterInjectorRegistry().registerInjector(Plot.class, | ||||
|                 this.injector.getInstance(PlotInjector.class)); | ||||
|         this.commandManager.parameterInjectorRegistry().registerInjectionService(GuiceInjectionService.create(this.injector)); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,36 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.plotsquared.core.command.CommandCategory; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
|  | ||||
| /** | ||||
|  * Shared {@link org.incendo.cloud.meta.CommandMeta command meta} keys. | ||||
|  */ | ||||
| public final class PlotSquaredCommandMeta { | ||||
|  | ||||
|     /** | ||||
|      * Key that determines what {@link CommandCategory category} a command belongs to. | ||||
|      */ | ||||
|     public static final CloudKey<CommandCategory> META_CATEGORY = CloudKey.of("category", CommandCategory.class); | ||||
|  | ||||
|     private PlotSquaredCommandMeta() { | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|  * 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.commands; | ||||
|  | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.processors.requirements.RequirementFailureHandler; | ||||
|  | ||||
| public final class PlotSquaredRequirementFailureHandler implements RequirementFailureHandler<PlotPlayer<?>, CommandRequirement> { | ||||
|  | ||||
|     @Override | ||||
|     public void handleFailure( | ||||
|             final @NonNull CommandContext<PlotPlayer<?>> context, | ||||
|             final @NonNull CommandRequirement requirement | ||||
|     ) { | ||||
|         context.sender().sendMessage(requirement.failureCaption(), requirement.tagResolvers()); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,120 @@ | ||||
| /* | ||||
|  * 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.commands.command.setting.flag; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.parser.PlotFlagParser; | ||||
| import com.plotsquared.core.commands.suggestions.FlagValueSuggestionProvider; | ||||
| import com.plotsquared.core.configuration.caption.CaptionUtility; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.events.PlotFlagAddEvent; | ||||
| import com.plotsquared.core.events.Result; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.flag.FlagParseException; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
|  | ||||
| import static com.plotsquared.core.commands.parser.PlotFlagParser.plotFlagParser; | ||||
| import static org.incendo.cloud.parser.standard.StringParser.greedyStringParser; | ||||
|  | ||||
| public final class FlagAddCommand extends FlagCommandBean { | ||||
|  | ||||
|     private static final CloudKey<PlotFlag<?, ?>> COMPONENT_FLAG = CloudKey.of("flag", new TypeToken<PlotFlag<?, ?>>() {}); | ||||
|     private static final CloudKey<String> COMPONENT_VALUE = CloudKey.of("value", String.class); | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     public FlagAddCommand(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( | ||||
|             final Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ) { | ||||
|         return builder.literal("add") | ||||
|                 .required(COMPONENT_FLAG, plotFlagParser(PlotFlagParser.FlagSource.GLOBAL)) | ||||
|                 .required(COMPONENT_VALUE, greedyStringParser(), new FlagValueSuggestionProvider(COMPONENT_FLAG)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(final @NonNull CommandContext<PlotPlayer<?>> commandContext) { | ||||
|         final PlotPlayer<?> player = commandContext.sender(); | ||||
|         final Plot plot = commandContext.inject(Plot.class).orElseThrow(); | ||||
|         final PlotFlag<?, ?> flag = commandContext.get(COMPONENT_FLAG); | ||||
|         final String flagValue = commandContext.get(COMPONENT_VALUE); | ||||
|  | ||||
|         final PlotFlagAddEvent event = this.eventDispatcher.callFlagAdd(flag, plot); | ||||
|         if (event.getEventResult() == Result.DENY) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("events.event_denied"), | ||||
|                     TagResolver.resolver("value", Tag.inserting(Component.text("Flag set"))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|         if (event.getEventResult() != Result.FORCE) { | ||||
|             final String[] split = flagValue.split(","); | ||||
|             for (final String entry : split) { | ||||
|                 if (!checkPermValue(player, flag, flag.getName(), entry)) { | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         final String sanitizedValue = CaptionUtility.stripClickEvents(flag, flagValue); | ||||
|         final PlotFlag<?, ?> parsedFlag; | ||||
|         try { | ||||
|             parsedFlag = flag.parse(flagValue); | ||||
|         } catch (final FlagParseException e) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("flag.flag_parse_error"), | ||||
|                     TagResolver.builder() | ||||
|                             .tag("flag_name", Tag.inserting(Component.text(flag.getName()))) | ||||
|                             .tag("flag_value", Tag.inserting(Component.text(e.getValue()))) | ||||
|                             .tag("error", Tag.inserting(e.getErrorMessage().toComponent(player))) | ||||
|                             .build() | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final boolean result = plot.setFlag(plot.getFlagContainer().getFlag(flag.getClass()).merge(parsedFlag.getValue())); | ||||
|         if (!result) { | ||||
|             player.sendMessage(TranslatableCaption.of("flag.flag_not_added")); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_added"), | ||||
|                 TagResolver.builder() | ||||
|                         .tag("flag", Tag.inserting(Component.text(flag.getName()))) | ||||
|                         .tag("value", Tag.inserting(Component.text(parsedFlag.toString()))) | ||||
|                         .build() | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,139 @@ | ||||
| /* | ||||
|  * 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.commands.command.setting.flag; | ||||
|  | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.command.CommandCategory; | ||||
| import com.plotsquared.core.commands.CommandRequirement; | ||||
| import com.plotsquared.core.commands.CommonCommandRequirement; | ||||
| import com.plotsquared.core.commands.PlotSquaredCommandBean; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.flag.FlagParseException; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.plot.flag.types.IntegerFlag; | ||||
| import com.plotsquared.core.plot.flag.types.ListFlag; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public abstract class FlagCommandBean extends PlotSquaredCommandBean { | ||||
|  | ||||
|     protected static boolean checkPermValue( | ||||
|             final @NonNull PlotPlayer<?> player, | ||||
|             final @NonNull PlotFlag<?, ?> flag, @NonNull String key, @NonNull String value | ||||
|     ) { | ||||
|         key = key.toLowerCase(); | ||||
|         value = value.toLowerCase(); | ||||
|         String perm = Permission.PERMISSION_SET_FLAG_KEY_VALUE.format(key.toLowerCase(), value.toLowerCase()); | ||||
|         if (flag instanceof IntegerFlag && MathMan.isInteger(value)) { | ||||
|             try { | ||||
|                 int numeric = Integer.parseInt(value); | ||||
|                 // Getting full permission without ".<amount>" at the end | ||||
|                 perm = perm.substring(0, perm.length() - value.length() - 1); | ||||
|                 boolean result = false; | ||||
|                 if (numeric >= 0) { | ||||
|                     int checkRange = PlotSquared.get().getPlatform().equalsIgnoreCase("bukkit") ? | ||||
|                             numeric : | ||||
|                             Settings.Limit.MAX_PLOTS; | ||||
|                     result = player.hasPermissionRange(perm, checkRange) >= numeric; | ||||
|                 } | ||||
|                 if (!result) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
|                             TagResolver.resolver( | ||||
|                                     "node", | ||||
|                                     Tag.inserting(Component.text(perm + "." + numeric)) | ||||
|                             ) | ||||
|                     ); | ||||
|                 } | ||||
|                 return result; | ||||
|             } catch (NumberFormatException ignore) { | ||||
|             } | ||||
|         } else if (flag instanceof final ListFlag<?, ?> listFlag) { | ||||
|             try { | ||||
|                 PlotFlag<? extends List<?>, ?> parsedFlag = listFlag.parse(value); | ||||
|                 for (final Object entry : parsedFlag.getValue()) { | ||||
|                     final String permission = Permission.PERMISSION_SET_FLAG_KEY_VALUE.format( | ||||
|                             key.toLowerCase(), | ||||
|                             entry.toString().toLowerCase() | ||||
|                     ); | ||||
|                     final boolean result = player.hasPermission(permission); | ||||
|                     if (!result) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.no_permission"), | ||||
|                                 TagResolver.resolver("node", Tag.inserting(Component.text(permission))) | ||||
|                         ); | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|             } catch (final FlagParseException e) { | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("flag.flag_parse_error"), | ||||
|                         TagResolver.builder() | ||||
|                                 .tag("flag_name", Tag.inserting(Component.text(flag.getName()))) | ||||
|                                 .tag("flag_value", Tag.inserting(Component.text(e.getValue()))) | ||||
|                                 .tag("error", Tag.inserting(e.getErrorMessage().toComponent(player))) | ||||
|                                 .build() | ||||
|                 ); | ||||
|                 return false; | ||||
|             } catch (final Exception e) { | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         boolean result; | ||||
|         String basePerm = Permission.PERMISSION_SET_FLAG_KEY.format(key.toLowerCase()); | ||||
|         if (flag.isValuedPermission()) { | ||||
|             result = player.hasKeyedPermission(basePerm, value); | ||||
|         } else { | ||||
|             result = player.hasPermission(basePerm); | ||||
|             perm = basePerm; | ||||
|         } | ||||
|         if (!result) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("permission.no_permission"), | ||||
|                     TagResolver.resolver("node", Tag.inserting(Component.text(perm))) | ||||
|             ); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public final @NonNull CommandCategory category() { | ||||
|         return CommandCategory.SETTINGS; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull List<@NonNull CommandRequirement> requirements() { | ||||
|         return List.of(CommonCommandRequirement.IS_OWNER.withPermissionOverride(Permission.PERMISSION_SET_FLAG_OTHER)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected final Command.@NonNull Builder<PlotPlayer<?>> prepare(final Command.@NonNull Builder<PlotPlayer<?>> builder) { | ||||
|         return builder.literal("flag"); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,88 @@ | ||||
| /* | ||||
|  * 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.commands.command.setting.flag; | ||||
|  | ||||
| import com.plotsquared.core.commands.parser.PlotFlagParser; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
|  | ||||
| import static com.plotsquared.core.commands.parser.PlotFlagParser.plotFlagParser; | ||||
|  | ||||
| public final class FlagInfoCommand extends FlagCommandBean { | ||||
|  | ||||
|     private static final CloudKey<PlotFlag<?, ?>> COMPONENT_FLAG = CloudKey.of("flag", new TypeToken<PlotFlag<?, ?>>() {}); | ||||
|  | ||||
|     @Override | ||||
|     protected Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand(final Command.@NonNull Builder<PlotPlayer<?>> builder) { | ||||
|         return builder.literal("info") | ||||
|                 .required(COMPONENT_FLAG, plotFlagParser(PlotFlagParser.FlagSource.GLOBAL)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(final @NonNull CommandContext<PlotPlayer<?>> commandContext) { | ||||
|         final PlotFlag<?, ?> plotFlag = commandContext.get(COMPONENT_FLAG); | ||||
|         final PlotPlayer<?> player = commandContext.sender(); | ||||
|  | ||||
|         player.sendMessage(TranslatableCaption.of("flag.flag_info_header")); | ||||
|         // Flag name | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_info_name"), | ||||
|                 TagResolver.resolver("flag", Tag.inserting(Component.text(plotFlag.getName()))) | ||||
|         ); | ||||
|         // Flag category | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_info_category"), | ||||
|                 TagResolver.resolver( | ||||
|                         "value", | ||||
|                         Tag.inserting(plotFlag.getFlagCategory().toComponent(player)) | ||||
|                 ) | ||||
|         ); | ||||
|         // Flag description | ||||
|         // TODO maybe merge and \n instead? | ||||
|         player.sendMessage(TranslatableCaption.of("flag.flag_info_description")); | ||||
|         player.sendMessage(plotFlag.getFlagDescription()); | ||||
|         // Flag example | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_info_example"), | ||||
|                 TagResolver.builder() | ||||
|                         .tag("command", Tag.preProcessParsed("/plot flag set")) | ||||
|                         .tag("flag", Tag.preProcessParsed(plotFlag.getName())) | ||||
|                         .tag("value", Tag.preProcessParsed(plotFlag.getExample())) | ||||
|                         .build() | ||||
|         ); | ||||
|         // Default value | ||||
|         final String defaultValue = player.getLocation().getPlotArea().getFlagContainer() | ||||
|                 .getFlagErased(plotFlag.getClass()).toString(); | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_info_default_value"), | ||||
|                 TagResolver.resolver("value", Tag.inserting(Component.text(defaultValue))) | ||||
|         ); | ||||
|         // Footer. Done this way to prevent the duplicate-message-thingy from catching it | ||||
|         player.sendMessage(TranslatableCaption.of("flag.flag_info_footer")); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,93 @@ | ||||
| /* | ||||
|  * 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.commands.command.setting.flag; | ||||
|  | ||||
| import com.plotsquared.core.configuration.caption.StaticCaption; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.flag.GlobalFlagContainer; | ||||
| import com.plotsquared.core.plot.flag.InternalFlag; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.TextComponent; | ||||
| import net.kyori.adventure.text.format.Style; | ||||
| import net.kyori.adventure.text.minimessage.MiniMessage; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Iterator; | ||||
| import java.util.Map; | ||||
|  | ||||
| public final class FlagListCommand extends FlagCommandBean { | ||||
|  | ||||
|     private static final MiniMessage MINI_MESSAGE = MiniMessage.builder().build(); | ||||
|  | ||||
|     @Override | ||||
|     protected Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( | ||||
|             final Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ) { | ||||
|         return builder.literal("list"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(final @NonNull CommandContext<PlotPlayer<?>> commandContext) { | ||||
|         final PlotPlayer<?> player = commandContext.sender(); | ||||
|  | ||||
|         final Map<Component, ArrayList<String>> flags = new HashMap<>(); | ||||
|         for (PlotFlag<?, ?> plotFlag : GlobalFlagContainer.getInstance().getRecognizedPlotFlags()) { | ||||
|             if (plotFlag instanceof InternalFlag) { | ||||
|                 continue; | ||||
|             } | ||||
|             final Component category = plotFlag.getFlagCategory().toComponent(player); | ||||
|             final Collection<String> flagList = flags.computeIfAbsent(category, k -> new ArrayList<>()); | ||||
|             flagList.add(plotFlag.getName()); | ||||
|         } | ||||
|  | ||||
|         for (final Map.Entry<Component, ArrayList<String>> entry : flags.entrySet()) { | ||||
|             Collections.sort(entry.getValue()); | ||||
|             Component category = | ||||
|                     MINI_MESSAGE.deserialize( | ||||
|                             TranslatableCaption.of("flag.flag_list_categories").getComponent(player), | ||||
|                             TagResolver.resolver("category", Tag.inserting(entry.getKey().style(Style.empty()))) | ||||
|                     ); | ||||
|             TextComponent.Builder builder = Component.text().append(category); | ||||
|             final Iterator<String> flagIterator = entry.getValue().iterator(); | ||||
|             while (flagIterator.hasNext()) { | ||||
|                 final String flag = flagIterator.next(); | ||||
|                 builder.append(MINI_MESSAGE | ||||
|                         .deserialize( | ||||
|                                 TranslatableCaption.of("flag.flag_list_flag").getComponent(player), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("command", Tag.preProcessParsed("/plat flag info " + flag)) | ||||
|                                         .tag("flag", Tag.inserting(Component.text(flag))) | ||||
|                                         .tag("suffix", Tag.inserting(Component.text(flagIterator.hasNext() ? ", " : ""))) | ||||
|                                         .build() | ||||
|                         )); | ||||
|             } | ||||
|             player.sendMessage(StaticCaption.of(MINI_MESSAGE.serialize(builder.build()))); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,171 @@ | ||||
| /* | ||||
|  * 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.commands.command.setting.flag; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.parser.PlotFlagParser; | ||||
| import com.plotsquared.core.commands.suggestions.FlagValueSuggestionProvider; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.events.PlotFlagAddEvent; | ||||
| import com.plotsquared.core.events.PlotFlagRemoveEvent; | ||||
| import com.plotsquared.core.events.Result; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.flag.FlagParseException; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.plot.flag.types.ListFlag; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
|  | ||||
| import static com.plotsquared.core.commands.parser.PlotFlagParser.plotFlagParser; | ||||
| import static org.incendo.cloud.parser.standard.StringParser.greedyStringParser; | ||||
|  | ||||
| public final class FlagRemoveCommand extends FlagCommandBean { | ||||
|  | ||||
|     private static final CloudKey<PlotFlag<?, ?>> COMPONENT_FLAG = CloudKey.of("flag", new TypeToken<PlotFlag<?, ?>>() {}); | ||||
|     private static final CloudKey<String> COMPONENT_VALUE = CloudKey.of("value", String.class); | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     public FlagRemoveCommand(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( | ||||
|             final Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ) { | ||||
|         return builder.literal("remove") | ||||
|                 .required(COMPONENT_FLAG, plotFlagParser(PlotFlagParser.FlagSource.PLOT)) | ||||
|                 .optional(COMPONENT_VALUE, greedyStringParser(), new FlagValueSuggestionProvider(COMPONENT_FLAG)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(final @NonNull CommandContext<PlotPlayer<?>> commandContext) { | ||||
|         final PlotPlayer<?> player = commandContext.sender(); | ||||
|         final Plot plot = commandContext.inject(Plot.class).orElseThrow(); | ||||
|         final PlotFlag<?, ?> flag = commandContext.get(COMPONENT_FLAG); | ||||
|         final String flagValue = commandContext.getOrDefault(COMPONENT_VALUE, null); | ||||
|  | ||||
|         final PlotFlagRemoveEvent event = this.eventDispatcher.callFlagRemove(flag, plot); | ||||
|         if (event.getEventResult() == Result.DENY) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("events.event_denied"), | ||||
|                     TagResolver.resolver("value", Tag.inserting(Component.text("Flag set"))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|         final String flagKey = flag.getName().toLowerCase(Locale.ENGLISH); | ||||
|         if (event.getEventResult() != Result.FORCE | ||||
|                 && !player.hasPermission(Permission.PERMISSION_SET_FLAG_KEY.format(flagKey))) { | ||||
|             if (flagValue == null) { | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("permission.no_permission"), | ||||
|                         TagResolver.resolver( | ||||
|                                 "node", | ||||
|                                 Tag.inserting(Component.text(Permission.PERMISSION_SET_FLAG_KEY.format(flagKey))) | ||||
|                         ) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (flagValue != null && flag instanceof ListFlag<?,?> listFlag) { | ||||
|             final List<?> list = new ArrayList<>(plot.getFlag(listFlag)); | ||||
|             final PlotFlag parsedFlag; | ||||
|             try { | ||||
|                 parsedFlag = listFlag.parse(flagValue); | ||||
|             } catch (final FlagParseException e) { | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("flag.flag_parse_error"), | ||||
|                         TagResolver.builder() | ||||
|                                 .tag("flag_name", Tag.inserting(Component.text(flag.getName()))) | ||||
|                                 .tag("flag_value", Tag.inserting(Component.text(e.getValue()))) | ||||
|                                 .tag("error", Tag.inserting(e.getErrorMessage().toComponent(player))) | ||||
|                                 .build() | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|             if (((List<?>) parsedFlag.getValue()).isEmpty()) { | ||||
|                 player.sendMessage(TranslatableCaption.of("flag.flag_not_removed")); | ||||
|                 return; | ||||
|             } | ||||
|             if (list.removeAll((List) parsedFlag.getValue())) { | ||||
|                 if (list.isEmpty()) { | ||||
|                     if (plot.removeFlag(flag)) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("flag.flag_removed"), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("flag", Tag.inserting(Component.text(flagKey))) | ||||
|                                         .tag("value", Tag.inserting(Component.text(flag.toString()))) | ||||
|                                         .build() | ||||
|                         ); | ||||
|                         return; | ||||
|                     } else { | ||||
|                         player.sendMessage(TranslatableCaption.of("flag.flag_not_removed")); | ||||
|                         return; | ||||
|                     } | ||||
|                 } else { | ||||
|                     PlotFlag<?, ?> plotFlag = parsedFlag.createFlagInstance(list); | ||||
|                     PlotFlagAddEvent addEvent = eventDispatcher.callFlagAdd(plotFlag, plot); | ||||
|                     if (addEvent.getEventResult() == Result.DENY) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("events.event_denied"), | ||||
|                                 TagResolver.resolver( | ||||
|                                         "value", | ||||
|                                         Tag.inserting(Component.text("Re-addition of " + plotFlag.getName())) | ||||
|                                 ) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (plot.setFlag(addEvent.getFlag())) { | ||||
|                         player.sendMessage(TranslatableCaption.of("flag.flag_partially_removed")); | ||||
|                         return; | ||||
|                     } else { | ||||
|                         player.sendMessage(TranslatableCaption.of("flag.flag_not_removed")); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } else if (!plot.removeFlag(flag)) { | ||||
|             player.sendMessage(TranslatableCaption.of("flag.flag_not_removed")); | ||||
|             return; | ||||
|         } | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_removed"), | ||||
|                 TagResolver.builder() | ||||
|                         .tag("flag", Tag.inserting(Component.text(flagKey))) | ||||
|                         .tag("value", Tag.inserting(Component.text(flag.toString()))) | ||||
|                         .build() | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,110 @@ | ||||
| /* | ||||
|  * 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.commands.command.setting.flag; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.parser.PlotFlagParser; | ||||
| import com.plotsquared.core.commands.suggestions.FlagValueSuggestionProvider; | ||||
| import com.plotsquared.core.configuration.caption.CaptionUtility; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.events.PlotFlagAddEvent; | ||||
| import com.plotsquared.core.events.Result; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.flag.FlagParseException; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.Command; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
|  | ||||
| import static com.plotsquared.core.commands.parser.PlotFlagParser.plotFlagParser; | ||||
| import static org.incendo.cloud.parser.standard.StringParser.greedyStringParser; | ||||
|  | ||||
| public final class FlagSetCommand extends FlagCommandBean { | ||||
|  | ||||
|     private static final CloudKey<PlotFlag<?, ?>> COMPONENT_FLAG = CloudKey.of("flag", new TypeToken<PlotFlag<?, ?>>() {}); | ||||
|     private static final CloudKey<String> COMPONENT_VALUE = CloudKey.of("value", String.class); | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     public FlagSetCommand(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected Command.@NonNull Builder<PlotPlayer<?>> configurePlotCommand( | ||||
|             final Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ) { | ||||
|         return builder.literal("set") | ||||
|                 .required(COMPONENT_FLAG, plotFlagParser(PlotFlagParser.FlagSource.GLOBAL)) | ||||
|                 .required(COMPONENT_VALUE, greedyStringParser(), new FlagValueSuggestionProvider(COMPONENT_FLAG)); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void execute(final @NonNull CommandContext<PlotPlayer<?>> commandContext) { | ||||
|         final PlotPlayer<?> player = commandContext.sender(); | ||||
|         final Plot plot = commandContext.inject(Plot.class).orElseThrow(); | ||||
|         final PlotFlag<?, ?> flag = commandContext.get(COMPONENT_FLAG); | ||||
|         final String flagValue = commandContext.get(COMPONENT_VALUE); | ||||
|  | ||||
|         final PlotFlagAddEvent event = this.eventDispatcher.callFlagAdd(flag, plot); | ||||
|         if (event.getEventResult() == Result.DENY) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("events.event_denied"), | ||||
|                     TagResolver.resolver("value", Tag.inserting(Component.text("Flag set"))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|         if (event.getEventResult() != Result.FORCE && !checkPermValue(player, flag, flag.getName(), flagValue)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final String sanitizedValue = CaptionUtility.stripClickEvents(flag, flagValue); | ||||
|         final PlotFlag<?, ?> parsedFlag; | ||||
|         try { | ||||
|             parsedFlag = flag.parse(flagValue); | ||||
|         } catch (final FlagParseException e) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("flag.flag_parse_error"), | ||||
|                     TagResolver.builder() | ||||
|                             .tag("flag_name", Tag.inserting(Component.text(flag.getName()))) | ||||
|                             .tag("flag_value", Tag.inserting(Component.text(e.getValue()))) | ||||
|                             .tag("error", Tag.inserting(e.getErrorMessage().toComponent(player))) | ||||
|                             .build() | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         plot.setFlag(parsedFlag); | ||||
|         player.sendMessage( | ||||
|                 TranslatableCaption.of("flag.flag_added"), | ||||
|                 TagResolver.builder() | ||||
|                         .tag("flag", Tag.inserting(Component.text(flag.getName()))) | ||||
|                         .tag("value", Tag.inserting(Component.text(parsedFlag.toString()))) | ||||
|                         .build() | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
|  * 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.commands.injection; | ||||
|  | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.injection.ParameterInjector; | ||||
| import org.incendo.cloud.util.annotation.AnnotationAccessor; | ||||
|  | ||||
| /** | ||||
|  * {@link ParameterInjector} that returns the current plot of the player. | ||||
|  */ | ||||
| public final class PlotInjector implements ParameterInjector<PlotPlayer<?>, Plot> { | ||||
|  | ||||
|     @Override | ||||
|     public @Nullable Plot create( | ||||
|             final @NonNull CommandContext<PlotPlayer<?>> context, | ||||
|             final @NonNull AnnotationAccessor annotationAccessor | ||||
|     ) { | ||||
|         // TODO: Allow for overriding for console. | ||||
|         return context.sender().getCurrentPlot(); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,158 @@ | ||||
| /* | ||||
|  * 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.commands.parser; | ||||
|  | ||||
| import com.plotsquared.core.configuration.caption.LocaleHolder; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.flag.FlagContainer; | ||||
| import com.plotsquared.core.plot.flag.GlobalFlagContainer; | ||||
| import com.plotsquared.core.plot.flag.InternalFlag; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.util.ComponentMessageThrowable; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.context.CommandInput; | ||||
| import org.incendo.cloud.exception.parsing.ParserException; | ||||
| import org.incendo.cloud.parser.ArgumentParseResult; | ||||
| import org.incendo.cloud.parser.ArgumentParser; | ||||
| import org.incendo.cloud.parser.ParserDescriptor; | ||||
| import org.incendo.cloud.suggestion.BlockingSuggestionProvider; | ||||
| import org.incendo.cloud.suggestion.Suggestion; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.function.Function; | ||||
|  | ||||
| /** | ||||
|  * Parser that parses and suggests {@link PlotFlag plot flags}. | ||||
|  */ | ||||
| public final class PlotFlagParser implements ArgumentParser<PlotPlayer<?>, PlotFlag<?, ?>>, | ||||
|         BlockingSuggestionProvider<PlotPlayer<?>> { | ||||
|  | ||||
|     /** | ||||
|      * Returns a new parser that parses {@link PlotFlag plot flags}. | ||||
|      * | ||||
|      * @param source the source of available flag values | ||||
|      * @return the parser | ||||
|      */ | ||||
|     public static @NonNull ParserDescriptor<PlotPlayer<?>, PlotFlag<?, ?>> plotFlagParser(final @NonNull FlagSource source) { | ||||
|         return ParserDescriptor.of(new PlotFlagParser(source), new TypeToken<PlotFlag<?, ?>>() { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     private final FlagSource flagSource; | ||||
|  | ||||
|     private PlotFlagParser(final @NonNull FlagSource flagSource) { | ||||
|         this.flagSource = flagSource; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull ArgumentParseResult<@NonNull PlotFlag<?, ?>> parse( | ||||
|             final @NonNull CommandContext<@NonNull PlotPlayer<?>> commandContext, | ||||
|             final @NonNull CommandInput commandInput | ||||
|     ) { | ||||
|         final String flagName = commandInput.readString(); | ||||
|         final PlotFlag<?, ?> flag = GlobalFlagContainer.getInstance().getFlagFromString(flagName); | ||||
|         if (flag == null) { | ||||
|             return ArgumentParseResult.failure(new PlotFlagParseException(commandContext)); | ||||
|         } | ||||
|         return ArgumentParseResult.success(flag); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull Iterable<@NonNull Suggestion> suggestions( | ||||
|             final @NonNull CommandContext<PlotPlayer<?>> context, | ||||
|             final @NonNull CommandInput input | ||||
|     ) { | ||||
|         return this.flagSource.flags(context.sender()) | ||||
|                 .stream() | ||||
|                 .filter(flag -> (!(flag instanceof InternalFlag))) | ||||
|                 .map(PlotFlag::getName) | ||||
|                 .map(Suggestion::simple) | ||||
|                 .toList(); | ||||
|     } | ||||
|  | ||||
|     public enum FlagSource { | ||||
|         /** | ||||
|          * All recognized flags. | ||||
|          */ | ||||
|         GLOBAL(player -> GlobalFlagContainer.getInstance(), false), | ||||
|         /** | ||||
|          * All flags that have been configured in the current plot. | ||||
|          */ | ||||
|         PLOT(player -> { | ||||
|             final Plot plot = player.getCurrentPlot(); | ||||
|             if (plot == null) { | ||||
|                 return GlobalFlagContainer.getInstance(); | ||||
|             } | ||||
|             return plot.getFlagContainer(); | ||||
|         }, true); | ||||
|  | ||||
|         private final Function<PlotPlayer<?>, FlagContainer> containerFunction; | ||||
|         private final boolean storedOnly; | ||||
|  | ||||
|         FlagSource(final @NonNull Function<PlotPlayer<?>, FlagContainer> containerFunction, final boolean storedOnly) { | ||||
|             this.containerFunction = containerFunction; | ||||
|             this.storedOnly = storedOnly; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns the flag container. | ||||
|          * | ||||
|          * @param player the player to get the container for | ||||
|          * @return the container | ||||
|          */ | ||||
|         public @NonNull FlagContainer flagContainer(final @NonNull PlotPlayer<?> player) { | ||||
|             return this.containerFunction.apply(player); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns the flags from this source. | ||||
|          * | ||||
|          * @param player the player to get the flags for | ||||
|          * @return the flags | ||||
|          */ | ||||
|         public @NonNull Collection<@NonNull PlotFlag<?, ?>> flags(final @NonNull PlotPlayer<?> player) { | ||||
|             final FlagContainer container = this.flagContainer(player); | ||||
|             if (this.storedOnly) { | ||||
|                 return container.getFlagMap().values(); | ||||
|             } | ||||
|             return container.getRecognizedPlotFlags(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Exception thrown when an invalid flag name is supplied. | ||||
|      */ | ||||
|     public static final class PlotFlagParseException extends ParserException implements ComponentMessageThrowable { | ||||
|  | ||||
|         private PlotFlagParseException(final @NonNull CommandContext<?> context) { | ||||
|             super(PlotFlagParser.class, context, TranslatableCaption.of("flag.not_valid_flag")); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public @NonNull Component componentMessage() { | ||||
|             // TODO(City): This sucks... | ||||
|             return ((TranslatableCaption) this.errorCaption()).toComponent(LocaleHolder.console()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,86 @@ | ||||
| /* | ||||
|  * 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.commands.suggestions; | ||||
|  | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.plot.flag.types.ListFlag; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.context.CommandContext; | ||||
| import org.incendo.cloud.context.CommandInput; | ||||
| import org.incendo.cloud.key.CloudKey; | ||||
| import org.incendo.cloud.suggestion.BlockingSuggestionProvider; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| /** | ||||
|  * Suggestion provider that provides context-aware {@link PlotFlag plot flag} value suggestions using | ||||
|  * {@link PlotFlag#getTabCompletions()}. | ||||
|  */ | ||||
| public final class FlagValueSuggestionProvider implements BlockingSuggestionProvider.Strings<PlotPlayer<?>> { | ||||
|  | ||||
|     private final CloudKey<PlotFlag<?, ?>> flagKey; | ||||
|  | ||||
|     /** | ||||
|      * Creates a new suggestion provider. | ||||
|      * | ||||
|      * @param flagKey the key of the argument that contains the flag to provide value suggestions for | ||||
|      */ | ||||
|     public FlagValueSuggestionProvider(final @NonNull CloudKey<PlotFlag<?, ?>> flagKey) { | ||||
|         this.flagKey = Objects.requireNonNull(flagKey, "flagKey"); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull Iterable<@NonNull String> stringSuggestions( | ||||
|             @NonNull final CommandContext<PlotPlayer<?>> context, | ||||
|             @NonNull final CommandInput input | ||||
|     ) { | ||||
|         final PlotFlag<?, ?> plotFlag = context.getOrDefault(this.flagKey, null); | ||||
|         if (plotFlag == null) { | ||||
|             return List.of(); | ||||
|         } | ||||
|         final Collection<String> completions = plotFlag.getTabCompletions(); | ||||
|         if (plotFlag instanceof ListFlag<?,?> && input.peekString().contains(",")) { | ||||
|             final String[] split = input.peekString().split(","); | ||||
|             final List<String> existingValues = new ArrayList<>(Arrays.asList(split)); | ||||
|  | ||||
|             final String completingValue; | ||||
|             if (!input.peekString().endsWith(",")) { | ||||
|                 // In this case we want to complete the value we're currently typing. | ||||
|                 completingValue = split[split.length - 1]; | ||||
|                 existingValues.remove(existingValues.size() - 1); | ||||
|             } else { | ||||
|                 completingValue = null; | ||||
|             } | ||||
|  | ||||
|             final String prefix = existingValues.stream().collect(Collectors.joining(",", "", ",")); | ||||
|             return completions.stream() | ||||
|                     .filter(value -> !existingValues.contains(value)) | ||||
|                     .filter(value -> completingValue == null || value.startsWith(completingValue)) | ||||
|                     .map(value -> prefix + value) | ||||
|                     .toList(); | ||||
|         } | ||||
|         return completions; | ||||
|     } | ||||
| } | ||||
| @@ -522,7 +522,7 @@ public class Settings extends Config { | ||||
|         @Comment("Should the limit be global (over multiple worlds)") | ||||
|         public static boolean GLOBAL = | ||||
|                 false; | ||||
|         @Comment({"The max range of permissions to check for, e.g. plots.plot.127", | ||||
|         @Comment({"The max range of integer permissions to check for, e.g. 'plots.plot.127' or 'plots.set.flag.mob-cap.127'", | ||||
|                 "The value covers the permission range to check, you need to assign the permission to players/groups still", | ||||
|                 "Modifying the value does NOT change the amount of plots players can claim"}) | ||||
|         public static int MAX_PLOTS = 127; | ||||
|   | ||||
| @@ -25,6 +25,7 @@ import net.kyori.adventure.text.minimessage.MiniMessage; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.incendo.cloud.caption.Caption; | ||||
| import org.jetbrains.annotations.NotNull; | ||||
|  | ||||
| import java.util.Locale; | ||||
| @@ -33,7 +34,7 @@ import java.util.regex.Pattern; | ||||
| /** | ||||
|  * Caption that is user modifiable | ||||
|  */ | ||||
| public final class TranslatableCaption implements NamespacedCaption { | ||||
| public final class TranslatableCaption implements NamespacedCaption, Caption { | ||||
|  | ||||
|     /** | ||||
|      * Default caption namespace | ||||
| @@ -72,6 +73,11 @@ public final class TranslatableCaption implements NamespacedCaption { | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public @NonNull String key() { | ||||
|         return this.getKey(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a new {@link TranslatableCaption} instance | ||||
|      * | ||||
|   | ||||
| @@ -0,0 +1,77 @@ | ||||
| /* | ||||
|  * 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.events; | ||||
|  | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.index.qual.NonNegative; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| /** | ||||
|  * Called every time after PlotSquared calculated a players plot limit based on their permission. | ||||
|  * <p> | ||||
|  * May be used to grant a player more plots based on another rank or bought feature. | ||||
|  * | ||||
|  * @since 7.3.0 | ||||
|  */ | ||||
| public class PlayerPlotLimitEvent { | ||||
|  | ||||
|     private final PlotPlayer<?> player; | ||||
|  | ||||
|     private int limit; | ||||
|  | ||||
|     public PlayerPlotLimitEvent(@NonNull final PlotPlayer<?> player, @NonNegative final int limit) { | ||||
|         this.player = player; | ||||
|         this.limit = limit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Overrides the previously calculated or set plot limit for {@link #player()}. | ||||
|      * | ||||
|      * @param limit The amount of plots a player may claim. Must be {@code 0} or greater. | ||||
|      * @since 7.3.0 | ||||
|      */ | ||||
|     public void limit(@NonNegative final int limit) { | ||||
|         if (limit < 0) { | ||||
|             throw new IllegalArgumentException("Player plot limit must be greater or equal 0"); | ||||
|         } | ||||
|         this.limit = limit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the previous set limit, if none was overridden before this event handler the default limit based on the players | ||||
|      * permissions node is returned. | ||||
|      * | ||||
|      * @return The currently defined plot limit of this player. | ||||
|      * @since 7.3.0 | ||||
|      */ | ||||
|     public @NonNegative int limit() { | ||||
|         return limit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The player for which the limit is queried. | ||||
|      * | ||||
|      * @return the player. | ||||
|      * @since 7.3.0 | ||||
|      */ | ||||
|     public @NonNull PlotPlayer<?> player() { | ||||
|         return player; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -21,21 +21,26 @@ package com.plotsquared.core.events; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import java.util.function.UnaryOperator; | ||||
|  | ||||
| /** | ||||
|  * Called when a player teleports to a plot | ||||
|  */ | ||||
| public class PlayerTeleportToPlotEvent extends PlotPlayerEvent implements CancellablePlotEvent { | ||||
|  | ||||
|     private final Location from; | ||||
|     private final TeleportCause cause; | ||||
|     private Result eventResult; | ||||
|     private final Location from; | ||||
|     private UnaryOperator<Location> locationTransformer; | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * PlayerTeleportToPlotEvent: Called when a player teleports to a plot | ||||
|      * | ||||
|      * @param player That was teleported | ||||
|      * @param from   Start location | ||||
|      * @param from   The origin location, from where the teleport was triggered (players location most likely) | ||||
|      * @param plot   Plot to which the player was teleported | ||||
|      * @param cause  Why the teleport is being completed | ||||
|      * @since 6.1.0 | ||||
| @@ -57,7 +62,8 @@ public class PlayerTeleportToPlotEvent extends PlotPlayerEvent implements Cancel | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the from location | ||||
|      * Get the location, from where the teleport was triggered | ||||
|      * (the players current location when executing the home command for example) | ||||
|      * | ||||
|      * @return Location | ||||
|      */ | ||||
| @@ -65,6 +71,27 @@ public class PlayerTeleportToPlotEvent extends PlotPlayerEvent implements Cancel | ||||
|         return this.from; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the currently applied {@link UnaryOperator<Location> transformer} or null, if none was set | ||||
|      * | ||||
|      * @return LocationTransformer | ||||
|      * @since 7.2.1 | ||||
|      */ | ||||
|     public @Nullable UnaryOperator<Location> getLocationTransformer() { | ||||
|         return this.locationTransformer; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Sets the {@link UnaryOperator<Location> transformer} to mutate the location where the player will be teleported to. | ||||
|      * May be {@code null}, if any previous set transformations should be discarded. | ||||
|      * | ||||
|      * @param locationTransformer The new transformer | ||||
|      * @since 7.2.1 | ||||
|      */ | ||||
|     public void setLocationTransformer(@Nullable UnaryOperator<Location> locationTransformer) { | ||||
|         this.locationTransformer = locationTransformer; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Result getEventResult() { | ||||
|         return eventResult; | ||||
|   | ||||
| @@ -0,0 +1,46 @@ | ||||
| /* | ||||
|  * 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.inject.modules; | ||||
|  | ||||
| import com.google.inject.AbstractModule; | ||||
| import com.google.inject.Scopes; | ||||
| import com.google.inject.multibindings.Multibinder; | ||||
| import com.plotsquared.core.commands.PlotSquaredCommandBean; | ||||
| import com.plotsquared.core.commands.command.setting.flag.FlagAddCommand; | ||||
| import com.plotsquared.core.commands.command.setting.flag.FlagInfoCommand; | ||||
| import com.plotsquared.core.commands.command.setting.flag.FlagListCommand; | ||||
| import com.plotsquared.core.commands.command.setting.flag.FlagRemoveCommand; | ||||
| import com.plotsquared.core.commands.command.setting.flag.FlagSetCommand; | ||||
|  | ||||
| public final class CommandModule extends AbstractModule { | ||||
|  | ||||
|     @Override | ||||
|     protected void configure() { | ||||
|         final Multibinder<PlotSquaredCommandBean> commands = Multibinder.newSetBinder( | ||||
|                 this.binder(), | ||||
|                 PlotSquaredCommandBean.class | ||||
|         ); | ||||
|  | ||||
|         commands.addBinding().to(FlagAddCommand.class).in(Scopes.SINGLETON); | ||||
|         commands.addBinding().to(FlagInfoCommand.class).in(Scopes.SINGLETON); | ||||
|         commands.addBinding().to(FlagListCommand.class).in(Scopes.SINGLETON); | ||||
|         commands.addBinding().to(FlagRemoveCommand.class).in(Scopes.SINGLETON); | ||||
|         commands.addBinding().to(FlagSetCommand.class).in(Scopes.SINGLETON); | ||||
|     } | ||||
| } | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.inject.modules; | ||||
|  | ||||
| import cloud.commandframework.services.ServicePipeline; | ||||
| import com.google.inject.AbstractModule; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.configuration.file.YamlConfiguration; | ||||
| @@ -31,6 +30,7 @@ import com.plotsquared.core.listener.PlotListener; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.uuid.UUIDPipeline; | ||||
| import com.sk89q.worldedit.WorldEdit; | ||||
| import org.incendo.cloud.services.ServicePipeline; | ||||
|  | ||||
| import java.io.File; | ||||
|  | ||||
|   | ||||
| @@ -364,7 +364,6 @@ public class PlotListener { | ||||
|     public boolean plotExit(final PlotPlayer<?> player, Plot plot) { | ||||
|         try (final MetaDataAccess<Plot> lastPlot = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { | ||||
|             final Plot previous = lastPlot.remove(); | ||||
|             this.eventDispatcher.callLeave(player, plot); | ||||
|  | ||||
|             List<StatusEffect> effects = playerEffects.remove(player.getUUID()); | ||||
|             if (effects != null) { | ||||
| @@ -467,6 +466,8 @@ public class PlotListener { | ||||
|                 feedRunnable.remove(player.getUUID()); | ||||
|                 healRunnable.remove(player.getUUID()); | ||||
|             } | ||||
|         } finally { | ||||
|             this.eventDispatcher.callLeave(player, plot); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|   | ||||
| @@ -59,6 +59,9 @@ public enum Permission implements ComponentLike { | ||||
|     PERMISSION_ADMIN_DESTROY_VEHICLE_UNOWNED("plots.admin.vehicle.break.unowned"), | ||||
|     PERMISSION_ADMIN_DESTROY_VEHICLE_OTHER("plots.admin.vehicle.break.other"), | ||||
|     PERMISSION_ADMIN_PVE("plots.admin.pve"), | ||||
|     PERMISSION_ADMIN_PLACE_VEHICLE_ROAD("plots.admin.vehicle.place.road"), | ||||
|     PERMISSION_ADMIN_PLACE_VEHICLE_UNOWNED("plots.admin.vehicle.place.unowned"), | ||||
|     PERMISSION_ADMIN_PLACE_VEHICLE_OTHER("plots.admin.vehicle.place.other"), | ||||
|     PERMISSION_ADMIN_PVP("plots.admin.pvp"), | ||||
|     PERMISSION_ADMIN_BUILD_ROAD("plots.admin.build.road"), | ||||
|     PERMISSION_ADMIN_PROJECTILE_ROAD("plots.admin.projectile.road"), | ||||
|   | ||||
| @@ -100,6 +100,7 @@ public interface PermissionHolder { | ||||
|         } | ||||
|         String[] nodes = stub.split("\\."); | ||||
|         StringBuilder builder = new StringBuilder(); | ||||
|         // Wildcard check from less specific permission to more specific permission | ||||
|         for (int i = 0; i < (nodes.length - 1); i++) { | ||||
|             builder.append(nodes[i]).append("."); | ||||
|             if (!stub.equals(builder + Permission.PERMISSION_STAR.toString())) { | ||||
| @@ -108,6 +109,7 @@ public interface PermissionHolder { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // Wildcard check for the full permission | ||||
|         if (hasPermission(stub + ".*")) { | ||||
|             return Integer.MAX_VALUE; | ||||
|         } | ||||
|   | ||||
| @@ -306,7 +306,8 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer, | ||||
|      * @return number of allowed plots within the scope (globally, or in the player's current world as defined in the settings.yml) | ||||
|      */ | ||||
|     public int getAllowedPlots() { | ||||
|         return hasPermissionRange("plots.plot", Settings.Limit.MAX_PLOTS); | ||||
|         final int calculatedLimit = hasPermissionRange("plots.plot", Settings.Limit.MAX_PLOTS); | ||||
|         return this.eventDispatcher.callPlayerPlotLimit(this, calculatedLimit).limit(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -29,6 +29,7 @@ import com.plotsquared.core.configuration.caption.CaptionUtility; | ||||
| import com.plotsquared.core.configuration.caption.StaticCaption; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| import com.plotsquared.core.events.PlayerTeleportToPlotEvent; | ||||
| import com.plotsquared.core.events.Result; | ||||
| import com.plotsquared.core.events.TeleportCause; | ||||
| import com.plotsquared.core.generator.ClassicPlotWorld; | ||||
| @@ -2573,8 +2574,9 @@ public class Plot { | ||||
|      */ | ||||
|     public void teleportPlayer(final PlotPlayer<?> player, TeleportCause cause, Consumer<Boolean> resultConsumer) { | ||||
|         Plot plot = this.getBasePlot(false); | ||||
|         Result result = this.eventDispatcher.callTeleport(player, player.getLocation(), plot, cause).getEventResult(); | ||||
|         if (result == Result.DENY) { | ||||
|  | ||||
|         PlayerTeleportToPlotEvent event = this.eventDispatcher.callTeleport(player, player.getLocation(), plot, cause); | ||||
|         if (event.getEventResult() == Result.DENY) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("events.event_denied"), | ||||
|                     TagResolver.resolver("value", Tag.inserting(Component.text("Teleport"))) | ||||
| @@ -2582,7 +2584,10 @@ public class Plot { | ||||
|             resultConsumer.accept(false); | ||||
|             return; | ||||
|         } | ||||
|         final Consumer<Location> locationConsumer = location -> { | ||||
|  | ||||
|         final Consumer<Location> locationConsumer = calculatedLocation -> { | ||||
|             Location location = event.getLocationTransformer() == null ? calculatedLocation : | ||||
|                     Objects.requireNonNullElse(event.getLocationTransformer().apply(calculatedLocation), calculatedLocation); | ||||
|             if (Settings.Teleport.DELAY == 0 || player.hasPermission("plots.teleport.delay.bypass")) { | ||||
|                 player.sendMessage(TranslatableCaption.of("teleport.teleported_to_plot")); | ||||
|                 player.teleport(location, cause); | ||||
|   | ||||
| @@ -42,6 +42,7 @@ import com.plotsquared.core.plot.flag.implementations.DeviceInteractFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DisablePhysicsFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DoneFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DropProtectionFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.EditSignFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.EntityCapFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.EntityChangeBlockFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.ExplosionFlag; | ||||
| @@ -88,6 +89,7 @@ import com.plotsquared.core.plot.flag.implementations.PlayerInteractFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.PreventCreativeCopyFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.PriceFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.ProjectileChangeBlockFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.ProjectilesFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.PveFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.PvpFlag; | ||||
| @@ -153,6 +155,7 @@ public final class GlobalFlagContainer extends FlagContainer { | ||||
|         this.addFlag(DeviceInteractFlag.DEVICE_INTERACT_FALSE); | ||||
|         this.addFlag(DisablePhysicsFlag.DISABLE_PHYSICS_FALSE); | ||||
|         this.addFlag(DropProtectionFlag.DROP_PROTECTION_FALSE); | ||||
|         this.addFlag(EditSignFlag.EDIT_SIGN_FALSE); | ||||
|         this.addFlag(EntityChangeBlockFlag.ENTITY_CHANGE_BLOCK_FALSE); | ||||
|         this.addFlag(ExplosionFlag.EXPLOSION_FALSE); | ||||
|         this.addFlag(ForcefieldFlag.FORCEFIELD_FALSE); | ||||
| @@ -183,6 +186,7 @@ public final class GlobalFlagContainer extends FlagContainer { | ||||
|         this.addFlag(NoWorldeditFlag.NO_WORLDEDIT_FALSE); | ||||
|         this.addFlag(PlayerInteractFlag.PLAYER_INTERACT_FALSE); | ||||
|         this.addFlag(PreventCreativeCopyFlag.PREVENT_CREATIVE_COPY_FALSE); | ||||
|         this.addFlag(ProjectileChangeBlockFlag.PROJECTILE_CHANGE_BLOCK_FALSE); | ||||
|         this.addFlag(PveFlag.PVE_FALSE); | ||||
|         this.addFlag(PvpFlag.PVP_FALSE); | ||||
|         this.addFlag(RedstoneFlag.REDSTONE_TRUE); | ||||
|   | ||||
| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * 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.plot.flag.implementations; | ||||
|  | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.plot.flag.types.BooleanFlag; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| /** | ||||
|  * @since 7.2.1 | ||||
|  */ | ||||
| public class EditSignFlag extends BooleanFlag<EditSignFlag> { | ||||
|     public static final EditSignFlag EDIT_SIGN_TRUE = new EditSignFlag(true); | ||||
|     public static final EditSignFlag EDIT_SIGN_FALSE = new EditSignFlag(false); | ||||
|  | ||||
|     private EditSignFlag(final boolean value) { | ||||
|         super(value, TranslatableCaption.of("flags.flag_description_edit_sign")); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected EditSignFlag flagOf(@NonNull final Boolean value) { | ||||
|         return value ? EDIT_SIGN_TRUE : EDIT_SIGN_FALSE; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,39 @@ | ||||
| /* | ||||
|  * 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.plot.flag.implementations; | ||||
|  | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.plot.flag.types.BooleanFlag; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| public class ProjectileChangeBlockFlag extends BooleanFlag<ProjectileChangeBlockFlag> { | ||||
|  | ||||
|     public static final ProjectileChangeBlockFlag PROJECTILE_CHANGE_BLOCK_TRUE = new ProjectileChangeBlockFlag(true); | ||||
|     public static final ProjectileChangeBlockFlag PROJECTILE_CHANGE_BLOCK_FALSE = new ProjectileChangeBlockFlag(false); | ||||
|  | ||||
|     private ProjectileChangeBlockFlag(boolean value) { | ||||
|         super(value, TranslatableCaption.of("flags.flag_description_projectile_change_block")); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected ProjectileChangeBlockFlag flagOf(@NonNull Boolean value) { | ||||
|         return value ? PROJECTILE_CHANGE_BLOCK_TRUE : PROJECTILE_CHANGE_BLOCK_FALSE; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.services.plots; | ||||
|  | ||||
| import cloud.commandframework.services.types.Service; | ||||
| import com.google.common.cache.Cache; | ||||
| import com.google.common.cache.CacheBuilder; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| @@ -26,6 +25,7 @@ import com.plotsquared.core.plot.PlotAreaType; | ||||
| import com.plotsquared.core.plot.PlotId; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
| import org.incendo.cloud.services.type.Service; | ||||
|  | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|   | ||||
| @@ -30,6 +30,7 @@ import com.plotsquared.core.events.PlayerEnterPlotEvent; | ||||
| import com.plotsquared.core.events.PlayerLeavePlotEvent; | ||||
| import com.plotsquared.core.events.PlayerPlotDeniedEvent; | ||||
| import com.plotsquared.core.events.PlayerPlotHelperEvent; | ||||
| import com.plotsquared.core.events.PlayerPlotLimitEvent; | ||||
| import com.plotsquared.core.events.PlayerPlotTrustedEvent; | ||||
| import com.plotsquared.core.events.PlayerTeleportToPlotEvent; | ||||
| import com.plotsquared.core.events.PlotAutoMergeEvent; | ||||
| @@ -63,6 +64,7 @@ import com.plotsquared.core.plot.PlotId; | ||||
| import com.plotsquared.core.plot.Rating; | ||||
| import com.plotsquared.core.plot.flag.PlotFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.DeviceInteractFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.EditSignFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.MiscPlaceFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.MobPlaceFlag; | ||||
| import com.plotsquared.core.plot.flag.implementations.PlaceFlag; | ||||
| @@ -74,6 +76,7 @@ import com.plotsquared.core.util.task.TaskManager; | ||||
| import com.sk89q.worldedit.WorldEdit; | ||||
| import com.sk89q.worldedit.entity.Entity; | ||||
| import com.sk89q.worldedit.function.pattern.Pattern; | ||||
| import com.sk89q.worldedit.world.block.BlockCategories; | ||||
| import com.sk89q.worldedit.world.block.BlockType; | ||||
| import com.sk89q.worldedit.world.block.BlockTypes; | ||||
| import net.kyori.adventure.text.Component; | ||||
| @@ -306,6 +309,12 @@ public class EventDispatcher { | ||||
|         return event; | ||||
|     } | ||||
|  | ||||
|     public PlayerPlotLimitEvent callPlayerPlotLimit(PlotPlayer<?> player, int calculatedLimit) { | ||||
|         PlayerPlotLimitEvent event = new PlayerPlotLimitEvent(player, calculatedLimit); | ||||
|         eventBus.post(event); | ||||
|         return event; | ||||
|     } | ||||
|  | ||||
|     public void doJoinTask(final PlotPlayer<?> player) { | ||||
|         if (player == null) { | ||||
|             return; //possible future warning message to figure out where we are retrieving null | ||||
| @@ -373,14 +382,10 @@ public class EventDispatcher { | ||||
|                             return true; | ||||
|                         } | ||||
|                     } | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD, notifyPerms); | ||||
|                 } | ||||
|                 if (!plot.hasOwner()) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_UNOWNED.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED, notifyPerms); | ||||
|                 } | ||||
|                 final List<BlockTypeWrapper> use = plot.getFlag(UseFlag.class); | ||||
|                 for (final BlockTypeWrapper blockTypeWrapper : use) { | ||||
| @@ -389,7 +394,13 @@ public class EventDispatcher { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|                 if (player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString(), false)) { | ||||
|                 if (player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER, false)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 // we check for the EditSignFlag in the PlayerSignOpenEvent again, but we must not cancel the interact event | ||||
|                 // or send a message if the flag is true | ||||
|                 if (BlockCategories.ALL_SIGNS != null && BlockCategories.ALL_SIGNS.contains(blockType) | ||||
|                         && plot.getFlag(EditSignFlag.class)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (notifyPerms) { | ||||
| @@ -408,14 +419,10 @@ public class EventDispatcher { | ||||
|                             return true; | ||||
|                         } | ||||
|                     } | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString(), false | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD, false); | ||||
|                 } | ||||
|                 if (!plot.hasOwner()) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_UNOWNED.toString(), false | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED, false); | ||||
|                 } | ||||
|                 if (plot.getFlag(DeviceInteractFlag.class)) { | ||||
|                     return true; | ||||
| @@ -427,21 +434,14 @@ public class EventDispatcher { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|                 return player.hasPermission( | ||||
|                         Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString(), | ||||
|                         false | ||||
|                 ); | ||||
|                 return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER, false); | ||||
|             } | ||||
|             case SPAWN_MOB -> { | ||||
|                 if (plot == null) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD, notifyPerms); | ||||
|                 } | ||||
|                 if (!plot.hasOwner()) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_UNOWNED.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED, notifyPerms); | ||||
|                 } | ||||
|                 if (plot.getFlag(MobPlaceFlag.class)) { | ||||
|                     return true; | ||||
| @@ -453,10 +453,7 @@ public class EventDispatcher { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|                 if (player.hasPermission( | ||||
|                         Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString(), | ||||
|                         false | ||||
|                 )) { | ||||
|                 if (player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER, false)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (notifyPerms) { | ||||
| @@ -476,14 +473,10 @@ public class EventDispatcher { | ||||
|             } | ||||
|             case PLACE_MISC -> { | ||||
|                 if (plot == null) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_ROAD, notifyPerms); | ||||
|                 } | ||||
|                 if (!plot.hasOwner()) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_UNOWNED.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_UNOWNED, notifyPerms); | ||||
|                 } | ||||
|                 if (plot.getFlag(MiscPlaceFlag.class)) { | ||||
|                     return true; | ||||
| @@ -495,10 +488,7 @@ public class EventDispatcher { | ||||
|                         return true; | ||||
|                     } | ||||
|                 } | ||||
|                 if (player.hasPermission( | ||||
|                         Permission.PERMISSION_ADMIN_INTERACT_OTHER.toString(), | ||||
|                         false | ||||
|                 )) { | ||||
|                 if (player.hasPermission(Permission.PERMISSION_ADMIN_INTERACT_OTHER, false)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (notifyPerms) { | ||||
| @@ -518,16 +508,28 @@ public class EventDispatcher { | ||||
|             } | ||||
|             case PLACE_VEHICLE -> { | ||||
|                 if (plot == null) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_ROAD.toString(), notifyPerms | ||||
|                     ); | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_PLACE_VEHICLE_ROAD, notifyPerms); | ||||
|                 } | ||||
|                 if (!plot.hasOwner()) { | ||||
|                     return player.hasPermission( | ||||
|                             Permission.PERMISSION_ADMIN_INTERACT_UNOWNED.toString(), notifyPerms | ||||
|                     return player.hasPermission(Permission.PERMISSION_ADMIN_PLACE_VEHICLE_UNOWNED, notifyPerms); | ||||
|                 } | ||||
|                 if (plot.getFlag(VehiclePlaceFlag.class)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (player.hasPermission(Permission.PERMISSION_ADMIN_PLACE_VEHICLE_OTHER, false)) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (notifyPerms) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("commandconfig.flag_tutorial_usage"), | ||||
|                             TagResolver.resolver( | ||||
|                                     "flag", | ||||
|                                     Tag.inserting( | ||||
|                                             PlotFlag.getFlagNameComponent(VehiclePlaceFlag.class) | ||||
|                                     ) | ||||
|                             ) | ||||
|                     ); | ||||
|                 } | ||||
|                 return plot.getFlag(VehiclePlaceFlag.class); | ||||
|             } | ||||
|             default -> { | ||||
|             } | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| /* | ||||
|  * 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.query; | ||||
|  | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| class HasOwnerFilter implements PlotFilter { | ||||
|  | ||||
|     @Override | ||||
|     public boolean accepts(final @NonNull Plot plot) { | ||||
|         return plot.hasOwner(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -219,6 +219,16 @@ public final class PlotQuery implements Iterable<Plot> { | ||||
|         return this.addFilter(new OwnersIncludeFilter(owner.getUUID())); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Query only for plots that have an owner | ||||
|      * | ||||
|      * @return The query instance | ||||
|      * @since 7.2.1 | ||||
|      */ | ||||
|  | ||||
|     public @NonNull PlotQuery hasOwner() { | ||||
|         return this.addFilter(new HasOwnerFilter()); | ||||
|     } | ||||
|     /** | ||||
|      * Query for plots with a specific alias | ||||
|      * | ||||
|   | ||||
| @@ -248,11 +248,11 @@ | ||||
|   "condense.skipping": "<prefix><red>Skipping complex plot: </red><gold><plot></gold><red>.</red>", | ||||
|   "condense.task_stopped": "<prefix><gold>Task already stopped.</gold>", | ||||
|   "condense.default_eval": "<dark_gray><strikethrough>=== <reset> <gold>DEFAULT EVAL </gold><dark_gray><strikethrough>===</dark_gray>", | ||||
|   "condense.minimum_radius": "<gold>Minimum radius: </gold><gray><minimumRadius></gray>", | ||||
|   "condense.maximum_moved": "<gold>Maximum moved: </gold><gray><maximumMoves></gray>", | ||||
|   "condense.minimum_radius": "<gold>Minimum radius: </gold><gray><minimum_radius></gray>", | ||||
|   "condense.maximum_moved": "<gold>Maximum moved: </gold><gray><maximum_moves></gray>", | ||||
|   "condense.input_eval": "<dark_gray><strikethrough>=== <reset> <gold>INPUT EVAL </gold><dark_gray><strikethrough>===</dark_gray>", | ||||
|   "condense.input_radius": "<gold>Input radius: </gold><gray><radius></gray>", | ||||
|   "condense.estimated_moves": "<gold>Estimated moves: </gold><gray><userMove></gray>", | ||||
|   "condense.estimated_moves": "<gold>Estimated moves: </gold><gray><user_move></gray>", | ||||
|   "condense.eta": "<prefix><gold>Estimated time: No idea, times will drastically change based on the system performance and load.</gold>", | ||||
|   "condense.radius_measured": "<yellow> - Radius is measured in plot width.</yellow>", | ||||
|   "database.starting_conversion": "<prefix><gold>Starting...</gold>", | ||||
| @@ -381,9 +381,9 @@ | ||||
|   "info.plot_list_default": "<gold><plot></gold>", | ||||
|   "info.plot_list_player_online": "<dark_aqua><prefix></dark_aqua><hover:show_text:'<dark_aqua>Online</dark_aqua>'><gold><player></gold></hover>", | ||||
|   "info.plot_list_player_offline": "<dark_aqua><prefix></dark_aqua><hover:show_text:'<dark_gray>Offline</dark_gray>'><gold><player></gold></hover>", | ||||
|   "info.plot_list_player_unknown": "<hover:show_text:'<red>The owner of this plot is unknown</red>'><white><info.unknown></white></hover>", | ||||
|   "info.plot_list_player_server": "<hover:show_text:'<red>The plot is owned by the server</red>'><white><info.server></white></hover>", | ||||
|   "info.plot_list_player_everyone": "<hover:show_text:'<blue>The plot is owned by everyone</blue>'><white><info.everyone></white></hover>", | ||||
|   "info.plot_list_player_unknown": "<hover:show_text:'<red>The owner of this plot is unknown</red>'><white><unknown></white></hover>", | ||||
|   "info.plot_list_player_server": "<hover:show_text:'<red>The plot is owned by the server</red>'><white><server></white></hover>", | ||||
|   "info.plot_list_player_everyone": "<hover:show_text:'<blue>The plot is owned by everyone</blue>'><white><everyone></white></hover>", | ||||
|   "info.area_info_format": "<header>\n<reset><gold>Name: </gold><gray><name></gray>\n<gold>Type: </gold><gray><type></gray>\n<gold>Terrain: </gold><gray><terrain></gray>\n<gold>Usage: </gold><gray><usage>%</gray>\n<gold>Claimed: </gold><gray><claimed></gray>\n<gold>Clusters: </gold><gray><clusters></gray>\n<gold>Region: </gold><gray><region></gray>\n<gold>Generator: </gold><gray><generator></gray>\n<footer>", | ||||
|   "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>", | ||||
| @@ -555,6 +555,7 @@ | ||||
|   "flags.flag_description_device_interact": "<gray>Set to `true` to allow devices to be interacted with in the plot.</gray>", | ||||
|   "flags.flag_description_disable_physics": "<gray>Set to `true` to disable block physics in the plot.</gray>", | ||||
|   "flags.flag_description_drop_protection": "<gray>Set to `true` to prevent dropped items from being picked up by non-members of the plot.</gray>", | ||||
|   "flags.flag_description_edit_sign": "<gray>Set to `true` to allow editing signs in the plot.</gray>", | ||||
|   "flags.flag_description_feed": "<gray>Specify an interval in seconds and an optional amount by which the players will be fed (amount is 1 by default).</gray>", | ||||
|   "flags.flag_description_forcefield": "<gray>Set to `true` to enable member forcefield in the plot.</gray>", | ||||
|   "flags.flag_description_grass_grow": "<gray>Set to `false` to prevent grass from growing within the plot.</gray>", | ||||
| @@ -588,6 +589,7 @@ | ||||
|   "flags.flag_description_place": "<gray>Define a list of materials players should be able to place in the plot.</gray>", | ||||
|   "flags.flag_description_player_interact": "<gray>Set to `true` to allow guests to interact with players in the plot.</gray>", | ||||
|   "flags.flag_description_price": "<gray>Set a price for a plot. Must be a positive decimal number.</gray>", | ||||
|   "flags.flag_description_projectile_change_block": "<gray>Set to `true` to allow projectiles to change blocks (tnt, etc.) on the plot.</gray>", | ||||
|   "flags.flag_description_pve": "<gray>Set to `true` to enable PVE inside the plot.</gray>", | ||||
|   "flags.flag_description_pvp": "<gray>Set to `true` to enable PVP inside the plot.</gray>", | ||||
|   "flags.flag_description_redstone": "<gray>Set to `false` to disable redstone in the plot.</gray>", | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import com.diffplug.gradle.spotless.SpotlessPlugin | ||||
| import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin | ||||
| import groovy.json.JsonSlurper | ||||
| import java.net.URI | ||||
| import xyz.jpenilla.runpaper.task.RunServer | ||||
| import java.net.URI | ||||
|  | ||||
| plugins { | ||||
|     java | ||||
| @@ -22,7 +22,7 @@ plugins { | ||||
| } | ||||
|  | ||||
| group = "com.intellectualsites.plotsquared" | ||||
| version = "7.2.0" | ||||
| version = "7.3.2-SNAPSHOT" | ||||
|  | ||||
| if (!File("$rootDir/.git").exists()) { | ||||
|     logger.lifecycle(""" | ||||
| @@ -79,7 +79,8 @@ subprojects { | ||||
|  | ||||
|     dependencies { | ||||
|         // Tests | ||||
|         testImplementation("org.junit.jupiter:junit-jupiter:5.10.0") | ||||
|         testImplementation("org.junit.jupiter:junit-jupiter:5.10.1") | ||||
|         testRuntimeOnly("org.junit.platform:junit-platform-launcher:1.10.1") | ||||
|     } | ||||
|  | ||||
|     plugins.withId("java") { | ||||
| @@ -224,7 +225,7 @@ tasks.getByName<Jar>("jar") { | ||||
|     enabled = false | ||||
| } | ||||
|  | ||||
| val supportedVersions = listOf("1.16.5", "1.17.1", "1.18.2", "1.19.4", "1.20.1", "1.20.2") | ||||
| val supportedVersions = listOf("1.16.5", "1.17.1", "1.18.2", "1.19.4", "1.20.1", "1.20.4") | ||||
| tasks { | ||||
|     register("cacheLatestFaweArtifact") { | ||||
|         val lastSuccessfulBuildUrl = uri("https://ci.athion.net/job/FastAsyncWorldEdit/lastSuccessfulBuild/api/json").toURL() | ||||
|   | ||||
| @@ -2,18 +2,18 @@ | ||||
| # Platform expectations | ||||
| paper = "1.20.2-R0.1-SNAPSHOT" | ||||
| guice = "7.0.0" | ||||
| spotbugs = "4.8.0" | ||||
| checkerqual = "3.39.0" | ||||
| spotbugs = "4.8.3" | ||||
| checkerqual = "3.42.0" | ||||
| gson = "2.10" | ||||
| guava = "31.1-jre" | ||||
| snakeyaml = "2.0" | ||||
| adventure = "4.14.0" | ||||
| adventure-bukkit = "4.3.1" | ||||
| adventure = "4.15.0" | ||||
| adventure-bukkit = "4.3.2" | ||||
| log4j = "2.19.0" | ||||
|  | ||||
| # Plugins | ||||
| worldedit = "7.2.17" | ||||
| fawe = "2.8.1" | ||||
| worldedit = "7.2.18" | ||||
| fawe = "2.8.3" | ||||
| placeholderapi = "2.11.5" | ||||
| luckperms = "5.4" | ||||
| essentialsx = "2.20.1" | ||||
| @@ -31,13 +31,15 @@ paperlib = "1.0.8" | ||||
| informative-annotations = "1.4" | ||||
| vault = "1.7.1" | ||||
| serverlib = "2.3.4" | ||||
| cloud = "2.0.0-beta.1" | ||||
| cloudRequirements = "1.0.0-beta.1" | ||||
|  | ||||
| # Gradle plugins | ||||
| shadow = "8.1.1" | ||||
| grgit = "4.1.1" | ||||
| spotless = "6.22.0" | ||||
| spotless = "6.23.3" | ||||
| nexus = "1.3.0" | ||||
| runPaper = "2.2.0" | ||||
| runPaper = "2.2.2" | ||||
|  | ||||
| [libraries] | ||||
| # Platform expectations | ||||
| @@ -66,7 +68,7 @@ faweBukkit = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Bukk | ||||
| # Third party | ||||
| prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" } | ||||
| aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" } | ||||
| cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud-services" } | ||||
| cloudServices = { group = "org.incendo", name = "cloud-services", version.ref = "cloud-services" } | ||||
| mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" } | ||||
| squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" } | ||||
| arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" } | ||||
| @@ -77,6 +79,10 @@ informativeAnnotations = { group = "com.intellectualsites.informative-annotation | ||||
| paperlib = { group = "io.papermc", name = "paperlib", version.ref = "paperlib" } | ||||
| vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" } | ||||
| serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" } | ||||
| cloud = { group = "org.incendo", name = "cloud-core", version.ref = "cloud" } | ||||
| cloudPaper = { group = "org.incendo", name = "cloud-paper", version.ref = "cloud" } | ||||
| cloudMinecraftExtras = { group = "org.incendo", name = "cloud-minecraft-extras", version.ref = "cloud" } | ||||
| cloudRequirements = { group = "org.incendo", name = "cloud-processors-requirements", version.ref = "cloudRequirements" } | ||||
|  | ||||
| [plugins] | ||||
| shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } | ||||
|   | ||||
							
								
								
									
										
											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 | ||||
| distributionPath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip | ||||
| networkTimeout=10000 | ||||
| validateDistributionUrl=true | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
|   | ||||
		Reference in New Issue
	
	Block a user