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.events.PlayerPlotAddRemoveEvent; 027import com.plotsquared.core.events.Result; 028import com.plotsquared.core.permissions.Permission; 029import com.plotsquared.core.player.PlotPlayer; 030import com.plotsquared.core.plot.Plot; 031import com.plotsquared.core.util.EventDispatcher; 032import com.plotsquared.core.util.PlayerManager; 033import com.plotsquared.core.util.TabCompletions; 034import com.plotsquared.core.util.task.RunnableVal2; 035import com.plotsquared.core.util.task.RunnableVal3; 036import net.kyori.adventure.text.Component; 037import net.kyori.adventure.text.minimessage.tag.Tag; 038import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 039import org.checkerframework.checker.nullness.qual.NonNull; 040 041import java.util.Collection; 042import java.util.Collections; 043import java.util.Iterator; 044import java.util.UUID; 045import java.util.concurrent.CompletableFuture; 046import java.util.concurrent.TimeoutException; 047 048@CommandDeclaration(command = "trust", 049 aliases = {"t"}, 050 requiredType = RequiredType.PLAYER, 051 usage = "/plot trust <player | *>", 052 category = CommandCategory.SETTINGS) 053public class Trust extends Command { 054 055 private final EventDispatcher eventDispatcher; 056 057 @Inject 058 public Trust(final @NonNull EventDispatcher eventDispatcher) { 059 super(MainCommand.getInstance(), true); 060 this.eventDispatcher = eventDispatcher; 061 } 062 063 @Override 064 public CompletableFuture<Boolean> execute( 065 final PlotPlayer<?> player, String[] args, 066 RunnableVal3<Command, Runnable, Runnable> confirm, 067 RunnableVal2<Command, CommandResult> whenDone 068 ) throws CommandException { 069 final Plot currentPlot = player.getCurrentPlot(); 070 if (currentPlot == null) { 071 throw new CommandException(TranslatableCaption.of("errors.not_in_plot")); 072 } 073 checkTrue(currentPlot.hasOwner(), TranslatableCaption.of("info.plot_unowned")); 074 checkTrue( 075 currentPlot.isOwner(player.getUUID()) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST), 076 TranslatableCaption.of("permission.no_plot_perms") 077 ); 078 079 checkTrue(args.length == 1, TranslatableCaption.of("commandconfig.command_syntax"), 080 TagResolver.resolver("value", Tag.inserting(Component.text(getUsage()))) 081 ); 082 083 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 084 PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> { 085 if (throwable != null) { 086 if (throwable instanceof TimeoutException) { 087 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 088 } else { 089 player.sendMessage( 090 TranslatableCaption.of("errors.invalid_player"), 091 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) 092 ); 093 } 094 future.completeExceptionally(throwable); 095 return; 096 } else { 097 checkTrue(!uuids.isEmpty(), TranslatableCaption.of("errors.invalid_player"), 098 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) 099 ); 100 101 Iterator<UUID> iterator = uuids.iterator(); 102 int size = currentPlot.getTrusted().size() + currentPlot.getMembers().size(); 103 while (iterator.hasNext()) { 104 UUID uuid = iterator.next(); 105 if (uuid == DBFunc.EVERYONE && !( 106 player.hasPermission(Permission.PERMISSION_TRUST_EVERYONE) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_TRUST))) { 107 player.sendMessage( 108 TranslatableCaption.of("errors.invalid_player"), 109 PlotSquared.platform().playerManager().getUsernameCaption(uuid) 110 .thenApply(caption -> TagResolver.resolver( 111 "value", 112 Tag.inserting(caption.toComponent(player)) 113 )) 114 ); 115 iterator.remove(); 116 continue; 117 } 118 if (currentPlot.isOwner(uuid)) { 119 player.sendMessage( 120 TranslatableCaption.of("member.already_added"), 121 PlotSquared.platform().playerManager().getUsernameCaption(uuid) 122 .thenApply(caption -> TagResolver.resolver( 123 "player", 124 Tag.inserting(caption.toComponent(player)) 125 )) 126 ); 127 iterator.remove(); 128 continue; 129 } 130 if (currentPlot.getTrusted().contains(uuid)) { 131 player.sendMessage( 132 TranslatableCaption.of("member.already_added"), 133 PlotSquared.platform().playerManager().getUsernameCaption(uuid) 134 .thenApply(caption -> TagResolver.resolver( 135 "player", 136 Tag.inserting(caption.toComponent(player)) 137 )) 138 ); 139 iterator.remove(); 140 continue; 141 } 142 size += currentPlot.getMembers().contains(uuid) ? 0 : 1; 143 } 144 checkTrue(!uuids.isEmpty(), null); 145 int localTrustSize = currentPlot.getTrusted().size(); 146 int maxTrustSize = player.hasPermissionRange(Permission.PERMISSION_TRUST, Settings.Limit.MAX_PLOTS); 147 if (localTrustSize >= maxTrustSize) { 148 player.sendMessage( 149 TranslatableCaption.of("members.plot_max_members_trusted"), 150 TagResolver.resolver("amount", Tag.inserting(Component.text(localTrustSize))) 151 ); 152 return; 153 } 154 // Success 155 confirm.run( 156 this, () -> { 157 for (UUID uuid : uuids) { 158 if (this.eventDispatcher 159 .callPlayerTrust(player, currentPlot, uuid, PlayerPlotAddRemoveEvent.Reason.COMMAND) 160 .getEventResult() == Result.DENY) { 161 player.sendMessage( 162 TranslatableCaption.of("events.event_denied"), 163 TagResolver.resolver("value", Tag.inserting(Component.text("Trust"))) 164 ); 165 return; 166 } 167 168 if (uuid != DBFunc.EVERYONE) { 169 if (!currentPlot.removeMember(uuid)) { 170 if (currentPlot.getDenied().contains(uuid)) { 171 currentPlot.removeDenied(uuid); 172 } 173 } 174 } 175 currentPlot.addTrusted(uuid); 176 this.eventDispatcher.callTrusted(player, currentPlot, uuid, true); 177 this.eventDispatcher.callPostTrusted( 178 player, 179 currentPlot, 180 uuid, 181 false, 182 PlayerPlotAddRemoveEvent.Reason.COMMAND 183 ); 184 player.sendMessage(TranslatableCaption.of("trusted.trusted_added")); 185 } 186 }, null 187 ); 188 } 189 future.complete(true); 190 } 191 ); 192 return CompletableFuture.completedFuture(true); 193 } 194 195 @Override 196 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 197 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 198 } 199 200}