From 3f7f537fc0f9be553524af9f3a0897d168765c24 Mon Sep 17 00:00:00 2001 From: Evenprime Date: Sun, 3 Apr 2011 22:43:31 +0200 Subject: [PATCH] v0.7.8: Fixed config file creation/initialization + Walking on Fence no longer causes false positives --- plugin.yml | 2 +- .../bukkit/nocheat/NoCheatConfiguration.java | 107 +++++++---- .../evenprime/bukkit/nocheat/NoCheatData.java | 14 +- .../bukkit/nocheat/actions/Action.java | 2 + .../bukkit/nocheat/actions/CancelAction.java | 4 + .../bukkit/nocheat/actions/CustomAction.java | 4 + .../bukkit/nocheat/actions/LogAction.java | 11 ++ .../bukkit/nocheat/checks/AirbuildCheck.java | 8 +- .../nocheat/checks/BedteleportCheck.java | 2 +- .../bukkit/nocheat/checks/MovingCheck.java | 171 ++++++++---------- 10 files changed, 171 insertions(+), 154 deletions(-) diff --git a/plugin.yml b/plugin.yml index 0922b475..95efa7c6 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,7 +3,7 @@ name: NoCheatPlugin author: Evenprime main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin -version: 0.7.7c +version: 0.7.8 commands: nocheat: diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java index 4792efe6..145b03d8 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatConfiguration.java @@ -29,9 +29,12 @@ public class NoCheatConfiguration { public final Logger logger = Logger.getLogger(loggerName); // The log level above which information gets logged to the specified logger - public Level chatLevel = Level.OFF; - public Level ircLevel = Level.OFF; - public Level consoleLevel = Level.OFF; + public Level chatLevel = Level.WARNING; + public Level ircLevel = Level.WARNING; + public Level consoleLevel = Level.SEVERE; + public Level fileLevel = Level.INFO; + + public String fileName = "plugins/NoCheat/nocheat.log"; public String ircTag = "nocheat"; @@ -63,10 +66,16 @@ public class NoCheatConfiguration { logger.setLevel(Level.INFO); logger.setUseParentHandlers(false); + chatLevel = stringToLevel(c.getString("logging.logtochat"), chatLevel); + consoleLevel = stringToLevel(c.getString("logging.logtoconsole"), consoleLevel); + fileLevel = stringToLevel(c.getString("logging.logtofile"), fileLevel); + ircLevel = stringToLevel(c.getString("logging.logtoirc"), ircLevel); + ircTag = c.getString("logging.logtoirctag", ircTag); + if(fh == null) { try { - fh = new FileHandler(c.getString("logging.filename"), true); - fh.setLevel(stringToLevel(c.getString("logging.logtofile"))); + fh = new FileHandler(fileName, true); + fh.setLevel(fileLevel); fh.setFormatter(Logger.getLogger("Minecraft").getHandlers()[0].getFormatter()); logger.addHandler(fh); @@ -76,13 +85,6 @@ 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"); - plugin.speedhackCheck.limits[0] = c.getInt("speedhack.limits.low", plugin.speedhackCheck.limits[0]); plugin.speedhackCheck.limits[1] = c.getInt("speedhack.limits.med", plugin.speedhackCheck.limits[1]); plugin.speedhackCheck.limits[2] = c.getInt("speedhack.limits.high", plugin.speedhackCheck.limits[2]); @@ -109,15 +111,14 @@ public class NoCheatConfiguration { plugin.bedteleportCheck.setActive(c.getBoolean("active.bedteleport", plugin.bedteleportCheck.isActive())); } - private Action[] stringToActions(String string, Action[] actions) { - - if(string == null) return actions; - + private Action[] stringToActions(String string, Action[] def) { + + if(string == null) return def; + System.out.println(string); List as = new LinkedList(); String[] parts = string.split(" "); - + for(String s : parts) { - s = s.trim(); if(s.equals("loglow")) as.add(LogAction.loglow); else if(s.equals("logmed")) @@ -136,35 +137,61 @@ public class NoCheatConfiguration { //as.add(new CustomAction(Integer.parseInt(s.substring(6)))); } catch(Exception e) { - plugin.log(Level.WARNING, "Couldn't parse number of custom action '" + s + "'"); + System.out.println("NC: Couldn't parse number of custom action '" + s + "'"); } } else { - plugin.log(Level.WARNING, "Can't parse action "+ s); + System.out.println("NC: Can't parse action "+ s); + } + } + + + return as.toArray(def); + } + + private String actionsToString(Action[] actions) { + + String s = ""; + + if(actions != null) { + for(Action a : actions) { + s = s + " " + a.getName(); } } - - return as.toArray(actions); + return s.trim(); } - /** * Convert a string into a log level * @param string * @return */ - private static Level stringToLevel(String string) { + private static Level stringToLevel(String string, Level def) { if(string == null) { - return Level.OFF; + return def; } if(string.trim().equals("info") || string.trim().equals("low")) return Level.INFO; if(string.trim().equals("warn") || string.trim().equals("med")) return Level.WARNING; if(string.trim().equals("severe")|| string.trim().equals("high")) return Level.SEVERE; + return Level.OFF; } + private static String levelToString(Level level) { + + if(level == null) { + return "off"; + } + + if(level.equals(Level.INFO)) return "low"; + else if(level.equals(Level.WARNING)) return "med"; + else if(level.equals(Level.SEVERE)) return "high"; + + return "off"; + } + /** * Standard configuration file for people who haven't got one yet * @param f @@ -177,12 +204,12 @@ public class NoCheatConfiguration { w.write("# Logging: potential log levels are low (info), med (warn), high (severe), off"); w.newLine(); w.write("logging:"); w.newLine(); - w.write(" filename: plugins/NoCheat/nocheat.log"); w.newLine(); - w.write(" logtofile: low"); w.newLine(); - w.write(" logtoconsole: high"); w.newLine(); - w.write(" logtochat: med"); w.newLine(); - w.write(" logtoirc: med"); w.newLine(); - w.write(" logtoirctag: nocheat"); w.newLine(); + w.write(" filename: "+fileName); w.newLine(); + w.write(" logtofile: "+levelToString(fileLevel)); w.newLine(); + w.write(" logtoconsole: "+levelToString(consoleLevel)); w.newLine(); + w.write(" logtochat: "+levelToString(chatLevel)); w.newLine(); + w.write(" logtoirc: "+levelToString(ircLevel)); w.newLine(); + w.write(" logtoirctag: "+ircTag); w.newLine(); w.write("# Checks and Bugfixes that are activated (true or false)"); w.newLine(); w.write("active:"); w.newLine(); w.write(" speedhack: "+plugin.speedhackCheck.isActive()); w.newLine(); @@ -197,16 +224,16 @@ public class NoCheatConfiguration { w.write(" high: "+plugin.speedhackCheck.limits[2]); w.newLine(); w.write("# Speedhack Action, one or more of 'loglow logmed loghigh reset'"); w.newLine(); w.write(" action:"); w.newLine(); - w.write(" low: "+plugin.speedhackCheck.actions[0]); w.newLine(); - w.write(" med: "+plugin.speedhackCheck.actions[1]); w.newLine(); - w.write(" high: "+plugin.speedhackCheck.actions[2]); w.newLine(); + w.write(" low: "+actionsToString(plugin.speedhackCheck.actions[0])); w.newLine(); + w.write(" med: "+actionsToString(plugin.speedhackCheck.actions[1])); w.newLine(); + w.write(" high: "+actionsToString(plugin.speedhackCheck.actions[2])); w.newLine(); w.write("# Moving specific options") ; w.newLine(); w.write("moving:"); w.newLine(); w.write("# Moving Action, one or more of 'loglow logmed loghigh reset'"); w.newLine(); w.write(" action:"); w.newLine(); - w.write(" low: "+plugin.movingCheck.actions[0]); w.newLine(); - w.write(" med: "+plugin.movingCheck.actions[1]); w.newLine(); - w.write(" high: "+plugin.movingCheck.actions[2]); w.newLine(); + w.write(" low: "+actionsToString(plugin.movingCheck.actions[0])); w.newLine(); + w.write(" med: "+actionsToString(plugin.movingCheck.actions[1])); w.newLine(); + w.write(" high: "+actionsToString(plugin.movingCheck.actions[2])); w.newLine(); w.write("# Airbuild specific options"); w.newLine(); w.write("airbuild:"); w.newLine(); w.write("# How many blocks per second are placed by the player in midair (determines log level)"); w.newLine(); @@ -216,9 +243,9 @@ public class NoCheatConfiguration { w.write(" high: "+plugin.airbuildCheck.limits[2]); w.newLine(); w.write("# Airbuild Action, one or more of 'loglow logmed loghigh deny'"); w.newLine(); w.write(" action:"); w.newLine(); - w.write(" low: "+plugin.airbuildCheck.actions[0]); w.newLine(); - w.write(" med: "+plugin.airbuildCheck.actions[1]); w.newLine(); - w.write(" high: "+plugin.airbuildCheck.actions[2]); w.newLine(); + w.write(" low: "+actionsToString(plugin.airbuildCheck.actions[0])); w.newLine(); + w.write(" med: "+actionsToString(plugin.airbuildCheck.actions[1])); w.newLine(); + w.write(" high: "+actionsToString(plugin.airbuildCheck.actions[2])); w.newLine(); w.write("# Bedteleport specific options (none exist yet)"); w.newLine(); w.write("bedteleport:"); w.newLine(); diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java index b0b25d39..6ed68cc7 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatData.java @@ -3,7 +3,6 @@ package cc.co.evenprime.bukkit.nocheat; import java.util.logging.Level; import org.bukkit.Location; -import org.bukkit.World; /** * Storage for data persistence between events @@ -17,15 +16,13 @@ public class NoCheatData { * Don't rely on any of these yet, they are likely going to change their name/functionality */ - public int movingJumpPhase = 0; // current jumpingPhase + public int movingJumpPhase = 0; public int movingViolationsInARow[] = { 0, 0, 0 }; - public World movingLastWorld = null; public double movingHorizFreedom = 0.0D; public double movingVertFreedom = 0.0D; public int movingVertFreedomCounter = 0; public Location movingSetBackPoint = null; - public Location movingLocation = null; - public Runnable movingRunnable = null; + public Runnable movingSummaryTask = null; public Level movingHighestLogLevel = null; // WORKAROUND for changed PLAYER_MOVE logic @@ -39,12 +36,7 @@ public class NoCheatData { public int speedhackViolationsInARow = 0; public int airbuildPerSecond = 0; - public Runnable airbuildRunnable = null; - - - - - + public Runnable airbuildSummaryTask = null; public NoCheatData() { } } \ No newline at end of file diff --git a/src/cc/co/evenprime/bukkit/nocheat/actions/Action.java b/src/cc/co/evenprime/bukkit/nocheat/actions/Action.java index 3eada34d..cedef336 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/actions/Action.java +++ b/src/cc/co/evenprime/bukkit/nocheat/actions/Action.java @@ -9,4 +9,6 @@ public abstract class Action { this.firstAfter = firstAfter; this.repeat = repeat; } + + public abstract String getName(); } \ No newline at end of file diff --git a/src/cc/co/evenprime/bukkit/nocheat/actions/CancelAction.java b/src/cc/co/evenprime/bukkit/nocheat/actions/CancelAction.java index 849644d9..1b2744a9 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/actions/CancelAction.java +++ b/src/cc/co/evenprime/bukkit/nocheat/actions/CancelAction.java @@ -5,4 +5,8 @@ public class CancelAction extends Action { public final static CancelAction cancel = new CancelAction(); private CancelAction() { super(1, true); } + + public String getName() { + return "cancel"; + } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/actions/CustomAction.java b/src/cc/co/evenprime/bukkit/nocheat/actions/CustomAction.java index 5395bbbe..4e5cdeb8 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/actions/CustomAction.java +++ b/src/cc/co/evenprime/bukkit/nocheat/actions/CustomAction.java @@ -9,4 +9,8 @@ public class CustomAction extends Action { super(firstAfter, repeat); this.command = command; } + + public String getName() { + return "custom"; + } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/actions/LogAction.java b/src/cc/co/evenprime/bukkit/nocheat/actions/LogAction.java index 17435c96..648d6ef0 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/actions/LogAction.java +++ b/src/cc/co/evenprime/bukkit/nocheat/actions/LogAction.java @@ -16,4 +16,15 @@ public class LogAction extends Action { super(firstAfter, repeat); this.level = level; } + + public String getName() { + if(level.equals(Level.INFO)) + return "loglow"; + else if(level.equals(Level.WARNING)) + return "logmed"; + else if(level.equals(Level.SEVERE)) + return "loghigh"; + else + return ""; + } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/AirbuildCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/AirbuildCheck.java index 95d7b5ec..0cc62cc0 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/AirbuildCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/AirbuildCheck.java @@ -45,19 +45,19 @@ public class AirbuildCheck extends Check { final NoCheatData data = plugin.getPlayerData(event.getPlayer()); final Player p = event.getPlayer(); - if(data.airbuildRunnable == null) { - data.airbuildRunnable = new Runnable() { + if(data.airbuildSummaryTask == null) { + data.airbuildSummaryTask = new Runnable() { @Override public void run() { summary(p, data); // deleting its own reference - data.airbuildRunnable = null; + data.airbuildSummaryTask = null; } }; // Give a summary in 20 ticks ~ 1 second - plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.airbuildRunnable, 20); + plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.airbuildSummaryTask, 20); } data.airbuildPerSecond++; diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/BedteleportCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/BedteleportCheck.java index 3854c1e3..cc225645 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/BedteleportCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/BedteleportCheck.java @@ -19,7 +19,7 @@ public class BedteleportCheck extends Check { return; if(event.getFrom().getWorld().getBlockTypeIdAt(event.getFrom()) == Material.BED_BLOCK.getId()) { - double yRest = Math.floor(event.getFrom().getY()) - event.getFrom().getY(); + double yRest = event.getFrom().getY() - Math.floor(event.getFrom().getY()); if(yRest > 0.099 && yRest < 0.101) // Don't allow the teleport event.setCancelled(true); diff --git a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java index 16b7f28b..29569f4e 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/checks/MovingCheck.java @@ -1,10 +1,13 @@ package cc.co.evenprime.bukkit.nocheat.checks; +import java.util.logging.Level; + import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.util.Vector; import cc.co.evenprime.bukkit.nocheat.NoCheatData; @@ -53,7 +56,7 @@ public class MovingCheck extends Check { // Block types that may be treated specially private enum BlockType { - SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN; + SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN, FENCE; } // Until I can think of a better way to determine if a block is solid or not, this is what I'll do @@ -139,7 +142,7 @@ public class MovingCheck extends Check { types[Material.CLAY.getId()]= BlockType.SOLID; types[Material.SUGAR_CANE_BLOCK.getId()]= BlockType.NONSOLID; types[Material.JUKEBOX.getId()]= BlockType.SOLID; - types[Material.FENCE.getId()]= BlockType.UNKNOWN; + types[Material.FENCE.getId()]= BlockType.FENCE; types[Material.PUMPKIN.getId()]= BlockType.SOLID; types[Material.NETHERRACK.getId()]= BlockType.SOLID; types[Material.SOUL_SAND.getId()]= BlockType.UNKNOWN; @@ -158,49 +161,17 @@ public class MovingCheck extends Check { // Get the player-specific data final NoCheatData data = plugin.getPlayerData(event.getPlayer()); - + // Get the two locations of the event final Location to = event.getTo(); + // WORKAROUND for changed PLAYER_MOVE logic final Location from = data.movingTeleportTo == null ? event.getFrom() : data.movingTeleportTo; data.movingTeleportTo = null; - - // Notice to myself: How world changes with e.g. command /world work: - // 1. TeleportEvent from the players current position to another position in the _same_ world - // 2. MoveEvent(s) (yes, multiple events can be triggered) from that position in the _new_ world - // to the actual target position in the new world - // strange... - // I've no real way to get informed about a world change, therefore I have to - // store the "lastWorld" and compare it to the world of the next event - if(data.movingLastWorld != to.getWorld()) { - - data.movingLastWorld = to.getWorld(); - // "Forget" previous setback points - data.movingSetBackPoint = null; - data.speedhackSetBackPoint = null; - - // Store the destination that this move goes to for later use - data.movingLocation = to.clone(); - - // the world changed since our last check, therefore I can't check anything - // for this event (reliably) - return; - } - - if(data.movingLocation != null && data.movingLocation.equals(to)) { - // If we are still trying to reach that location, accept the move - return; - } - else if(data.movingLocation != null) { - // If we try to go somewhere else, delete the location. It is no longer needed - data.movingLocation = null; - } - - // Ignore vehicles + // vehicles are a special case if(event.getPlayer().isInsideVehicle()) { - data.movingSetBackPoint = null; - data.speedhackSetBackPoint = null; + resetData(data, event.getTo()); return; } @@ -211,7 +182,7 @@ public class MovingCheck extends Check { double zDistance = Math.abs(from.getZ()-to.getZ()); double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance)); - + // If the target is a bed and distance not too big, allow it if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && combined < 8.0D) { return; // players are allowed to "teleport" into a bed over "short" distances @@ -273,7 +244,7 @@ public class MovingCheck extends Check { double limit = data.movingVertFreedom; Location newSetBack = null; - + // Walk or start Jump if(onGroundFrom) { @@ -324,19 +295,17 @@ public class MovingCheck extends Check { } } - int vl = max(vl1, vl2); - - + int vl = vl1 > vl2 ? vl1 : vl2; if(vl < 0) { data.movingSetBackPoint = newSetBack == null ? data.movingSetBackPoint : newSetBack; } - + // If we haven't already got a setback point by now, make this location the new setback point if(data.movingSetBackPoint == null) { data.movingSetBackPoint = event.getFrom().clone(); } - + if(vl >= 0) { setupSummaryTask(event.getPlayer(), data); @@ -347,47 +316,57 @@ public class MovingCheck extends Check { } } - private void setupSummaryTask(final Player player, final NoCheatData data) { + private void setupSummaryTask(final Player p, final NoCheatData data) { // Setup task to display summary later - if(data.movingRunnable == null) { - data.movingRunnable = new Runnable() { + if(data.movingSummaryTask == null) { + data.movingSummaryTask = new Runnable() { @Override public void run() { - summary(player, data); + if(data.movingHighestLogLevel != null) { + String logString = "Moving summary of last ~" + (ticksBeforeSummary/20) + " seconds: "+p.getName() + " total Violations: ("+ data.movingViolationsInARow[0] + "," + data.movingViolationsInARow[1] + "," + data.movingViolationsInARow[2] + ")"; + plugin.log(data.movingHighestLogLevel, logString); + } // deleting its own reference - data.movingRunnable = null; + data.movingSummaryTask = null; + + data.movingViolationsInARow[0] = 0; + data.movingViolationsInARow[1] = 0; + data.movingViolationsInARow[2] = 0; } }; // Give a summary in x ticks. 20 ticks ~ 1 second - plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.movingRunnable, ticksBeforeSummary); + plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.movingSummaryTask, ticksBeforeSummary); } - } - public void teleported(PlayerMoveEvent event) { + + /** + * Call this when a player got successfully teleported with the corresponding event to set new "setback" points + * and reset data (if necessary) + * + * @param event + */ + public void teleported(PlayerTeleportEvent event) { NoCheatData data = plugin.getPlayerData(event.getPlayer()); - if(data.reset) { // My plugin requested this teleport, so we don't do anything + if(data.reset) { // My plugin requested this teleport while handling another event data.reset = false; } else { if(!event.isCancelled()) { // If it wasn't our plugin that ordered the teleport, forget (almost) all our information and start from scratch - // Setback points are created automatically the next time a move event is handled - data.speedhackSetBackPoint = event.getTo().clone(); - data.movingSetBackPoint = event.getTo().clone(); - data.speedhackEventsSinceLastCheck = 0; - data.movingJumpPhase = 0; + resetData(data, event.getTo()); } } - // WORKAROUND for changed PLAYER_MOVE logic + // WORKAROUND for changed PLAYER_MOVE logic - I need to remember the "to" location of teleports and use it as a from-Location + // for the move event that comes next data.movingTeleportTo = event.getTo(); } /** - * Perform actions that were specified by the admin + * Perform actions that were specified in the config file * @param event * @param action */ @@ -396,7 +375,7 @@ public class MovingCheck extends Check { if(actions == null) return; boolean cancelled = false; - // prepare log message if neccessary + // prepare log message if necessary String logMessage = null; if(loggingAllowed) { @@ -404,9 +383,10 @@ public class MovingCheck extends Check { } for(Action a : actions) { - if(a instanceof LogAction) { + if(loggingAllowed && a instanceof LogAction) { plugin.log(((LogAction)a).level, logMessage); - data.movingHighestLogLevel = ((LogAction)a).level.intValue() > data.movingHighestLogLevel.intValue() ? ((LogAction)a).level : data.movingHighestLogLevel; + if(data.movingHighestLogLevel == null) data.movingHighestLogLevel = Level.ALL; + if(data.movingHighestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.movingHighestLogLevel = ((LogAction)a).level; } else if(!cancelled && a instanceof CancelAction) { resetPlayer(event, from); @@ -417,13 +397,6 @@ public class MovingCheck extends Check { } } - private void summary(Player p, NoCheatData data) { - - String logString = "Moving summary of last ~" + (ticksBeforeSummary/20) + " seconds: "+p.getName() + " total Violations: ("+ data.movingViolationsInARow[0] + "," + data.movingViolationsInARow[1] + "," + data.movingViolationsInARow[2] + ")"; - - plugin.log(data.movingHighestLogLevel, logString); - } - private int limitCheck(double value, double limits[]) { for(int i = limits.length - 1; i >= 0; i--) { @@ -435,12 +408,6 @@ public class MovingCheck extends Check { return -1; } - private static int max(int a, int b) { - if(a > b) { - return a; - } - return b; - } /** * Return the player to a stored location or if that is not available, * the previous location. @@ -455,27 +422,22 @@ public class MovingCheck extends Check { // on solid ground, but in case it isn't (maybe the ground is gone now) we // still have to allow the player some freedom with vertical movement due // to lost vertical momentum to prevent him from getting stuck - data.movingJumpPhase = 0; - data.movingVertFreedom = 0.0D; - Location l = data.movingSetBackPoint; + if(data.movingSetBackPoint == null) data.movingSetBackPoint = from.clone(); + // Set a flag that gets used while handling teleport events data.reset = true; - // If we have stored a location for the player, we put him back there - if(l != null) { - // Lets try it that way. Maybe now people don't "disappear" any longer - event.setFrom(l.clone()); - event.setTo(l.clone()); - event.getPlayer().teleport(l.clone()); - event.setCancelled(true); - } - else { - // If we don't have a setback point, we'll have to use the from location - event.setFrom(from.clone()); - event.setTo(from.clone()); - event.getPlayer().teleport(from.clone()); - event.setCancelled(true); - } + + resetData(data, data.movingSetBackPoint); + + // Put the player back to the chosen location + event.setFrom(data.movingSetBackPoint.clone()); + event.setTo(data.movingSetBackPoint.clone()); + event.getPlayer().teleport(data.movingSetBackPoint.clone()); + event.setCancelled(true); + + + } @@ -496,8 +458,8 @@ public class MovingCheck extends Check { types[w.getBlockTypeIdAt(values[1], values[2]-1, values[4])] != BlockType.NONSOLID ) return true; // Check if he is hanging onto a ladder - else if(types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ())] == BlockType.LADDER || - types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()+1, l.getBlockZ())] == BlockType.LADDER) + else if(types[w.getBlockTypeIdAt(l.getBlockX(), values[2], l.getBlockZ())] == BlockType.LADDER || + types[w.getBlockTypeIdAt(l.getBlockX(), values[2]+1, l.getBlockZ())] == BlockType.LADDER) return true; // check if he is standing "in" a block that's potentially solid (we give him the benefit of a doubt and see that as a legit move) // If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case) @@ -524,6 +486,12 @@ public class MovingCheck extends Check { types[w.getBlockTypeIdAt(values[0], values[2], values[3]+1)] == BlockType.LIQUID || types[w.getBlockTypeIdAt(values[0], values[2]+1, values[3]+1)] == BlockType.LIQUID) return true; + // Running on fences + else if(types[w.getBlockTypeIdAt(values[0], values[2]-2, values[3])] == BlockType.FENCE || + types[w.getBlockTypeIdAt(values[1], values[2]-2, values[3])] == BlockType.FENCE || + types[w.getBlockTypeIdAt(values[0], values[2]-2, values[4])] == BlockType.FENCE || + types[w.getBlockTypeIdAt(values[1], values[2]-2, values[4])] == BlockType.FENCE ) + return true; else return false; } @@ -552,6 +520,15 @@ public class MovingCheck extends Check { return (int) (floor - d4); } + private void resetData(NoCheatData data, Location l) { + // If it wasn't our plugin that ordered the teleport, forget (almost) all our information and start from scratch + data.speedhackSetBackPoint = l; + data.movingSetBackPoint = l; + data.speedhackEventsSinceLastCheck = 0; + data.movingJumpPhase = 0; + data.movingTeleportTo = null; + } + @Override public String getName() { return "moving";