Fixed teleports (for real this time) by completely rewriting how they

are handled.
This commit is contained in:
Evenprime 2011-07-03 13:06:17 +02:00
parent c3b6148245
commit 272f2d410c
4 changed files with 45 additions and 43 deletions

View File

@ -3,7 +3,7 @@ name: NoCheat
author: Evenprime author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheat main: cc.co.evenprime.bukkit.nocheat.NoCheat
version: 1.07 version: 1.07a
softdepend: [ Permissions, CraftIRC ] softdepend: [ Permissions, CraftIRC ]

View File

@ -1,3 +1,4 @@
package cc.co.evenprime.bukkit.nocheat.checks; package cc.co.evenprime.bukkit.nocheat.checks;
import java.util.Locale; import java.util.Locale;
@ -102,7 +103,7 @@ public class MovingCheck extends Check {
// Get the player-specific data // Get the player-specific data
final MovingData data = MovingData.get(player); final MovingData data = MovingData.get(player);
// Get the two locations of the event // Get the two locations of the event
final Location to = event.getTo(); final Location to = event.getTo();
@ -117,9 +118,6 @@ public class MovingCheck extends Check {
return; return;
} }
if(to.distanceSquared(data.lastLocation) < to.distanceSquared(from)) {
from = data.lastLocation;
}
/**** Horizontal movement check START ****/ /**** Horizontal movement check START ****/
// First check the distance the player has moved horizontally // 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) { private boolean shouldBeIgnored(final Player player, final MovingData data, final Location from, final Location to) {
// First the simple yes/no checks // Now it gets complicated: (a friendly reminder to myself why this actually works in CB 950+)
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;
}
final double x = from.getX(); // data.teleportTo gets a location assigned if a teleport event is successfully executed.
final double y = from.getY(); // But there is a delay between the serverside execution of the teleport (instantly) and
final double z = from.getZ(); // 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
// Player didn't move at all // by bukkit as PLAYER_MOVE events, despite the server not accepting them (the players
if(x == to.getX() && z == to.getZ() && y == to.getY() ) { // 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; return true;
} }
@ -453,16 +457,18 @@ public class MovingCheck extends Check {
MovingData data = MovingData.get(event.getPlayer()); MovingData data = MovingData.get(event.getPlayer());
// We can enforce a teleport, if that flag is explicitly set // We can enforce a teleport, if that flag is explicitly set (but I'd rather have other plugins
if(event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportTo)) { // not arbitrarily cancel teleport events in the first place...
if(data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) {
event.setCancelled(false); event.setCancelled(false);
data.teleportInitializedByMe = null;
} }
if(!event.isCancelled()) { if(!event.isCancelled()) {
data.jumpPhase = 0; data.jumpPhase = 0;
data.teleportTo = event.getTo().clone(); data.teleportTo = event.getTo().clone();
data.lastLocation = event.getTo().clone();
data.setBackPoint = event.getTo().clone(); data.setBackPoint = event.getTo().clone();
//data.lastLocation = event.getTo().clone();
} }
} }
@ -471,8 +477,8 @@ public class MovingCheck extends Check {
* @param event * @param event
*/ */
public void respawned(PlayerRespawnEvent event) { public void respawned(PlayerRespawnEvent event) {
MovingData data = MovingData.get(event.getPlayer()); //MovingData data = MovingData.get(event.getPlayer());
data.setBackPoint = event.getRespawnLocation().clone(); //data.setBackPoint = event.getRespawnLocation().clone();
} }
/** /**
@ -536,9 +542,9 @@ public class MovingCheck extends Check {
data.setBackPoint.setY(y); data.setBackPoint.setY(y);
// Remember the location we send the player to, to identify teleports that were started by us // 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 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_MOVE, new MovingPlayerListener(this), Priority.Lowest, plugin);
pm.registerEvent(Event.Type.PLAYER_INTERACT, movingPlayerMonitor, Priority.Monitor, 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_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.ENTITY_DAMAGE, new MovingEntityListener(this), Priority.Monitor, plugin);
pm.registerEvent(Event.Type.PLAYER_TELEPORT, new MovingPlayerMonitor(this), Priority.Monitor, plugin); pm.registerEvent(Event.Type.PLAYER_TELEPORT, new MovingPlayerMonitor(this), Priority.Monitor, plugin);
} }

View File

@ -6,6 +6,7 @@ import net.minecraft.server.Block;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheatData; import cc.co.evenprime.bukkit.nocheat.NoCheatData;
@ -31,9 +32,11 @@ public class MovingData {
public boolean insideVehicle = false; 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 teleportTo = null;
public Location lastLocation = null;
// Use to track the world the player is in
public World lastLocation = null;
public Location teleportInitializedByMe = null; public Location teleportInitializedByMe = null;
@ -81,7 +84,7 @@ public class MovingData {
if(data.moving == null) { if(data.moving == null) {
data.moving = new MovingData(); data.moving = new MovingData();
data.moving.lastLocation = p.getLocation(); data.moving.lastLocation = p.getLocation().getWorld();
} }
return data.moving; return data.moving;

View File

@ -3,7 +3,6 @@ package cc.co.evenprime.bukkit.nocheat.listeners;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerListener;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck; import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
@ -22,16 +21,11 @@ public class MovingPlayerMonitor extends PlayerListener {
this.check = check; this.check = check;
} }
@Override
public void onPlayerRespawn(PlayerRespawnEvent event) {
check.respawned(event);
}
@Override @Override
public void onPlayerTeleport(PlayerTeleportEvent event) { public void onPlayerTeleport(PlayerTeleportEvent event) {
check.teleported(event); check.teleported(event);
} }
@Override @Override
public void onPlayerInteract(PlayerInteractEvent event) { public void onPlayerInteract(PlayerInteractEvent event) {
check.updateVelocity(event.getPlayer().getVelocity(), MovingData.get(event.getPlayer())); check.updateVelocity(event.getPlayer().getVelocity(), MovingData.get(event.getPlayer()));
@ -41,8 +35,8 @@ public class MovingPlayerMonitor extends PlayerListener {
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if(!event.isCancelled()) { if(!event.isCancelled()) {
MovingData data = MovingData.get(event.getPlayer()); MovingData data = MovingData.get(event.getPlayer());
data.lastLocation = event.getTo(); data.lastLocation = event.getPlayer().getLocation().getWorld();
if(event.getPlayer().isInsideVehicle()) { if( event.getPlayer().isInsideVehicle()) {
data.setBackPoint = event.getTo(); data.setBackPoint = event.getTo();
} }
else { else {