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.caption.TranslatableCaption;
023import com.plotsquared.core.location.Location;
024import com.plotsquared.core.permissions.Permission;
025import com.plotsquared.core.player.PlotPlayer;
026import com.plotsquared.core.plot.Plot;
027import com.plotsquared.core.plot.PlotArea;
028import com.plotsquared.core.plot.world.PlotAreaManager;
029import com.plotsquared.core.util.task.RunnableVal2;
030import com.plotsquared.core.util.task.RunnableVal3;
031import net.kyori.adventure.text.Component;
032import net.kyori.adventure.text.minimessage.tag.Tag;
033import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
034import org.checkerframework.checker.nullness.qual.NonNull;
035
036import java.util.concurrent.CompletableFuture;
037
038@CommandDeclaration(usage = "/plot move <X;Z>",
039        command = "move",
040        permission = "plots.move",
041        category = CommandCategory.CLAIMING,
042        requiredType = RequiredType.PLAYER)
043public class Move extends SubCommand {
044
045    private final PlotAreaManager plotAreaManager;
046
047    @Inject
048    public Move(final @NonNull PlotAreaManager plotAreaManager) {
049        this.plotAreaManager = plotAreaManager;
050    }
051
052    @Override
053    public CompletableFuture<Boolean> execute(
054            PlotPlayer<?> player, String[] args,
055            RunnableVal3<Command, Runnable, Runnable> confirm,
056            RunnableVal2<Command, CommandResult> whenDone
057    ) {
058        Location location = player.getLocation();
059        Plot plot1 = location.getPlotAbs();
060        if (plot1 == null) {
061            player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
062            return CompletableFuture.completedFuture(false);
063        }
064        if (!plot1.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN)) {
065            player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
066            return CompletableFuture.completedFuture(false);
067        }
068        boolean override = false;
069        if (args.length == 2 && args[1].equalsIgnoreCase("-f")) {
070            args = new String[]{args[0]};
071            override = true;
072        }
073        if (args.length != 1) {
074            sendUsage(player);
075            return CompletableFuture.completedFuture(false);
076        }
077        PlotArea area = this.plotAreaManager.getPlotAreaByString(args[0]);
078        Plot plot2;
079        if (area == null) {
080            plot2 = Plot.getPlotFromString(player, args[0], true);
081            if (plot2 == null) {
082                return CompletableFuture.completedFuture(false);
083            }
084        } else {
085            plot2 = area.getPlotAbs(plot1.getId());
086        }
087        if (plot1.equals(plot2)) {
088            player.sendMessage(TranslatableCaption.of("invalid.origin_cant_be_target"));
089            return CompletableFuture.completedFuture(false);
090        }
091        if (!plot1.getArea().isCompatible(plot2.getArea()) && (!override || !player.hasPermission(Permission.PERMISSION_ADMIN))) {
092            player.sendMessage(TranslatableCaption.of("errors.plotworld_incompatible"));
093            return CompletableFuture.completedFuture(false);
094        }
095        if (plot1.isMerged() || plot2.isMerged()) {
096            player.sendMessage(TranslatableCaption.of("move.move_merged"));
097            return CompletableFuture.completedFuture(false);
098        }
099
100        // Set strings here as the plot objects are mutable (the PlotID changes after being moved).
101        String p1 = plot1.toString();
102        String p2 = plot2.toString();
103
104        return plot1.getPlotModificationManager().move(plot2, player, () -> {
105        }, false).thenApply(result -> {
106            if (result) {
107                player.sendMessage(
108                        TranslatableCaption.of("move.move_success"),
109                        TagResolver.builder()
110                                .tag("origin", Tag.inserting(Component.text(p1)))
111                                .tag("target", Tag.inserting(Component.text(p2)))
112                                .build()
113                );
114                return true;
115            } else {
116                player.sendMessage(TranslatableCaption.of("move.requires_unowned"));
117                return false;
118            }
119        });
120    }
121
122    @Override
123    public boolean onCommand(final PlotPlayer<?> player, String[] args) {
124        return true;
125    }
126
127}