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