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.events.TeleportCause; 029import com.plotsquared.core.location.Location; 030import com.plotsquared.core.permissions.Permission; 031import com.plotsquared.core.player.PlotPlayer; 032import com.plotsquared.core.plot.Plot; 033import com.plotsquared.core.plot.world.PlotAreaManager; 034import com.plotsquared.core.util.EventDispatcher; 035import com.plotsquared.core.util.PlayerManager; 036import com.plotsquared.core.util.TabCompletions; 037import com.plotsquared.core.util.WorldUtil; 038import com.sk89q.worldedit.world.gamemode.GameModes; 039import net.kyori.adventure.text.Component; 040import net.kyori.adventure.text.minimessage.tag.Tag; 041import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; 042import org.checkerframework.checker.nullness.qual.NonNull; 043 044import java.util.Collection; 045import java.util.Collections; 046import java.util.UUID; 047import java.util.concurrent.TimeoutException; 048 049@CommandDeclaration(command = "deny", 050 aliases = {"d", "ban"}, 051 usage = "/plot deny <player>", 052 category = CommandCategory.SETTINGS, 053 requiredType = RequiredType.PLAYER) 054public class Deny extends SubCommand { 055 056 private final PlotAreaManager plotAreaManager; 057 private final EventDispatcher eventDispatcher; 058 private final WorldUtil worldUtil; 059 060 @Inject 061 public Deny( 062 final @NonNull PlotAreaManager plotAreaManager, 063 final @NonNull EventDispatcher eventDispatcher, 064 final @NonNull WorldUtil worldUtil 065 ) { 066 super(Argument.PlayerName); 067 this.plotAreaManager = plotAreaManager; 068 this.eventDispatcher = eventDispatcher; 069 this.worldUtil = worldUtil; 070 } 071 072 @Override 073 public boolean onCommand(PlotPlayer<?> player, String[] args) { 074 075 final Plot plot = player.getCurrentPlot(); 076 if (plot == null) { 077 player.sendMessage(TranslatableCaption.of("errors.not_in_plot")); 078 return false; 079 } 080 if (!plot.hasOwner()) { 081 player.sendMessage(TranslatableCaption.of("info.plot_unowned")); 082 return false; 083 } 084 if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_DENY)) { 085 player.sendMessage(TranslatableCaption.of("permission.no_plot_perms")); 086 return true; 087 } 088 089 int maxDenySize = player.hasPermissionRange(Permission.PERMISSION_DENY, Settings.Limit.MAX_PLOTS); 090 int size = plot.getDenied().size(); 091 if (size >= maxDenySize) { 092 player.sendMessage( 093 TranslatableCaption.of("members.plot_max_members_denied"), 094 TagResolver.resolver("amount", Tag.inserting(Component.text(size))) 095 ); 096 return false; 097 } 098 099 PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> { 100 if (throwable instanceof TimeoutException) { 101 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 102 } else if (throwable != null || uuids.isEmpty()) { 103 player.sendMessage( 104 TranslatableCaption.of("errors.invalid_player"), 105 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) 106 ); 107 } else { 108 for (UUID uuid : uuids) { 109 if (uuid == DBFunc.EVERYONE && !( 110 player.hasPermission(Permission.PERMISSION_DENY_EVERYONE) || player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_DENY))) { 111 player.sendMessage( 112 TranslatableCaption.of("errors.invalid_player"), 113 TagResolver.resolver("value", Tag.inserting(Component.text(args[0]))) 114 ); 115 } else if (plot.isOwner(uuid)) { 116 player.sendMessage(TranslatableCaption.of("deny.cant_remove_owner")); 117 return; 118 } else if (plot.getDenied().contains(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 return; 128 } else { 129 if (this.eventDispatcher 130 .callPlayerDeny(player, plot, uuid, PlayerPlotAddRemoveEvent.Reason.COMMAND) 131 .getEventResult() == Result.DENY) { 132 player.sendMessage( 133 TranslatableCaption.of("events.event_denied"), 134 TagResolver.resolver("value", Tag.inserting(Component.text("Deny"))) 135 ); 136 continue; 137 } 138 if (uuid != DBFunc.EVERYONE) { 139 plot.removeMember(uuid); 140 plot.removeTrusted(uuid); 141 } 142 plot.addDenied(uuid); 143 this.eventDispatcher.callDenied(player, plot, uuid, true); 144 this.eventDispatcher.callPostDenied(player, plot, uuid, true, PlayerPlotAddRemoveEvent.Reason.COMMAND); 145 if (!uuid.equals(DBFunc.EVERYONE)) { 146 handleKick(PlotSquared.platform().playerManager().getPlayerIfExists(uuid), plot); 147 } else { 148 for (PlotPlayer<?> plotPlayer : plot.getPlayersInPlot()) { 149 if (plot.isDenied(plotPlayer.getUUID())) { 150 handleKick(plotPlayer, plot); 151 } 152 } 153 } 154 } 155 } 156 player.sendMessage(TranslatableCaption.of("deny.denied_added")); 157 } 158 }); 159 160 return true; 161 } 162 163 @Override 164 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 165 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 166 } 167 168 private void handleKick(PlotPlayer<?> player, Plot plot) { 169 plot = plot.getBasePlot(false); 170 if (player == null) { 171 return; 172 } 173 if (!plot.equals(player.getCurrentPlot())) { 174 return; 175 } 176 if (player.hasPermission("plots.admin.entry.denied")) { 177 return; 178 } 179 if (player.getGameMode() == GameModes.SPECTATOR) { 180 player.stopSpectating(); 181 } 182 Location location = player.getLocation(); 183 Location spawn = this.worldUtil.getSpawn(location.getWorldName()); 184 player.sendMessage(TranslatableCaption.of("deny.you_got_denied")); 185 if (plot.equals(spawn.getPlot())) { 186 Location newSpawn = this.worldUtil.getSpawn(this.plotAreaManager.getAllWorlds()[0]); 187 if (plot.equals(newSpawn.getPlot())) { 188 // Kick from server if you can't be teleported to spawn 189 // Use string based message here for legacy uses 190 player.kick("You got kicked from the plot! This server did not set up a loaded spawn, so you got " + 191 "kicked from the server."); 192 } else { 193 player.teleport(newSpawn, TeleportCause.DENIED); 194 } 195 } else { 196 player.teleport(spawn, TeleportCause.DENIED); 197 } 198 } 199 200}