Reworked movingcheck to make it easier later-on to modify/adapt.

Now instead of resetting the player after every minor illegal move, he
gets 2 moves in a row. If one of them is legal, we allow it. This is
to give stuck players the chance to escape themselves.

16 minor illegal moves in a row count now as one "normal" illegal
move.
This commit is contained in:
Evenprime 2011-02-20 10:01:53 +01:00
parent b31f476149
commit 2daeabc157
3 changed files with 72 additions and 60 deletions

View File

@ -3,5 +3,5 @@ name: NoCheatPlugin
author: Evenprime author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin
version: 0.5.1a version: 0.5.1b

View File

@ -1,5 +1,6 @@
package cc.co.evenprime.bukkit.nocheat; package cc.co.evenprime.bukkit.nocheat;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
@ -13,8 +14,12 @@ public class MovingCheck {
// Each entry represents the maximum gain in height per move event. // Each entry represents the maximum gain in height per move event.
private static double jumpingPhases[] = new double[]{ 0.501D, 0.34D, 0.26D, 0.17D, 0.09D, 0.02D, 0.00D, -0.07D, -0.15D, -0.22D, -0.29D, -0.36D, -0.43D, -0.50D }; private static double jumpingPhases[] = new double[]{ 0.501D, 0.34D, 0.26D, 0.17D, 0.09D, 0.02D, 0.00D, -0.07D, -0.15D, -0.22D, -0.29D, -0.36D, -0.43D, -0.50D };
private static final int HEAVY = 3;
private static final int NORMAL = 2;
private static final int MINOR = 1;
private static final int NONE = 0;
public enum BlockType { private enum BlockType {
SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN; SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN;
} }
@ -112,17 +117,20 @@ public class MovingCheck {
} }
public static void check(NoCheatPluginData data, PlayerMoveEvent event) { public static void check(NoCheatPluginData data, PlayerMoveEvent event) {
// Get the two locations of the event
Location from = event.getFrom();
Location to = event.getTo();
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.moving")) { if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.moving")) {
return; return;
} }
else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) { else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) {
return; return;
} }
// Get the two locations of the event
Location from = event.getFrom();
Location to = event.getTo();
int vl = NONE; // The violation level (none, minor, normal, heavy)
// First check the distance the player has moved horizontally // First check the distance the player has moved horizontally
// TODO: Make this check much more precise // TODO: Make this check much more precise
@ -132,13 +140,13 @@ public class MovingCheck {
// How far are we off? // How far are we off?
if(xDistance > NoCheatConfiguration.movingDistanceHigh || zDistance > NoCheatConfiguration.movingDistanceHigh) { if(xDistance > NoCheatConfiguration.movingDistanceHigh || zDistance > NoCheatConfiguration.movingDistanceHigh) {
heavyViolation(data, event); vl = vl > HEAVY ? vl : HEAVY;
} }
else if(xDistance > NoCheatConfiguration.movingDistanceMed || zDistance > NoCheatConfiguration.movingDistanceMed) { else if(xDistance > NoCheatConfiguration.movingDistanceMed || zDistance > NoCheatConfiguration.movingDistanceMed) {
normalViolation(data, event); vl = vl > NORMAL ? vl : NORMAL;
} }
else if(xDistance > NoCheatConfiguration.movingDistanceLow || zDistance > NoCheatConfiguration.movingDistanceLow) { else if(xDistance > NoCheatConfiguration.movingDistanceLow || zDistance > NoCheatConfiguration.movingDistanceLow) {
minorViolation(data, event); vl = vl > MINOR ? vl : MINOR;
} }
} }
@ -169,9 +177,9 @@ public class MovingCheck {
double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase];
if(offset > 2D) heavyViolation(data, event); if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY;
else if(offset > 0.6D) normalViolation(data, event); else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL;
else minorViolation(data, event); else vl = vl > MINOR ? vl : MINOR;
} }
} }
// player is starting to jump (or starting to fall down somewhere) // player is starting to jump (or starting to fall down somewhere)
@ -185,9 +193,9 @@ public class MovingCheck {
double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase];
if(offset > 2D) heavyViolation(data, event); if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY;
else if(offset > 0.6D) normalViolation(data, event); else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL;
else minorViolation(data, event); else vl = vl > MINOR ? vl : MINOR;
} }
else if(to.getY() <= from.getY()) { else if(to.getY() <= from.getY()) {
// Very special case if running over a cliff and then immediately jumping. // Very special case if running over a cliff and then immediately jumping.
@ -203,9 +211,9 @@ public class MovingCheck {
double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase];
if(offset > 2D) heavyViolation(data, event); if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY;
else if(offset > 0.6D) normalViolation(data, event); else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL;
else minorViolation(data, event); else vl = vl > MINOR ? vl : MINOR;
} }
else { else {
data.phase = 0; // He is on ground now, so reset the jump data.phase = 0; // He is on ground now, so reset the jump
@ -213,14 +221,14 @@ public class MovingCheck {
} }
// Player is moving through air (during jumping, falling) // Player is moving through air (during jumping, falling)
else { else {
// May also be at the very edge of a platform (I seem to not be able to reliably tell if that's the case // May also be at the very edge of a platform (I seem to not be able to reliably tell if that's the case)
if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) {
double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase];
if(offset > 2D) heavyViolation(data, event); if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY;
else if(offset > 0.6D) normalViolation(data, event); else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL;
else minorViolation(data, event); else vl = vl > MINOR ? vl : MINOR;
} }
else { else {
data.phase++; // Enter next phase of the flight data.phase++; // Enter next phase of the flight
@ -234,73 +242,79 @@ public class MovingCheck {
} }
} }
if(!event.isCancelled()) { // Treat the violation(s)
if(data.movingViolationsDirty) { switch(vl) {
combineViolationCount(data); case MINOR:
} minorViolation(data, event);
data.movingSetBackPoint = null; break;
case NORMAL:
normalViolation(data, event);
break;
case HEAVY:
heavyViolation(data, event);
break;
default:
legitimateMove(data, event);
} }
} }
private static void minorViolation(NoCheatPluginData data, PlayerMoveEvent event) { protected static void minorViolation(NoCheatPluginData data, PlayerMoveEvent event) {
data.movingViolations[0]++;
data.movingViolationsDirty = true; if(data.minorViolationsInARow == 0) {
if(data.movingViolations[0] == 0) {
// Store the source location for later use // Store the source location for later use
data.movingSetBackPoint = event.getFrom().clone(); data.movingSetBackPoint = event.getFrom().clone();
System.out.println("RESET point recorded: "+data.movingSetBackPoint);
} }
if(data.movingViolations[0] > 2) {
data.minorViolationsInARow++;
if(data.minorViolationsInARow % 16 == 0) {
normalViolation(data, event);
}
else if(data.minorViolationsInARow % 2 == 0) {
// now we need it // now we need it
resetPlayer(data, event); resetPlayer(data, event);
NoCheatPlugin.log.info("NoCheatPlugin: Moving: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); NoCheatPlugin.log.info("NoCheatPlugin: Moving: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()));
} }
} }
private static void normalViolation(NoCheatPluginData data, PlayerMoveEvent event) { protected static void normalViolation(NoCheatPluginData data, PlayerMoveEvent event) {
data.movingViolations[1]++;
data.movingViolationsDirty = true;
resetPlayer(data, event); resetPlayer(data, event);
// Log the violation
NoCheatPlugin.log.warning("NoCheatPlugin: Moving: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); NoCheatPlugin.log.warning("NoCheatPlugin: Moving: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()));
} }
private static void heavyViolation(NoCheatPluginData data, PlayerMoveEvent event) { protected static void heavyViolation(NoCheatPluginData data, PlayerMoveEvent event) {
data.movingViolations[2]++;
data.movingViolationsDirty = true;
resetPlayer(data, event); resetPlayer(data, event);
// Log the violation // Log the violation
NoCheatPlugin.log.severe("NoCheatPlugin: Moving: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); NoCheatPlugin.log.severe("NoCheatPlugin: Moving: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ()));
} }
private static void combineViolationCount(NoCheatPluginData data) { protected static void legitimateMove(NoCheatPluginData data, PlayerMoveEvent event) {
data.minorViolationsInARow = 0;
data.movingViolationsTotal[0] += data.movingViolations[0]; data.movingSetBackPoint = null;
data.movingViolationsTotal[1] += data.movingViolations[1];
data.movingViolationsTotal[2] += data.movingViolations[2];
data.movingViolations[0] = 0;
data.movingViolations[1] = 0;
data.movingViolations[2] = 0;
data.movingViolationsDirty = false;
} }
/**
* Cancel the event and return the player to a stored location or if that is not available,
* the the previous location.
* @param data
* @param event
*/
private static void resetPlayer(NoCheatPluginData data, PlayerMoveEvent event) { private static void resetPlayer(NoCheatPluginData data, PlayerMoveEvent event) {
event.setCancelled(true); event.setCancelled(true);
if(data.phase > 7) {
data.phase = 7;
}
if(data.movingSetBackPoint != null) { if(data.movingSetBackPoint != null) {
event.getPlayer().teleportTo(data.movingSetBackPoint); event.getPlayer().teleportTo(data.movingSetBackPoint);
data.movingSetBackPoint = null;
} }
else else
event.getPlayer().teleportTo(event.getFrom()); event.getPlayer().teleportTo(event.getFrom());
combineViolationCount(data);
} }

View File

@ -33,9 +33,7 @@ public class NoCheatPluginPlayerListener extends PlayerListener {
int eventsSinceLastSpeedHackCheck = 0; // used to identify speedhacks int eventsSinceLastSpeedHackCheck = 0; // used to identify speedhacks
int ignoreNextXEvents = 0; int ignoreNextXEvents = 0;
int movingViolations[] = {0,0,0}; int minorViolationsInARow = 0;
int movingViolationsTotal[] = {0,0,0};
boolean movingViolationsDirty = false;
Location movingSetBackPoint = null; Location movingSetBackPoint = null;
private NoCheatPluginData() { } private NoCheatPluginData() { }