001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.command; 020 021import com.google.inject.Inject; 022import com.plotsquared.core.PlotSquared; 023import com.plotsquared.core.configuration.Settings; 024import com.plotsquared.core.configuration.caption.TranslatableCaption; 025import com.plotsquared.core.database.DBFunc; 026import com.plotsquared.core.permissions.Permission; 027import com.plotsquared.core.player.PlotPlayer; 028import com.plotsquared.core.plot.Plot; 029import com.plotsquared.core.util.EventDispatcher; 030import com.plotsquared.core.util.PlayerManager; 031import com.plotsquared.core.util.TabCompletions; 032import com.plotsquared.core.util.task.RunnableVal2; 033import com.plotsquared.core.util.task.RunnableVal3; 034import net.kyori.adventure.text.Component; 035import net.kyori.adventure.text.minimessage.tag.Tag; 036import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 037import org.checkerframework.checker.nullness.qual.NonNull; 038 039import java.util.Collection; 040import java.util.Collections; 041import java.util.Iterator; 042import java.util.UUID; 043import java.util.concurrent.CompletableFuture; 044import java.util.concurrent.TimeoutException; 045 046@CommandDeclaration(command = "add", 047 usage = "/plot add <player | *>", 048 category = CommandCategory.SETTINGS, 049 permission = "plots.add", 050 requiredType = RequiredType.PLAYER) 051public class Add extends Command { 052 053 private final EventDispatcher eventDispatcher; 054 055 @Inject 056 public Add(final @NonNull EventDispatcher eventDispatcher) { 057 super(MainCommand.getInstance(), true); 058 this.eventDispatcher = eventDispatcher; 059 } 060 061 @Override 062 public CompletableFuture<Boolean> execute( 063 final PlotPlayer<?> player, 064 String[] args, 065 RunnableVal3<Command, Runnable, Runnable> confirm, 066 RunnableVal2<Command, CommandResult> whenDone 067 ) throws CommandException { 068 final Plot plot = check(player.getCurrentPlot(), TranslatableCaption.of("errors.not_in_plot")); 069 checkTrue(plot.hasOwner(), TranslatableCaption.of("info.plot_unowned")); 070 checkTrue( 071 plot.isOwner(player.getUUID()) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST), 072 TranslatableCaption.of("permission.no_plot_perms") 073 ); 074 checkTrue( 075 args.length == 1, 076 TranslatableCaption.of("commandconfig.command_syntax"), 077 TagResolver.resolver("value", Tag.inserting(Component.text("/plot add <player | *>"))) 078 ); 079 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 080 PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> { 081 if (throwable != null) { 082 if (throwable instanceof TimeoutException) { 083 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 084 } else { 085 player.sendMessage( 086 TranslatableCaption.of("errors.invalid_player"), 087 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) 088 ); 089 } 090 future.completeExceptionally(throwable); 091 return; 092 } else { 093 try { 094 checkTrue(!uuids.isEmpty(), TranslatableCaption.of("errors.invalid_player"), 095 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) 096 ); 097 Iterator<UUID> iterator = uuids.iterator(); 098 int size = plot.getTrusted().size() + plot.getMembers().size(); 099 while (iterator.hasNext()) { 100 UUID uuid = iterator.next(); 101 if (uuid == DBFunc.EVERYONE && !(player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission( 102 Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { 103 player.sendMessage( 104 TranslatableCaption.of("errors.invalid_player"), 105 PlotSquared 106 .platform() 107 .playerManager() 108 .getUsernameCaption(uuid) 109 .thenApply(caption -> TagResolver.resolver( 110 "value", 111 Tag.inserting(caption.toComponent(player)) 112 )) 113 ); 114 iterator.remove(); 115 continue; 116 } 117 if (plot.isOwner(uuid)) { 118 player.sendMessage( 119 TranslatableCaption.of("member.already_added"), 120 PlotSquared.platform().playerManager().getUsernameCaption(uuid) 121 .thenApply(caption -> TagResolver.resolver( 122 "player", 123 Tag.inserting(caption.toComponent(player)) 124 )) 125 ); 126 iterator.remove(); 127 continue; 128 } 129 if (plot.getMembers().contains(uuid)) { 130 player.sendMessage( 131 TranslatableCaption.of("member.already_added"), 132 PlotSquared.platform().playerManager().getUsernameCaption(uuid) 133 .thenApply(caption -> TagResolver.resolver( 134 "player", 135 Tag.inserting(caption.toComponent(player)) 136 )) 137 ); 138 iterator.remove(); 139 continue; 140 } 141 size += plot.getTrusted().contains(uuid) ? 0 : 1; 142 } 143 checkTrue(!uuids.isEmpty(), null); 144 int localAddSize = plot.getMembers().size(); 145 int maxAddSize = player.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS); 146 if (localAddSize >= maxAddSize) { 147 player.sendMessage( 148 TranslatableCaption.of("members.plot_max_members_added"), 149 TagResolver.resolver("amount", Tag.inserting(Component.text(localAddSize))) 150 ); 151 return; 152 } 153 // Success 154 confirm.run(this, () -> { 155 for (UUID uuid : uuids) { 156 if (uuid != DBFunc.EVERYONE) { 157 if (!plot.removeTrusted(uuid)) { 158 if (plot.getDenied().contains(uuid)) { 159 plot.removeDenied(uuid); 160 } 161 } 162 } 163 plot.addMember(uuid); 164 this.eventDispatcher.callMember(player, plot, uuid, true); 165 player.sendMessage(TranslatableCaption.of("member.member_added")); 166 } 167 }, null); 168 } catch (final Throwable exception) { 169 future.completeExceptionally(exception); 170 return; 171 } 172 } 173 future.complete(true); 174 }); 175 return future; 176 } 177 178 @Override 179 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 180 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 181 } 182 183}