From 02628becaf0454b83f4bc1bb0a87655de362c736 Mon Sep 17 00:00:00 2001 From: Evenprime Date: Tue, 22 Feb 2011 17:30:00 +0100 Subject: [PATCH] Option to "log" to moderators + more code comments + info about active checks at startup --- plugin.yml | 2 +- .../bukkit/nocheat/BlockPlacingCheck.java | 43 ++++--- .../evenprime/bukkit/nocheat/MovingCheck.java | 114 ++++++++++-------- .../bukkit/nocheat/NoCheatConfiguration.java | 37 +++++- .../bukkit/nocheat/NoCheatPlugin.java | 107 ++++++++++++++-- .../nocheat/NoCheatPluginBlockListener.java | 6 + .../bukkit/nocheat/NoCheatPluginData.java | 15 +-- .../nocheat/NoCheatPluginPlayerListener.java | 7 +- .../nocheat/NoCheatPluginVehicleListener.java | 1 + .../bukkit/nocheat/SpeedhackCheck.java | 21 ++-- 10 files changed, 255 insertions(+), 98 deletions(-) diff --git a/plugin.yml b/plugin.yml index 475cae6d..6458eb14 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,5 +3,5 @@ name: NoCheatPlugin author: Evenprime main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin -version: 0.5.3 +version: 0.5.3a diff --git a/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java index f033f8d3..604e9c1d 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java @@ -5,30 +5,39 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.event.block.BlockPlaceEvent; + +/** + * Check if the player tries to place blocks in midair (which shouldn't be possible) + * + * @author Evenprime + * + */ public class BlockPlacingCheck { - public static void check(BlockPlaceEvent event) { - - if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.airbuild")) { + public static void check(BlockPlaceEvent event) { + + // Should we check at all? + if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.airbuild")) { return; } else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) { return; } - - Location l = event.getBlockPlaced().getLocation(); - World w = event.getBlock().getWorld(); - int airId = Material.AIR.getId(); - - if(w.getBlockTypeIdAt(l.getBlockX()-1, l.getBlockY(), l.getBlockZ()) == airId && - w.getBlockTypeIdAt(l.getBlockX()+1, l.getBlockY(), l.getBlockZ()) == airId && - w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()-1, l.getBlockZ()) == airId && - w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()+1, l.getBlockZ()) == airId && - w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()-1) == airId && - w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()+1) == airId) { - event.setCancelled(true); - NoCheatPlugin.log.warning("NoCheatPlugin: Airbuild violation: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air"); - } + + Location l = event.getBlockPlaced().getLocation(); + World w = event.getBlock().getWorld(); + int airId = Material.AIR.getId(); + + // Are all 6 sides "air-blocks" -> cancel the event + if(w.getBlockTypeIdAt(l.getBlockX()-1, l.getBlockY(), l.getBlockZ()) == airId && + w.getBlockTypeIdAt(l.getBlockX()+1, l.getBlockY(), l.getBlockZ()) == airId && + w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()-1, l.getBlockZ()) == airId && + w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()+1, l.getBlockZ()) == airId && + w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()-1) == airId && + w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ()+1) == airId) { + event.setCancelled(true); + NoCheatPlugin.logNormal("NoCheatPlugin: Airbuild violation: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() +"," + l.getBlockZ()); + } } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java index 581059e7..5253a26d 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java @@ -6,20 +6,28 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.event.player.PlayerMoveEvent; - +/** + * Check if the player should be allowed to make that move, e.g. is he allowed to jump here or move that far in one step + * + * @author Evenprime + * + */ 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.50D }; + // Violation levels private static final int HEAVY = 3; private static final int NORMAL = 2; private static final int MINOR = 1; private static final int NONE = 0; + // Every player gets freebee moves to prevent them from getting stuck to easy private static final int freeIllegalMoves = 1; + // Block types that may be treated specially private enum BlockType { SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN; } @@ -117,9 +125,10 @@ public class MovingCheck { types[Material.CAKE_BLOCK.getId()]= BlockType.UNKNOWN; } + public static void check(NoCheatPluginData data, PlayerMoveEvent event) { - + // Should we check at all if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.moving")) { return; } @@ -163,16 +172,16 @@ public class MovingCheck { if(onGroundFrom && onGroundTo) { // reset jumping - data.phase = 0; + 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 // 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.phase])) { + if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; @@ -183,12 +192,12 @@ public class MovingCheck { else if(onGroundFrom && !onGroundTo) { // reset jumping - data.phase = 0; + data.movingJumpPhase = 0; // Check if player isn't jumping too high - if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { + if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; @@ -198,46 +207,46 @@ public class MovingCheck { // 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 data.phase++; // Setup next phase of the jump + 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.phase])) { + if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; else vl = vl > MINOR ? vl : MINOR; } else { - data.phase = 0; // He is on ground now, so reset the jump + data.movingJumpPhase = 0; // He is on ground now, so reset the jump } } // 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.phase])) { + if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) { - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase]; if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; else vl = vl > MINOR ? vl : MINOR; } - data.phase++; // Enter next phase of the flight + 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) - if(!(data.phase < jumpingPhases.length)) { - data.phase = jumpingPhases.length - 1; + if(!(data.movingJumpPhase < jumpingPhases.length)) { + data.movingJumpPhase = jumpingPhases.length - 1; } - // Treat the violation(s) + // Treat the violation(s) according to their level switch(vl) { case MINOR: minorViolation(data, event); @@ -256,86 +265,91 @@ public class MovingCheck { protected static void minorViolation(NoCheatPluginData data, PlayerMoveEvent event) { - if(data.minorViolationsInARow == 0) { - // Store the source location for later use + // If it is the first violation, store the "from" location for potential later use + if(data.movingMinorViolationsInARow == 0) { data.movingSetBackPoint = event.getFrom().clone(); } - // Start logging only after the freebee illegal moves are over - if(data.minorViolationsInARow == freeIllegalMoves + 1) { - NoCheatPlugin.log.info("NoCheatPlugin: Moving violation: "+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())); + // Start logging only after the freebee illegal moves have all been used + if(data.movingMinorViolationsInARow == freeIllegalMoves + 1) { + NoCheatPlugin.logMinor("NoCheatPlugin: Moving violation: "+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())); } - data.minorViolationsInARow++; + data.movingMinorViolationsInARow++; // 16 minor violations in a row count as one normal violation - if(data.minorViolationsInARow % 16 == 0) { + if(data.movingMinorViolationsInARow % 16 == 0) { normalViolation(data, event); } - else if(data.minorViolationsInARow % (freeIllegalMoves+1) == 0) { - // now we need it + // Each time the freebee moves are all used up, we may reset the player to his old location + else if(data.movingMinorViolationsInARow % (freeIllegalMoves + 1) == 0) { resetPlayer(data, event); } } protected static void normalViolation(NoCheatPluginData data, PlayerMoveEvent event) { // Log the first violation in a row - if(data.normalViolationsInARow == 0) - NoCheatPlugin.log.warning("NoCheatPlugin: Moving violation: "+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())); + if(data.movingNormalViolationsInARow == 0) + NoCheatPlugin.logNormal("NoCheatPlugin: Moving violation: "+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())); resetPlayer(data, event); - data.normalViolationsInARow++; + data.movingNormalViolationsInARow++; } protected static void heavyViolation(NoCheatPluginData data, PlayerMoveEvent event) { - if(data.heavyViolationsInARow == 0) - NoCheatPlugin.log.severe("NoCheatPlugin: Moving violation: "+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())); + // Log the first violation in a row + if(data.movingHeavyViolationsInARow == 0) + NoCheatPlugin.logHeavy("NoCheatPlugin: Moving violation: "+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())); resetPlayer(data, event); - data.heavyViolationsInARow++; - // Log the first violation in a row + data.movingHeavyViolationsInARow++; } protected static void legitimateMove(NoCheatPluginData data, PlayerMoveEvent event) { - // Give some additional logs - if(data.heavyViolationsInARow > 0) { - NoCheatPlugin.log.severe("NoCheatPlugin: Moving violation stopped: "+event.getPlayer().getName() + " total Events: "+ data.heavyViolationsInARow); - data.heavyViolationsInARow = 0; + // Give some additional logs about now ending violations + if(data.movingHeavyViolationsInARow > 0) { + NoCheatPlugin.logHeavy("NoCheatPlugin: Moving violation stopped: "+event.getPlayer().getName() + " total Events: "+ data.movingHeavyViolationsInARow); + data.movingHeavyViolationsInARow = 0; } - else if(data.normalViolationsInARow > 0) { - NoCheatPlugin.log.warning("NoCheatPlugin: Moving violation stopped: "+event.getPlayer().getName()+ " total Events: "+ data.normalViolationsInARow); - data.normalViolationsInARow = 0; + else if(data.movingNormalViolationsInARow > 0) { + NoCheatPlugin.logNormal("NoCheatPlugin: Moving violation stopped: "+event.getPlayer().getName()+ " total Events: "+ data.movingNormalViolationsInARow); + data.movingNormalViolationsInARow = 0; } - else if(data.minorViolationsInARow > freeIllegalMoves) { - NoCheatPlugin.log.info("NoCheatPlugin: Moving violation stopped: "+event.getPlayer().getName()+ " total Events: "+ data.minorViolationsInARow); - data.minorViolationsInARow = 0; + else if(data.movingMinorViolationsInARow > freeIllegalMoves) { + NoCheatPlugin.logMinor("NoCheatPlugin: Moving violation stopped: "+event.getPlayer().getName()+ " total Events: "+ data.movingMinorViolationsInARow); + data.movingMinorViolationsInARow = 0; } else { - data.minorViolationsInARow = 0; + data.movingMinorViolationsInARow = 0; } + // Setback point isn't needed anymore data.movingSetBackPoint = null; } /** - * Cancel the event and return the player to a stored location or if that is not available, - * the the previous location. + * Return the player to a stored location or if that is not available, + * the previous location. * @param data * @param event */ private static void resetPlayer(NoCheatPluginData data, PlayerMoveEvent event) { - // If we only log, we never reset the player to his original location + // If we only log, we never reset the player to his original location and can end here already if(NoCheatConfiguration.movingLogOnly) return; - if(data.phase > 7) { - data.phase = 7; + // 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; } + // 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 diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java index a449aa15..be7689e6 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java @@ -11,31 +11,50 @@ import java.util.logging.Logger; import org.bukkit.util.config.Configuration; +/** + * Central location for everything that's described in the configuration file + * + * @author Evenprime + * + */ public class NoCheatConfiguration { + // Our personal logger public static final String loggerName = "cc.co.evenprime.bukkit.nocheat"; public static final Logger logger = Logger.getLogger(loggerName); + // Which checks are active public static boolean speedhackCheckActive = true; public static boolean movingCheckActive = true; public static boolean airbuildCheckActive = false; + // Limits for the speedhack check public static int speedhackInterval = 2000; public static int speedhackLow = 60; public static int speedhackMed = 90; public static int speedhackHigh = 120; + // Limits for the moving check public static double movingDistanceLow = 0.5D; public static double movingDistanceMed = 1.0D; public static double movingDistanceHigh = 5.0D; + // Should moving violations be punished? public static boolean movingLogOnly = false; + // The log level above which players with the permission nocheat.notify will get informed about violations + public static Level notifyLevel = Level.OFF; + + // Our two log outputs, the console and a file private static ConsoleHandler ch = null; private static FileHandler fh = null; private NoCheatConfiguration() {} + /** + * Read the configuration file and assign either standard values or whatever is declared in the file + * @param configurationFile + */ public static void config(File configurationFile) { if(!configurationFile.exists()) { @@ -46,7 +65,8 @@ public class NoCheatConfiguration { logger.setLevel(Level.INFO); logger.setUseParentHandlers(false); - + + if(ch == null) { ch = new ConsoleHandler(); @@ -55,9 +75,10 @@ public class NoCheatConfiguration { logger.addHandler(ch); } + if(fh == null) { try { - fh = new FileHandler(c.getString("logging.filename"), true); + fh = new FileHandler(c.getString("logging.filename"), 2000, 2, true); fh.setLevel(stringToLevel(c.getString("logging.logtofile"))); fh.setFormatter(Logger.getLogger("Minecraft").getHandlers()[0].getFormatter()); logger.addHandler(fh); @@ -68,6 +89,8 @@ public class NoCheatConfiguration { } } + notifyLevel = stringToLevel(c.getString("logging.logtonotify")); + speedhackCheckActive = c.getBoolean("active.speedhack", true); movingCheckActive = c.getBoolean("active.moving", true); airbuildCheckActive = c.getBoolean("active.airbuild", false); @@ -80,6 +103,11 @@ public class NoCheatConfiguration { movingLogOnly = c.getBoolean("moving.logonly", false); } + /** + * Convert a string into a log level + * @param string + * @return + */ private static Level stringToLevel(String string) { if(string == null) { @@ -92,6 +120,10 @@ public class NoCheatConfiguration { return Level.OFF; } + /** + * Standard configuration file for people who haven't got one yet + * @param f + */ private static void createStandardConfigFile(File f) { try { f.getParentFile().mkdirs(); @@ -103,6 +135,7 @@ public class NoCheatConfiguration { w.write(" filename: plugins/NoCheat/nocheat.log"); w.newLine(); w.write(" logtofile: info"); w.newLine(); w.write(" logtoconsole: severe"); w.newLine(); + w.write(" logtonotify: warn"); w.newLine(); w.write("# Checks that are activated (true or false)"); w.newLine(); w.write("active:"); w.newLine(); w.write(" speedhack: true"); w.newLine(); diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java index a23da1bc..b4381c37 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java @@ -3,6 +3,7 @@ package cc.co.evenprime.bukkit.nocheat; import java.io.File; import java.util.HashMap; import java.util.Map; +import java.util.logging.Level; import java.util.logging.Logger; import org.bukkit.Server; @@ -22,32 +23,60 @@ import org.bukkit.plugin.Plugin; * * NoCheatPlugin * -* Check PLAYER_MOVE events for their plausibility and cancel them if they are implausible +* Check various player events for their plausibilty and log/deny them based on configuration * * @author Evenprime */ public class NoCheatPlugin extends JavaPlugin { + // Various listeners needed for different Checks private final NoCheatPluginPlayerListener playerListener; private final NoCheatPluginVehicleListener vehicleListener; private final NoCheatPluginBlockListener blockListener; - public static Logger log; + // My main logger + private static Logger log; + + // Permissions 2.0, if available public static PermissionHandler Permissions = null; + // A reference to the instance of the plugin + private static NoCheatPlugin p = null; + // Store data between Events public static Map playerData = new HashMap(); + /** + * Ridiculously long constructor to keep supporting older bukkit versions, as long as it is possible + * + * @param pluginLoader + * @param instance + * @param desc + * @param f1 + * @param f2 + * @param cLoader + */ public NoCheatPlugin(PluginLoader pluginLoader, Server instance, PluginDescriptionFile desc, File f1, File f2, ClassLoader cLoader) { super(pluginLoader, instance, desc, f1, f2, cLoader); + // Create our listeners and feed them with neccessary information playerListener = new NoCheatPluginPlayerListener(); vehicleListener = new NoCheatPluginVehicleListener(playerListener); blockListener = new NoCheatPluginBlockListener(); log = NoCheatConfiguration.logger; + + p = this; } + /** + * Main access to data that needs to be stored between different events. + * Always returns a NoCheatPluginData object, because if there isn't one + * for the specified player, one will be created. + * + * @param p + * @return + */ public static NoCheatPluginData getPlayerData(Player p) { NoCheatPluginData data = null; @@ -71,19 +100,30 @@ public class NoCheatPlugin extends JavaPlugin { public void onEnable() { PluginManager pm = getServer().getPluginManager(); - pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Lowest, this); - pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this); - pm.registerEvent(Event.Type.VEHICLE_EXIT, vehicleListener, Priority.Monitor, this); - pm.registerEvent(Event.Type.VEHICLE_DAMAGE, vehicleListener, Priority.Monitor, this); - pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Low, this); + pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Lowest, this); // needed for speedhack and moving checks + pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this); // used to delete old data of users + pm.registerEvent(Event.Type.VEHICLE_EXIT, vehicleListener, Priority.Monitor, this); // used for moving check + pm.registerEvent(Event.Type.VEHICLE_DAMAGE, vehicleListener, Priority.Monitor, this); // used for moving check + pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Low, this); // used for airbuild check PluginDescriptionFile pdfFile = this.getDescription(); - Logger.getLogger("Minecraft").info( "NoCheat version " + pdfFile.getVersion() + " is enabled!" ); - + + // Get, if available, the Permissions 2.0 plugin setupPermissions(); + + // parse the nocheat.yml config file setupConfig(); + + String checks = (NoCheatConfiguration.movingCheckActive ? "moving ": "") + + (NoCheatConfiguration.speedhackCheckActive ? "speedhack " : "") + + (NoCheatConfiguration.airbuildCheckActive ? "airbuild " : ""); + + Logger.getLogger("Minecraft").info( "NoCheatPlugin version " + pdfFile.getVersion() + " is enabled with the following checks: "+checks); } + /** + * Get, if available, a reference to the Permissions-plugin + */ public void setupPermissions() { Plugin test = this.getServer().getPluginManager().getPlugin("Permissions"); @@ -94,9 +134,56 @@ public class NoCheatPlugin extends JavaPlugin { this.getServer().getPluginManager().disablePlugin(this); } } + + /** + * Log a minor violation message to all locations declared in the config file + * @param message + */ + public static void logMinor(String message) { + if(NoCheatConfiguration.notifyLevel.intValue() <= Level.INFO.intValue()) { + for(Player player : p.getServer().getOnlinePlayers()) { + if(Permissions.has(player, "nocheat.notify")) { + player.sendMessage("[INFO] " + message); + } + } + } + log.info(message); + } + /** + * Log a normal violation message to all locations declared in the config file + * @param message + */ + public static void logNormal(String message) { + if(NoCheatConfiguration.notifyLevel.intValue() <= Level.WARNING.intValue()) { + for(Player player : p.getServer().getOnlinePlayers()) { + if(Permissions.has(player, "nocheat.notify")) { + player.sendMessage("[WARNING] " + message); + } + } + } + log.warning(message); + } + + /** + * Log a heavy violation message to all locations declared in the config file + * @param message + */ + public static void logHeavy(String message) { + if(NoCheatConfiguration.notifyLevel.intValue() <= Level.SEVERE.intValue()) { + for(Player player : p.getServer().getOnlinePlayers()) { + if(Permissions.has(player, "nocheat.notify")) { + player.sendMessage("[SEVERE] " + message); + } + } + } + log.severe(message); + } + + /** + * Read the config file + */ public void setupConfig() { NoCheatConfiguration.config(new File("plugins/NoCheat/nocheat.yml")); - } } \ No newline at end of file diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java index ca9f1c5a..ea9b94a4 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java @@ -3,6 +3,12 @@ package cc.co.evenprime.bukkit.nocheat; import org.bukkit.event.block.BlockListener; import org.bukkit.event.block.BlockPlaceEvent; +/** + * Handle events for all Block related events + * + * @author Evenprime + * + */ public class NoCheatPluginBlockListener extends BlockListener { diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java index 9aa499b8..dcde4f3f 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java @@ -4,22 +4,23 @@ import org.bukkit.Location; /** * Storage for data persistence between events + * + * @author Evenprime * */ public class NoCheatPluginData { /** - * Don't rely on any of these yet, they are likely going to - * change their name/functionality + * Don't rely on any of these yet, they are likely going to change their name/functionality */ - int phase = 0; // current jumpingPhase + int movingJumpPhase = 0; // current jumpingPhase long lastSpeedHackCheck = System.currentTimeMillis(); // timestamp of last check for speedhacks int eventsSinceLastSpeedHackCheck = 0; // used to identify speedhacks - int ignoreNextXEvents = 0; + int movingIgnoreNextXEvents = 0; - int minorViolationsInARow = 0; - int normalViolationsInARow = 0; - int heavyViolationsInARow = 0; + int movingMinorViolationsInARow = 0; + int movingNormalViolationsInARow = 0; + int movingHeavyViolationsInARow = 0; Location movingSetBackPoint = null; NoCheatPluginData() { } diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java index fd703381..68ad2112 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java @@ -9,6 +9,7 @@ import org.bukkit.event.player.PlayerMoveEvent; /** * Handle events for all Player related events + * * @author Evenprime */ @@ -27,7 +28,7 @@ public class NoCheatPluginPlayerListener extends PlayerListener { NoCheatPluginData data = NoCheatPlugin.playerData.get(player); if(data != null) { - data.ignoreNextXEvents = count; + data.movingIgnoreNextXEvents = count; } } @@ -37,8 +38,8 @@ public class NoCheatPluginPlayerListener extends PlayerListener { // Get the player-specific data NoCheatPluginData data = NoCheatPlugin.getPlayerData(event.getPlayer()); - if(data.ignoreNextXEvents > 0 ) { - data.ignoreNextXEvents--; + if(data.movingIgnoreNextXEvents > 0 ) { + data.movingIgnoreNextXEvents--; return; } diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java index b3fc1823..3d5ea13d 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java @@ -7,6 +7,7 @@ import org.bukkit.event.vehicle.VehicleListener; /** * Handle events for all Player related events + * * @author Evenprime */ diff --git a/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java b/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java index 2beb73c5..61cde87b 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java @@ -2,21 +2,26 @@ package cc.co.evenprime.bukkit.nocheat; import org.bukkit.event.player.PlayerMoveEvent; - +/** + * Log if a player sends to many move events in a specific time frame, usually the result of tinkering with the system clock + * + * @author Evenprime + * + */ public class SpeedhackCheck { public static void check(NoCheatPluginData data, PlayerMoveEvent event) { - // Get the time of the server - long time = System.currentTimeMillis(); - - + // Should we check at all? if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.speedhack")) { return; } else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) { return; } + + // Get the time of the server + long time = System.currentTimeMillis(); // Is it time for a speedhack check now? if(time > NoCheatConfiguration.speedhackInterval + data.lastSpeedHackCheck ) { @@ -28,11 +33,11 @@ public class SpeedhackCheck { int limitHigh = (int)((NoCheatConfiguration.speedhackHigh * (time - data.lastSpeedHackCheck)) / NoCheatConfiguration.speedhackInterval); if(data.eventsSinceLastSpeedHackCheck > limitHigh) - NoCheatPlugin.log.severe("NoCheatPlugin: "+event.getPlayer().getName()+" sent "+ data.eventsSinceLastSpeedHackCheck + " move events, but only "+limitLow+ " were allowed. Speedhack?"); + NoCheatPlugin.logHeavy("NoCheatPlugin: "+event.getPlayer().getName()+" sent "+ data.eventsSinceLastSpeedHackCheck + " move events, but only "+limitLow+ " were allowed. Speedhack?"); else if(data.eventsSinceLastSpeedHackCheck > limitMed) - NoCheatPlugin.log.warning("NoCheatPlugin: "+event.getPlayer().getName()+" sent "+ data.eventsSinceLastSpeedHackCheck + " move events, but only "+limitLow+ " were allowed. Speedhack?"); + NoCheatPlugin.logNormal("NoCheatPlugin: "+event.getPlayer().getName()+" sent "+ data.eventsSinceLastSpeedHackCheck + " move events, but only "+limitLow+ " were allowed. Speedhack?"); else if(data.eventsSinceLastSpeedHackCheck > limitLow) - NoCheatPlugin.log.info("NoCheatPlugin: "+event.getPlayer().getName()+" sent "+ data.eventsSinceLastSpeedHackCheck + " move events, but only "+limitLow+ " were allowed. Speedhack?"); + NoCheatPlugin.logMinor("NoCheatPlugin: "+event.getPlayer().getName()+" sent "+ data.eventsSinceLastSpeedHackCheck + " move events, but only "+limitLow+ " were allowed. Speedhack?"); // Reset values for next check data.eventsSinceLastSpeedHackCheck = 0; data.lastSpeedHackCheck = time;