From 272f2d410cdfad5eb491275081f4bb1dd2d93288 Mon Sep 17 00:00:00 2001 From: Evenprime Date: Sun, 3 Jul 2011 13:06:17 +0200 Subject: [PATCH] Fixed teleports (for real this time) by completely rewriting how they are handled. --- plugin.yml | 2 +- .../bukkit/nocheat/checks/MovingCheck.java | 65 ++++++++++--------- .../bukkit/nocheat/data/MovingData.java | 9 ++- .../listeners/MovingPlayerMonitor.java | 12 +--- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/plugin.yml b/plugin.yml index 7872bdaa..f092e653 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,7 +3,7 @@ name: NoCheat author: Evenprime main: cc.co.evenprime.bukkit.nocheat.NoCheat -version: 1.07 +version: 1.07a softdepend: [ Permissions, CraftIRC ] diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java index 266f094c..abd52316 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java @@ -1,3 +1,4 @@ + package cc.co.evenprime.bukkit.nocheat.checks; import java.util.Locale; @@ -102,7 +103,7 @@ public class MovingCheck extends Check { // Get the player-specific data final MovingData data = MovingData.get(player); - + // Get the two locations of the event final Location to = event.getTo(); @@ -117,9 +118,6 @@ public class MovingCheck extends Check { return; } - if(to.distanceSquared(data.lastLocation) < to.distanceSquared(from)) { - from = data.lastLocation; - } /**** Horizontal movement check START ****/ // First check the distance the player has moved horizontally @@ -386,25 +384,31 @@ public class MovingCheck extends Check { */ private boolean shouldBeIgnored(final Player player, final MovingData data, final Location from, final Location to) { - // First the simple yes/no checks - if(data.insideVehicle || player.isInsideVehicle()) { - return true; - } - - if(!from.getWorld().equals(data.lastLocation.getWorld())) { - return true; - } - - if(data.teleportTo != null && from.getX() == data.teleportTo.getX() && from.getY() == data.teleportTo.getY() && from.getZ() == data.teleportTo.getZ()) { - return true; - } + // Now it gets complicated: (a friendly reminder to myself why this actually works in CB 950+) - final double x = from.getX(); - final double y = from.getY(); - final double z = from.getZ(); - - // Player didn't move at all - if(x == to.getX() && z == to.getZ() && y == to.getY() ) { + // data.teleportTo gets a location assigned if a teleport event is successfully executed. + // But there is a delay between the serverside execution of the teleport (instantly) and + // the execution on the client side (may take an arbitrary time). During that time, the + // client may send new move events relative to his old location. These events get treated + // by bukkit as PLAYER_MOVE events, despite the server not accepting them (the players + // serverside location won't get updated). Therefore comparing the teleport destination + // with the servers location of the player (which is almost the same as the "from" location + // in the move event) tells us if the server is still waiting for the clientside teleporting + // to be executed. We are only interested in client's move events after it executed the + // teleport, therefore just ignore all events before that. + if(data.teleportTo != null && data.teleportTo.distanceSquared(from) < 0.01D) { + return true; + } + else { + data.teleportTo = null; + } + // Dead or in vehicles -> I don't care + if(player.isDead() || data.insideVehicle || player.isInsideVehicle()) { + return true; + } + // If the player moved between worlds between events, don't check (wouldn't make sense + // to check coordinates between different worlds...) + if(!from.getWorld().equals(data.lastLocation)) { return true; } @@ -453,16 +457,18 @@ public class MovingCheck extends Check { MovingData data = MovingData.get(event.getPlayer()); - // We can enforce a teleport, if that flag is explicitly set - if(event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportTo)) { + // We can enforce a teleport, if that flag is explicitly set (but I'd rather have other plugins + // not arbitrarily cancel teleport events in the first place... + if(data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) { event.setCancelled(false); + data.teleportInitializedByMe = null; } if(!event.isCancelled()) { data.jumpPhase = 0; data.teleportTo = event.getTo().clone(); - data.lastLocation = event.getTo().clone(); data.setBackPoint = event.getTo().clone(); + //data.lastLocation = event.getTo().clone(); } } @@ -471,8 +477,8 @@ public class MovingCheck extends Check { * @param event */ public void respawned(PlayerRespawnEvent event) { - MovingData data = MovingData.get(event.getPlayer()); - data.setBackPoint = event.getRespawnLocation().clone(); + //MovingData data = MovingData.get(event.getPlayer()); + //data.setBackPoint = event.getRespawnLocation().clone(); } /** @@ -536,9 +542,9 @@ public class MovingCheck extends Check { data.setBackPoint.setY(y); // Remember the location we send the player to, to identify teleports that were started by us - data.teleportTo = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), event.getTo().getYaw(), event.getTo().getPitch()); + data.teleportInitializedByMe = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), event.getTo().getYaw(), event.getTo().getPitch()); - event.setTo(data.teleportTo); + event.setTo(data.teleportInitializedByMe); cancelled = true; // just prevent us from treating more than one "cancel" action, which would make no sense } @@ -739,7 +745,6 @@ public class MovingCheck extends Check { pm.registerEvent(Event.Type.PLAYER_MOVE, new MovingPlayerListener(this), Priority.Lowest, plugin); pm.registerEvent(Event.Type.PLAYER_INTERACT, movingPlayerMonitor, Priority.Monitor, plugin); pm.registerEvent(Event.Type.PLAYER_MOVE, movingPlayerMonitor, Priority.Monitor, plugin); - pm.registerEvent(Event.Type.PLAYER_RESPAWN, movingPlayerMonitor, Priority.Monitor, plugin); pm.registerEvent(Event.Type.ENTITY_DAMAGE, new MovingEntityListener(this), Priority.Monitor, plugin); pm.registerEvent(Event.Type.PLAYER_TELEPORT, new MovingPlayerMonitor(this), Priority.Monitor, plugin); } diff --git a/src/cc/co/evenprime/bukkit/nocheat/data/MovingData.java b/src/cc/co/evenprime/bukkit/nocheat/data/MovingData.java index c01ebc16..9dc27e2e 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/data/MovingData.java +++ b/src/cc/co/evenprime/bukkit/nocheat/data/MovingData.java @@ -6,6 +6,7 @@ import net.minecraft.server.Block; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.entity.Player; import cc.co.evenprime.bukkit.nocheat.NoCheatData; @@ -31,9 +32,11 @@ public class MovingData { public boolean insideVehicle = false; - // WORKAROUND for changed PLAYER_MOVE logic + // Use to determine if an move event should be handled public Location teleportTo = null; - public Location lastLocation = null; + + // Use to track the world the player is in + public World lastLocation = null; public Location teleportInitializedByMe = null; @@ -81,7 +84,7 @@ public class MovingData { if(data.moving == null) { data.moving = new MovingData(); - data.moving.lastLocation = p.getLocation(); + data.moving.lastLocation = p.getLocation().getWorld(); } return data.moving; diff --git a/src/cc/co/evenprime/bukkit/nocheat/listeners/MovingPlayerMonitor.java b/src/cc/co/evenprime/bukkit/nocheat/listeners/MovingPlayerMonitor.java index 62ec09f5..49a0d36a 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/listeners/MovingPlayerMonitor.java +++ b/src/cc/co/evenprime/bukkit/nocheat/listeners/MovingPlayerMonitor.java @@ -3,7 +3,6 @@ package cc.co.evenprime.bukkit.nocheat.listeners; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck; @@ -22,16 +21,11 @@ public class MovingPlayerMonitor extends PlayerListener { this.check = check; } - @Override - public void onPlayerRespawn(PlayerRespawnEvent event) { - check.respawned(event); - } - @Override public void onPlayerTeleport(PlayerTeleportEvent event) { check.teleported(event); } - + @Override public void onPlayerInteract(PlayerInteractEvent event) { check.updateVelocity(event.getPlayer().getVelocity(), MovingData.get(event.getPlayer())); @@ -41,8 +35,8 @@ public class MovingPlayerMonitor extends PlayerListener { public void onPlayerMove(PlayerMoveEvent event) { if(!event.isCancelled()) { MovingData data = MovingData.get(event.getPlayer()); - data.lastLocation = event.getTo(); - if(event.getPlayer().isInsideVehicle()) { + data.lastLocation = event.getPlayer().getLocation().getWorld(); + if( event.getPlayer().isInsideVehicle()) { data.setBackPoint = event.getTo(); } else {