Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Events for Plot Move + Plot Swap #3769

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions Core/src/main/java/com/plotsquared/core/command/Move.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@

import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.PlotMoveEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.PlotId;
import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.task.RunnableVal2;
import com.plotsquared.core.util.task.RunnableVal3;
import net.kyori.adventure.text.Component;
Expand All @@ -43,10 +47,12 @@
public class Move extends SubCommand {

private final PlotAreaManager plotAreaManager;
private final EventDispatcher eventDispatcher;

@Inject
public Move(final @NonNull PlotAreaManager plotAreaManager) {
public Move(final @NonNull PlotAreaManager plotAreaManager, final @NonNull EventDispatcher eventDispatcher) {
this.plotAreaManager = plotAreaManager;
this.eventDispatcher = eventDispatcher;
}

@Override
Expand All @@ -68,40 +74,54 @@ public CompletableFuture<Boolean> execute(
boolean override = false;
if (args.length == 2 && args[1].equalsIgnoreCase("-f")) {
args = new String[]{args[0]};
override = true;
override = player.hasPermission(Permission.PERMISSION_ADMIN); // Only allow force with admin permission
}
if (args.length != 1) {
sendUsage(player);
return CompletableFuture.completedFuture(false);
}
PlotArea area = this.plotAreaManager.getPlotAreaByString(args[0]);
Plot plot2;
Plot tmpTargetPlot;
if (area == null) {
plot2 = Plot.getPlotFromString(player, args[0], true);
if (plot2 == null) {
tmpTargetPlot = Plot.getPlotFromString(player, args[0], true);
if (tmpTargetPlot == null) {
return CompletableFuture.completedFuture(false);
}
} else {
plot2 = area.getPlotAbs(plot1.getId());
tmpTargetPlot = area.getPlotAbs(plot1.getId());
}
if (plot1.equals(plot2)) {
final PlotMoveEvent moveEvent = this.eventDispatcher.callMove(player, plot1, tmpTargetPlot);
final Plot targetPlot = moveEvent.destination();
if (!override) {
override = moveEvent.getEventResult() == Result.FORCE;
}

if (moveEvent.getEventResult() == Result.DENY) {
if (moveEvent.sendErrorMessage()) {
player.sendMessage(TranslatableCaption.of("move.event_cancelled"));
}
return CompletableFuture.completedFuture(false);
}

if (plot1.equals(targetPlot)) {
player.sendMessage(TranslatableCaption.of("invalid.origin_cant_be_target"));
return CompletableFuture.completedFuture(false);
}
if (!plot1.getArea().isCompatible(plot2.getArea()) && (!override || !player.hasPermission(Permission.PERMISSION_ADMIN))) {
if (!plot1.getArea().isCompatible(targetPlot.getArea()) && !override) {
player.sendMessage(TranslatableCaption.of("errors.plotworld_incompatible"));
return CompletableFuture.completedFuture(false);
}
if (plot1.isMerged() || plot2.isMerged()) {
if (plot1.isMerged() || targetPlot.isMerged()) {
player.sendMessage(TranslatableCaption.of("move.move_merged"));
return CompletableFuture.completedFuture(false);
}

// Set strings here as the plot objects are mutable (the PlotID changes after being moved).
PlotId oldPlotId = PlotId.of(plot1.getId().getX(), plot1.getId().getY());
String p1 = plot1.toString();
String p2 = plot2.toString();
String p2 = targetPlot.toString();

return plot1.getPlotModificationManager().move(plot2, player, () -> {
return plot1.getPlotModificationManager().move(targetPlot, player, () -> {
}, false).thenApply(result -> {
if (result) {
player.sendMessage(
Expand All @@ -111,6 +131,7 @@ public CompletableFuture<Boolean> execute(
.tag("target", Tag.inserting(Component.text(p2)))
.build()
);
this.eventDispatcher.callPostMove(player, oldPlotId, targetPlot);
return true;
} else {
player.sendMessage(TranslatableCaption.of("move.requires_unowned"));
Expand Down
44 changes: 30 additions & 14 deletions Core/src/main/java/com/plotsquared/core/command/Swap.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@
*/
package com.plotsquared.core.command;

import com.google.inject.Inject;
import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.events.PlotSwapEvent;
import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.permissions.Permission;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.task.RunnableVal2;
import com.plotsquared.core.util.task.RunnableVal3;
import net.kyori.adventure.text.Component;
Expand All @@ -38,48 +42,59 @@
requiredType = RequiredType.PLAYER)
public class Swap extends SubCommand {

@Inject
private EventDispatcher eventDispatcher;

@Override
public CompletableFuture<Boolean> execute(
PlotPlayer<?> player, String[] args,
RunnableVal3<Command, Runnable, Runnable> confirm,
RunnableVal2<Command, CommandResult> whenDone
) {
Location location = player.getLocation();
Plot plot1 = location.getPlotAbs();
if (plot1 == null) {
Plot plot = location.getPlotAbs();
if (plot == null) {
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
return CompletableFuture.completedFuture(false);
}
if (!plot1.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN)) {
player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
return CompletableFuture.completedFuture(false);
}
if (args.length != 1) {
sendUsage(player);
return CompletableFuture.completedFuture(false);
}
Plot plot2 = Plot.getPlotFromString(player, args[0], true);
if (plot2 == null) {
final Plot plotArg = Plot.getPlotFromString(player, args[0], true);
if (plotArg == null) {
return CompletableFuture.completedFuture(false);
}
final PlotSwapEvent event = this.eventDispatcher.callSwap(player, plot, plotArg);
if (event.getEventResult() == Result.DENY) {
if (event.sendErrorMessage()) {
player.sendMessage(TranslatableCaption.of("swap.event_cancelled"));
}
return CompletableFuture.completedFuture(false);
}
if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN) && event.getEventResult() != Result.FORCE) {
player.sendMessage(TranslatableCaption.of("permission.no_plot_perms"));
return CompletableFuture.completedFuture(false);
}
if (plot1.equals(plot2)) {
final Plot target = event.target();
if (plot.equals(target)) {
player.sendMessage(TranslatableCaption.of("invalid.origin_cant_be_target"));
return CompletableFuture.completedFuture(false);
}
if (!plot1.getArea().isCompatible(plot2.getArea())) {
if (!plot.getArea().isCompatible(target.getArea())) {
player.sendMessage(TranslatableCaption.of("errors.plotworld_incompatible"));
return CompletableFuture.completedFuture(false);
}
if (plot1.isMerged() || plot2.isMerged()) {
if (plot.isMerged() || target.isMerged()) {
player.sendMessage(TranslatableCaption.of("swap.swap_merged"));
return CompletableFuture.completedFuture(false);
}

// Set strings here as the plot objects are mutable (the PlotID changes after being moved).
String p1 = plot1.toString();
String p2 = plot2.toString();
String p1 = plot.toString();
String p2 = target.toString();

return plot1.getPlotModificationManager().move(plot2, player, () -> {
return plot.getPlotModificationManager().move(target, player, () -> {
}, true).thenApply(result -> {
if (result) {
player.sendMessage(
Expand All @@ -89,6 +104,7 @@ public CompletableFuture<Boolean> execute(
.tag("target", Tag.inserting(Component.text(p2)))
.build()
);
this.eventDispatcher.callPostSwap(player, plot, target);
return true;
} else {
player.sendMessage(TranslatableCaption.of("swap.swap_overlap"));
Expand Down
119 changes: 119 additions & 0 deletions Core/src/main/java/com/plotsquared/core/events/PlotMoveEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* PlotSquared, a land and world management plugin for Minecraft.
* Copyright (C) IntellectualSites <https://intellectualsites.com>
* Copyright (C) IntellectualSites team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.events;

import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotId;
import org.checkerframework.checker.nullness.qual.NonNull;

import java.util.Objects;

/**
* Called when a {@link PlotPlayer} attempts to move a {@link Plot} to another {@link Plot}.
*
* <br>
* <ul>
* <li>{@link #getPlotPlayer()} is the initiator of the move action (most likely the command executor)</li>
* <li>{@link #getPlot()} is the plot to be moved</li>
* <li>{@link #destination()} is the plot, where the plot will be moved to.</li>
* </ul>
*
* @see com.plotsquared.core.command.Move
* @since TODO
*/
public class PlotMoveEvent extends PlotPlayerEvent implements CancellablePlotEvent {

private Plot destination;
private boolean sendErrorMessage = true;
private Result result = Result.ACCEPT;

public PlotMoveEvent(final PlotPlayer<?> initiator, final Plot plot, final Plot destination) {
super(initiator, plot);
this.destination = destination;
}

/**
* Set the new {@link Plot} to where the plot should be moved to.
*
* @param destination The plot representing the new location.
* @since TODO
*/
public void setDestination(@NonNull final Plot destination) {
this.destination = Objects.requireNonNull(destination);
}

/**
* Set the new destination based off their X and Y coordinates. Calls {@link #setDestination(Plot)} while using the
* {@link com.plotsquared.core.plot.PlotArea} provided by the current {@link #destination()}.
* <p>
* <b>Note:</b> the coordinates are not minecraft world coordinates, but the underlying {@link PlotId}s coordinates.
*
* @param x The X coordinate of the {@link PlotId}
* @param y The Y coordinate of the {@link PlotId}
* @since TODO
*/
public void setDestination(final int x, final int y) {
this.destination = Objects.requireNonNull(this.destination.getArea()).getPlot(PlotId.of(x, y));
}

/**
* Set whether to send a generic message to the user ({@code Move was cancelled by an external plugin}). If set to {@code
* false}, make sure to send a message to the player yourself to avoid confusion.
*
* @param sendErrorMessage {@code true} if PlotSquared should send a generic error message to the player.
* @since TODO
*/
public void setSendErrorMessage(final boolean sendErrorMessage) {
this.sendErrorMessage = sendErrorMessage;
}

/**
* @return The destination for the plot to be moved to.
* @since TODO
*/
public Plot destination() {
return destination;
}

/**
* @return {@code true} if PlotSquared should send a generic error message to the player.
* @since TODO
*/
public boolean sendErrorMessage() {
return sendErrorMessage;
}

/**
* {@inheritDoc}
*/
@Override
public Result getEventResult() {
return result;
}

/**
* {@inheritDoc}
*/
@Override
public void setEventResult(Result eventResult) {
this.result = Objects.requireNonNull(eventResult);
}

}
Loading
Loading