diff --git a/plugin.yml b/plugin.yml index 09dd2c68..91a77376 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,7 +3,7 @@ name: NoCheatPlugin author: Evenprime main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin -version: 0.6.4 +version: 0.6.4a commands: nocheat: diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java index 633787a3..5925bb2f 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java @@ -40,7 +40,7 @@ public class NoCheatConfiguration { public static String speedhackActionNormal = ""; public static String speedhackActionHeavy = ""; - public static int movingFreeMoves = 10; + public static int movingFreeMoves = 5; // How should moving violations be treated? public static String movingActionMinor = ""; @@ -109,7 +109,7 @@ public class NoCheatConfiguration { speedhackLimitMed = c.getInt("speedhack.limits.med", 45); speedhackLimitHigh = c.getInt("speedhack.limits.high", 60); - movingFreeMoves = c.getInt("moving.freemoves", 10); + movingFreeMoves = c.getInt("moving.freemoves", 5); movingActionMinor = c.getString("moving.action.low", "loglow reset"); movingActionNormal = c.getString("moving.action.med", "logmed reset"); @@ -121,7 +121,7 @@ public class NoCheatConfiguration { airbuildAction = c.getString("airbuild.action", "logmed deny"); - if(movingFreeMoves < 10) movingFreeMoves = 10; + if(movingFreeMoves < 5) movingFreeMoves = 5; } /** diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java index a8452d7d..6a2e148f 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java @@ -15,6 +15,7 @@ public class NoCheatData { */ public int movingJumpPhase = 0; // current jumpingPhase + public int movingLegitMovesInARow = 0; public int movingMinorViolationsInARow = 0; public int movingNormalViolationsInARow = 0; public int movingHeavyViolationsInARow = 0; diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java index c4ff8ffc..02d6e855 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java @@ -28,6 +28,9 @@ public class MovingCheck { public static double movingDistanceLow = 0.1D; public static double movingDistanceMed = 2.0D; public static double movingDistanceHigh = 5.0D; + + final static double magic = 0.30000001192092896D; + final static double magic2 = 0.69999998807907103D; // Block types that may be treated specially private enum BlockType { @@ -137,7 +140,7 @@ public class MovingCheck { // Get the two locations of the event Location from = event.getFrom(); Location to = event.getTo(); - + // First check the distance the player has moved horizontally // TODO: Make this check much more precise double xDistance = Math.abs(from.getX() - to.getX()); @@ -164,60 +167,77 @@ public class MovingCheck { // pre-calculate boundary values that are needed multiple times in the following checks // the array each contains [lowerX, higherX, Y, lowerZ, higherZ] - int fromValues[] = {floor_double(from.getX() - 0.3D), (int)Math.floor(from.getX() + 0.3D), from.getBlockY(), floor_double(from.getZ() - 0.3D),(int)Math.floor(from.getZ() + 0.3D) }; - int toValues[] = {floor_double(to.getX() - 0.3D), (int)Math.floor(to.getX() + 0.3D), to.getBlockY(), floor_double(to.getZ() - 0.3D), (int)Math.floor(to.getZ() + 0.3D) }; + int fromValues[] = {lowerBorder(from.getX()), upperBorder(from.getX()), from.getBlockY(), lowerBorder(from.getZ()),upperBorder(from.getZ()) }; + int toValues[] = {lowerBorder(to.getX()), upperBorder(to.getX()), to.getBlockY(), lowerBorder(to.getZ()), upperBorder(to.getZ()) }; // compare locations to the world to guess if the player is standing on the ground, a half-block or next to a ladder boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from); boolean onGroundTo = playerIsOnGround(from.getWorld(), toValues, to); + // Both locations seem to be on solid ground or at a ladder if(onGroundFrom && onGroundTo) { - // reset jumping - data.movingJumpPhase = 0; - // Check if the player isn't 'walking' up unrealistically far in one step // Finally found out why this can happen: - // If a player runs into a wall at an angle from above, the game tries to + // If a player runs into a wall, the game tries to // place him above the block he bumped into, by placing him 0.5 m above // the target block - if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { + if(!(to.getY() - from.getY() < jumpingPhases[0])) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; + double offset = (to.getY() - from.getY()) - jumpingPhases[0]; if(offset > 2D) vl = max(vl, Level.SEVERE); - else if(offset > 1D) vl = max(vl, Level.WARNING); + else if(offset > 0.5D) vl = max(vl, Level.WARNING); else vl = max(vl, Level.INFO); } + else + { + // reset jumping + data.movingJumpPhase = 0; + data.movingSetBackPoint = event.getTo().clone(); + } } // player is starting to jump (or starting to fall down somewhere) else if(onGroundFrom && !onGroundTo) { - // reset jumping - data.movingJumpPhase = 0; - // Check if player isn't jumping too high - if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { + if(!(to.getY() - from.getY() < jumpingPhases[0])) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; + double offset = (to.getY() - from.getY()) - jumpingPhases[0]; if(offset > 2D) vl = max(vl, Level.SEVERE); - else if(offset > 1D) vl = max(vl, Level.WARNING); + else if(offset > 0.5D) vl = max(vl, Level.WARNING); else vl = max(vl, Level.INFO); } - else if(to.getY() <= from.getY()) { - // Very special case if running over a cliff and then immediately jumping. - // Some sort of "air jump", MC allows it, so we have to do so too. + else { + // Setup next phase of the jump + data.movingJumpPhase = 1; + data.movingSetBackPoint = event.getFrom().clone(); } - else data.movingJumpPhase++; // Setup next phase of the jump } // player is probably landing somewhere else if(!onGroundFrom && onGroundTo) { // Check if player isn't landing to high (sounds weird, but has its use) - if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { + if(!(to.getY() - from.getY() < Math.max(jumpingPhases[data.movingJumpPhase], 0D))) { + double offset = (to.getY() - from.getY()) - Math.max(jumpingPhases[data.movingJumpPhase], 0D); + + if(offset > 2D) vl = max(vl, Level.SEVERE); + else if(offset > 0.5D) vl = max(vl, Level.WARNING); + else vl = max(vl, Level.INFO); + } + else { + data.movingJumpPhase = 0; // He is on ground now, so reset the jump + data.movingSetBackPoint = event.getTo().clone(); + } + } + // Player is moving through air (during jumping, falling) + else { + + if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) + { double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; if(offset > 2D) vl = max(vl, Level.SEVERE); @@ -225,23 +245,10 @@ public class MovingCheck { else vl = max(vl, Level.INFO); } else { - data.movingJumpPhase = 0; // He is on ground now, so reset the jump + data.movingJumpPhase++; // Enter next phase of the flight + // Setback point stays the same } } - // Player is moving through air (during jumping, falling) - 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) - if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { - - double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; - - if(offset > 2D) vl = max(vl, Level.SEVERE); - else if(offset > 1D) vl = max(vl, Level.WARNING); - else vl = max(vl, Level.INFO); - } - - data.movingJumpPhase++; // Enter next phase of the flight - } // do a security check on the jumping phase, such that we don't get // OutOfArrayBoundsExceptions at long air times (falling off high places) @@ -249,20 +256,19 @@ public class MovingCheck { data.movingJumpPhase = jumpingPhases.length - 1; } - if(vl == null) { + if(vl == null && (onGroundFrom || onGroundTo)) { legitimateMove(data, event); } - else { + else if(vl != null) { + + data.movingLegitMovesInARow = 0; + String actions = null; boolean log = true; - - // If it is the first violation, store the "from" location for potential later use - if(data.movingSetBackPoint == null) { - data.movingSetBackPoint = event.getFrom().clone(); - } - + // Find out with what actions to treat the violation(s) if(Level.INFO.equals(vl)) { + data.movingMinorViolationsInARow++; actions = NoCheatConfiguration.movingActionMinor; @@ -323,23 +329,29 @@ public class MovingCheck { protected static void legitimateMove(NoCheatData data, PlayerMoveEvent event) { - // Give some additional logs about now ending violations - if(data.movingHeavyViolationsInARow > 0) { - NoCheatPlugin.logAction(NoCheatConfiguration.movingActionHeavy, "Moving violation ended: "+event.getPlayer().getName() + " total Events: "+ data.movingHeavyViolationsInARow); - data.movingHeavyViolationsInARow = 0; - } - if(data.movingNormalViolationsInARow > 0) { - NoCheatPlugin.logAction(NoCheatConfiguration.movingActionNormal, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingNormalViolationsInARow); - data.movingNormalViolationsInARow = 0; - } - if(data.movingMinorViolationsInARow > NoCheatConfiguration.movingFreeMoves) { - NoCheatPlugin.logAction(NoCheatConfiguration.movingActionMinor, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingMinorViolationsInARow); + + data.movingLegitMovesInARow++; + + if(data.movingLegitMovesInARow > 40) { + + data.movingLegitMovesInARow = 0; + + // Give some additional logs about now ending violations + if(data.movingHeavyViolationsInARow > 0) { + NoCheatPlugin.logAction(NoCheatConfiguration.movingActionHeavy, "Moving violation ended: "+event.getPlayer().getName() + " total Events: "+ data.movingHeavyViolationsInARow); + data.movingHeavyViolationsInARow = 0; + } + if(data.movingNormalViolationsInARow > 0) { + NoCheatPlugin.logAction(NoCheatConfiguration.movingActionNormal, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingNormalViolationsInARow); + data.movingNormalViolationsInARow = 0; + } + if(data.movingMinorViolationsInARow > NoCheatConfiguration.movingFreeMoves) { + NoCheatPlugin.logAction(NoCheatConfiguration.movingActionMinor, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingMinorViolationsInARow); + data.movingMinorViolationsInARow = 0; + } + data.movingMinorViolationsInARow = 0; } - - data.movingMinorViolationsInARow = 0; - - data.movingSetBackPoint = null; } private static Level max(Level l1, Level l2) { @@ -361,13 +373,10 @@ public class MovingCheck { // Still not a perfect solution. After resetting a player his vertical momentum gets lost // Therefore we can't expect him to fall big distances in his next move, therefore we have to // set his flying phase to something he can work with. - if(data.movingJumpPhase > 7) { - data.movingJumpPhase = 7; - } + data.movingJumpPhase = 0; // If we have stored a location for the player, we put him back there if(data.movingSetBackPoint != null) { - // Lets try it that way. Maybe now people don't "disappear" any longer event.setFrom(data.movingSetBackPoint); event.setTo(data.movingSetBackPoint); @@ -443,4 +452,20 @@ public class MovingCheck { int i = (int)d; return d > (double)i ? i : i - 1; } + + public static int lowerBorder(double d1) { + double floor = Math.floor(d1); + double d4 = (d1 - floor) - magic; + //System.out.println(d4); + return (int) (floor + d4); + } + + public static int upperBorder(double d1) { + double floor = Math.floor(d1); + double d4 = (d1 - floor) - magic2; + //System.out.println(d4); + int tmp = (int) (floor - d4); + + return tmp < floor ? tmp + 2 : (int)floor ; + } }