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.plotsquared.core.PlotSquared;
022import com.plotsquared.core.configuration.Settings;
023import com.plotsquared.core.configuration.caption.TranslatableCaption;
024import com.plotsquared.core.location.Location;
025import com.plotsquared.core.permissions.Permission;
026import com.plotsquared.core.player.PlotPlayer;
027import com.plotsquared.core.plot.Plot;
028import com.plotsquared.core.util.MathMan;
029import com.plotsquared.core.util.query.PlotQuery;
030import net.kyori.adventure.text.Component;
031import net.kyori.adventure.text.minimessage.tag.Tag;
032import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
033
034import java.util.ArrayList;
035import java.util.Collection;
036import java.util.Collections;
037import java.util.List;
038import java.util.concurrent.TimeoutException;
039
040@CommandDeclaration(command = "alias",
041        permission = "plots.alias",
042        usage = "/plot alias <set | remove> <alias>",
043        aliases = {"setalias", "sa", "name", "rename", "setname", "seta", "nameplot"},
044        category = CommandCategory.SETTINGS,
045        requiredType = RequiredType.PLAYER)
046public class Alias extends SubCommand {
047
048    private static final Command SET_COMMAND = new Command(null, false, "set", null, RequiredType.NONE, null) {
049    };
050    private static final Command REMOVE_COMMAND = new Command(null, false, "remove", null, RequiredType.NONE, null) {
051    };
052
053    @Override
054    public boolean onCommand(PlotPlayer<?> player, String[] args) {
055
056        if (args.length == 0) {
057            sendUsage(player);
058            return false;
059        }
060
061        Location location = player.getLocation();
062        Plot plot = location.getPlotAbs();
063        if (plot == null) {
064            player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
065            return false;
066        }
067
068        if (!plot.hasOwner()) {
069            player.sendMessage(TranslatableCaption.of("working.plot_not_claimed"));
070            return false;
071        }
072
073        boolean result = false;
074
075        boolean owner = plot.isOwner(player.getUUID());
076        boolean permission;
077        boolean admin;
078        switch (args[0].toLowerCase()) {
079            case "set" -> {
080                if (args.length != 2) {
081                    sendUsage(player);
082                    return false;
083                }
084                permission = isPermitted(player, Permission.PERMISSION_ALIAS_SET);
085                admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_SET);
086                if (!admin && !owner) {
087                    player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
088                    return false;
089                }
090                if (permission) { // is either admin or owner
091                    setAlias(player, plot, args[1]);
092                    return true;
093                } else {
094                    player.sendMessage(
095                            TranslatableCaption.of("permission.no_permission"),
096                            TagResolver.resolver(
097                                    "node",
098                                    Tag.inserting(Permission.PERMISSION_ALIAS_SET)
099                            )
100                    );
101                }
102            }
103            case "remove" -> {
104                permission = isPermitted(player, Permission.PERMISSION_ALIAS_REMOVE);
105                admin = isPermitted(player, Permission.PERMISSION_ADMIN_ALIAS_REMOVE);
106                if (!admin && !owner) {
107                    player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
108                    return false;
109                }
110                if (permission) {
111                    result = removeAlias(player, plot);
112                } else {
113                    player.sendMessage(
114                            TranslatableCaption.of("permission.no_permission"),
115                            TagResolver.resolver(
116                                    "node",
117                                    Tag.inserting(Permission.PERMISSION_ALIAS_REMOVE)
118                            )
119                    );
120                }
121            }
122            default -> {
123                sendUsage(player);
124                result = false;
125            }
126        }
127
128        return result;
129    }
130
131    @Override
132    public Collection<Command> tab(PlotPlayer<?> player, String[] args, boolean space) {
133        final List<Command> commands = new ArrayList<>(2);
134        if (args.length == 1) {
135            if ("set".startsWith(args[0])) {
136                commands.add(SET_COMMAND);
137            }
138            if ("remove".startsWith(args[0])) {
139                commands.add(REMOVE_COMMAND);
140            }
141            return commands;
142        }
143        return Collections.emptySet();
144    }
145
146    private void setAlias(PlotPlayer<?> player, Plot plot, String alias) {
147        if (alias.isEmpty()) {
148            sendUsage(player);
149        } else if (alias.length() >= 50) {
150            player.sendMessage(TranslatableCaption.of("alias.alias_too_long"));
151        } else if (MathMan.isInteger(alias)) {
152            player.sendMessage(TranslatableCaption.of("flag.not_valid_value")); // TODO this is obviously wrong
153        } else {
154            if (PlotQuery.newQuery().inArea(plot.getArea())
155                    .withAlias(alias)
156                    .anyMatch()) {
157                player.sendMessage(
158                        TranslatableCaption.of("alias.alias_is_taken"),
159                        TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
160                );
161                return;
162            }
163            if (Settings.UUID.OFFLINE) {
164                plot.setAlias(alias);
165                player.sendMessage(
166                        TranslatableCaption.of("alias.alias_set_to"),
167                        TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
168                );
169                return;
170            }
171            PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> {
172                if (throwable instanceof TimeoutException) {
173                    player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout"));
174                } else if (uuid != null) {
175                    player.sendMessage(
176                            TranslatableCaption.of("alias.alias_is_taken"),
177                            TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
178                    );
179                } else {
180                    plot.setAlias(alias);
181                    player.sendMessage(
182                            TranslatableCaption.of("alias.alias_set_to"),
183                            TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
184                    );
185                }
186            }));
187        }
188    }
189
190    private boolean removeAlias(PlotPlayer<?> player, Plot plot) {
191        String alias = plot.getAlias();
192        if (!plot.getAlias().isEmpty()) {
193            player.sendMessage(
194                    TranslatableCaption.of("alias.alias_removed"),
195                    TagResolver.resolver("alias", Tag.inserting(Component.text(alias)))
196            );
197        } else {
198            player.sendMessage(
199                    TranslatableCaption.of("alias.no_alias_set")
200            );
201        }
202        plot.setAlias(null);
203        return true;
204    }
205
206    private boolean isPermitted(PlotPlayer<?> player, Permission permission) {
207        return player.hasPermission(permission);
208    }
209
210}