diff --git a/plugin.yml b/plugin.yml index 6caee185..622b91c9 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.9 +version: 0.6.9a commands: nocheat: diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java index 7629b84b..e1ab22c6 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java @@ -4,7 +4,6 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; import java.util.logging.Level; import java.util.logging.Logger; @@ -20,7 +19,7 @@ import org.bukkit.util.config.Configuration; public class NoCheatConfiguration { // Our personal logger - public static final String loggerName = "cc.co.evenprime.bukkit.nocheat"; + public static final String loggerName = "cc.co.evenprime.nocheat"; public static final Logger logger = Logger.getLogger(loggerName); // Which checks are active @@ -39,7 +38,7 @@ public class NoCheatConfiguration { public static String speedhackActionNormal = ""; public static String speedhackActionHeavy = ""; - public static int movingFreeMoves = 5; + public static int movingFreeMoves = 1; // How should moving violations be treated? public static String movingActionMinor = ""; @@ -49,14 +48,14 @@ public class NoCheatConfiguration { // How should airbuild violations be treated? public static String airbuildAction = ""; - // The log level above which players with the permission nocheat.notify will get informed about violations + // The log level above which information gets logged to the specified logger public static Level chatLevel = Level.OFF; public static Level ircLevel = Level.OFF; + public static Level consoleLevel = Level.OFF; public static String ircTag = ""; - // Our two log outputs, the console and a file - private static ConsoleHandler ch = null; + // Our log output to a file private static FileHandler fh = null; private NoCheatConfiguration() {} @@ -75,16 +74,6 @@ public class NoCheatConfiguration { logger.setLevel(Level.INFO); logger.setUseParentHandlers(false); - - - if(ch == null) { - ch = new ConsoleHandler(); - - ch.setLevel(stringToLevel(c.getString("logging.logtoconsole"))); - ch.setFormatter(Logger.getLogger("Minecraft").getHandlers()[0].getFormatter()); - logger.addHandler(ch); - } - if(fh == null) { try { @@ -101,6 +90,7 @@ public class NoCheatConfiguration { chatLevel = stringToLevel(c.getString("logging.logtonotify")); // deprecated, will be deleted eventually chatLevel = stringToLevel(c.getString("logging.logtochat")); + consoleLevel = stringToLevel(c.getString("logging.logtoconsole")); ircLevel = stringToLevel(c.getString("logging.logtoirc")); ircTag = c.getString("logging.logtoirctag", "nocheat"); @@ -114,7 +104,7 @@ public class NoCheatConfiguration { speedhackLimitMed = c.getInt("speedhack.limits.med", 45); speedhackLimitHigh = c.getInt("speedhack.limits.high", 60); - movingFreeMoves = c.getInt("moving.freemoves", 5); + movingFreeMoves = c.getInt("moving.freemoves", 1); movingActionMinor = c.getString("moving.action.low", "loglow reset"); movingActionNormal = c.getString("moving.action.med", "logmed reset"); @@ -187,7 +177,7 @@ public class NoCheatConfiguration { w.write("# Moving specific options") ; w.newLine(); w.write("moving:"); w.newLine(); w.write("# After how many minor violations should the plugin react (minimum 1)"); w.newLine(); - w.write(" freemoves: 5"); w.newLine(); + w.write(" freemoves: 1"); w.newLine(); w.write("# Moving Action, one or more of 'loglow logmed loghigh reset'"); w.newLine(); w.write(" action:"); w.newLine(); w.write(" low: loglow reset"); w.newLine(); diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java index cffb4645..ae9ac57e 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java @@ -40,7 +40,8 @@ public class NoCheatPlugin extends JavaPlugin { private NoCheatEntityListener entityListener; // My main logger - private static Logger log; + private static Logger consoleLogger; + private static Logger fileLogger; private static NoCheatPlugin p; @@ -139,7 +140,8 @@ public class NoCheatPlugin extends JavaPlugin { blockListener = new NoCheatBlockListener(); entityListener = new NoCheatEntityListener(); - log = NoCheatConfiguration.logger; + fileLogger = NoCheatConfiguration.logger; + consoleLogger = Logger.getLogger("Minecraft"); PluginManager pm = getServer().getPluginManager(); pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Lowest, this); // used for speedhack and moving checks @@ -212,7 +214,8 @@ public class NoCheatPlugin extends JavaPlugin { if(l != null) { logToChat(l, message); logToIRC(l, message); - log.log(l, message); + logToConsole(l, message); + fileLogger.log(l, message); } } @@ -232,6 +235,12 @@ public class NoCheatPlugin extends JavaPlugin { } } + private static void logToConsole(Level l, String message) { + if( NoCheatConfiguration.consoleLevel.intValue() <= l.intValue()) { + consoleLogger.log(l, message); + } + } + public static void logAction(String actions, String message) { if(actions == null) return; diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java index 51b19a30..6e55f88b 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java @@ -22,7 +22,9 @@ public class MovingCheck { // previously-calculated upper bound values for jumps. Minecraft is very deterministic when it comes to jumps // 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.49D }; + static final int jumpingLimit = 3; + static final double jumpingHeightLimit = 1.3D; + static double stepHeight = 0.501D; // Limits for the moving check public static double movingDistanceLow = 0.1D; @@ -183,7 +185,7 @@ public class MovingCheck { // 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); + boolean onGroundTo = playerIsOnGround(to.getWorld(), toValues, to); // Both locations seem to be on solid ground or at a ladder @@ -194,9 +196,9 @@ public class MovingCheck { // 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[0])) { + if(!(to.getY() - from.getY() < stepHeight)) { - double offset = (to.getY() - from.getY()) - jumpingPhases[0]; + double offset = (to.getY() - from.getY()) - stepHeight; if(offset > 2D) vl = max(vl, Level.SEVERE); else if(offset > 0.5D) vl = max(vl, Level.WARNING); @@ -206,17 +208,19 @@ public class MovingCheck { { // reset jumping data.movingJumpPhase = 0; - data.movingSetBackPoint = event.getTo().clone(); + data.movingSetBackPoint = from.clone(); } } // player is starting to jump (or starting to fall down somewhere) else if(onGroundFrom && !onGroundTo) { // Check if player isn't jumping too high - if(!(to.getY() - from.getY() < jumpingPhases[0])) { - - double offset = (to.getY() - from.getY()) - jumpingPhases[0]; + double limit = jumpingHeightLimit; + + if(to.getY() - from.getY() > limit) { + double offset = (to.getY() - from.getY()) - limit; + if(offset > 2D) vl = max(vl, Level.SEVERE); else if(offset > 0.5D) vl = max(vl, Level.WARNING); else vl = max(vl, Level.INFO); @@ -224,16 +228,21 @@ public class MovingCheck { else { // Setup next phase of the jump data.movingJumpPhase = 1; - data.movingSetBackPoint = event.getFrom().clone(); + data.movingSetBackPoint = from.clone(); } } // 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() < Math.max(jumpingPhases[data.movingJumpPhase], 0D))) { + Location l = data.movingSetBackPoint; + if(l == null) { l = from; } + + double limit = jumpingHeightLimit; + + if(to.getY() - l.getY() > limit) { - double offset = (to.getY() - from.getY()) - Math.max(jumpingPhases[data.movingJumpPhase], 0D); + double offset = (to.getY() - l.getY()) - limit; if(offset > 2D) vl = max(vl, Level.SEVERE); else if(offset > 0.5D) vl = max(vl, Level.WARNING); @@ -241,32 +250,35 @@ public class MovingCheck { } else { data.movingJumpPhase = 0; // He is on ground now, so reset the jump - data.movingSetBackPoint = event.getTo().clone(); + data.movingSetBackPoint = to.clone(); } } // Player is moving through air (during jumping, falling) else { + // Check if player isn't landing to high (sounds weird, but has its use) + Location l = data.movingSetBackPoint; + if(l == null) { l = from; } - if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) + // The expected fall velocity is a rough estimate - players usually accelerate by that value + double limit = (data.movingJumpPhase > jumpingLimit) ? jumpingHeightLimit - (data.movingJumpPhase-jumpingLimit) * 0.2D : jumpingHeightLimit; + + if(to.getY() - l.getY() > limit) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; - + double offset = (to.getY() - l.getY()) - limit; + 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 { data.movingJumpPhase++; // Enter next phase of the flight - // Setback point stays the same + // Setback point stays the same. IF we don't have one, take the "from" location as a setback point for now + if(data.movingSetBackPoint == null) { + data.movingSetBackPoint = from.clone(); + } } } - // do a security check on the jumping phase, such that we don't get - // OutOfArrayBoundsExceptions at long air times (falling off high places) - if(!(data.movingJumpPhase < jumpingPhases.length)) { - data.movingJumpPhase = jumpingPhases.length - 1; - } - if(vl == null && (onGroundFrom || onGroundTo)) { legitimateMove(data, event); } @@ -317,14 +329,14 @@ public class MovingCheck { data.movingHeavyViolationsInARow++; actions = NoCheatConfiguration.movingActionHeavy; } - + action(event, actions, log); } } /** - * Perform actions that were specified by the player + * Perform actions that were specified by the admin * @param event * @param actions */ @@ -347,7 +359,7 @@ public class MovingCheck { protected static void legitimateMove(NoCheatData data, PlayerMoveEvent event) { // Give some logging about violations if the player hasn't done any for at least two seconds - if(data.movingLastViolationTime != 0 && data.movingLastViolationTime + 1000L > System.currentTimeMillis()) { + if(data.movingLastViolationTime != 0 && data.movingLastViolationTime + 2000L < System.currentTimeMillis()) { data.movingLastViolationTime = 0; @@ -360,7 +372,7 @@ public class MovingCheck { NoCheatPlugin.logAction(NoCheatConfiguration.movingActionNormal, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingNormalViolationsInARow); data.movingNormalViolationsInARow = 0; } - if(data.movingMinorViolationsInARow > NoCheatConfiguration.movingFreeMoves +1) { + if(data.movingMinorViolationsInARow > NoCheatConfiguration.movingFreeMoves) { NoCheatPlugin.logAction(NoCheatConfiguration.movingActionMinor, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingMinorViolationsInARow); data.movingMinorViolationsInARow = 0; }