chore: Implement suggested changes

This commit is contained in:
Ben Woo 2023-02-21 00:24:38 +08:00
parent a196bbd3e0
commit 4833111a2c
No known key found for this signature in database
GPG Key ID: FB2A3645536E12C8
11 changed files with 139 additions and 34 deletions

View File

@ -142,7 +142,7 @@ public class AnchorManager {
} }
MVWorld mvWorld = this.plugin.getMVWorldManager().getMVWorld(ancLoc.getWorld()); MVWorld mvWorld = this.plugin.getMVWorldManager().getMVWorld(ancLoc.getWorld());
if (mvWorld != null) { if (mvWorld != null) {
if (!this.plugin.getPlayerActionChecker().hasAccessToWorld(p, mvWorld).isSuccessful()) { if (this.plugin.getPlayerActionChecker().hasAccessToWorld(p, mvWorld).isUnsuccessful()) {
Logging.finer("Player '%s' does not have access to anchor '%s' in world '%s'.", Logging.finer("Player '%s' does not have access to anchor '%s' in world '%s'.",
p.getName(), anchor, mvWorld.getName()); p.getName(), anchor, mvWorld.getName());
continue; continue;

View File

@ -12,16 +12,36 @@ import org.jetbrains.annotations.Nullable;
* A response that have multiple results. * A response that have multiple results.
*/ */
public class ActionResponse implements ActionResult { public class ActionResponse implements ActionResult {
/**
* Create a new {@link ActionResponse} instance.
* Does not continue if one result is not successful.
*
* @return The new {@link ActionResponse} instance.
*/
public static ActionResponse create() { public static ActionResponse create() {
return new ActionResponse(); return new ActionResponse(false);
} }
/**
* Create a new {@link ActionResponse} instance.
*
* @param continueIfFail If true, the response will continue to add results even if one of the results is not successful.
* @return The new {@link ActionResponse} instance.
*/
public static ActionResponse create(boolean continueIfFail) { public static ActionResponse create(boolean continueIfFail) {
return new ActionResponse(continueIfFail); return new ActionResponse(continueIfFail);
} }
/**
* Create a response with a single result.
* Does not continue if one result is not successful.
*
* @param result The result.
* @return The new {@link ActionResponse} instance.
*/
public static ActionResponse of(ActionResult result) { public static ActionResponse of(ActionResult result) {
return new ActionResponse().addResult(result); return new ActionResponse(false).addResult(result);
} }
private final Set<ActionResult> results; private final Set<ActionResult> results;
@ -29,14 +49,10 @@ public class ActionResponse implements ActionResult {
private boolean isSuccessful = true; private boolean isSuccessful = true;
public ActionResponse() {
this(false);
}
/** /**
* @param continueIfFail If true, the response will continue to add results even if one of the results is not successful. * @param continueIfFail If true, the response will continue to add results even if one of the results is not successful.
*/ */
public ActionResponse(boolean continueIfFail) { protected ActionResponse(boolean continueIfFail) {
this.results = new HashSet<>(); this.results = new HashSet<>();
this.continueIfFail = continueIfFail; this.continueIfFail = continueIfFail;
} }
@ -66,7 +82,7 @@ public class ActionResponse implements ActionResult {
} }
results.add(result); results.add(result);
if (!result.isSuccessful()) { if (result.isUnsuccessful()) {
isSuccessful = false; isSuccessful = false;
} }
return this; return this;
@ -88,6 +104,14 @@ public class ActionResponse implements ActionResult {
return isSuccessful; return isSuccessful;
} }
/**
* {@inheritDoc}
*/
@Override
public boolean isUnsuccessful() {
return !isSuccessful;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */

View File

@ -20,6 +20,13 @@ public interface ActionResult {
*/ */
boolean isSuccessful(); boolean isSuccessful();
/**
* Check if the result is unsuccessful.
*
* @return true if the result is unsuccessful.
*/
boolean isUnsuccessful();
/** /**
* Check if the result is in the response. * Check if the result is in the response.
* *

View File

@ -2,7 +2,42 @@ package com.onarandombox.MultiverseCore.api.action;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/**
* A simple implementation of {@link ActionResult}.
*/
public class SimpleActionResult implements ActionResult { public class SimpleActionResult implements ActionResult {
/**
* Creates a new ActionResult that is successful with the given name.
*
* @param name The name of the result.
* @return The new ActionResult.
*/
public static ActionResult forSuccess(String name) {
return new SimpleActionResult(name, true);
}
/**
* Creates a new ActionResult that is unsuccessful with the given name.
*
* @param name The name of the result.
* @return The new ActionResult.
*/
public static ActionResult forFailure(String name) {
return new SimpleActionResult(name, false);
}
/**
* Creates a new ActionResult.
*
* @param name The name of the result.
* @param isSuccessful true if the result is successful.
* @return The new ActionResult.
*/
public static ActionResult of(String name, boolean isSuccessful) {
return new SimpleActionResult(name, isSuccessful);
}
private final String name; private final String name;
private final boolean isSuccessful; private final boolean isSuccessful;
@ -12,7 +47,7 @@ public class SimpleActionResult implements ActionResult {
* @param name The name of the result. * @param name The name of the result.
* @param isSuccessful true if the result is successful. * @param isSuccessful true if the result is successful.
*/ */
public SimpleActionResult(String name, boolean isSuccessful) { protected SimpleActionResult(String name, boolean isSuccessful) {
this.name = name; this.name = name;
this.isSuccessful = isSuccessful; this.isSuccessful = isSuccessful;
} }
@ -33,6 +68,14 @@ public class SimpleActionResult implements ActionResult {
return isSuccessful; return isSuccessful;
} }
/**
* {@inheritDoc}
*/
@Override
public boolean isUnsuccessful() {
return !isSuccessful;
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
@ -40,4 +83,12 @@ public class SimpleActionResult implements ActionResult {
public boolean hasResult(@Nullable ActionResult result) { public boolean hasResult(@Nullable ActionResult result) {
return result == this; return result == this;
} }
@Override
public String toString() {
return "SimpleActionResult{" +
"name='" + name + '\'' +
", isSuccessful=" + isSuccessful +
'}';
}
} }

View File

@ -35,10 +35,10 @@ public class CheckCommand extends MultiverseCoreCommand {
) { ) {
issuer.sendMessage("Checking " + player + " to " + destination + "..."); issuer.sendMessage("Checking " + player + " to " + destination + "...");
//TODO More detailed output on permissions required. //TODO More detailed output on permissions required.
if (!this.plugin.getPlayerActionChecker().canUseDestinationToTeleport(issuer.getIssuer(), player, destination).isSuccessful()) { if (this.plugin.getPlayerActionChecker().canUseDestinationToTeleport(issuer.getIssuer(), player, destination).isUnsuccessful()) {
issuer.sendMessage("You don't have permission to use this destination."); issuer.sendMessage("You don't have permission to use this destination.");
} }
if (!this.plugin.getPlayerActionChecker().canGoToDestination(issuer.getIssuer(), player, destination).isSuccessful()) { if (this.plugin.getPlayerActionChecker().canGoToDestination(issuer.getIssuer(), player, destination).isUnsuccessful()) {
issuer.sendMessage("You don't have permission to teleport to this destination."); issuer.sendMessage("You don't have permission to teleport to this destination.");
} }
} }

View File

@ -35,7 +35,7 @@ public class TeleportCommand extends MultiverseCoreCommand {
) { ) {
// TODO Add warning if teleporting too many players at once. // TODO Add warning if teleporting too many players at once.
for (Player player : players) { for (Player player : players) {
if (!this.plugin.getPlayerActionChecker().canUseDestinationToTeleport(issuer.getIssuer(), player, destination).isSuccessful()) { if (this.plugin.getPlayerActionChecker().canUseDestinationToTeleport(issuer.getIssuer(), player, destination).isUnsuccessful()) {
issuer.sendMessage("You don't have permission to use this destination."); issuer.sendMessage("You don't have permission to use this destination.");
continue; continue;
} }

View File

@ -56,8 +56,7 @@ public class DestinationsProvider {
@Nullable String deststring @Nullable String deststring
) { ) {
return destinationMap.values().stream() return destinationMap.values().stream()
.filter(destination -> this.plugin.getPermissionsTool().hasDestinationTeleportPermission(null, issuer.getIssuer(), destination) .filter(destination -> hasSelfOrOtherTeleportPermission(issuer, destination))
|| this.plugin.getPermissionsTool().hasDestinationTeleportPermission(issuer.getIssuer(), this.plugin.getServer().getConsoleSender(), destination))
.map(destination -> destination.suggestDestinations(issuer, deststring).stream() .map(destination -> destination.suggestDestinations(issuer, deststring).stream()
.map(s -> destination.getIdentifier() + SEPARATOR + s) .map(s -> destination.getIdentifier() + SEPARATOR + s)
.collect(Collectors.toList())) .collect(Collectors.toList()))
@ -65,6 +64,11 @@ public class DestinationsProvider {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
private boolean hasSelfOrOtherTeleportPermission(@NotNull BukkitCommandIssuer issuer, Destination<?> destination) {
return this.plugin.getPermissionsTool().hasDestinationTeleportPermission(issuer.getIssuer(), destination)
|| this.plugin.getPermissionsTool().hasDestinationTeleportPermission(issuer.getIssuer(), this.plugin.getServer().getConsoleSender(), destination);
}
/** /**
* Converts a destination string to a destination object. * Converts a destination string to a destination object.
* *

View File

@ -22,6 +22,7 @@ import com.onarandombox.MultiverseCore.event.MVRespawnEvent;
import com.onarandombox.MultiverseCore.utils.player.PlayerActionChecker; import com.onarandombox.MultiverseCore.utils.player.PlayerActionChecker;
import com.onarandombox.MultiverseCore.utils.player.checkresult.BlacklistResult; import com.onarandombox.MultiverseCore.utils.player.checkresult.BlacklistResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.EntryFeeResult; import com.onarandombox.MultiverseCore.utils.player.checkresult.EntryFeeResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.GameModeResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.NullPlaceResult; import com.onarandombox.MultiverseCore.utils.player.checkresult.NullPlaceResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.PlayerLimitResult; import com.onarandombox.MultiverseCore.utils.player.checkresult.PlayerLimitResult;
import com.onarandombox.MultiverseCore.utils.player.checkresult.WorldAccessResult; import com.onarandombox.MultiverseCore.utils.player.checkresult.WorldAccessResult;
@ -135,7 +136,7 @@ public class MVPlayerListener implements Listener {
return; return;
} }
if (!this.plugin.getPlayerActionChecker().hasAccessToWorld(player, world).isSuccessful()) { if (this.plugin.getPlayerActionChecker().hasAccessToWorld(player, world).isUnsuccessful()) {
player.sendMessage("[MV] - Sorry you can't be in this world anymore!"); player.sendMessage("[MV] - Sorry you can't be in this world anymore!");
this.sendPlayerToDefaultWorld(player); this.sendPlayerToDefaultWorld(player);
} }
@ -200,9 +201,15 @@ public class MVPlayerListener implements Listener {
MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld()); MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld());
MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld()); MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld());
ActionResponse actionCheckResponse = this.actionChecker.canGoFromToWorld(teleporter, teleportee, fromWorld, toWorld); ActionResponse actionCheckResponse = this.actionChecker.canGoFromWorldToWorld(teleporter, teleportee, fromWorld, toWorld);
Logging.fine(actionCheckResponse.toString()); Logging.fine(actionCheckResponse.toString());
if (!actionCheckResponse.isSuccessful()) {
if (actionCheckResponse.hasResult(NullPlaceResult.NOT_MV_WORLD)) {
Logging.fine("Player '" + teleportee.getName() + "' is teleporting to a non-MV world. Ignoring.");
return;
}
if (actionCheckResponse.isUnsuccessful()) {
tellReason(teleporter, teleportee, fromWorld, toWorld, actionCheckResponse); tellReason(teleporter, teleportee, fromWorld, toWorld, actionCheckResponse);
event.setCancelled(true); event.setCancelled(true);
return; return;
@ -256,9 +263,9 @@ public class MVPlayerListener implements Listener {
MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld()); MVWorld fromWorld = this.worldManager.getMVWorld(event.getFrom().getWorld());
MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld()); MVWorld toWorld = this.worldManager.getMVWorld(event.getTo().getWorld());
ActionResponse actionCheckResponse = this.actionChecker.canGoFromToWorld(event.getPlayer(), event.getPlayer(), fromWorld, toWorld); ActionResponse actionCheckResponse = this.actionChecker.canGoFromWorldToWorld(event.getPlayer(), event.getPlayer(), fromWorld, toWorld);
Logging.fine(actionCheckResponse.toString()); Logging.fine(actionCheckResponse.toString());
if (!actionCheckResponse.isSuccessful()) { if (actionCheckResponse.isUnsuccessful()) {
tellReason(event.getPlayer(), event.getPlayer(), fromWorld, toWorld, actionCheckResponse); tellReason(event.getPlayer(), event.getPlayer(), fromWorld, toWorld, actionCheckResponse);
event.setCancelled(true); event.setCancelled(true);
return; return;
@ -297,8 +304,9 @@ public class MVPlayerListener implements Listener {
* @param world The world the player is in. * @param world The world the player is in.
*/ */
public void applyGameModeAndFlight(@NotNull Player player, @NotNull MVWorld world) { public void applyGameModeAndFlight(@NotNull Player player, @NotNull MVWorld world) {
if (MVPlayerListener.this.actionChecker.canKeepGameMode(player, world).isSuccessful()) { GameModeResult keepGameModeResult = MVPlayerListener.this.actionChecker.canKeepGameMode(player, world);
Logging.fine("Player: " + player.getName() + " is IMMUNE to gamemode changes!"); if (keepGameModeResult.isSuccessful()) {
Logging.fine("Player: " + player.getName() + " can keep their gamemode. " + "Reason: " + keepGameModeResult.getName());
return; return;
} }
@ -309,8 +317,7 @@ public class MVPlayerListener implements Listener {
return; return;
} }
Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString()); Logging.fine("Handling gamemode for player: %s, Changing to %s", player.getName(), world.getGameMode().toString());
Logging.finest("From World: %s", player.getWorld()); Logging.finest("From World: %s --> To World: %s", player.getWorld());
Logging.finest("To World: %s", world);
player.setGameMode(world.getGameMode()); player.setGameMode(world.getGameMode());
// Check if their flight mode should change // Check if their flight mode should change
@ -347,17 +354,13 @@ public class MVPlayerListener implements Listener {
if (result.hasResult(NullPlaceResult.NULL_DESTINATION)) { if (result.hasResult(NullPlaceResult.NULL_DESTINATION)) {
issuer.sendMessage(targetName + " cannot be teleported to because the destination is null."); issuer.sendMessage(targetName + " cannot be teleported to because the destination is null.");
return;
} }
if (result.hasResult(NullPlaceResult.NULL_LOCATION)) { if (result.hasResult(NullPlaceResult.NULL_LOCATION)) {
issuer.sendMessage(targetName + " cannot be teleported to because the location is null."); issuer.sendMessage(targetName + " cannot be teleported to because the location is null.");
return;
} }
if (result.hasResult(NullPlaceResult.NULL_WORLD)) { if (result.hasResult(NullPlaceResult.NULL_WORLD)) {
issuer.sendMessage(targetName + " cannot be teleported because the world is null."); issuer.sendMessage(targetName + " cannot be teleported because the world is null.");
return;
} }
if (result.hasResult(WorldAccessResult.NO_WORLD_ACCESS)) { if (result.hasResult(WorldAccessResult.NO_WORLD_ACCESS)) {
issuer.sendMessage(targetName + " cannot be teleported to because you does not have access to " + toWorld.getName()); issuer.sendMessage(targetName + " cannot be teleported to because you does not have access to " + toWorld.getName());
} }

View File

@ -96,6 +96,9 @@ public class PlayerActionChecker {
if (location == null) { if (location == null) {
return ActionResponse.of(NullPlaceResult.NULL_LOCATION); return ActionResponse.of(NullPlaceResult.NULL_LOCATION);
} }
if (location.getWorld() == null) {
return ActionResponse.of(NullPlaceResult.NULL_WORLD);
}
MVWorld toWorld = this.worldManager.getMVWorld(location.getWorld()); MVWorld toWorld = this.worldManager.getMVWorld(location.getWorld());
return canGoToWorld(teleporter, teleportee, toWorld); return canGoToWorld(teleporter, teleportee, toWorld);
} }
@ -113,7 +116,7 @@ public class PlayerActionChecker {
@NotNull MVWorld toWorld @NotNull MVWorld toWorld
) { ) {
MVWorld fromWorld = this.worldManager.getMVWorld(teleportee.getWorld()); MVWorld fromWorld = this.worldManager.getMVWorld(teleportee.getWorld());
return canGoFromToWorld(teleporter, teleportee, fromWorld, toWorld); return canGoFromWorldToWorld(teleporter, teleportee, fromWorld, toWorld);
} }
/** /**
@ -124,13 +127,13 @@ public class PlayerActionChecker {
* @param toWorld The world to teleport to. * @param toWorld The world to teleport to.
* @return One or more of the above action results. * @return One or more of the above action results.
*/ */
public ActionResponse canGoFromToWorld(@Nullable CommandSender teleporter, public ActionResponse canGoFromWorldToWorld(@Nullable CommandSender teleporter,
@NotNull CommandSender teleportee, @NotNull CommandSender teleportee,
@Nullable MVWorld fromWorld, @Nullable MVWorld fromWorld,
@Nullable MVWorld toWorld @Nullable MVWorld toWorld
) { ) {
if (toWorld == null) { if (toWorld == null) {
return ActionResponse.of(NullPlaceResult.NULL_WORLD); return ActionResponse.of(NullPlaceResult.NOT_MV_WORLD);
} }
CommandSender targetSender = (teleporter == null) ? teleportee : teleporter; CommandSender targetSender = (teleporter == null) ? teleportee : teleporter;
@ -229,6 +232,9 @@ public class PlayerActionChecker {
* @return The action check result. * @return The action check result.
*/ */
public GameModeResult canKeepGameMode(@NotNull Player player, @NotNull MVWorld toWorld) { public GameModeResult canKeepGameMode(@NotNull Player player, @NotNull MVWorld toWorld) {
if (player.getGameMode().equals(toWorld.getGameMode())) {
return GameModeResult.KEEP_GAME_MODE;
}
//TODO: Add config option disable game mode enforcement //TODO: Add config option disable game mode enforcement
return permissionsTool.hasBypassGameModeEnforcement(player, toWorld) return permissionsTool.hasBypassGameModeEnforcement(player, toWorld)
? GameModeResult.KEEP_GAME_MODE : GameModeResult.ENFORCE_GAME_MODE; ? GameModeResult.KEEP_GAME_MODE : GameModeResult.ENFORCE_GAME_MODE;

View File

@ -13,6 +13,11 @@ public class GameModeResult extends SimpleActionResult {
*/ */
public static final GameModeResult BYPASS_ENFORCE_GAME_MODE = new GameModeResult("BYPASS_ENFORCE_GAME_MODE", true); public static final GameModeResult BYPASS_ENFORCE_GAME_MODE = new GameModeResult("BYPASS_ENFORCE_GAME_MODE", true);
/**
* The player's game mode is the same as the destination's game mode.
*/
public static final GameModeResult SAME_GAME_MODE = new GameModeResult("SAME_GAME_MODE", true);
/** /**
* The player's game mode should be enforced. * The player's game mode should be enforced.
*/ */

View File

@ -4,6 +4,11 @@ import com.onarandombox.MultiverseCore.api.action.ActionResult;
import com.onarandombox.MultiverseCore.api.action.SimpleActionResult; import com.onarandombox.MultiverseCore.api.action.SimpleActionResult;
public class NullPlaceResult extends SimpleActionResult { public class NullPlaceResult extends SimpleActionResult {
/**
* The target world is not a Multiverse world. So we just let the player go there without any checks
*/
public static final ActionResult NOT_MV_WORLD = new NullPlaceResult("NOT_MV_WORLD", true);
/** /**
* The target destination is null. * The target destination is null.
*/ */