v0.7.8: Fixed config file creation/initialization + Walking on Fence

no longer causes false positives
This commit is contained in:
Evenprime 2011-04-03 22:43:31 +02:00
parent c47c2d98e8
commit 3f7f537fc0
10 changed files with 171 additions and 154 deletions

View File

@ -3,7 +3,7 @@ name: NoCheatPlugin
author: Evenprime author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin
version: 0.7.7c version: 0.7.8
commands: commands:
nocheat: nocheat:

View File

@ -29,9 +29,12 @@ public class NoCheatConfiguration {
public final Logger logger = Logger.getLogger(loggerName); public final Logger logger = Logger.getLogger(loggerName);
// The log level above which information gets logged to the specified logger // The log level above which information gets logged to the specified logger
public Level chatLevel = Level.OFF; public Level chatLevel = Level.WARNING;
public Level ircLevel = Level.OFF; public Level ircLevel = Level.WARNING;
public Level consoleLevel = Level.OFF; public Level consoleLevel = Level.SEVERE;
public Level fileLevel = Level.INFO;
public String fileName = "plugins/NoCheat/nocheat.log";
public String ircTag = "nocheat"; public String ircTag = "nocheat";
@ -63,10 +66,16 @@ public class NoCheatConfiguration {
logger.setLevel(Level.INFO); logger.setLevel(Level.INFO);
logger.setUseParentHandlers(false); 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) { if(fh == null) {
try { try {
fh = new FileHandler(c.getString("logging.filename"), true); fh = new FileHandler(fileName, true);
fh.setLevel(stringToLevel(c.getString("logging.logtofile"))); fh.setLevel(fileLevel);
fh.setFormatter(Logger.getLogger("Minecraft").getHandlers()[0].getFormatter()); fh.setFormatter(Logger.getLogger("Minecraft").getHandlers()[0].getFormatter());
logger.addHandler(fh); 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[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[1] = c.getInt("speedhack.limits.med", plugin.speedhackCheck.limits[1]);
plugin.speedhackCheck.limits[2] = c.getInt("speedhack.limits.high", plugin.speedhackCheck.limits[2]); 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())); plugin.bedteleportCheck.setActive(c.getBoolean("active.bedteleport", plugin.bedteleportCheck.isActive()));
} }
private Action[] stringToActions(String string, Action[] actions) { private Action[] stringToActions(String string, Action[] def) {
if(string == null) return actions; if(string == null) return def;
System.out.println(string);
List<Action> as = new LinkedList<Action>(); List<Action> as = new LinkedList<Action>();
String[] parts = string.split(" "); String[] parts = string.split(" ");
for(String s : parts) { for(String s : parts) {
s = s.trim();
if(s.equals("loglow")) if(s.equals("loglow"))
as.add(LogAction.loglow); as.add(LogAction.loglow);
else if(s.equals("logmed")) else if(s.equals("logmed"))
@ -136,35 +137,61 @@ public class NoCheatConfiguration {
//as.add(new CustomAction(Integer.parseInt(s.substring(6)))); //as.add(new CustomAction(Integer.parseInt(s.substring(6))));
} }
catch(Exception e) { 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 { 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 s.trim();
return as.toArray(actions);
} }
/** /**
* Convert a string into a log level * Convert a string into a log level
* @param string * @param string
* @return * @return
*/ */
private static Level stringToLevel(String string) { private static Level stringToLevel(String string, Level def) {
if(string == null) { if(string == null) {
return Level.OFF; return def;
} }
if(string.trim().equals("info") || string.trim().equals("low")) return Level.INFO; 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("warn") || string.trim().equals("med")) return Level.WARNING;
if(string.trim().equals("severe")|| string.trim().equals("high")) return Level.SEVERE; if(string.trim().equals("severe")|| string.trim().equals("high")) return Level.SEVERE;
return Level.OFF; 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 * Standard configuration file for people who haven't got one yet
* @param f * @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: potential log levels are low (info), med (warn), high (severe), off"); w.newLine();
w.write("logging:"); w.newLine(); w.write("logging:"); w.newLine();
w.write(" filename: plugins/NoCheat/nocheat.log"); w.newLine(); w.write(" filename: "+fileName); w.newLine();
w.write(" logtofile: low"); w.newLine(); w.write(" logtofile: "+levelToString(fileLevel)); w.newLine();
w.write(" logtoconsole: high"); w.newLine(); w.write(" logtoconsole: "+levelToString(consoleLevel)); w.newLine();
w.write(" logtochat: med"); w.newLine(); w.write(" logtochat: "+levelToString(chatLevel)); w.newLine();
w.write(" logtoirc: med"); w.newLine(); w.write(" logtoirc: "+levelToString(ircLevel)); w.newLine();
w.write(" logtoirctag: nocheat"); w.newLine(); w.write(" logtoirctag: "+ircTag); w.newLine();
w.write("# Checks and Bugfixes that are activated (true or false)"); w.newLine(); w.write("# Checks and Bugfixes that are activated (true or false)"); w.newLine();
w.write("active:"); w.newLine(); w.write("active:"); w.newLine();
w.write(" speedhack: "+plugin.speedhackCheck.isActive()); 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(" high: "+plugin.speedhackCheck.limits[2]); w.newLine();
w.write("# Speedhack Action, one or more of 'loglow logmed loghigh reset'"); w.newLine(); w.write("# Speedhack Action, one or more of 'loglow logmed loghigh reset'"); w.newLine();
w.write(" action:"); w.newLine(); w.write(" action:"); w.newLine();
w.write(" low: "+plugin.speedhackCheck.actions[0]); w.newLine(); w.write(" low: "+actionsToString(plugin.speedhackCheck.actions[0])); w.newLine();
w.write(" med: "+plugin.speedhackCheck.actions[1]); w.newLine(); w.write(" med: "+actionsToString(plugin.speedhackCheck.actions[1])); w.newLine();
w.write(" high: "+plugin.speedhackCheck.actions[2]); w.newLine(); w.write(" high: "+actionsToString(plugin.speedhackCheck.actions[2])); w.newLine();
w.write("# Moving specific options") ; w.newLine(); w.write("# Moving specific options") ; w.newLine();
w.write("moving:"); w.newLine(); w.write("moving:"); w.newLine();
w.write("# Moving Action, one or more of 'loglow logmed loghigh reset'"); w.newLine(); w.write("# Moving Action, one or more of 'loglow logmed loghigh reset'"); w.newLine();
w.write(" action:"); w.newLine(); w.write(" action:"); w.newLine();
w.write(" low: "+plugin.movingCheck.actions[0]); w.newLine(); w.write(" low: "+actionsToString(plugin.movingCheck.actions[0])); w.newLine();
w.write(" med: "+plugin.movingCheck.actions[1]); w.newLine(); w.write(" med: "+actionsToString(plugin.movingCheck.actions[1])); w.newLine();
w.write(" high: "+plugin.movingCheck.actions[2]); w.newLine(); w.write(" high: "+actionsToString(plugin.movingCheck.actions[2])); w.newLine();
w.write("# Airbuild specific options"); w.newLine(); w.write("# Airbuild specific options"); w.newLine();
w.write("airbuild:"); 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(); 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(" high: "+plugin.airbuildCheck.limits[2]); w.newLine();
w.write("# Airbuild Action, one or more of 'loglow logmed loghigh deny'"); w.newLine(); w.write("# Airbuild Action, one or more of 'loglow logmed loghigh deny'"); w.newLine();
w.write(" action:"); w.newLine(); w.write(" action:"); w.newLine();
w.write(" low: "+plugin.airbuildCheck.actions[0]); w.newLine(); w.write(" low: "+actionsToString(plugin.airbuildCheck.actions[0])); w.newLine();
w.write(" med: "+plugin.airbuildCheck.actions[1]); w.newLine(); w.write(" med: "+actionsToString(plugin.airbuildCheck.actions[1])); w.newLine();
w.write(" high: "+plugin.airbuildCheck.actions[2]); 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 specific options (none exist yet)"); w.newLine();
w.write("bedteleport:"); w.newLine(); w.write("bedteleport:"); w.newLine();

View File

@ -3,7 +3,6 @@ package cc.co.evenprime.bukkit.nocheat;
import java.util.logging.Level; import java.util.logging.Level;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
/** /**
* Storage for data persistence between events * 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 * 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 int movingViolationsInARow[] = { 0, 0, 0 };
public World movingLastWorld = null;
public double movingHorizFreedom = 0.0D; public double movingHorizFreedom = 0.0D;
public double movingVertFreedom = 0.0D; public double movingVertFreedom = 0.0D;
public int movingVertFreedomCounter = 0; public int movingVertFreedomCounter = 0;
public Location movingSetBackPoint = null; public Location movingSetBackPoint = null;
public Location movingLocation = null; public Runnable movingSummaryTask = null;
public Runnable movingRunnable = null;
public Level movingHighestLogLevel = null; public Level movingHighestLogLevel = null;
// WORKAROUND for changed PLAYER_MOVE logic // WORKAROUND for changed PLAYER_MOVE logic
@ -39,12 +36,7 @@ public class NoCheatData {
public int speedhackViolationsInARow = 0; public int speedhackViolationsInARow = 0;
public int airbuildPerSecond = 0; public int airbuildPerSecond = 0;
public Runnable airbuildRunnable = null; public Runnable airbuildSummaryTask = null;
public NoCheatData() { } public NoCheatData() { }
} }

View File

@ -9,4 +9,6 @@ public abstract class Action {
this.firstAfter = firstAfter; this.firstAfter = firstAfter;
this.repeat = repeat; this.repeat = repeat;
} }
public abstract String getName();
} }

View File

@ -5,4 +5,8 @@ public class CancelAction extends Action {
public final static CancelAction cancel = new CancelAction(); public final static CancelAction cancel = new CancelAction();
private CancelAction() { super(1, true); } private CancelAction() { super(1, true); }
public String getName() {
return "cancel";
}
} }

View File

@ -9,4 +9,8 @@ public class CustomAction extends Action {
super(firstAfter, repeat); super(firstAfter, repeat);
this.command = command; this.command = command;
} }
public String getName() {
return "custom";
}
} }

View File

@ -16,4 +16,15 @@ public class LogAction extends Action {
super(firstAfter, repeat); super(firstAfter, repeat);
this.level = level; 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 "";
}
} }

View File

@ -45,19 +45,19 @@ public class AirbuildCheck extends Check {
final NoCheatData data = plugin.getPlayerData(event.getPlayer()); final NoCheatData data = plugin.getPlayerData(event.getPlayer());
final Player p = event.getPlayer(); final Player p = event.getPlayer();
if(data.airbuildRunnable == null) { if(data.airbuildSummaryTask == null) {
data.airbuildRunnable = new Runnable() { data.airbuildSummaryTask = new Runnable() {
@Override @Override
public void run() { public void run() {
summary(p, data); summary(p, data);
// deleting its own reference // deleting its own reference
data.airbuildRunnable = null; data.airbuildSummaryTask = null;
} }
}; };
// Give a summary in 20 ticks ~ 1 second // 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++; data.airbuildPerSecond++;

View File

@ -19,7 +19,7 @@ public class BedteleportCheck extends Check {
return; return;
if(event.getFrom().getWorld().getBlockTypeIdAt(event.getFrom()) == Material.BED_BLOCK.getId()) { 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) if(yRest > 0.099 && yRest < 0.101)
// Don't allow the teleport // Don't allow the teleport
event.setCancelled(true); event.setCancelled(true);

View File

@ -1,10 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks; package cc.co.evenprime.bukkit.nocheat.checks;
import java.util.logging.Level;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheatData; import cc.co.evenprime.bukkit.nocheat.NoCheatData;
@ -53,7 +56,7 @@ public class MovingCheck extends Check {
// Block types that may be treated specially // Block types that may be treated specially
private enum BlockType { 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 // 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.CLAY.getId()]= BlockType.SOLID;
types[Material.SUGAR_CANE_BLOCK.getId()]= BlockType.NONSOLID; types[Material.SUGAR_CANE_BLOCK.getId()]= BlockType.NONSOLID;
types[Material.JUKEBOX.getId()]= BlockType.SOLID; 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.PUMPKIN.getId()]= BlockType.SOLID;
types[Material.NETHERRACK.getId()]= BlockType.SOLID; types[Material.NETHERRACK.getId()]= BlockType.SOLID;
types[Material.SOUL_SAND.getId()]= BlockType.UNKNOWN; types[Material.SOUL_SAND.getId()]= BlockType.UNKNOWN;
@ -158,49 +161,17 @@ public class MovingCheck extends Check {
// Get the player-specific data // Get the player-specific data
final NoCheatData data = plugin.getPlayerData(event.getPlayer()); final NoCheatData data = plugin.getPlayerData(event.getPlayer());
// Get the two locations of the event // Get the two locations of the event
final Location to = event.getTo(); final Location to = event.getTo();
// WORKAROUND for changed PLAYER_MOVE logic // WORKAROUND for changed PLAYER_MOVE logic
final Location from = data.movingTeleportTo == null ? event.getFrom() : data.movingTeleportTo; final Location from = data.movingTeleportTo == null ? event.getFrom() : data.movingTeleportTo;
data.movingTeleportTo = null; 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 // vehicles are a special case
// 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
if(event.getPlayer().isInsideVehicle()) { if(event.getPlayer().isInsideVehicle()) {
data.movingSetBackPoint = null; resetData(data, event.getTo());
data.speedhackSetBackPoint = null;
return; return;
} }
@ -211,7 +182,7 @@ public class MovingCheck extends Check {
double zDistance = Math.abs(from.getZ()-to.getZ()); double zDistance = Math.abs(from.getZ()-to.getZ());
double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance)); double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance));
// If the target is a bed and distance not too big, allow it // 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) { if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && combined < 8.0D) {
return; // players are allowed to "teleport" into a bed over "short" distances 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; double limit = data.movingVertFreedom;
Location newSetBack = null; Location newSetBack = null;
// Walk or start Jump // Walk or start Jump
if(onGroundFrom) 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) { if(vl < 0) {
data.movingSetBackPoint = newSetBack == null ? data.movingSetBackPoint : newSetBack; 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 we haven't already got a setback point by now, make this location the new setback point
if(data.movingSetBackPoint == null) { if(data.movingSetBackPoint == null) {
data.movingSetBackPoint = event.getFrom().clone(); data.movingSetBackPoint = event.getFrom().clone();
} }
if(vl >= 0) { if(vl >= 0) {
setupSummaryTask(event.getPlayer(), data); 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 // Setup task to display summary later
if(data.movingRunnable == null) { if(data.movingSummaryTask == null) {
data.movingRunnable = new Runnable() { data.movingSummaryTask = new Runnable() {
@Override @Override
public void run() { 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 // 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 // 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()); 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; data.reset = false;
} }
else { else {
if(!event.isCancelled()) { if(!event.isCancelled()) {
// If it wasn't our plugin that ordered the teleport, forget (almost) all our information and start from scratch // 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 resetData(data, event.getTo());
data.speedhackSetBackPoint = event.getTo().clone();
data.movingSetBackPoint = event.getTo().clone();
data.speedhackEventsSinceLastCheck = 0;
data.movingJumpPhase = 0;
} }
} }
// 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(); data.movingTeleportTo = event.getTo();
} }
/** /**
* Perform actions that were specified by the admin * Perform actions that were specified in the config file
* @param event * @param event
* @param action * @param action
*/ */
@ -396,7 +375,7 @@ public class MovingCheck extends Check {
if(actions == null) return; if(actions == null) return;
boolean cancelled = false; boolean cancelled = false;
// prepare log message if neccessary // prepare log message if necessary
String logMessage = null; String logMessage = null;
if(loggingAllowed) { if(loggingAllowed) {
@ -404,9 +383,10 @@ public class MovingCheck extends Check {
} }
for(Action a : actions) { for(Action a : actions) {
if(a instanceof LogAction) { if(loggingAllowed && a instanceof LogAction) {
plugin.log(((LogAction)a).level, logMessage); 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) { else if(!cancelled && a instanceof CancelAction) {
resetPlayer(event, from); 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[]) { private int limitCheck(double value, double limits[]) {
for(int i = limits.length - 1; i >= 0; i--) { for(int i = limits.length - 1; i >= 0; i--) {
@ -435,12 +408,6 @@ public class MovingCheck extends Check {
return -1; 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, * Return the player to a stored location or if that is not available,
* the previous location. * 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 // 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 // still have to allow the player some freedom with vertical movement due
// to lost vertical momentum to prevent him from getting stuck // 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; data.reset = true;
// If we have stored a location for the player, we put him back there
if(l != null) { resetData(data, data.movingSetBackPoint);
// Lets try it that way. Maybe now people don't "disappear" any longer
event.setFrom(l.clone()); // Put the player back to the chosen location
event.setTo(l.clone()); event.setFrom(data.movingSetBackPoint.clone());
event.getPlayer().teleport(l.clone()); event.setTo(data.movingSetBackPoint.clone());
event.setCancelled(true); event.getPlayer().teleport(data.movingSetBackPoint.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);
}
} }
@ -496,8 +458,8 @@ public class MovingCheck extends Check {
types[w.getBlockTypeIdAt(values[1], values[2]-1, values[4])] != BlockType.NONSOLID ) types[w.getBlockTypeIdAt(values[1], values[2]-1, values[4])] != BlockType.NONSOLID )
return true; return true;
// Check if he is hanging onto a ladder // Check if he is hanging onto a ladder
else if(types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ())] == BlockType.LADDER || else if(types[w.getBlockTypeIdAt(l.getBlockX(), values[2], l.getBlockZ())] == BlockType.LADDER ||
types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()+1, l.getBlockZ())] == BlockType.LADDER) types[w.getBlockTypeIdAt(l.getBlockX(), values[2]+1, l.getBlockZ())] == BlockType.LADDER)
return true; 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) // 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) // 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], values[3]+1)] == BlockType.LIQUID ||
types[w.getBlockTypeIdAt(values[0], values[2]+1, values[3]+1)] == BlockType.LIQUID) types[w.getBlockTypeIdAt(values[0], values[2]+1, values[3]+1)] == BlockType.LIQUID)
return true; 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 else
return false; return false;
} }
@ -552,6 +520,15 @@ public class MovingCheck extends Check {
return (int) (floor - d4); 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 @Override
public String getName() { public String getName() {
return "moving"; return "moving";