From e89df1d7ea563246822eb47f0eb45b640d66c55c Mon Sep 17 00:00:00 2001 From: The456 Date: Fri, 11 Aug 2023 04:27:10 +0100 Subject: [PATCH] add changeworld listener (#16) * add changeworld listener * simplify logic, add notification for run exit on death remove portals from canceling run, ensure gamemode is only changed in certain teleport events make it more explicit that IslandEnterEvent checks source world before changing gamemode non-parkour -> parkour: PlayerChangedWorldEvent set gm non-parkour -> non-parkour: none parkour -> parkour: same island: PlayerTeleportEvent set gm if not running between islands: IslandEnterEvent set gm parkour -> non-parkour: none --------- Co-authored-by: tastybento --- .../listeners/CourseRunnerListener.java | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java b/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java index 8f3b3ad..e7e126b 100644 --- a/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java +++ b/src/main/java/world/bentobox/parkour/listeners/CourseRunnerListener.java @@ -17,6 +17,7 @@ import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerQuitEvent; @@ -73,10 +74,40 @@ public void onVisitorArrive(IslandEnterEvent e) { } else if (!parkourRunManager.timers().containsKey(e.getPlayerUUID())) { user.notify("parkour.to-start"); } - if (island.getFlag(addon.PARKOUR_CREATIVE) <= island.getRank(user)) { - user.setGameMode(GameMode.CREATIVE); - } else { - user.setGameMode(GameMode.SURVIVAL); + + // the location that the player teleports from + Location fromLocation = user.getLocation(); + + if (addon.inWorld(fromLocation)) { + // if the player is staying in a parkour managed world they can have their gamemode changed + // this occurs when their island changes, so wont risk affecting players that are currently running + // since exit would trigger first + // cross (unmanaged) world teleportation is handled in onPlayerChangeWorld + + if (island.getFlag(addon.PARKOUR_CREATIVE) <= island.getRank(user)) { + user.setGameMode(GameMode.CREATIVE); + } else { + user.setGameMode(GameMode.SURVIVAL); + } + } + } + + @EventHandler + public void onPlayerChangeWorld(PlayerChangedWorldEvent event) { + User user = User.getInstance(event.getPlayer()); + Location currentLocation = user.getLocation(); + boolean fromParkour = addon.inWorld(event.getFrom()); + boolean toParkour = addon.inWorld(currentLocation); + + if (toParkour && !fromParkour) { + // switching from non-parkour world to parkour world + addon.getIslandsManager().getIslandAt(currentLocation).ifPresent(island -> { + if (island.getFlag(addon.PARKOUR_CREATIVE) <= island.getRank(user)) { + user.setGameMode(GameMode.CREATIVE); + } else { + user.setGameMode(GameMode.SURVIVAL); + } + }); } } @@ -93,6 +124,10 @@ public void onVisitorLeave(IslandExitEvent e) { @EventHandler(priority = EventPriority.NORMAL) public void onPlayerDeath(PlayerDeathEvent e) { // Game over + User user = User.getInstance(e.getEntity().getUniqueId()); + if (parkourRunManager.checkpoints().containsKey(e.getEntity().getUniqueId()) && user.isOnline()) { + user.notify("parkour.session-ended"); + } parkourRunManager.clear(e.getEntity().getUniqueId()); } @@ -125,8 +160,8 @@ public void onVisitorFall(EntityDamageEvent e) { @EventHandler public void onTeleport(PlayerTeleportEvent e) { boolean shouldStopRun = switch (e.getCause()) { - case ENDER_PEARL, CHORUS_FRUIT, DISMOUNT, EXIT_BED -> false; - case COMMAND, PLUGIN, NETHER_PORTAL, END_PORTAL, SPECTATE, END_GATEWAY, UNKNOWN -> true; + case ENDER_PEARL, CHORUS_FRUIT, DISMOUNT, EXIT_BED, NETHER_PORTAL, END_PORTAL -> false; + case COMMAND, PLUGIN, SPECTATE, END_GATEWAY, UNKNOWN -> true; }; UUID playerUUID = e.getPlayer().getUniqueId(); if (!parkourRunManager.currentlyTeleporting().contains(playerUUID) && shouldStopRun && parkourRunManager.timers().containsKey(playerUUID)) { @@ -146,7 +181,11 @@ public void onTeleport(PlayerTeleportEvent e) { Optional fromIsland = addon.getIslands().getIslandAt(e.getFrom()); Optional toIsland = addon.getIslands().getIslandAt(e.getTo()); - if (fromIsland.isPresent() && toIsland.isPresent() && fromIsland.get().equals(toIsland.get())) { + boolean shouldAlterGamemode = switch (e.getCause()) { + case COMMAND, PLUGIN, UNKNOWN -> true; + default -> false; + }; + if (shouldAlterGamemode && fromIsland.isPresent() && toIsland.isPresent() && fromIsland.get().equals(toIsland.get())) { // same island teleport Island island = fromIsland.get(); User user = User.getInstance(e.getPlayer());