From e14007380f7baa68a796008657bc64de4e9e39da Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Tue, 12 Oct 2021 02:47:09 +0200 Subject: [PATCH] Adds proper checking and odd case catching before teleporting players through artificial end portals Adds a proper permission check to make sure players are allowed to teleport through the artificial portal Adds a teleportation back to the entrance as the teleportation event cannot be properly cancelled Adds a proper class for storing info about the teleportation --- .../container/FromTheEndTeleportation.java | 43 +++++++++++++++++ .../listener/PlayerEventListener.java | 47 +------------------ .../listener/PortalEventListener.java | 27 ++++++----- .../stargate/utility/PermissionHelper.java | 44 +++++++++++++++++ 4 files changed, 103 insertions(+), 58 deletions(-) create mode 100644 src/main/java/net/knarcraft/stargate/container/FromTheEndTeleportation.java diff --git a/src/main/java/net/knarcraft/stargate/container/FromTheEndTeleportation.java b/src/main/java/net/knarcraft/stargate/container/FromTheEndTeleportation.java new file mode 100644 index 0000000..364dfff --- /dev/null +++ b/src/main/java/net/knarcraft/stargate/container/FromTheEndTeleportation.java @@ -0,0 +1,43 @@ +package net.knarcraft.stargate.container; + +import net.knarcraft.stargate.portal.Portal; +import org.bukkit.entity.Player; + +/** + * This class represents a player teleporting from the end to the over-world using an artificial end portal + */ +public class FromTheEndTeleportation { + + private final Player teleportingPlayer; + private final Portal exitPortal; + + /** + * Instantiates a new teleportation from the end + * + * @param teleportingPlayer

The teleporting player

+ * @param exitPortal

The portal to exit from

+ */ + public FromTheEndTeleportation(Player teleportingPlayer, Portal exitPortal) { + this.teleportingPlayer = teleportingPlayer; + this.exitPortal = exitPortal; + } + + /** + * Gets the teleporting player + * + * @return

The teleporting player

+ */ + public Player getPlayer() { + return this.teleportingPlayer; + } + + /** + * Gets the portal to exit from + * + * @return

The portal to exit from

+ */ + public Portal getExit() { + return this.exitPortal; + } + +} diff --git a/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java index 2b1ebbb..8dcfbfc 100644 --- a/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/PlayerEventListener.java @@ -5,8 +5,6 @@ import net.knarcraft.stargate.container.BlockLocation; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalHandler; import net.knarcraft.stargate.utility.BungeeHelper; -import net.knarcraft.stargate.utility.EconomyHandler; -import net.knarcraft.stargate.utility.EconomyHelper; import net.knarcraft.stargate.utility.MaterialHelper; import net.knarcraft.stargate.utility.PermissionHelper; import org.bukkit.GameMode; @@ -127,7 +125,7 @@ public class PlayerEventListener implements Listener { Portal destination = entrancePortal.getDestination(player); //Decide if the anything stops the player from teleport - if (!playerCanTeleport(entrancePortal, destination, player, event)) { + if (PermissionHelper.playerCannotTeleport(entrancePortal, destination, player, event)) { return false; } @@ -322,47 +320,4 @@ public class PlayerEventListener implements Listener { return true; } - /** - * Decide of the player can teleport through a portal - * - * @param entrancePortal

The portal the player is entering from

- * @param destination

The destination of the portal the player is inside

- * @param player

The player wanting to teleport

- * @param event

The move event causing the teleportation

- * @return

True if the player can teleport. False otherwise

- */ - private boolean playerCanTeleport(Portal entrancePortal, Portal destination, Player player, PlayerMoveEvent event) { - // No portal or not open - if (entrancePortal == null || !entrancePortal.isOpen()) { - return false; - } - - // Not open for this player - if (!entrancePortal.isOpenFor(player)) { - Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); - entrancePortal.teleport(player, entrancePortal, event); - return false; - } - - //No destination - if (!entrancePortal.getOptions().isBungee() && destination == null) { - return false; - } - - //Player cannot access portal - if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destination)) { - Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); - entrancePortal.teleport(player, entrancePortal, event); - entrancePortal.close(false); - return false; - } - - //Player cannot pay for teleportation - int cost = EconomyHandler.getUseCost(player, entrancePortal, destination); - if (cost > 0) { - return EconomyHelper.payTeleportFee(entrancePortal, player, cost); - } - return true; - } - } diff --git a/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java b/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java index 29e86ba..2932fe1 100644 --- a/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java +++ b/src/main/java/net/knarcraft/stargate/listener/PortalEventListener.java @@ -1,8 +1,9 @@ package net.knarcraft.stargate.listener; -import net.knarcraft.stargate.container.TwoTuple; +import net.knarcraft.stargate.container.FromTheEndTeleportation; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalHandler; +import net.knarcraft.stargate.utility.PermissionHelper; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; @@ -23,7 +24,7 @@ import java.util.List; */ public class PortalEventListener implements Listener { - private static final List> playersFromTheEnd = new ArrayList<>(); + private static final List playersFromTheEnd = new ArrayList<>(); /** * Listen for and abort vanilla portal creation caused by stargate creation @@ -55,12 +56,18 @@ public class PortalEventListener implements Listener { World world = location.getWorld(); Entity entity = event.getEntity(); //Block normal portal teleportation if teleporting from a stargate - if (entity instanceof Player && location.getBlock().getType() == Material.END_PORTAL && world != null && + if (entity instanceof Player player && location.getBlock().getType() == Material.END_PORTAL && world != null && world.getEnvironment() == World.Environment.THE_END) { Portal portal = PortalHandler.getByAdjacentEntrance(location); - if (portal != null) { - playersFromTheEnd.add(new TwoTuple<>((Player) entity, portal.getDestination())); + + //Remove any old player teleportations in case weird things happen + playersFromTheEnd.removeIf((teleportation -> teleportation.getPlayer() == player)); + //Decide if the anything stops the player from teleporting + if (PermissionHelper.playerCannotTeleport(portal, portal.getDestination(), player, null)) { + //Teleport the player back to the portal they came in, just in case + playersFromTheEnd.add(new FromTheEndTeleportation(player, portal)); } + playersFromTheEnd.add(new FromTheEndTeleportation(player, portal.getDestination())); } } @@ -72,14 +79,10 @@ public class PortalEventListener implements Listener { @EventHandler public void onRespawn(PlayerRespawnEvent event) { Player respawningPlayer = event.getPlayer(); - playersFromTheEnd.forEach((tuple) -> { + playersFromTheEnd.forEach((teleportation) -> { //Check if player is actually teleporting from the end - if (tuple.getFirstValue() == respawningPlayer) { - Portal exitPortal = tuple.getSecondValue(); - //Need to make sure the player is allowed to exit from the portal - if (!exitPortal.isOpenFor(respawningPlayer)) { - return; - } + if (teleportation.getPlayer() == respawningPlayer) { + Portal exitPortal = teleportation.getExit(); //Overwrite respawn location to respawn in front of the portal event.setRespawnLocation(exitPortal.getExit(respawningPlayer, respawningPlayer.getLocation())); //Properly close the portal to prevent it from staying in a locked state until it times out diff --git a/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java b/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java index 588247a..3be876d 100644 --- a/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java +++ b/src/main/java/net/knarcraft/stargate/utility/PermissionHelper.java @@ -5,6 +5,7 @@ import net.knarcraft.stargate.event.StargateAccessEvent; import net.knarcraft.stargate.portal.Portal; import net.knarcraft.stargate.portal.PortalOption; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerMoveEvent; /** * Helper class for deciding which actions a player is allowed to perform @@ -368,4 +369,47 @@ public final class PermissionHelper { return portal.isOwner(player) && hasPermission(player, "stargate.destroy.personal"); } + /** + * Decide of the player can teleport through a portal + * + * @param entrancePortal

The portal the player is entering from

+ * @param destination

The destination of the portal the player is inside

+ * @param player

The player wanting to teleport

+ * @param event

The move event causing the teleportation

+ * @return

True if the player cannot teleport. False otherwise

+ */ + public static boolean playerCannotTeleport(Portal entrancePortal, Portal destination, Player player, PlayerMoveEvent event) { + // No portal or not open + if (entrancePortal == null || !entrancePortal.isOpen()) { + return true; + } + + // Not open for this player + if (!entrancePortal.isOpenFor(player)) { + Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); + entrancePortal.teleport(player, entrancePortal, event); + return true; + } + + //No destination + if (!entrancePortal.getOptions().isBungee() && destination == null) { + return true; + } + + //Player cannot access portal + if (PermissionHelper.cannotAccessPortal(player, entrancePortal, destination)) { + Stargate.sendErrorMessage(player, Stargate.getString("denyMsg")); + entrancePortal.teleport(player, entrancePortal, event); + entrancePortal.close(false); + return true; + } + + //Player cannot pay for teleportation + int cost = EconomyHandler.getUseCost(player, entrancePortal, destination); + if (cost > 0) { + return !EconomyHelper.payTeleportFee(entrancePortal, player, cost); + } + return false; + } + }