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.configuration.Settings; 023import com.plotsquared.core.configuration.caption.TranslatableCaption; 024import com.plotsquared.core.database.DBFunc; 025import com.plotsquared.core.permissions.Permission; 026import com.plotsquared.core.player.PlotPlayer; 027import com.plotsquared.core.plot.Plot; 028import com.plotsquared.core.util.EventDispatcher; 029import com.plotsquared.core.util.PlayerManager; 030import com.plotsquared.core.util.TabCompletions; 031import com.plotsquared.core.util.task.RunnableVal2; 032import com.plotsquared.core.util.task.RunnableVal3; 033import net.kyori.adventure.text.minimessage.Template; 034import org.checkerframework.checker.nullness.qual.NonNull; 035 036import java.util.Collection; 037import java.util.Collections; 038import java.util.Iterator; 039import java.util.UUID; 040import java.util.concurrent.CompletableFuture; 041import java.util.concurrent.TimeoutException; 042 043@CommandDeclaration(command = "add", 044 usage = "/plot add <player | *>", 045 category = CommandCategory.SETTINGS, 046 permission = "plots.add", 047 requiredType = RequiredType.PLAYER) 048public class Add extends Command { 049 050 private final EventDispatcher eventDispatcher; 051 052 @Inject 053 public Add(final @NonNull EventDispatcher eventDispatcher) { 054 super(MainCommand.getInstance(), true); 055 this.eventDispatcher = eventDispatcher; 056 } 057 058 @Override 059 public CompletableFuture<Boolean> execute( 060 final PlotPlayer<?> player, 061 String[] args, 062 RunnableVal3<Command, Runnable, Runnable> confirm, 063 RunnableVal2<Command, CommandResult> whenDone 064 ) throws CommandException { 065 final Plot plot = check(player.getCurrentPlot(), TranslatableCaption.of("errors.not_in_plot")); 066 checkTrue(plot.hasOwner(), TranslatableCaption.of("info.plot_unowned")); 067 checkTrue( 068 plot.isOwner(player.getUUID()) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST), 069 TranslatableCaption.of("permission.no_plot_perms") 070 ); 071 checkTrue( 072 args.length == 1, 073 TranslatableCaption.of("commandconfig.command_syntax"), 074 Template.of("value", "/plot add <player | *>") 075 ); 076 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 077 PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> { 078 if (throwable != null) { 079 if (throwable instanceof TimeoutException) { 080 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 081 } else { 082 player.sendMessage( 083 TranslatableCaption.of("errors.invalid_player"), 084 Template.of("value", args[0]) 085 ); 086 } 087 future.completeExceptionally(throwable); 088 return; 089 } else { 090 try { 091 checkTrue(!uuids.isEmpty(), TranslatableCaption.of("errors.invalid_player"), 092 Template.of("value", args[0]) 093 ); 094 Iterator<UUID> iterator = uuids.iterator(); 095 int size = plot.getTrusted().size() + plot.getMembers().size(); 096 while (iterator.hasNext()) { 097 UUID uuid = iterator.next(); 098 if (uuid == DBFunc.EVERYONE && !(player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission( 099 Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { 100 player.sendMessage( 101 TranslatableCaption.of("errors.invalid_player"), 102 Template.of("value", PlayerManager.resolveName(uuid).getComponent(player)) 103 ); 104 iterator.remove(); 105 continue; 106 } 107 if (plot.isOwner(uuid)) { 108 player.sendMessage( 109 TranslatableCaption.of("member.already_added"), 110 Template.of("player", PlayerManager.resolveName(uuid).getComponent(player)) 111 ); 112 iterator.remove(); 113 continue; 114 } 115 if (plot.getMembers().contains(uuid)) { 116 player.sendMessage( 117 TranslatableCaption.of("member.already_added"), 118 Template.of("player", PlayerManager.resolveName(uuid).getComponent(player)) 119 ); 120 iterator.remove(); 121 continue; 122 } 123 size += plot.getTrusted().contains(uuid) ? 0 : 1; 124 } 125 checkTrue(!uuids.isEmpty(), null); 126 int localAddSize = plot.getMembers().size(); 127 int maxAddSize = player.hasPermissionRange(Permission.PERMISSION_ADD, Settings.Limit.MAX_PLOTS); 128 if (localAddSize >= maxAddSize) { 129 player.sendMessage( 130 TranslatableCaption.of("members.plot_max_members_added"), 131 Template.of("amount", String.valueOf(localAddSize)) 132 ); 133 return; 134 } 135 // Success 136 confirm.run(this, () -> { 137 for (UUID uuid : uuids) { 138 if (uuid != DBFunc.EVERYONE) { 139 if (!plot.removeTrusted(uuid)) { 140 if (plot.getDenied().contains(uuid)) { 141 plot.removeDenied(uuid); 142 } 143 } 144 } 145 plot.addMember(uuid); 146 this.eventDispatcher.callMember(player, plot, uuid, true); 147 player.sendMessage(TranslatableCaption.of("member.member_added")); 148 } 149 }, null); 150 } catch (final Throwable exception) { 151 future.completeExceptionally(exception); 152 return; 153 } 154 } 155 future.complete(true); 156 }); 157 return future; 158 } 159 160 @Override 161 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 162 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 163 } 164 165}