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.caption.TranslatableCaption;
024import com.plotsquared.core.database.DBFunc;
025import com.plotsquared.core.location.Location;
026import com.plotsquared.core.permissions.Permission;
027import com.plotsquared.core.player.PlotPlayer;
028import com.plotsquared.core.plot.Plot;
029import com.plotsquared.core.plot.world.PlotAreaManager;
030import com.plotsquared.core.util.PlayerManager;
031import com.plotsquared.core.util.TabCompletions;
032import com.plotsquared.core.util.WorldUtil;
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.HashSet;
039import java.util.Set;
040import java.util.UUID;
041import java.util.concurrent.TimeoutException;
042
043@CommandDeclaration(command = "kick",
044        aliases = "k",
045        permission = "plots.kick",
046        usage = "/plot kick <player | *>",
047        category = CommandCategory.TELEPORT,
048        requiredType = RequiredType.PLAYER)
049public class Kick extends SubCommand {
050
051    private final PlotAreaManager plotAreaManager;
052    private final WorldUtil worldUtil;
053
054    @Inject
055    public Kick(
056            final @NonNull PlotAreaManager plotAreaManager,
057            final @NonNull WorldUtil worldUtil
058    ) {
059        super(Argument.PlayerName);
060        this.plotAreaManager = plotAreaManager;
061        this.worldUtil = worldUtil;
062    }
063
064    @Override
065    public boolean onCommand(PlotPlayer<?> player, String[] args) {
066        Location location = player.getLocation();
067        Plot plot = location.getPlot();
068        if (plot == null) {
069            player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
070            return false;
071        }
072        if ((!plot.hasOwner() || !plot.isOwner(player.getUUID())) && !player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_KICK)) {
073            player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
074            return false;
075        }
076
077        PlayerManager.getUUIDsFromString(args[0], (uuids, throwable) -> {
078            if (throwable instanceof TimeoutException) {
079                player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout"));
080            } else if (throwable != null || uuids.isEmpty()) {
081                player.sendMessage(
082                        TranslatableCaption.of("errors.invalid_player"),
083                        Template.of("value", args[0])
084                );
085            } else {
086                Set<PlotPlayer<?>> players = new HashSet<>();
087                for (UUID uuid : uuids) {
088                    if (uuid == DBFunc.EVERYONE) {
089                        for (PlotPlayer<?> pp : plot.getPlayersInPlot()) {
090                            if (pp == player || pp.hasPermission(Permission.PERMISSION_ADMIN_ENTRY_DENIED)) {
091                                continue;
092                            }
093                            players.add(pp);
094                        }
095                        continue;
096                    }
097                    PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuid);
098                    if (pp != null) {
099                        players.add(pp);
100                    }
101                }
102                players.remove(player); // Don't ever kick the calling player
103                if (players.isEmpty()) {
104                    player.sendMessage(
105                            TranslatableCaption.of("errors.invalid_player"),
106                            Template.of("value", args[0])
107                    );
108                    return;
109                }
110                for (PlotPlayer<?> player2 : players) {
111                    if (!plot.equals(player2.getCurrentPlot())) {
112                        player.sendMessage(
113                                TranslatableCaption.of("errors.invalid_player"),
114                                Template.of("value", args[0])
115                        );
116                        return;
117                    }
118                    if (player2.hasPermission(Permission.PERMISSION_ADMIN_ENTRY_DENIED)) {
119                        player.sendMessage(
120                                TranslatableCaption.of("cluster.cannot_kick_player"),
121                                Template.of("name", player2.getName())
122                        );
123                        return;
124                    }
125                    Location spawn = this.worldUtil.getSpawn(location.getWorldName());
126                    player2.sendMessage(TranslatableCaption.of("kick.you_got_kicked"));
127                    if (plot.equals(spawn.getPlot())) {
128                        Location newSpawn = this.worldUtil.getSpawn(this.plotAreaManager.getAllWorlds()[0]);
129                        if (plot.equals(newSpawn.getPlot())) {
130                            // Kick from server if you can't be teleported to spawn
131                            // Use string based message here for legacy uses
132                            player2.kick("You got kicked from the plot! This server did not set up a loaded spawn, so you got " +
133                                    "kicked from the server.");
134                        } else {
135                            player2.plotkick(newSpawn);
136                        }
137                    } else {
138                        player2.plotkick(spawn);
139                    }
140                }
141            }
142        });
143
144        return true;
145    }
146
147    @Override
148    public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) {
149        Location location = player.getLocation();
150        Plot plot = location.getPlotAbs();
151        if (plot == null) {
152            return Collections.emptyList();
153        }
154        return TabCompletions.completePlayersInPlot(plot, String.join(",", args).trim(),
155                Collections.singletonList(player.getName())
156        );
157    }
158
159}