From a2c9242adc047bca568534875741c6775d2aebaa Mon Sep 17 00:00:00 2001 From: RoboMWM Date: Fri, 30 Sep 2016 12:56:23 -0700 Subject: [PATCH] Finished implementing new portal trap improvements #13 Probably will need some testing though --- .../CheckForPortalTrapTask.java | 24 +++---- .../GriefPrevention/GriefPrevention.java | 64 +++++++++++++++++-- .../GriefPrevention/PlayerData.java | 4 +- .../GriefPrevention/PlayerEventHandler.java | 25 ++------ 4 files changed, 74 insertions(+), 43 deletions(-) diff --git a/src/me/ryanhamshire/GriefPrevention/CheckForPortalTrapTask.java b/src/me/ryanhamshire/GriefPrevention/CheckForPortalTrapTask.java index 5579d6d..71d85c4 100644 --- a/src/me/ryanhamshire/GriefPrevention/CheckForPortalTrapTask.java +++ b/src/me/ryanhamshire/GriefPrevention/CheckForPortalTrapTask.java @@ -30,36 +30,28 @@ import org.bukkit.scheduler.BukkitRunnable; //if that happens, we detect the problem and send them back through the portal. class CheckForPortalTrapTask extends BukkitRunnable { + GriefPrevention instance; //player who recently teleported via nether portal private Player player; //where to send the player back to if he hasn't left the portal frame - private Location returnLocation; + //private Location returnLocation; - public CheckForPortalTrapTask(Player player, Location location) + public CheckForPortalTrapTask(Player player, GriefPrevention plugin) { this.player = player; - this.returnLocation = location; + this.instance = plugin; } @Override public void run() { //if player has logged out, do nothing - if(!player.isOnline()) return; - - Block playerBlock = this.player.getLocation().getBlock(); - //if still standing in a portal frame, teleport him back through - if(GriefPrevention.instance.isPlayerTrappedInPortal(playerBlock)) + if(!player.isOnline()) { - GriefPrevention.instance.rescuePlayerTrappedInPortal(player, returnLocation); + instance.portalReturnTaskMap.remove(player.getUniqueId()); + return; } - - //otherwise, note that he 'escaped' the portal frame - else - { - PlayerEventHandler.portalReturnMap.remove(player.getUniqueId()); - PlayerEventHandler.portalReturnTaskMap.remove(player.getUniqueId()); - } + instance.rescuePlayerTrappedInPortal(player); } } diff --git a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java index 006795c..4f724a2 100644 --- a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java +++ b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java @@ -63,6 +63,8 @@ import org.bukkit.inventory.PlayerInventory; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.BlockIterator; public class GriefPrevention extends JavaPlugin @@ -2728,6 +2730,21 @@ public class GriefPrevention extends JavaPlugin return true; } + + else if(cmd.getName().equalsIgnoreCase("undorescue")) + { + Location location = dataStore.getPlayerData(player.getUniqueId()).portalTrappedLocation; + if (location == null) + { + //TODO: tell player they were not initially rescued (if necessary?) + return true; + } + //Start a new rescue task in case the player was indeed trapped, but dumbly sent the command anyway + startRescueTask(player, player.getLocation()); + player.teleport(location); + dataStore.getPlayerData(player.getUniqueId()).portalTrappedLocation = null; + return true; + } return false; } @@ -3613,11 +3630,50 @@ public class GriefPrevention extends JavaPlugin || block.getRelative(BlockFace.SOUTH).getType() == Material.PORTAL; } - public Location rescuePlayerTrappedInPortal(Player player, Location returnLocation) + public void rescuePlayerTrappedInPortal(final Player player) { - Location oldLocation = player.getLocation(); - player.teleport(returnLocation); + final Location oldLocation = player.getLocation(); + if (!isPlayerTrappedInPortal(oldLocation.getBlock())) + { + //Note that he 'escaped' the portal frame + instance.portalReturnMap.remove(player.getUniqueId()); + instance.portalReturnTaskMap.remove(player.getUniqueId()); + return; + } + + Location rescueLocation = portalReturnMap.get(player.getUniqueId()); + + if (rescueLocation == null) + return; + + //Temporarily store the old location, in case the player wishes to undo the rescue + dataStore.getPlayerData(player.getUniqueId()).portalTrappedLocation = oldLocation; + + player.teleport(rescueLocation); sendMessage(player, TextMode.Info, Messages.RescuedFromPortalTrap); - return oldLocation; + portalReturnMap.remove(player.getUniqueId()); + + new BukkitRunnable() + { + public void run() + { + if (oldLocation == dataStore.getPlayerData(player.getUniqueId()).portalTrappedLocation) + dataStore.getPlayerData(player.getUniqueId()).portalTrappedLocation = null; + } + }.runTaskLater(this, 600L); + } + + //remember where players teleport from (via portals) in case they're trapped at the destination + ConcurrentHashMap portalReturnMap = new ConcurrentHashMap(); + ConcurrentHashMap portalReturnTaskMap = new ConcurrentHashMap(); + public void startRescueTask(Player player, Location rescueLocation) + { + BukkitTask task = new CheckForPortalTrapTask(player, this).runTaskLater(GriefPrevention.instance, 600L); + portalReturnMap.put(player.getUniqueId(), rescueLocation); + + //Cancel existing rescue task + if (portalReturnTaskMap.containsKey(player.getUniqueId())) + portalReturnTaskMap.get(player.getUniqueId()).cancel(); + portalReturnTaskMap.put(player.getUniqueId(), task); } } diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerData.java b/src/me/ryanhamshire/GriefPrevention/PlayerData.java index 67fa154..a314a5b 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerData.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerData.java @@ -131,8 +131,8 @@ public class PlayerData //this is an anti-bot strategy. Location noChatLocation = null; - //last sign message, to prevent sign spam - String lastSignMessage = null; + //last rescue location, if player was recently rescued (to undo if rescue was unnecessary) + Location portalTrappedLocation = null; //ignore list //true means invisible (admin-forced ignore), false means player-created ignore diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java index 72c821d..6273bf1 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java @@ -77,6 +77,7 @@ import org.bukkit.util.BlockIterator; class PlayerEventHandler implements Listener { private DataStore dataStore; + private GriefPrevention instance; //list of temporarily banned ip's private ArrayList tempBannedIps = new ArrayList(); @@ -100,6 +101,7 @@ class PlayerEventHandler implements Listener PlayerEventHandler(DataStore dataStore, GriefPrevention plugin) { this.dataStore = dataStore; + this.instance = plugin; } //when a player chats, monitor for spam @@ -761,16 +763,7 @@ class PlayerEventHandler implements Listener new IgnoreLoaderThread(playerID, playerData.ignoredPlayers).start(); //is he possibly stuck in a portal frame? - Location returnLocation = PlayerEventHandler.portalReturnMap.get(player.getUniqueId()); - if(returnLocation != null) - { - PlayerEventHandler.portalReturnMap.remove(player.getUniqueId()); - Block playerBlock = player.getLocation().getBlock(); - if(GriefPrevention.instance.isPlayerTrappedInPortal(playerBlock)) - { - GriefPrevention.instance.rescuePlayerTrappedInPortal(player, returnLocation); - } - } + instance.rescuePlayerTrappedInPortal(player); //if we're holding a logout message for this player, don't send that or this event's join message if(GriefPrevention.instance.config_spam_logoutMessageDelaySeconds > 0) @@ -974,10 +967,6 @@ class PlayerEventHandler implements Listener } } - //remember where players teleport from (via portals) in case they're trapped at the destination - static ConcurrentHashMap portalReturnMap = new ConcurrentHashMap(); - static ConcurrentHashMap portalReturnTaskMap = new ConcurrentHashMap(); - //when a player teleports via a portal @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) void onPlayerPortal(PlayerPortalEvent event) @@ -993,13 +982,7 @@ class PlayerEventHandler implements Listener if(event.getCause() == TeleportCause.NETHER_PORTAL) { //FEATURE: when players get trapped in a nether portal, send them back through to the other side - BukkitTask task = new CheckForPortalTrapTask(player, event.getFrom()).runTaskLater(GriefPrevention.instance, 600L); - portalReturnMap.put(player.getUniqueId(), event.getFrom()); - - //Cancel existing rescue task - if (portalReturnTaskMap.containsKey(player.getUniqueId())) - portalReturnTaskMap.get(player.getUniqueId()).cancel(); - portalReturnTaskMap.put(player.getUniqueId(), task); + instance.startRescueTask(player, event.getFrom()); //FEATURE: if the player teleporting doesn't have permission to build a nether portal and none already exists at the destination, cancel the teleportation if(GriefPrevention.instance.config_claims_portalsRequirePermission)