mirror of
				https://github.com/IntellectualSites/PlotSquared.git
				synced 2025-10-25 07:33:44 +02:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			fix/IOOBE-
			...
			feature/v7
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 99133ee485 | ||
|   | e415dcc8a4 | ||
|   | f2da7cbdc9 | ||
|   | f175c24523 | ||
|   | f3f44b55c4 | ||
|   | b946f31fe3 | ||
|   | 6bb1ebe1a1 | ||
|   | ab64836fc0 | ||
|   | d932d2eae6 | 
| @@ -53,6 +53,10 @@ dependencies { | ||||
|  | ||||
|     // Adventure | ||||
|     implementation("net.kyori:adventure-platform-bukkit") | ||||
|  | ||||
|     // Cloud | ||||
|     implementation(libs.cloudPaper) | ||||
|     implementation(libs.cloudMinecraftExtras) | ||||
| } | ||||
|  | ||||
| tasks.processResources { | ||||
|   | ||||
| @@ -63,6 +63,7 @@ import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; | ||||
| import com.plotsquared.core.PlotPlatform; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.backup.BackupManager; | ||||
| import com.plotsquared.core.commands.PlotSquaredCommandManager; | ||||
| import com.plotsquared.core.components.ComponentPresetManager; | ||||
| import com.plotsquared.core.configuration.ConfigurationNode; | ||||
| import com.plotsquared.core.configuration.ConfigurationSection; | ||||
| @@ -215,6 +216,8 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|     @Inject | ||||
|     private PlatformWorldManager<World> worldManager; | ||||
|     private Locale serverLocale; | ||||
|     @Inject | ||||
|     private PlotSquaredCommandManager commandManager; | ||||
|  | ||||
|     @SuppressWarnings("StringSplitter") | ||||
|     @Override | ||||
| @@ -382,6 +385,7 @@ public final class BukkitPlatform extends JavaPlugin implements Listener, PlotPl | ||||
|         // Commands | ||||
|         if (Settings.Enabled_Components.COMMANDS) { | ||||
|             this.registerCommands(); | ||||
|             this.commandManager.initializeCommands(); | ||||
|         } | ||||
|  | ||||
|         // Permissions | ||||
|   | ||||
| @@ -18,12 +18,16 @@ | ||||
|  */ | ||||
| package com.plotsquared.bukkit.inject; | ||||
|  | ||||
| import cloud.commandframework.CommandManager; | ||||
| import cloud.commandframework.execution.AsynchronousCommandExecutionCoordinator; | ||||
| import cloud.commandframework.paper.PaperCommandManager; | ||||
| import com.google.inject.AbstractModule; | ||||
| import com.google.inject.Provides; | ||||
| import com.google.inject.Singleton; | ||||
| import com.google.inject.assistedinject.FactoryModuleBuilder; | ||||
| import com.plotsquared.bukkit.BukkitPlatform; | ||||
| import com.plotsquared.bukkit.listener.SingleWorldListener; | ||||
| import com.plotsquared.bukkit.player.BukkitPlayer; | ||||
| import com.plotsquared.bukkit.player.BukkitPlayerManager; | ||||
| import com.plotsquared.bukkit.queue.BukkitChunkCoordinator; | ||||
| import com.plotsquared.bukkit.queue.BukkitQueueCoordinator; | ||||
| @@ -47,6 +51,8 @@ import com.plotsquared.core.inject.factory.ChunkCoordinatorBuilderFactory; | ||||
| import com.plotsquared.core.inject.factory.ChunkCoordinatorFactory; | ||||
| import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; | ||||
| import com.plotsquared.core.inject.factory.ProgressSubscriberFactory; | ||||
| import com.plotsquared.core.player.ConsolePlayer; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.world.DefaultPlotAreaManager; | ||||
| import com.plotsquared.core.plot.world.PlotAreaManager; | ||||
| import com.plotsquared.core.plot.world.SinglePlotAreaManager; | ||||
| @@ -68,10 +74,14 @@ import com.sk89q.worldedit.extension.platform.Actor; | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.bukkit.Bukkit; | ||||
| import org.bukkit.command.CommandSender; | ||||
| import org.bukkit.command.ConsoleCommandSender; | ||||
| import org.bukkit.entity.Player; | ||||
| import org.bukkit.plugin.java.JavaPlugin; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.function.Function; | ||||
|  | ||||
| public class BukkitModule extends AbstractModule { | ||||
|  | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + BukkitModule.class.getSimpleName()); | ||||
| @@ -145,4 +155,27 @@ public class BukkitModule extends AbstractModule { | ||||
|         return EconHandler.nullEconHandler(); | ||||
|     } | ||||
|  | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     @NonNull CommandManager<PlotPlayer<?>> provideCommandManager() throws Exception { | ||||
|         final Function<PlotPlayer<?>, CommandSender> plotToPlatform = plotPlayer -> { | ||||
|             if (plotPlayer instanceof BukkitPlayer bukkitPlayer) { | ||||
|                 return bukkitPlayer.getPlatformPlayer(); | ||||
|             } | ||||
|             return Bukkit.getConsoleSender(); | ||||
|         }; | ||||
|         final Function<CommandSender, PlotPlayer<?>> platformToPlot = commandSender -> { | ||||
|             if (commandSender instanceof Player player) { | ||||
|                 return BukkitUtil.adapt(player); | ||||
|             } | ||||
|             return ConsolePlayer.getConsole(); | ||||
|         }; | ||||
|  | ||||
|         return new PaperCommandManager<>( | ||||
|                 this.bukkitPlatform, | ||||
|                 AsynchronousCommandExecutionCoordinator.<PlotPlayer<?>>builder().withSynchronousParsing().build(), | ||||
|                 platformToPlot, | ||||
|                 plotToPlatform | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,11 @@ dependencies { | ||||
|     api("net.kyori:adventure-api") | ||||
|     api("net.kyori:adventure-text-minimessage") | ||||
|  | ||||
|     // Cloud | ||||
|     api(libs.cloudServices) | ||||
|     api(libs.cloudCore) | ||||
|     api(libs.cloudAnnotations) | ||||
|  | ||||
|     // Guice | ||||
|     api(libs.guice) { | ||||
|         exclude(group = "com.google.guava") | ||||
| @@ -40,7 +45,6 @@ dependencies { | ||||
|     // Other libraries | ||||
|     api(libs.prtree) | ||||
|     api(libs.aopalliance) | ||||
|     api(libs.cloudServices) | ||||
|     api(libs.arkitektonika) | ||||
|     api("com.intellectualsites.paster:Paster") | ||||
|     api("com.intellectualsites.informative-annotations:informative-annotations") | ||||
|   | ||||
| @@ -1,172 +0,0 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.command; | ||||
|  | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.util.PlayerManager; | ||||
| import com.plotsquared.core.util.TabCompletions; | ||||
| import com.plotsquared.core.util.task.RunnableVal2; | ||||
| import com.plotsquared.core.util.task.RunnableVal3; | ||||
| 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 java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.Iterator; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.TimeoutException; | ||||
|  | ||||
| @CommandDeclaration(command = "add", | ||||
|         usage = "/plot add <player | *>", | ||||
|         category = CommandCategory.SETTINGS, | ||||
|         permission = "plots.add", | ||||
|         requiredType = RequiredType.PLAYER) | ||||
| public class Add extends Command { | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     public Add(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         super(MainCommand.getInstance(), true); | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public CompletableFuture<Boolean> execute( | ||||
|             final PlotPlayer<?> player, | ||||
|             String[] args, | ||||
|             RunnableVal3<Command, Runnable, Runnable> confirm, | ||||
|             RunnableVal2<Command, CommandResult> whenDone | ||||
|     ) throws CommandException { | ||||
|         final Plot plot = check(player.getCurrentPlot(), TranslatableCaption.of("errors.not_in_plot")); | ||||
|         checkTrue(plot.hasOwner(), TranslatableCaption.of("info.plot_unowned")); | ||||
|         checkTrue( | ||||
|                 plot.isOwner(player.getUUID()) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST), | ||||
|                 TranslatableCaption.of("permission.no_plot_perms") | ||||
|         ); | ||||
|         checkTrue(args.length == 1, | ||||
|                 TranslatableCaption.of("commandconfig.command_syntax"), | ||||
|                 TagResolver.resolver("value", Tag.inserting(Component.text("/plot add <player | *>"))) | ||||
|         ); | ||||
|         final CompletableFuture<Boolean> future = new CompletableFuture<>(); | ||||
|         PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> { | ||||
|             if (throwable != null) { | ||||
|                 if (throwable instanceof TimeoutException) { | ||||
|                     player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("errors.invalid_player"), | ||||
|                             TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) | ||||
|                     ); | ||||
|                 } | ||||
|                 future.completeExceptionally(throwable); | ||||
|                 return; | ||||
|             } else { | ||||
|                 try { | ||||
|                     checkTrue(!uuids.isEmpty(), TranslatableCaption.of("errors.invalid_player"), | ||||
|                             TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) | ||||
|                     ); | ||||
|                     Iterator<UUID> iterator = uuids.iterator(); | ||||
|                     int size = plot.getTrusted().size() + plot.getMembers().size(); | ||||
|                     while (iterator.hasNext()) { | ||||
|                         UUID uuid = iterator.next(); | ||||
|                         if (uuid == DBFunc.EVERYONE && !(player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission( | ||||
|                                 Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { | ||||
|                             player.sendMessage( | ||||
|                                     TranslatableCaption.of("errors.invalid_player"), | ||||
|                                     TagResolver.resolver("value", Tag.inserting( | ||||
|                                             PlayerManager.resolveName(uuid).toComponent(player) | ||||
|                                     )) | ||||
|                             ); | ||||
|                             iterator.remove(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         if (plot.isOwner(uuid)) { | ||||
|                             player.sendMessage( | ||||
|                                     TranslatableCaption.of("member.already_added"), | ||||
|                                     TagResolver.resolver("player", Tag.inserting( | ||||
|                                             PlayerManager.resolveName(uuid).toComponent(player) | ||||
|                                     )) | ||||
|                             ); | ||||
|                             iterator.remove(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         if (plot.getMembers().contains(uuid)) { | ||||
|                             player.sendMessage( | ||||
|                                     TranslatableCaption.of("member.already_added"), | ||||
|                                     TagResolver.resolver("player", Tag.inserting( | ||||
|                                             PlayerManager.resolveName(uuid).toComponent(player) | ||||
|                                     )) | ||||
|                             ); | ||||
|                             iterator.remove(); | ||||
|                             continue; | ||||
|                         } | ||||
|                         size += plot.getTrusted().contains(uuid) ? 0 : 1; | ||||
|                     } | ||||
|                     checkTrue(!uuids.isEmpty(), null); | ||||
|                     int localAddSize = plot.getMembers().size(); | ||||
|                     int maxAddSize = player.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS); | ||||
|                     if (localAddSize >= maxAddSize) { | ||||
|                         player.sendMessage( | ||||
|                                 TranslatableCaption.of("members.plot_max_members_added"), | ||||
|                                 TagResolver.resolver("amount", Tag.inserting(Component.text(localAddSize))) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                     // Success | ||||
|                     confirm.run(this, () -> { | ||||
|                         for (UUID uuid : uuids) { | ||||
|                             if (uuid != DBFunc.EVERYONE) { | ||||
|                                 if (!plot.removeTrusted(uuid)) { | ||||
|                                     if (plot.getDenied().contains(uuid)) { | ||||
|                                         plot.removeDenied(uuid); | ||||
|                                     } | ||||
|                                 } | ||||
|                             } | ||||
|                             plot.addMember(uuid); | ||||
|                             this.eventDispatcher.callMember(player, plot, uuid, true); | ||||
|                             player.sendMessage(TranslatableCaption.of("member.member_added")); | ||||
|                         } | ||||
|                     }, null); | ||||
|                 } catch (final Throwable exception) { | ||||
|                     future.completeExceptionally(exception); | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
|             future.complete(true); | ||||
|         }); | ||||
|         return future; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { | ||||
|         return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,210 +0,0 @@ | ||||
| /* | ||||
|  * PlotSquared, a land and world management plugin for Minecraft. | ||||
|  * Copyright (C) IntellectualSites <https://intellectualsites.com> | ||||
|  * Copyright (C) IntellectualSites team and contributors | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| package com.plotsquared.core.command; | ||||
|  | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.query.PlotQuery; | ||||
| import net.kyori.adventure.text.Component; | ||||
| import net.kyori.adventure.text.minimessage.tag.Tag; | ||||
| import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.concurrent.TimeoutException; | ||||
|  | ||||
| @CommandDeclaration(command = "alias", | ||||
|         permission = "plots.alias", | ||||
|         usage = "/plot alias <set | remove> <alias>", | ||||
|         aliases = {"setalias", "sa", "name", "rename", "setname", "seta", "nameplot"}, | ||||
|         category = CommandCategory.SETTINGS, | ||||
|         requiredType = RequiredType.PLAYER) | ||||
| public class Alias extends SubCommand { | ||||
|  | ||||
|     private static final Command SET_COMMAND = new Command(null, false, "set", null, RequiredType.NONE, null) { | ||||
|     }; | ||||
|     private static final Command REMOVE_COMMAND = new Command(null, false, "remove", null, RequiredType.NONE, null) { | ||||
|     }; | ||||
|  | ||||
|     @Override | ||||
|     public boolean onCommand(PlotPlayer<?> player, String[] args) { | ||||
|  | ||||
|         if (args.length == 0) { | ||||
|             sendUsage(player); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         Location location = player.getLocation(); | ||||
|         Plot plot = location.getPlotAbs(); | ||||
|         if (plot == null) { | ||||
|             player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!plot.hasOwner()) { | ||||
|             player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         boolean result = false; | ||||
|  | ||||
|         boolean owner = plot.isOwner(player.getUUID()); | ||||
|         boolean permission; | ||||
|         boolean admin; | ||||
|         switch (args[0].toLowerCase()) { | ||||
|             case "set" -> { | ||||
|                 if (args.length != 2) { | ||||
|                     sendUsage(player); | ||||
|                     return false; | ||||
|                 } | ||||
|                 permission = isPermitted(player, Permission.PERMISSION_ALIAS_SET); | ||||
|                 admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_SET); | ||||
|                 if (!admin && !owner) { | ||||
|                     player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|                     return false; | ||||
|                 } | ||||
|                 if (permission) { // is either admin or owner | ||||
|                     setAlias(player, plot, args[1]); | ||||
|                     return true; | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
|                             TagResolver.resolver( | ||||
|                                     "node", | ||||
|                                     Tag.inserting(Permission.PERMISSION_ALIAS_SET) | ||||
|                             ) | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|             case "remove" -> { | ||||
|                 permission = isPermitted(player, Permission.PERMISSION_ALIAS_REMOVE); | ||||
|                 admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_REMOVE); | ||||
|                 if (!admin && !owner) { | ||||
|                     player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|                     return false; | ||||
|                 } | ||||
|                 if (permission) { | ||||
|                     result = removeAlias(player, plot); | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("permission.no_permission"), | ||||
|                             TagResolver.resolver( | ||||
|                                     "node", | ||||
|                                     Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE) | ||||
|                             ) | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
|             default -> { | ||||
|                 sendUsage(player); | ||||
|                 result = false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Collection<Command> tab(PlotPlayer<?> player, String[] args, boolean space) { | ||||
|         final List<Command> commands = new ArrayList<>(2); | ||||
|         if (args.length == 1) { | ||||
|             if ("set".startsWith(args[0])) { | ||||
|                 commands.add(SET_COMMAND); | ||||
|             } | ||||
|             if ("remove".startsWith(args[0])) { | ||||
|                 commands.add(REMOVE_COMMAND); | ||||
|             } | ||||
|             return commands; | ||||
|         } | ||||
|         return Collections.emptySet(); | ||||
|     } | ||||
|  | ||||
|     private void setAlias(PlotPlayer<?> player, Plot plot, String alias) { | ||||
|         if (alias.isEmpty()) { | ||||
|             sendUsage(player); | ||||
|         } else if (alias.length() >= 50) { | ||||
|             player.sendMessage(TranslatableCaption.of("alias.alias_too_long")); | ||||
|         } else if (MathMan.isInteger(alias)) { | ||||
|             player.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong | ||||
|         } else { | ||||
|             if (PlotQuery.newQuery().inArea(plot.getArea()) | ||||
|                     .withAlias(alias) | ||||
|                     .anyMatch()) { | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|             if (Settings.UUID.OFFLINE) { | ||||
|                 plot.setAlias(alias); | ||||
|                 player.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_set_to"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|             PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { | ||||
|                 if (throwable instanceof TimeoutException) { | ||||
|                     player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|                 } else if (uuid != null) { | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                             TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                     ); | ||||
|                 } else { | ||||
|                     plot.setAlias(alias); | ||||
|                     player.sendMessage( | ||||
|                             TranslatableCaption.of("alias.alias_set_to"), | ||||
|                             TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                     ); | ||||
|                 } | ||||
|             })); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private boolean removeAlias(PlotPlayer<?> player, Plot plot) { | ||||
|         String alias = plot.getAlias(); | ||||
|         if (!plot.getAlias().isEmpty()) { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("alias.alias_removed"), | ||||
|                     TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|             ); | ||||
|         } else { | ||||
|             player.sendMessage( | ||||
|                     TranslatableCaption.of("alias.no_alias_set") | ||||
|             ); | ||||
|         } | ||||
|         plot.setAlias(null); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     private boolean isPermitted(PlotPlayer<?> player, Permission permission) { | ||||
|         return player.hasPermission(permission); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -86,7 +86,6 @@ public class MainCommand extends Command { | ||||
|             commands.add(CreateRoadSchematic.class); | ||||
|             commands.add(DebugAllowUnsafe.class); | ||||
|             commands.add(RegenAllRoads.class); | ||||
|             commands.add(Claim.class); | ||||
|             commands.add(Auto.class); | ||||
|             commands.add(HomeCommand.class); | ||||
|             commands.add(Visit.class); | ||||
| @@ -94,7 +93,6 @@ public class MainCommand extends Command { | ||||
|             commands.add(Clear.class); | ||||
|             commands.add(Delete.class); | ||||
|             commands.add(Trust.class); | ||||
|             commands.add(Add.class); | ||||
|             commands.add(Leave.class); | ||||
|             commands.add(Deny.class); | ||||
|             commands.add(Remove.class); | ||||
| @@ -130,7 +128,6 @@ public class MainCommand extends Command { | ||||
|             commands.add(Owner.class); | ||||
|             commands.add(Desc.class); | ||||
|             commands.add(Biome.class); | ||||
|             commands.add(Alias.class); | ||||
|             commands.add(SetHome.class); | ||||
|             commands.add(Cluster.class); | ||||
|             commands.add(DebugImportWorlds.class); | ||||
|   | ||||
							
								
								
									
										104
									
								
								Core/src/main/java/com/plotsquared/core/commands/CommandAdd.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								Core/src/main/java/com/plotsquared/core/commands/CommandAdd.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| /* | ||||
|  * 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 cloud.commandframework.annotations.Argument; | ||||
| import cloud.commandframework.annotations.CommandMethod; | ||||
| import cloud.commandframework.annotations.CommandPermission; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.arguments.PlotMember; | ||||
| import com.plotsquared.core.commands.requirements.Requirement; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirement; | ||||
| 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.Plot; | ||||
| import com.plotsquared.core.util.EventDispatcher; | ||||
| import com.plotsquared.core.util.PlayerManager; | ||||
| 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; | ||||
|  | ||||
| class CommandAdd implements PlotSquaredCommandContainer { | ||||
|  | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|  | ||||
|     @Inject | ||||
|     CommandAdd(final @NonNull EventDispatcher eventDispatcher) { | ||||
|         this.eventDispatcher = eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.IS_OWNER) | ||||
|     @CommandPermission("plots.add") | ||||
|     @CommandMethod("${command.prefix} add [target]") | ||||
|     public void commandAdd( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             @Argument("target") final PlotMember target, | ||||
|             final @NonNull Plot plot | ||||
|     ) { | ||||
|         if (target instanceof PlotMember.Everyone) { | ||||
|             if (!sender.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) && !sender.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST)) { | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("errors.invalid_player"), | ||||
|                         TagResolver.resolver("value", Tag.inserting( | ||||
|                                 PlayerManager.resolveName(target.uuid()).toComponent(sender) | ||||
|                         )) | ||||
|                 ); | ||||
|                 return; | ||||
|             } | ||||
|         } else if (plot.isOwner(target.uuid())) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("member.already_added"), | ||||
|                     TagResolver.resolver("player", Tag.inserting( | ||||
|                             PlayerManager.resolveName(target.uuid()).toComponent(sender) | ||||
|                     )) | ||||
|             ); | ||||
|             return; | ||||
|         } else if (plot.getMembers().contains(target.uuid())) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("member.already_added"), | ||||
|                     TagResolver.resolver("player", Tag.inserting( | ||||
|                             PlayerManager.resolveName(target.uuid()).toComponent(sender) | ||||
|                     )) | ||||
|             ); | ||||
|             return; | ||||
|         } else if (plot.getMembers().size() >= sender.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS)) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("members.plot_max_members_added"), | ||||
|                     TagResolver.resolver("amount", Tag.inserting(Component.text(plot.getMembers().size()))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (target instanceof PlotMember.Player) { | ||||
|             if (!plot.removeTrusted(target.uuid())) { | ||||
|                 if (plot.getDenied().contains(target.uuid())) { | ||||
|                     plot.removeDenied(target.uuid()); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         plot.addMember(target.uuid()); | ||||
|         this.eventDispatcher.callMember(sender, plot, target.uuid(), true); | ||||
|         sender.sendMessage(TranslatableCaption.of("member.member_added")); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,136 @@ | ||||
| package com.plotsquared.core.commands; | ||||
|  | ||||
| import cloud.commandframework.annotations.Argument; | ||||
| import cloud.commandframework.annotations.CommandMethod; | ||||
| import cloud.commandframework.annotations.CommandPermission; | ||||
| import com.plotsquared.core.PlotSquared; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirement; | ||||
| import com.plotsquared.core.commands.requirements.Requirement; | ||||
| 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.Plot; | ||||
| import com.plotsquared.core.util.MathMan; | ||||
| import com.plotsquared.core.util.query.PlotQuery; | ||||
| 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 java.util.concurrent.TimeoutException; | ||||
|  | ||||
| public class CommandAlias implements PlotSquaredCommandContainer { | ||||
|  | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.PLOT_HAS_OWNER) | ||||
|     @CommandPermission("plots.alias") | ||||
|     @CommandMethod("${command.prefix} alias set <alias>") | ||||
|     public void commandAliasSet( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             final @NonNull Plot plot, | ||||
|             @Argument("alias") final @NonNull String alias | ||||
|     ) { | ||||
|         final boolean isOwner = plot.isOwner(sender.getUUID()); | ||||
|  | ||||
|         if (!isOwner && !sender.hasPermission(Permission.PERMISSION_ADMIN_ALIAS_SET)) { | ||||
|             sender.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|             return; | ||||
|         } else if (!sender.hasPermission(Permission.PERMISSION_ALIAS_SET)) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("permission.no_permission"), | ||||
|                     TagResolver.resolver( | ||||
|                             "node", | ||||
|                             Tag.inserting(Permission.PERMISSION_ALIAS_SET) | ||||
|                     ) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (alias.length() >= 50) { | ||||
|             sender.sendMessage(TranslatableCaption.of("alias.alias_too_long")); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (MathMan.isInteger(alias)) { | ||||
|             sender.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (PlotQuery.newQuery().inArea(plot.getArea()) | ||||
|                 .withAlias(alias) | ||||
|                 .anyMatch()) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                     TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (Settings.UUID.OFFLINE) { | ||||
|             plot.setAlias(alias); | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("alias.alias_set_to"), | ||||
|                     TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { | ||||
|             if (throwable instanceof TimeoutException) { | ||||
|                 sender.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); | ||||
|             } else if (uuid != null) { | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_is_taken"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|             } else { | ||||
|                 plot.setAlias(alias); | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("alias.alias_set_to"), | ||||
|                         TagResolver.resolver("alias", Tag.inserting(Component.text(alias))) | ||||
|                 ); | ||||
|             } | ||||
|         })); | ||||
|     } | ||||
|  | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.PLOT_HAS_OWNER) | ||||
|     @CommandPermission("plots.alias") | ||||
|     @CommandMethod("${command.prefix} alias remove") | ||||
|     public void commandAliasRemove( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             final @NonNull Plot plot | ||||
|     ) { | ||||
|         final boolean isOwner = plot.isOwner(sender.getUUID()); | ||||
|  | ||||
|         if (!isOwner && !sender.hasPermission(Permission.PERMISSION_ADMIN_ALIAS_REMOVE)) { | ||||
|             sender.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); | ||||
|             return; | ||||
|         } else if (!sender.hasPermission(Permission.PERMISSION_ALIAS_REMOVE)) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("permission.no_permission"), | ||||
|                     TagResolver.resolver( | ||||
|                             "node", | ||||
|                             Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE) | ||||
|                     ) | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (plot.getAlias().isEmpty()) { | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("alias.no_alias_set") | ||||
|             ); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         final String currentAlias = plot.getAlias(); | ||||
|         plot.setAlias(null); | ||||
|  | ||||
|         sender.sendMessage( | ||||
|                 TranslatableCaption.of("alias.alias_removed"), | ||||
|                 TagResolver.resolver("alias", Tag.inserting(Component.text(currentAlias))) | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| @@ -1,24 +1,11 @@ | ||||
| /* | ||||
|  * 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.command; | ||||
| package com.plotsquared.core.commands; | ||||
| 
 | ||||
| import cloud.commandframework.annotations.Argument; | ||||
| import cloud.commandframework.annotations.CommandMethod; | ||||
| import cloud.commandframework.annotations.CommandPermission; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirement; | ||||
| import com.plotsquared.core.commands.requirements.Requirement; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| @@ -26,7 +13,6 @@ import com.plotsquared.core.events.PlayerClaimPlotEvent; | ||||
| import com.plotsquared.core.events.PlotMergeEvent; | ||||
| import com.plotsquared.core.events.Result; | ||||
| import com.plotsquared.core.location.Direction; | ||||
| import com.plotsquared.core.location.Location; | ||||
| import com.plotsquared.core.permissions.Permission; | ||||
| import com.plotsquared.core.player.MetaDataAccess; | ||||
| import com.plotsquared.core.player.PlayerMetaDataKeys; | ||||
| @@ -43,22 +29,17 @@ import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; | ||||
| 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; | ||||
| 
 | ||||
| @CommandDeclaration( | ||||
|         command = "claim", | ||||
|         aliases = "c", | ||||
|         category = CommandCategory.CLAIMING, | ||||
|         requiredType = RequiredType.PLAYER, permission = "plots.claim", | ||||
|         usage = "/plot claim") | ||||
| public class Claim extends SubCommand { | ||||
| public class CommandClaim implements PlotSquaredCommandContainer { | ||||
| 
 | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + Claim.class.getSimpleName()); | ||||
|     private static final Logger LOGGER = LogManager.getLogger("PlotSquared/" + CommandClaim.class.getSimpleName()); | ||||
| 
 | ||||
|     private final EventDispatcher eventDispatcher; | ||||
|     private final EconHandler econHandler; | ||||
| 
 | ||||
|     @Inject | ||||
|     public Claim( | ||||
|     CommandClaim( | ||||
|             final @NonNull EventDispatcher eventDispatcher, | ||||
|             final @NonNull EconHandler econHandler | ||||
|     ) { | ||||
| @@ -66,124 +47,132 @@ public class Claim extends SubCommand { | ||||
|         this.econHandler = econHandler; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean onCommand(final PlotPlayer<?> player, String[] args) { | ||||
|         String schematic = null; | ||||
|         if (args.length >= 1) { | ||||
|             schematic = args[0]; | ||||
|         } | ||||
|         Location location = player.getLocation(); | ||||
|         Plot plot = location.getPlotAbs(); | ||||
|         if (plot == null) { | ||||
|             player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); | ||||
|             return false; | ||||
|         } | ||||
|         final PlayerClaimPlotEvent event = this.eventDispatcher.callClaim(player, plot, schematic); | ||||
|         schematic = event.getSchematic(); | ||||
|     @Requirement(CommandRequirement.PLAYER) | ||||
|     @Requirement(CommandRequirement.IN_PLOT) | ||||
|     @CommandPermission("plots.add") | ||||
|     @CommandMethod("${command.prefix} claim [schematic]") | ||||
|     public void commandClaim( | ||||
|             final @NonNull PlotPlayer<?> sender, | ||||
|             final @NonNull Plot plot, | ||||
|             @Argument("schematic") final @Nullable String schematic | ||||
|     ) { | ||||
|         final PlayerClaimPlotEvent event = this.eventDispatcher.callClaim(sender, plot, schematic); | ||||
|         if (event.getEventResult() == Result.DENY) { | ||||
|             player.sendMessage( | ||||
|             sender.sendMessage( | ||||
|                     TranslatableCaption.of("events.event_denied"), | ||||
|                     TagResolver.resolver("value", Tag.inserting(Component.text("Claim"))) | ||||
|             ); | ||||
|             return true; | ||||
|             return; | ||||
|         } | ||||
|         boolean force = event.getEventResult() == Result.FORCE; | ||||
|         int currentPlots = Settings.Limit.GLOBAL ? | ||||
|                 player.getPlotCount() : | ||||
|                 player.getPlotCount(location.getWorldName()); | ||||
| 
 | ||||
|         final boolean forceClaim = event.getEventResult() == Result.FORCE; | ||||
|         final int currentPlots = Settings.Limit.GLOBAL ? | ||||
|                 sender.getPlotCount() : | ||||
|                 sender.getPlotCount(sender.getLocation().getWorldName()); | ||||
|         final PlotArea area = plot.getArea(); | ||||
| 
 | ||||
|         try (final MetaDataAccess<Integer> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { | ||||
|         try (final MetaDataAccess<Integer> metaDataAccess = sender.accessPersistentMetaData( | ||||
|                 PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS | ||||
|         )) { | ||||
|             int grants = 0; | ||||
|             if (currentPlots >= player.getAllowedPlots() && !force) { | ||||
|             if (currentPlots >= sender.getAllowedPlots() && !forceClaim) { | ||||
|                 if (metaDataAccess.isPresent()) { | ||||
|                     grants = metaDataAccess.get().orElse(0); | ||||
|                     if (grants <= 0) { | ||||
|                         player.sendMessage( | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.cant_claim_more_plots"), | ||||
|                                 TagResolver.resolver("amount", Tag.inserting(Component.text(grants))) | ||||
|                         ); | ||||
|                         metaDataAccess.remove(); | ||||
|                     } | ||||
|                 } else { | ||||
|                     player.sendMessage( | ||||
|                     sender.sendMessage( | ||||
|                             TranslatableCaption.of("permission.cant_claim_more_plots"), | ||||
|                             TagResolver.resolver("amount", Tag.inserting(Component.text(player.getAllowedPlots()))) | ||||
|                             TagResolver.resolver("amount", Tag.inserting(Component.text(sender.getAllowedPlots()))) | ||||
|                     ); | ||||
|                     return false; | ||||
|                     return; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!plot.canClaim(player)) { | ||||
|                 player.sendMessage(TranslatableCaption.of("working.plot_is_claimed")); | ||||
|                 return false; | ||||
|             if (!plot.canClaim(sender)) { | ||||
|                 sender.sendMessage(TranslatableCaption.of("working.plot_is_claimed")); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (schematic != null && !schematic.isEmpty()) { | ||||
|                 if (area.isSchematicClaimSpecify()) { | ||||
|                     if (!area.hasSchematic(schematic)) { | ||||
|                         player.sendMessage( | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("schematics.schematic_invalid_named"), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("schemname", Tag.inserting(Component.text(schematic))) | ||||
|                                         .tag("reason", Tag.inserting(Component.text("non-existent"))) | ||||
|                                         .build() | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (!player.hasPermission(Permission.PERMISSION_CLAIM_SCHEMATIC | ||||
|                             .format(schematic)) && !player.hasPermission( | ||||
| 
 | ||||
|                     if (!sender.hasPermission( | ||||
|                             Permission.PERMISSION_CLAIM_SCHEMATIC.format(schematic) | ||||
|                     ) && !sender.hasPermission( | ||||
|                             "plots.admin.command.schematic" | ||||
|                     ) && !force) { | ||||
|                         player.sendMessage( | ||||
|                     ) && !forceClaim) { | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("permission.no_schematic_permission"), | ||||
|                                 TagResolver.resolver("value", Tag.inserting(Component.text(schematic))) | ||||
|                         ); | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (this.econHandler.isEnabled(area) && !force) { | ||||
|                 PlotExpression costExr = area.getPrices().get("claim"); | ||||
|                 double cost = costExr.evaluate(currentPlots); | ||||
| 
 | ||||
|             if (this.econHandler.isEnabled(area) && !forceClaim) { | ||||
|                 final PlotExpression costExr = area.getPrices().get("claim"); | ||||
|                 final double cost = costExr.evaluate(currentPlots); | ||||
| 
 | ||||
|                 if (cost > 0d) { | ||||
|                     if (!this.econHandler.isSupported()) { | ||||
|                         player.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); | ||||
|                         return false; | ||||
|                         sender.sendMessage(TranslatableCaption.of("economy.vault_or_consumer_null")); | ||||
|                         return; | ||||
|                     } | ||||
|                     if (this.econHandler.getMoney(player) < cost) { | ||||
|                         player.sendMessage( | ||||
|                     if (this.econHandler.getMoney(sender) < cost) { | ||||
|                         sender.sendMessage( | ||||
|                                 TranslatableCaption.of("economy.cannot_afford_plot"), | ||||
|                                 TagResolver.builder() | ||||
|                                         .tag("money", Tag.inserting(Component.text(this.econHandler.format(cost)))) | ||||
|                                         .tag( | ||||
|                                                 "balance", | ||||
|                                                 Tag.inserting(Component.text(this.econHandler.format(this.econHandler.getMoney( | ||||
|                                                         player)))) | ||||
|                                                 Tag.inserting( | ||||
|                                                         Component.text(this.econHandler.format(this.econHandler.getMoney(sender))) | ||||
|                                                 ) | ||||
|                                         ) | ||||
|                                         .build() | ||||
|                         ); | ||||
|                         return false; | ||||
|                         return; | ||||
|                     } | ||||
|                     this.econHandler.withdrawMoney(player, cost); | ||||
|                     player.sendMessage( | ||||
|                     this.econHandler.withdrawMoney(sender, cost); | ||||
|                     sender.sendMessage( | ||||
|                             TranslatableCaption.of("economy.removed_balance"), | ||||
|                             TagResolver.builder() | ||||
|                                     .tag("money", Tag.inserting(Component.text(this.econHandler.format(cost)))) | ||||
|                                     .tag( | ||||
|                                             "balance", | ||||
|                                             Tag.inserting(Component.text(this.econHandler.format(this.econHandler.getMoney( | ||||
|                                                     player)))) | ||||
|                                             Tag.inserting( | ||||
|                                                     Component.text(this.econHandler.format(this.econHandler.getMoney(sender))) | ||||
|                                             ) | ||||
|                                     ) | ||||
|                                     .build() | ||||
|                     ); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (grants > 0) { | ||||
|                 if (grants == 1) { | ||||
|                     metaDataAccess.remove(); | ||||
|                 } else { | ||||
|                     metaDataAccess.set(grants - 1); | ||||
|                 } | ||||
|                 player.sendMessage( | ||||
|                 sender.sendMessage( | ||||
|                         TranslatableCaption.of("economy.removed_granted_plot"), | ||||
|                         TagResolver.builder() | ||||
|                                 .tag("usedGrants", Tag.inserting(Component.text(grants - 1))) | ||||
| @@ -192,27 +181,34 @@ public class Claim extends SubCommand { | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         if (!player.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { | ||||
|             int border = area.getBorder(); | ||||
|             if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !force) { | ||||
|                 player.sendMessage(TranslatableCaption.of("border.denied")); | ||||
|                 return false; | ||||
| 
 | ||||
|         if (!sender.hasPermission(Permission.PERMISSION_ADMIN_BYPASS_BORDER)) { | ||||
|             final int border = area.getBorder(); | ||||
|             if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !forceClaim) { | ||||
|                 sender.sendMessage(TranslatableCaption.of("border.denied")); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|         plot.setOwnerAbs(player.getUUID()); | ||||
|         final String finalSchematic = schematic; | ||||
| 
 | ||||
|         // Actually update the owner :) | ||||
|         plot.setOwnerAbs(sender.getUUID()); | ||||
| 
 | ||||
|         DBFunc.createPlotSafe(plot, () -> { | ||||
|             try { | ||||
|                 TaskManager.getPlatformImplementation().sync(() -> { | ||||
|                     if (!plot.claim(player, true, finalSchematic, false, false)) { | ||||
|                     if (!plot.claim(sender, true, event.getSchematic(), false, false)) { | ||||
|                         LOGGER.info("Failed to claim plot {}", plot.getId().toCommaSeparatedString()); | ||||
|                         player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|                         sender.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|                         plot.setOwnerAbs(null); | ||||
|                     } else if (area.isAutoMerge()) { | ||||
|                         PlotMergeEvent mergeEvent = Claim.this.eventDispatcher | ||||
|                                 .callMerge(plot, Direction.ALL, Integer.MAX_VALUE, player); | ||||
|                         final PlotMergeEvent mergeEvent = this.eventDispatcher.callMerge( | ||||
|                                 plot, | ||||
|                                 Direction.ALL, | ||||
|                                 Integer.MAX_VALUE, | ||||
|                                 sender | ||||
|                         ); | ||||
|                         if (mergeEvent.getEventResult() == Result.DENY) { | ||||
|                             player.sendMessage( | ||||
|                             sender.sendMessage( | ||||
|                                     TranslatableCaption.of("events.event_denied"), | ||||
|                                     TagResolver.resolver("value", Tag.inserting(Component.text("Auto merge on claim"))) | ||||
|                             ); | ||||
| @@ -220,11 +216,11 @@ public class Claim extends SubCommand { | ||||
|                             if (plot.getPlotModificationManager().autoMerge( | ||||
|                                     mergeEvent.getDir(), | ||||
|                                     mergeEvent.getMax(), | ||||
|                                     player.getUUID(), | ||||
|                                     player, | ||||
|                                     sender.getUUID(), | ||||
|                                     sender, | ||||
|                                     true | ||||
|                             )) { | ||||
|                                 eventDispatcher.callPostMerge(player, plot); | ||||
|                                 eventDispatcher.callPostMerge(sender, plot); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| @@ -235,10 +231,8 @@ public class Claim extends SubCommand { | ||||
|             } | ||||
|         }, () -> { | ||||
|             LOGGER.info("Failed to add plot to database: {}", plot.getId().toCommaSeparatedString()); | ||||
|             player.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|             sender.sendMessage(TranslatableCaption.of("working.plot_not_claimed")); | ||||
|             plot.setOwnerAbs(null); | ||||
|         }); | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
|  * 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 cloud.commandframework.captions.Caption; | ||||
|  | ||||
| public final class PlotSquaredCaptionKeys { | ||||
|  | ||||
|     public static final Caption ARGUMENT_PARSE_FAILURE_TARGET = Caption.of("argument.parse.failure.target"); | ||||
| } | ||||
| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
|  * 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; | ||||
|  | ||||
| /** | ||||
|  * Indicates that a class contains commands. | ||||
|  */ | ||||
| public interface PlotSquaredCommandContainer { | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,82 @@ | ||||
| /* | ||||
|  * 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 cloud.commandframework.CommandManager; | ||||
| import cloud.commandframework.annotations.AnnotationParser; | ||||
| import cloud.commandframework.meta.SimpleCommandMeta; | ||||
| import com.google.inject.Inject; | ||||
| import com.google.inject.Injector; | ||||
| import com.plotsquared.core.commands.parsers.PlotMemberParser; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirementBuilderModifier; | ||||
| import com.plotsquared.core.commands.requirements.CommandRequirementPostProcessor; | ||||
| import com.plotsquared.core.commands.requirements.Requirements; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.stream.Stream; | ||||
|  | ||||
| public class PlotSquaredCommandManager { | ||||
|  | ||||
|     private final Injector injector; | ||||
|     private final CommandManager<PlotPlayer<?>> commandManager; | ||||
|     private final AnnotationParser<PlotPlayer<?>> annotationParser; | ||||
|  | ||||
|     @Inject | ||||
|     public PlotSquaredCommandManager( | ||||
|             final @NonNull Injector injector, | ||||
|             final @NonNull CommandManager<PlotPlayer<?>> commandManager | ||||
|     ) { | ||||
|         this.injector = injector; | ||||
|         this.commandManager = commandManager; | ||||
|         this.annotationParser = new AnnotationParser<PlotPlayer<?>>( | ||||
|                 this.commandManager, | ||||
|                 new TypeToken<PlotPlayer<?>>() { | ||||
|                 }, | ||||
|                 parameters -> SimpleCommandMeta.empty() | ||||
|         ); | ||||
|         this.annotationParser.registerBuilderModifier(Requirements.class, new CommandRequirementBuilderModifier()); | ||||
|         this.commandManager.registerCommandPostProcessor(new CommandRequirementPostProcessor()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Scans the given {@code instance} for commands, and registers them. | ||||
|      * | ||||
|      * @param instance the instance to scan | ||||
|      */ | ||||
|     public void scanClass(final @NonNull Object instance) { | ||||
|         this.annotationParser.parse(instance); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Initializes all the known commands. | ||||
|      */ | ||||
|     public void initializeCommands() { | ||||
|         // We start by scanning the parsers. | ||||
|         Stream.of( | ||||
|                 PlotMemberParser.class | ||||
|         ).map(this.injector::getInstance).forEach(this::scanClass); | ||||
|         // Then we scan the commands. | ||||
|         Stream.of( | ||||
|                 CommandAdd.class, | ||||
|                 CommandClaim.class | ||||
|         ).map(this.injector::getInstance).forEach(this::scanClass); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|  * 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.arguments; | ||||
|  | ||||
| import cloud.commandframework.context.CommandContext; | ||||
| import com.plotsquared.core.commands.parsers.PlotMemberParser; | ||||
| import com.plotsquared.core.database.DBFunc; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.MonotonicNonNull; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|  | ||||
| import java.util.UUID; | ||||
|  | ||||
| public sealed interface PlotMember { | ||||
|  | ||||
|     PlotMember EVERYONE = new Everyone(); | ||||
|  | ||||
|     default @NonNull UUID uuid(@NonNull CommandContext<PlotPlayer<?>> context) { | ||||
|         return this.uuid(); | ||||
|     } | ||||
|  | ||||
|     @NonNull UUID uuid(); | ||||
|  | ||||
|     sealed interface PlayerLike extends PlotMember { | ||||
|     } | ||||
|  | ||||
|     record Player(@NonNull UUID uuid) implements PlayerLike { | ||||
|     } | ||||
|  | ||||
|     final class LazyPlayer implements PlayerLike { | ||||
|  | ||||
|         private final String candidate; | ||||
|         private final UuidSupplier uuidSupplier; | ||||
|         private @MonotonicNonNull UUID cachedUuid = null; | ||||
|  | ||||
|         public LazyPlayer( | ||||
|                 final @NonNull String candidate, | ||||
|                 final @NonNull UuidSupplier uuidSupplier | ||||
|         ) { | ||||
|             this.candidate = candidate; | ||||
|             this.uuidSupplier = uuidSupplier; | ||||
|         } | ||||
|  | ||||
|         public @NonNull UUID uuid() { | ||||
|             throw new UnsupportedOperationException(); | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public synchronized @NonNull UUID uuid(final @NonNull CommandContext<PlotPlayer<?>> context) { | ||||
|             if (this.cachedUuid == null) { | ||||
|                 try { | ||||
|                     this.cachedUuid = this.uuidSupplier.uuid(); | ||||
|                 } catch (Exception ignored) { | ||||
|                 } | ||||
|  | ||||
|                 // The player didn't exist :-( | ||||
|                 if (this.cachedUuid == null) { | ||||
|                     throw new PlotMemberParser.TargetParseException(this.candidate, context); | ||||
|                 } | ||||
|             } | ||||
|             return this.cachedUuid; | ||||
|         } | ||||
|  | ||||
|         @FunctionalInterface | ||||
|         public interface UuidSupplier { | ||||
|             @Nullable UUID uuid() throws Exception; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     final class Everyone implements PlotMember { | ||||
|  | ||||
|         @Override | ||||
|         public @NonNull UUID uuid() { | ||||
|             return DBFunc.EVERYONE; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,124 @@ | ||||
| /* | ||||
|  * 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.parsers; | ||||
|  | ||||
| import cloud.commandframework.annotations.parsers.Parser; | ||||
| import cloud.commandframework.captions.CaptionVariable; | ||||
| import cloud.commandframework.context.CommandContext; | ||||
| import cloud.commandframework.exceptions.parsing.NoInputProvidedException; | ||||
| import cloud.commandframework.exceptions.parsing.ParserException; | ||||
| import com.google.inject.Inject; | ||||
| import com.plotsquared.core.commands.PlotSquaredCaptionKeys; | ||||
| import com.plotsquared.core.commands.arguments.PlotMember; | ||||
| import com.plotsquared.core.configuration.Settings; | ||||
| import com.plotsquared.core.inject.annotations.ImpromptuPipeline; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.uuid.UUIDMapping; | ||||
| import com.plotsquared.core.uuid.UUIDPipeline; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.util.Queue; | ||||
| import java.util.UUID; | ||||
|  | ||||
| public class PlotMemberParser { | ||||
|  | ||||
|     private final UUIDPipeline uuidPipeline; | ||||
|  | ||||
|     @Inject | ||||
|     public PlotMemberParser(@ImpromptuPipeline final @NonNull UUIDPipeline uuidPipeline) { | ||||
|         this.uuidPipeline = uuidPipeline; | ||||
|     } | ||||
|  | ||||
|     @Parser | ||||
|     public @NonNull PlotMember parse( | ||||
|             final @NonNull CommandContext<PlotPlayer<?>> context, | ||||
|             final @NonNull Queue<@NonNull String> input | ||||
|     ) { | ||||
|         final var candidate = input.peek(); | ||||
|         if (candidate == null) { | ||||
|             throw new NoInputProvidedException(this.getClass(), context); | ||||
|         } | ||||
|  | ||||
|         if ("*".equals(candidate)) { | ||||
|             return PlotMember.EVERYONE; | ||||
|         } else if (candidate.length() > 16) { | ||||
|             try { | ||||
|                 return new PlotMember.Player(UUID.fromString(candidate)); | ||||
|             } catch (IllegalArgumentException ignored) { | ||||
|                 throw new TargetParseException(candidate, context); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (Settings.Paper_Components.PAPER_LISTENERS) { | ||||
|             try { | ||||
|                 return this.uuidPipeline.getUUID(candidate, Settings.UUID.NON_BLOCKING_TIMEOUT) | ||||
|                         .get() | ||||
|                         .map(UUIDMapping::getUuid) | ||||
|                         .map(PlotMember.Player::new) | ||||
|                         .orElseThrow(); | ||||
|             } catch (Exception e) { | ||||
|                 throw new TargetParseException(candidate, context); | ||||
|             } | ||||
|         } else { | ||||
|             return new PlotMember.LazyPlayer( | ||||
|                     candidate, | ||||
|                     () -> this.uuidPipeline.getUUID(candidate, Settings.UUID.NON_BLOCKING_TIMEOUT) | ||||
|                             .get() | ||||
|                             .map(UUIDMapping::getUuid) | ||||
|                             .orElse(null) | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static final class TargetParseException extends ParserException { | ||||
|  | ||||
|         @Serial | ||||
|         private static final long serialVersionUID = 927476591631527552L; | ||||
|         private final String input; | ||||
|  | ||||
|         /** | ||||
|          * Construct a new Player parse exception | ||||
|          * | ||||
|          * @param input   String input | ||||
|          * @param context Command context | ||||
|          */ | ||||
|         public TargetParseException( | ||||
|                 final @NonNull String input, | ||||
|                 final @NonNull CommandContext<?> context | ||||
|         ) { | ||||
|             super( | ||||
|                     PlotMemberParser.class, | ||||
|                     context, | ||||
|                     PlotSquaredCaptionKeys.ARGUMENT_PARSE_FAILURE_TARGET, | ||||
|                     CaptionVariable.of("input", input) | ||||
|             ); | ||||
|             this.input = input; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get the supplied input | ||||
|          * | ||||
|          * @return String value | ||||
|          */ | ||||
|         public @NonNull String getInput() { | ||||
|             return this.input; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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.requirements; | ||||
|  | ||||
| import cloud.commandframework.meta.CommandMeta; | ||||
| import com.plotsquared.core.configuration.caption.Caption; | ||||
| import com.plotsquared.core.configuration.caption.TranslatableCaption; | ||||
| import com.plotsquared.core.player.ConsolePlayer; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import io.leangen.geantyref.TypeToken; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.EnumSet; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
| import java.util.Set; | ||||
| import java.util.function.Predicate; | ||||
|  | ||||
| public enum CommandRequirement { | ||||
|     PLAYER( | ||||
|             "", | ||||
|             player -> !(player instanceof ConsolePlayer) | ||||
|     ), | ||||
|     IN_PLOT( | ||||
|             "errors.not_in_plot", | ||||
|             player -> player.getCurrentPlot() != null | ||||
|     ), | ||||
|     PLOT_HAS_OWNER( | ||||
|             "info.plot_unowned", | ||||
|             player -> Objects.requireNonNull(player.getCurrentPlot()).hasOwner(), | ||||
|             IN_PLOT | ||||
|     ), | ||||
|     IS_OWNER( | ||||
|             "permission.no_plot_perms", | ||||
|             player -> Objects.requireNonNull(player.getCurrentPlot()).isOwner(player.getUUID()), | ||||
|             PLOT_HAS_OWNER | ||||
|     ); | ||||
|  | ||||
|     public static final CommandMeta.Key<List<CommandRequirement>> COMMAND_REQUIREMENTS_KEY = CommandMeta.Key.of( | ||||
|             new TypeToken<List<CommandRequirement>>() { | ||||
|             }, | ||||
|             "command_requirements" | ||||
|     ); | ||||
|  | ||||
|     private final @NonNull Caption caption; | ||||
|     private final @NonNull Predicate<@NonNull PlotPlayer<?>> requirementPredicate; | ||||
|     private final @NonNull Set<@NonNull CommandRequirement> inheritedRequirements; | ||||
|  | ||||
|     CommandRequirement( | ||||
|             final @NonNull String caption, | ||||
|             final @NonNull Predicate<@NonNull PlotPlayer<?>> requirementPredicate, | ||||
|             final @NonNull CommandRequirement... inheritedRequirements | ||||
|     ) { | ||||
|         this.caption = TranslatableCaption.of(caption); | ||||
|         this.requirementPredicate = requirementPredicate; | ||||
|         this.inheritedRequirements = EnumSet.copyOf(Arrays.asList(inheritedRequirements)); | ||||
|     } | ||||
|  | ||||
|     public @NonNull Set<@NonNull CommandRequirement> inheritedRequirements() { | ||||
|         return Collections.unmodifiableSet(this.inheritedRequirements); | ||||
|     } | ||||
|  | ||||
|     public @NonNull Caption caption() { | ||||
|         return this.caption; | ||||
|     } | ||||
|  | ||||
|     public boolean checkRequirement(final @NonNull PlotPlayer<?> player) { | ||||
|         return this.requirementPredicate.test(player); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,61 @@ | ||||
| /* | ||||
|  * 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.requirements; | ||||
|  | ||||
| import cloud.commandframework.Command; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.EnumSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.function.BiFunction; | ||||
|  | ||||
| public class CommandRequirementBuilderModifier implements BiFunction< | ||||
|         @NonNull Requirements, | ||||
|         Command.@NonNull Builder<PlotPlayer<?>>, | ||||
|         Command.@NonNull Builder<PlotPlayer<?>> | ||||
| > { | ||||
|  | ||||
|     @Override | ||||
|     public Command.@NonNull Builder<PlotPlayer<?>> apply( | ||||
|             final @NonNull Requirements requirements, | ||||
|             final Command.@NonNull Builder<PlotPlayer<?>> builder | ||||
|     ) { | ||||
|         // We use a list, because we want them to be evaluated in order. | ||||
|         final Set<CommandRequirement> commandRequirements = EnumSet.noneOf(CommandRequirement.class); | ||||
|         for (final Requirement requirement : requirements.value()) { | ||||
|             this.addRequirements(commandRequirements, requirement.value()); | ||||
|         } | ||||
|         // We then sort the requirements. | ||||
|         final List<CommandRequirement> sortedRequirements = commandRequirements.stream().sorted().toList(); | ||||
|         // We then register all the types in the command metadata. | ||||
|         return builder.meta(CommandRequirement.COMMAND_REQUIREMENTS_KEY, sortedRequirements); | ||||
|     } | ||||
|  | ||||
|     private void addRequirements( | ||||
|             final @NonNull Set<@NonNull CommandRequirement> requirements, | ||||
|             final @NonNull CommandRequirement requirement | ||||
|     ) { | ||||
|         for (final CommandRequirement inheritedRequirement : requirement.inheritedRequirements()) { | ||||
|             addRequirements(requirements, inheritedRequirement); | ||||
|         } | ||||
|         requirements.add(requirement); | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,54 @@ | ||||
| /* | ||||
|  * 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.requirements; | ||||
|  | ||||
| import cloud.commandframework.Command; | ||||
| import cloud.commandframework.execution.postprocessor.CommandPostprocessingContext; | ||||
| import cloud.commandframework.execution.postprocessor.CommandPostprocessor; | ||||
| import cloud.commandframework.services.types.ConsumerService; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public class CommandRequirementPostProcessor implements CommandPostprocessor<PlotPlayer<?>> { | ||||
|  | ||||
|     @Override | ||||
|     public void accept( | ||||
|             @NonNull final CommandPostprocessingContext<PlotPlayer<?>> context | ||||
|     ) { | ||||
|         final Command<PlotPlayer<?>> command = context.getCommand(); | ||||
|         final PlotPlayer<?> player = context.getCommandContext().getSender();; | ||||
|         final List<CommandRequirement> commandRequirements = command.getCommandMeta().get( | ||||
|                 CommandRequirement.COMMAND_REQUIREMENTS_KEY | ||||
|         ).orElse(List.of()); | ||||
|  | ||||
|         for (final CommandRequirement requirement : commandRequirements) { | ||||
|             if (requirement.checkRequirement(player)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // They failed the requirement =( | ||||
|             player.sendMessage(requirement.caption()); | ||||
|  | ||||
|             // Then we interrupt to make sure the command isn't executed. | ||||
|             ConsumerService.interrupt(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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.requirements; | ||||
|  | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Repeatable; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
|  | ||||
| @Repeatable(Requirements.class) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target(ElementType.METHOD) | ||||
| public @interface Requirement { | ||||
|  | ||||
|     @NonNull CommandRequirement value(); | ||||
| } | ||||
| @@ -0,0 +1,33 @@ | ||||
| /* | ||||
|  * 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.requirements; | ||||
|  | ||||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||||
|  | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
|  | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| @Target(ElementType.METHOD) | ||||
| public @interface Requirements { | ||||
|  | ||||
|     @NonNull Requirement @NonNull[] value(); | ||||
| } | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.events; | ||||
|  | ||||
| import com.plotsquared.core.command.Claim; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import com.plotsquared.core.plot.PlotArea; | ||||
|   | ||||
| @@ -18,7 +18,6 @@ | ||||
|  */ | ||||
| package com.plotsquared.core.events; | ||||
|  | ||||
| import com.plotsquared.core.command.Claim; | ||||
| import com.plotsquared.core.player.PlotPlayer; | ||||
| import com.plotsquared.core.plot.Plot; | ||||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||||
|   | ||||
| @@ -288,7 +288,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer, | ||||
|      * | ||||
|      * @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea} | ||||
|      */ | ||||
|     public Plot getCurrentPlot() { | ||||
|     public @Nullable Plot getCurrentPlot() { | ||||
|         try (final MetaDataAccess<Plot> lastPlotAccess = | ||||
|                      this.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { | ||||
|             if (lastPlotAccess.get().orElse(null) == null && !Settings.Enabled_Components.EVENTS) { | ||||
|   | ||||
| @@ -36,6 +36,7 @@ import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
| import java.util.Set; | ||||
| import java.util.UUID; | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| @@ -273,6 +274,25 @@ public class UUIDPipeline { | ||||
|         return this.getUUIDs(requests).orTimeout(timeout, TimeUnit.MILLISECONDS); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Asynchronously attempt to fetch the mapping from a name. | ||||
|      * <p> | ||||
|      * This will timeout after the specified time and throws a {@link TimeoutException} | ||||
|      * if this happens | ||||
|      * | ||||
|      * @param username Name | ||||
|      * @param timeout  Timeout in milliseconds | ||||
|      * @return Mapping | ||||
|      */ | ||||
|     public @NonNull CompletableFuture<Optional<UUIDMapping>> getUUID( | ||||
|             final @NonNull String username, | ||||
|             final long timeout | ||||
|     ) { | ||||
|         return this.getUUIDs(List.of(username), timeout).thenApply( | ||||
|                 results -> results.stream().findFirst() | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Asynchronously attempt to fetch the mapping from a list of UUIDs | ||||
|      * | ||||
|   | ||||
| @@ -13,9 +13,9 @@ mvdwapi = "3.1.1" | ||||
| # Third party | ||||
| prtree = "2.0.0" | ||||
| aopalliance = "1.0" | ||||
| cloud-services = "1.8.0" | ||||
| arkitektonika = "2.1.1" | ||||
| squirrelid = "0.3.1" | ||||
| cloud = "1.8.0" | ||||
|  | ||||
| # Gradle plugins | ||||
| shadow = "7.1.2" | ||||
| @@ -39,10 +39,14 @@ essentialsx = { group = "net.essentialsx", name = "EssentialsX", version.ref = " | ||||
| # Third party | ||||
| prtree = { group = "com.intellectualsites.prtree", name = "PRTree", version.ref = "prtree" } | ||||
| aopalliance = { group = "aopalliance", name = "aopalliance", version.ref = "aopalliance" } | ||||
| cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud-services" } | ||||
| mvdwapi = { group = "com.intellectualsites.mvdwplaceholderapi", name = "MVdWPlaceholderAPI", version.ref = "mvdwapi" } | ||||
| squirrelid = { group = "org.enginehub", name = "squirrelid", version.ref = "squirrelid" } | ||||
| arkitektonika = { group = "com.intellectualsites.arkitektonika", name = "Arkitektonika-Client", version.ref = "arkitektonika" } | ||||
| cloudServices = { group = "cloud.commandframework", name = "cloud-services", version.ref = "cloud" } | ||||
| cloudCore = { group = "cloud.commandframework", name = "cloud-core", version.ref = "cloud" } | ||||
| cloudAnnotations = { group = "cloud.commandframework", name = "cloud-annotations", version.ref = "cloud" } | ||||
| cloudPaper = { group = "cloud.commandframework", name = "cloud-paper", version.ref = "cloud" } | ||||
| cloudMinecraftExtras = { group = "cloud.commandframework", name = "cloud-minecraft-extras", version.ref = "cloud" } | ||||
|  | ||||
| [plugins] | ||||
| shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user