mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-31 09:33:43 +01:00 
			
		
		
		
	Compare commits
	
		
			14 Commits
		
	
	
		
			fix/miniMe
			...
			feature/cl
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | c8e5cf163f | ||
|   | 628c520c1b | ||
|   | e0c7c58aaa | ||
|   | a659832613 | ||
|   | 2a0ad92a97 | ||
|   | 780c65e68c | ||
|   | 92a00ef60a | ||
|   | 3a1b373c8e | ||
|   | 1a277bbbeb | ||
|   | 24d7fe626d | ||
|   | b62a237dab | ||
|   | 2ac2f6648e | ||
|   | 6088dd8409 | ||
|   | e4613cfc62 | 
| @@ -53,6 +53,9 @@ dependencies { | |||||||
|  |  | ||||||
|     // Adventure |     // Adventure | ||||||
|     implementation(libs.adventureBukkit) |     implementation(libs.adventureBukkit) | ||||||
|  |  | ||||||
|  |     // Cloud | ||||||
|  |     implementation(libs.cloudPaper) | ||||||
| } | } | ||||||
|  |  | ||||||
| tasks.processResources { | tasks.processResources { | ||||||
| @@ -77,6 +80,7 @@ tasks.named<ShadowJar>("shadowJar") { | |||||||
|     relocate("com.google.inject", "com.plotsquared.google") |     relocate("com.google.inject", "com.plotsquared.google") | ||||||
|     relocate("org.aopalliance", "com.plotsquared.core.aopalliance") |     relocate("org.aopalliance", "com.plotsquared.core.aopalliance") | ||||||
|     relocate("cloud.commandframework.services", "com.plotsquared.core.services") |     relocate("cloud.commandframework.services", "com.plotsquared.core.services") | ||||||
|  |     relocate("cloud.commandframework", "com.plotsquared.commands") | ||||||
|     relocate("io.leangen.geantyref", "com.plotsquared.core.geantyref") |     relocate("io.leangen.geantyref", "com.plotsquared.core.geantyref") | ||||||
|     relocate("com.intellectualsites.arkitektonika", "com.plotsquared.core.arkitektonika") |     relocate("com.intellectualsites.arkitektonika", "com.plotsquared.core.arkitektonika") | ||||||
|     relocate("com.intellectualsites.http", "com.plotsquared.core.http") |     relocate("com.intellectualsites.http", "com.plotsquared.core.http") | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ import com.google.inject.TypeLiteral; | |||||||
| import com.plotsquared.bukkit.generator.BukkitPlotGenerator; | import com.plotsquared.bukkit.generator.BukkitPlotGenerator; | ||||||
| import com.plotsquared.bukkit.inject.BackupModule; | import com.plotsquared.bukkit.inject.BackupModule; | ||||||
| import com.plotsquared.bukkit.inject.BukkitModule; | import com.plotsquared.bukkit.inject.BukkitModule; | ||||||
|  | import com.plotsquared.bukkit.inject.CloudModule; | ||||||
| import com.plotsquared.bukkit.inject.PermissionModule; | import com.plotsquared.bukkit.inject.PermissionModule; | ||||||
| import com.plotsquared.bukkit.inject.WorldManagerModule; | import com.plotsquared.bukkit.inject.WorldManagerModule; | ||||||
| import com.plotsquared.bukkit.listener.BlockEventListener; | import com.plotsquared.bukkit.listener.BlockEventListener; | ||||||
| @@ -64,6 +65,7 @@ import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; | |||||||
| import com.plotsquared.core.PlotPlatform; | import com.plotsquared.core.PlotPlatform; | ||||||
| import com.plotsquared.core.PlotSquared; | import com.plotsquared.core.PlotSquared; | ||||||
| import com.plotsquared.core.backup.BackupManager; | import com.plotsquared.core.backup.BackupManager; | ||||||
|  | import com.plotsquared.core.commands.PlotSquaredCommandManager; | ||||||
| import com.plotsquared.core.components.ComponentPresetManager; | import com.plotsquared.core.components.ComponentPresetManager; | ||||||
| import com.plotsquared.core.configuration.ConfigurationNode; | import com.plotsquared.core.configuration.ConfigurationNode; | ||||||
| import com.plotsquared.core.configuration.ConfigurationSection; | import com.plotsquared.core.configuration.ConfigurationSection; | ||||||
| @@ -83,6 +85,7 @@ import com.plotsquared.core.inject.annotations.DefaultGenerator; | |||||||
| import com.plotsquared.core.inject.annotations.ImpromptuPipeline; | import com.plotsquared.core.inject.annotations.ImpromptuPipeline; | ||||||
| import com.plotsquared.core.inject.annotations.WorldConfig; | import com.plotsquared.core.inject.annotations.WorldConfig; | ||||||
| import com.plotsquared.core.inject.annotations.WorldFile; | 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.inject.modules.PlotSquaredModule; | ||||||
| import com.plotsquared.core.listener.PlotListener; | import com.plotsquared.core.listener.PlotListener; | ||||||
| import com.plotsquared.core.listener.WESubscriber; | import com.plotsquared.core.listener.WESubscriber; | ||||||
| @@ -293,6 +296,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | |||||||
|                         new PermissionModule(), |                         new PermissionModule(), | ||||||
|                         new WorldManagerModule(), |                         new WorldManagerModule(), | ||||||
|                         new PlotSquaredModule(), |                         new PlotSquaredModule(), | ||||||
|  |                         new CommandModule(), | ||||||
|  |                         new CloudModule(this), | ||||||
|                         new BukkitModule(this), |                         new BukkitModule(this), | ||||||
|                         new BackupModule() |                         new BackupModule() | ||||||
|                 ); |                 ); | ||||||
| @@ -388,6 +393,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | |||||||
|         // Commands |         // Commands | ||||||
|         if (Settings.Enabled_Components.COMMANDS) { |         if (Settings.Enabled_Components.COMMANDS) { | ||||||
|             this.registerCommands(); |             this.registerCommands(); | ||||||
|  |             // Register the commands. | ||||||
|  |             this.injector().getInstance(PlotSquaredCommandManager.class).registerDefaultCommands(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Permissions |         // Permissions | ||||||
|   | |||||||
| @@ -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); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -55,6 +55,14 @@ public class TranslationUpdateManager { | |||||||
|         String userMove = "userMove"; |         String userMove = "userMove"; | ||||||
|         String userMoveReplacement = "user_move"; |         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()))) { |         try (Stream<Path> paths = Files.walk(Paths.get(PlotSquared.platform().getDirectory().toPath().resolve("lang").toUri()))) { | ||||||
|             paths |             paths | ||||||
|                     .filter(Files::isRegularFile) |                     .filter(Files::isRegularFile) | ||||||
| @@ -68,6 +76,9 @@ public class TranslationUpdateManager { | |||||||
|                         replaceInFile(p, minimumRadius, minimumRadiusReplacement); |                         replaceInFile(p, minimumRadius, minimumRadiusReplacement); | ||||||
|                         replaceInFile(p, maximumMoves, maximumMovesReplacement); |                         replaceInFile(p, maximumMoves, maximumMovesReplacement); | ||||||
|                         replaceInFile(p, userMove, userMoveReplacement); |                         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.adventureApi) | ||||||
|     api(libs.adventureMiniMessage) |     api(libs.adventureMiniMessage) | ||||||
|  |  | ||||||
|  |     // Cloud | ||||||
|  |     api(libs.cloud) | ||||||
|  |     api(libs.cloudMinecraftExtras) | ||||||
|  |     api(libs.cloudRequirements) | ||||||
|  |  | ||||||
|     // Guice |     // Guice | ||||||
|     api(libs.guice) { |     api(libs.guice) { | ||||||
|         exclude(group = "com.google.guava") |         exclude(group = "com.google.guava") | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ | |||||||
|  */ |  */ | ||||||
| package com.plotsquared.core; | package com.plotsquared.core; | ||||||
|  |  | ||||||
| import cloud.commandframework.services.ServicePipeline; |  | ||||||
| import com.google.inject.Injector; | import com.google.inject.Injector; | ||||||
| import com.google.inject.Key; | import com.google.inject.Key; | ||||||
| import com.google.inject.TypeLiteral; | import com.google.inject.TypeLiteral; | ||||||
| @@ -47,6 +46,7 @@ import net.kyori.adventure.audience.Audience; | |||||||
| import net.kyori.adventure.text.Component; | import net.kyori.adventure.text.Component; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
| import org.checkerframework.checker.nullness.qual.Nullable; | import org.checkerframework.checker.nullness.qual.Nullable; | ||||||
|  | import org.incendo.cloud.services.ServicePipeline; | ||||||
|  |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ | |||||||
|  */ |  */ | ||||||
| package com.plotsquared.core.command; | package com.plotsquared.core.command; | ||||||
|  |  | ||||||
| import cloud.commandframework.services.ServicePipeline; |  | ||||||
| import com.google.inject.Inject; | import com.google.inject.Inject; | ||||||
| import com.plotsquared.core.PlotSquared; | import com.plotsquared.core.PlotSquared; | ||||||
| import com.plotsquared.core.configuration.Settings; | 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 net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
| import org.checkerframework.checker.nullness.qual.Nullable; | import org.checkerframework.checker.nullness.qual.Nullable; | ||||||
|  | import org.incendo.cloud.services.ServicePipeline; | ||||||
|  |  | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.Iterator; | import java.util.Iterator; | ||||||
| @@ -332,7 +332,7 @@ public class Auto extends SubCommand { | |||||||
|         List<Plot> plots = this.servicePipeline |         List<Plot> plots = this.servicePipeline | ||||||
|                 .pump(new AutoQuery(player, null, sizeX, sizeZ, plotarea)) |                 .pump(new AutoQuery(player, null, sizeX, sizeZ, plotarea)) | ||||||
|                 .through(AutoService.class) |                 .through(AutoService.class) | ||||||
|                 .getResult(); |                 .complete(); | ||||||
|  |  | ||||||
|         plots = this.eventDispatcher.callAutoPlotsChosen(player, plots).getPlots(); |         plots = this.eventDispatcher.callAutoPlotsChosen(player, plots).getPlots(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -465,7 +465,7 @@ public class ListCmd extends SubCommand { | |||||||
|                 TextComponent.Builder builder = Component.text(); |                 TextComponent.Builder builder = Component.text(); | ||||||
|                 if (plot.getFlag(ServerPlotFlag.class)) { |                 if (plot.getFlag(ServerPlotFlag.class)) { | ||||||
|                     TagResolver serverResolver = TagResolver.resolver( |                     TagResolver serverResolver = TagResolver.resolver( | ||||||
|                             "info.server", |                             "server", | ||||||
|                             Tag.inserting(TranslatableCaption.of("info.server").toComponent(player)) |                             Tag.inserting(TranslatableCaption.of("info.server").toComponent(player)) | ||||||
|                     ); |                     ); | ||||||
|                     builder.append(MINI_MESSAGE.deserialize(server, serverResolver)); |                     builder.append(MINI_MESSAGE.deserialize(server, serverResolver)); | ||||||
| @@ -483,13 +483,13 @@ public class ListCmd extends SubCommand { | |||||||
|                                 builder.append(MINI_MESSAGE.deserialize(online, resolver)); |                                 builder.append(MINI_MESSAGE.deserialize(online, resolver)); | ||||||
|                             } else if (uuidMapping.username().equalsIgnoreCase("unknown")) { |                             } else if (uuidMapping.username().equalsIgnoreCase("unknown")) { | ||||||
|                                 TagResolver unknownResolver = TagResolver.resolver( |                                 TagResolver unknownResolver = TagResolver.resolver( | ||||||
|                                         "info.unknown", |                                         "unknown", | ||||||
|                                         Tag.inserting(TranslatableCaption.of("info.unknown").toComponent(player)) |                                         Tag.inserting(TranslatableCaption.of("info.unknown").toComponent(player)) | ||||||
|                                 ); |                                 ); | ||||||
|                                 builder.append(MINI_MESSAGE.deserialize(unknown, unknownResolver)); |                                 builder.append(MINI_MESSAGE.deserialize(unknown, unknownResolver)); | ||||||
|                             } else if (uuidMapping.uuid().equals(DBFunc.EVERYONE)) { |                             } else if (uuidMapping.uuid().equals(DBFunc.EVERYONE)) { | ||||||
|                                 TagResolver everyoneResolver = TagResolver.resolver( |                                 TagResolver everyoneResolver = TagResolver.resolver( | ||||||
|                                         "info.everyone", |                                         "everyone", | ||||||
|                                         Tag.inserting(TranslatableCaption.of("info.everyone").toComponent(player)) |                                         Tag.inserting(TranslatableCaption.of("info.everyone").toComponent(player)) | ||||||
|                                 ); |                                 ); | ||||||
|                                 builder.append(MINI_MESSAGE.deserialize(everyone, everyoneResolver)); |                                 builder.append(MINI_MESSAGE.deserialize(everyone, everyoneResolver)); | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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.Tag; | ||||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
|  | import org.incendo.cloud.caption.Caption; | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
|  |  | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| @@ -33,7 +34,7 @@ import java.util.regex.Pattern; | |||||||
| /** | /** | ||||||
|  * Caption that is user modifiable |  * Caption that is user modifiable | ||||||
|  */ |  */ | ||||||
| public final class TranslatableCaption implements NamespacedCaption { | public final class TranslatableCaption implements NamespacedCaption, Caption { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Default caption namespace |      * 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 |      * Get a new {@link TranslatableCaption} instance | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -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; | package com.plotsquared.core.inject.modules; | ||||||
|  |  | ||||||
| import cloud.commandframework.services.ServicePipeline; |  | ||||||
| import com.google.inject.AbstractModule; | import com.google.inject.AbstractModule; | ||||||
| import com.plotsquared.core.PlotSquared; | import com.plotsquared.core.PlotSquared; | ||||||
| import com.plotsquared.core.configuration.file.YamlConfiguration; | 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.util.EventDispatcher; | ||||||
| import com.plotsquared.core.uuid.UUIDPipeline; | import com.plotsquared.core.uuid.UUIDPipeline; | ||||||
| import com.sk89q.worldedit.WorldEdit; | import com.sk89q.worldedit.WorldEdit; | ||||||
|  | import org.incendo.cloud.services.ServicePipeline; | ||||||
|  |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ | |||||||
|  */ |  */ | ||||||
| package com.plotsquared.core.services.plots; | package com.plotsquared.core.services.plots; | ||||||
|  |  | ||||||
| import cloud.commandframework.services.types.Service; |  | ||||||
| import com.google.common.cache.Cache; | import com.google.common.cache.Cache; | ||||||
| import com.google.common.cache.CacheBuilder; | import com.google.common.cache.CacheBuilder; | ||||||
| import com.plotsquared.core.plot.Plot; | import com.plotsquared.core.plot.Plot; | ||||||
| @@ -26,6 +25,7 @@ import com.plotsquared.core.plot.PlotAreaType; | |||||||
| import com.plotsquared.core.plot.PlotId; | import com.plotsquared.core.plot.PlotId; | ||||||
| import org.checkerframework.checker.nullness.qual.NonNull; | import org.checkerframework.checker.nullness.qual.NonNull; | ||||||
| import org.checkerframework.checker.nullness.qual.Nullable; | import org.checkerframework.checker.nullness.qual.Nullable; | ||||||
|  | import org.incendo.cloud.services.type.Service; | ||||||
|  |  | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|   | |||||||
| @@ -381,9 +381,9 @@ | |||||||
|   "info.plot_list_default": "<gold><plot></gold>", |   "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_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_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_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><info.server></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><info.everyone></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_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_tooltip": "<gold>Claimed=</gold><gray><claimed></gray>\n<gold>Usage=</gold><gray><usage></gray>\n<gold>Clusters=</gold><gray><clusters></gray>\n<gold>Region=</gold><gray><region></gray>\n<gold>Generator=</gold><gray><generator></gray>", | ||||||
|   "info.area_list_item": "<click:run_command:'<command_tp>'><hover:show_text:'<command_tp>'><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:'<command_info>'><hover:show_text:'<hover_info>'><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>", |   "info.area_list_item": "<click:run_command:'<command_tp>'><hover:show_text:'<command_tp>'><dark_gray>[</dark_gray><gold><number></gold><dark_gray>]</dark_gray></hover></click> <click:run_command:'<command_info>'><hover:show_text:'<hover_info>'><gold><area_name></gold></hover></click><gray> - </gray><gray><area_type>:<area_terrain></gray>", | ||||||
|   | |||||||
| @@ -31,6 +31,8 @@ paperlib = "1.0.8" | |||||||
| informative-annotations = "1.4" | informative-annotations = "1.4" | ||||||
| vault = "1.7.1" | vault = "1.7.1" | ||||||
| serverlib = "2.3.4" | serverlib = "2.3.4" | ||||||
|  | cloud = "2.0.0-beta.1" | ||||||
|  | cloudRequirements = "1.0.0-beta.1" | ||||||
|  |  | ||||||
| # Gradle plugins | # Gradle plugins | ||||||
| shadow = "8.1.1" | shadow = "8.1.1" | ||||||
| @@ -66,7 +68,7 @@ faweBukkit = { group = "com.fastasyncworldedit", name = "FastAsyncWorldEdit-Bukk | |||||||
| # Third party | # Third party | ||||||
| prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" } | prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" } | ||||||
| aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" } | 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" } | mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" } | ||||||
| squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" } | squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" } | ||||||
| arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" } | 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" } | paperlib = { group = "io.papermc", name = "paperlib", version.ref = "paperlib" } | ||||||
| vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" } | vault = { group = "com.github.MilkBowl", name = "VaultAPI", version.ref = "vault" } | ||||||
| serverlib = { group = "dev.notmyfault.serverlib", name = "ServerLib", version.ref = "serverlib" } | 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] | [plugins] | ||||||
| shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } | shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user