Rewritten parts of moving check

This commit is contained in:
Evenprime 2011-03-26 14:15:39 +01:00
parent 77f347e182
commit 74e39bc99e
4 changed files with 136 additions and 163 deletions

View File

@ -80,21 +80,21 @@ public class NoCheatConfiguration {
plugin.speedhackCheck.limitMed = c.getInt("speedhack.limits.med", plugin.speedhackCheck.limitMed); plugin.speedhackCheck.limitMed = c.getInt("speedhack.limits.med", plugin.speedhackCheck.limitMed);
plugin.speedhackCheck.limitHigh = c.getInt("speedhack.limits.high", plugin.speedhackCheck.limitHigh); plugin.speedhackCheck.limitHigh = c.getInt("speedhack.limits.high", plugin.speedhackCheck.limitHigh);
plugin.movingCheck.actionLow = c.getString("moving.action.low", plugin.movingCheck.actionLow); plugin.movingCheck.actions[0] = c.getString("moving.action.low", plugin.movingCheck.actions[0]);
plugin.movingCheck.actionMed = c.getString("moving.action.med", plugin.movingCheck.actionMed); plugin.movingCheck.actions[1] = c.getString("moving.action.med", plugin.movingCheck.actions[1]);
plugin.movingCheck.actionHigh = c.getString("moving.action.high", plugin.movingCheck.actionHigh); plugin.movingCheck.actions[2] = c.getString("moving.action.high", plugin.movingCheck.actions[2]);
plugin.speedhackCheck.actionLow = c.getString("speedhack.action.low", plugin.speedhackCheck.actionLow); plugin.speedhackCheck.actionLow = c.getString("speedhack.action.low", plugin.speedhackCheck.actionLow);
plugin.speedhackCheck.actionMed = c.getString("speedhack.action.med", plugin.speedhackCheck.actionMed); plugin.speedhackCheck.actionMed = c.getString("speedhack.action.med", plugin.speedhackCheck.actionMed);
plugin.speedhackCheck.actionHigh = c.getString("speedhack.action.high", plugin.speedhackCheck.actionHigh); plugin.speedhackCheck.actionHigh = c.getString("speedhack.action.high", plugin.speedhackCheck.actionHigh);
plugin.airbuildCheck.limitLow = c.getInt("airbuild.limits.low", plugin.airbuildCheck.limitLow); plugin.airbuildCheck.limits[0] = c.getInt("airbuild.limits.low", plugin.airbuildCheck.limits[0]);
plugin.airbuildCheck.limitMed = c.getInt("airbuild.limits.med", plugin.airbuildCheck.limitMed); plugin.airbuildCheck.limits[1] = c.getInt("airbuild.limits.med", plugin.airbuildCheck.limits[1]);
plugin.airbuildCheck.limitHigh = c.getInt("airbuild.limits.high", plugin.airbuildCheck.limitHigh); plugin.airbuildCheck.limits[2] = c.getInt("airbuild.limits.high", plugin.airbuildCheck.limits[2]);
plugin.airbuildCheck.actionLow = c.getString("airbuild.action.low", plugin.airbuildCheck.actionLow); plugin.airbuildCheck.actions[0] = c.getString("airbuild.action.low", plugin.airbuildCheck.actions[0]);
plugin.airbuildCheck.actionMed = c.getString("airbuild.action.med", plugin.airbuildCheck.actionMed); plugin.airbuildCheck.actions[1] = c.getString("airbuild.action.med", plugin.airbuildCheck.actions[1]);
plugin.airbuildCheck.actionHigh = c.getString("airbuild.action.high", plugin.airbuildCheck.actionHigh); plugin.airbuildCheck.actions[2] = c.getString("airbuild.action.high", plugin.airbuildCheck.actions[2]);
plugin.speedhackCheck.setActive(c.getBoolean("active.speedhack", plugin.speedhackCheck.isActive())); plugin.speedhackCheck.setActive(c.getBoolean("active.speedhack", plugin.speedhackCheck.isActive()));
plugin.movingCheck.setActive(c.getBoolean("active.moving", plugin.movingCheck.isActive())); plugin.movingCheck.setActive(c.getBoolean("active.moving", plugin.movingCheck.isActive()));
@ -158,21 +158,21 @@ public class NoCheatConfiguration {
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.actionLow); w.newLine(); w.write(" low: "+plugin.movingCheck.actions[0]); w.newLine();
w.write(" med: "+plugin.movingCheck.actionMed); w.newLine(); w.write(" med: "+plugin.movingCheck.actions[1]); w.newLine();
w.write(" high: "+plugin.movingCheck.actionHigh); w.newLine(); w.write(" high: "+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();
w.write(" limits:"); w.newLine(); w.write(" limits:"); w.newLine();
w.write(" low: "+plugin.airbuildCheck.limitLow); w.newLine(); w.write(" low: "+plugin.airbuildCheck.limits[0]); w.newLine();
w.write(" med: "+plugin.airbuildCheck.limitMed); w.newLine(); w.write(" med: "+plugin.airbuildCheck.limits[1]); w.newLine();
w.write(" high: "+plugin.airbuildCheck.limitHigh); 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.actionLow); w.newLine(); w.write(" low: "+plugin.airbuildCheck.actions[0]); w.newLine();
w.write(" med: "+plugin.airbuildCheck.actionMed); w.newLine(); w.write(" med: "+plugin.airbuildCheck.actions[1]); w.newLine();
w.write(" high: "+plugin.airbuildCheck.actionHigh); w.newLine(); w.write(" high: "+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

@ -17,9 +17,7 @@ public class NoCheatData {
public int movingJumpPhase = 0; // current jumpingPhase public int movingJumpPhase = 0; // current jumpingPhase
public long movingLastViolationTime = 0; public long movingLastViolationTime = 0;
public int movingMinorViolationsInARow = 0; public int movingViolationsInARow[] = { 0, 0, 0 };
public int movingNormalViolationsInARow = 0;
public int movingHeavyViolationsInARow = 0;
public World movingLastWorld = null; public World movingLastWorld = null;
public int movingHorizFreeMoves = 4; public int movingHorizFreeMoves = 4;
public Location movingSetBackPoint = null; public Location movingSetBackPoint = null;

View File

@ -18,13 +18,9 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
public class AirbuildCheck extends Check { public class AirbuildCheck extends Check {
// How should airbuild violations be treated? // How should airbuild violations be treated?
public String actionLow = "loglow deny"; public final String actions[] = { "loglow deny", "logmed deny", "loghigh deny" };
public String actionMed = "logmed deny";
public String actionHigh = "loghigh deny"; public final int limits[] = { 1, 3, 10 };
public int limitLow = 1;
public int limitMed = 3;
public int limitHigh = 10;
public AirbuildCheck(NoCheatPlugin plugin) { public AirbuildCheck(NoCheatPlugin plugin) {
super(plugin); super(plugin);
@ -60,28 +56,17 @@ public class AirbuildCheck extends Check {
data.airbuildPerSecond++; data.airbuildPerSecond++;
boolean log = false; boolean log = false;
// Only explicitly log certain "milestones"
if(data.airbuildPerSecond >= limitHigh) { // which limit has been reached
if(data.airbuildPerSecond == limitHigh) { for(int i = limits.length-1; i >= 0; i--) {
log = true; if(data.airbuildPerSecond >= limits[i]) {
// Only explicitly log certain "milestones"
if(data.airbuildPerSecond == limits[i]) {
log = true;
}
action(actions[i], event, log);
break;
} }
action(actionHigh, event, log);
}
else if(data.airbuildPerSecond >= limitMed) {
if(data.airbuildPerSecond == limitMed) {
log = true;
}
action(actionMed, event, log);
}
else if(data.airbuildPerSecond >= limitLow) {
if(data.airbuildPerSecond == limitLow) {
log = true;
}
action(actionLow, event, log);
}
else
{
// ignore for now
} }
} }
} }
@ -102,17 +87,12 @@ public class AirbuildCheck extends Check {
private void summary(Player player, NoCheatData data) { private void summary(Player player, NoCheatData data) {
String logLine = "Airbuild violation summary: " +player.getName() + " total events per second: " + data.airbuildPerSecond;
// Give a summary according to the highest violation level we encountered in that second // Give a summary according to the highest violation level we encountered in that second
if(data.airbuildPerSecond >= limitHigh) { for(int i = limits.length-1; i >= 0; i--) {
plugin.logAction(actionHigh, logLine); if(data.airbuildPerSecond >= limits[i]) {
} plugin.logAction(actions[i], "Airbuild violation summary: " +player.getName() + " total events per second: " + data.airbuildPerSecond);
else if(data.airbuildPerSecond >= limitMed) { break;
plugin.logAction(actionMed, logLine); }
}
else if(data.airbuildPerSecond >= limitLow) {
plugin.logAction(actionLow, logLine);
} }
data.airbuildPerSecond = 0; data.airbuildPerSecond = 0;

View File

@ -1,8 +1,5 @@
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;
@ -25,26 +22,24 @@ public class MovingCheck extends Check {
} }
// How many move events can a player have in air before he is expected to lose altitude (or land somewhere) // How many move events can a player have in air before he is expected to lose altitude (or land somewhere)
static final int jumpingLimit = 4; private final int jumpingLimit = 4;
// How high may a player get compared to his last location with ground contact // How high may a player get compared to his last location with ground contact
static final double jumpingHeightLimit = 1.3D; private final double jumpHeight = 1.3D;
// How high may a player move in one event on ground // How high may a player move in one event on ground
static double stepHeight = 0.501D; private double stepHeight = 0.501D;
// Limits for the horizontal moving check // Limits
public static double movingDistanceLow = 0.1D; public final double moveLimits[] = { 0.1D, 2.0D, 5.0D };
public static double movingDistanceMed = 2.0D;
public static double movingDistanceHigh = 5.0D;
// How should moving violations be treated? public final double heightLimits[] = { 0.0D, 0.5D, 2.0D };
public String actionLow = "loglow reset";
public String actionMed = "logmed reset";
public String actionHigh = "loghigh reset";
final static double magic = 0.30000001192092896D; // How should moving violations be treated?
final static double magic2 = 0.69999998807907103D; public final String actions[] = { "loglow reset", "logmed reset", "loghigh reset" };
private static final double magic = 0.30000001192092896D;
private static final double magic2 = 0.69999998807907103D;
// Block types that may be treated specially // Block types that may be treated specially
private enum BlockType { private enum BlockType {
@ -220,20 +215,20 @@ public class MovingCheck extends Check {
return; // players are allowed to "teleport" into a bed over short distances return; // players are allowed to "teleport" into a bed over short distances
} }
Level vl = null; // The violation level (none, minor, normal, heavy) int vlx = -1;
// How far are we off? // How far are we off?
if(combined > movingDistanceHigh) { if(combined > moveLimits[2]) {
vl = max(vl, Level.SEVERE); vlx = max(vlx, 2);
} }
else if(combined > movingDistanceMed) { else if(combined > moveLimits[1]) {
vl = max(vl, Level.WARNING); vlx = max(vlx, 1);
} }
else if(combined > movingDistanceLow) { else if(combined > moveLimits[0]) {
if(data.movingHorizFreeMoves > 0) { if(data.movingHorizFreeMoves > 0) {
data.movingHorizFreeMoves--; data.movingHorizFreeMoves--;
} }
else vl = max(vl, Level.INFO); else vlx = max(vlx, 0);
} }
else{ else{
data.movingHorizFreeMoves = 4; data.movingHorizFreeMoves = 4;
@ -248,88 +243,75 @@ public class MovingCheck extends Check {
boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from); boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from);
boolean onGroundTo = playerIsOnGround(to.getWorld(), toValues, to); boolean onGroundTo = playerIsOnGround(to.getWorld(), toValues, to);
// Both locations seem to be on solid ground or at a ladder // Handle 4 distinct cases: Walk, Jump, Land, Fly
// Walk
if(onGroundFrom && onGroundTo) if(onGroundFrom && onGroundTo)
{ {
// Check if the player isn't 'walking' up unrealistically far in one step double limit = stepHeight;
// Finally found out why this can happen: double distance = to.getY() - from.getY();
// 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() < stepHeight)) {
double offset = (to.getY() - from.getY()) - stepHeight; vlx = max(vlx, heightLimitCheck(limit, distance));
if(offset > 2D) vl = max(vl, Level.SEVERE); if(vlx < 0)
else if(offset > 0.5D) vl = max(vl, Level.WARNING);
else vl = max(vl, Level.INFO);
}
else
{ {
// reset jumping // reset jumping
data.movingJumpPhase = 0; data.movingJumpPhase = 0;
data.movingSetBackPoint = from.clone(); data.movingSetBackPoint = from.clone();
} }
} }
// player is starting to jump (or starting to fall down somewhere) // Jump
else if(onGroundFrom && !onGroundTo) else if(onGroundFrom && !onGroundTo)
{ {
double limit = jumpHeight;
double distance = to.getY() - from.getY();
// Check if player isn't jumping too high // Check if player isn't jumping too high
double limit = jumpingHeightLimit; vlx = max(vlx, heightLimitCheck(limit, distance));
if(to.getY() - from.getY() > limit) { if(vlx < 0) {
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);
}
else {
// Setup next phase of the jump // Setup next phase of the jump
data.movingJumpPhase = 1; data.movingJumpPhase = 1;
data.movingSetBackPoint = from.clone(); data.movingSetBackPoint = from.clone();
} }
} }
// player is probably landing somewhere // Land
else if(!onGroundFrom && onGroundTo) else if(!onGroundFrom && onGroundTo)
{ {
// Check if player isn't landing to high (sounds weird, but has its use) Location l = data.movingSetBackPoint == null ? from : data.movingSetBackPoint;
Location l = data.movingSetBackPoint;
if(l == null) { l = from; }
double limit = jumpingHeightLimit + stepHeight; double limit;
if(to.getY() - l.getY() > limit) { if(data.movingJumpPhase > jumpingLimit)
limit = jumpHeight + stepHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
else limit = jumpHeight;
double offset = (to.getY() - l.getY()) - limit; double distance = to.getY() - l.getY();
if(offset > 2D) vl = max(vl, Level.SEVERE); // Check if player isn't jumping too high
else if(offset > 0.5D) vl = max(vl, Level.WARNING); vlx = max(vlx, heightLimitCheck(limit, distance));
else vl = max(vl, Level.INFO);
} if(vlx < 0) {
else {
data.movingJumpPhase = 0; // He is on ground now, so reset the jump data.movingJumpPhase = 0; // He is on ground now, so reset the jump
data.movingSetBackPoint = to.clone(); data.movingSetBackPoint = to.clone();
} }
} }
// Player is moving through air (during jumping, falling) // Player is moving through air (during jumping, falling)
else { else {
Location l = data.movingSetBackPoint; Location l = data.movingSetBackPoint == null ? from : data.movingSetBackPoint;
if(l == null) { l = from; }
// The expected fall velocity is a rough estimate - players usually accelerate by that value double limit;
double limit = (data.movingJumpPhase > jumpingLimit) ? jumpingHeightLimit - (data.movingJumpPhase-jumpingLimit) * 0.2D : jumpingHeightLimit;
if(to.getY() - l.getY() > limit) if(data.movingJumpPhase > jumpingLimit)
{ limit = jumpHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
double offset = (to.getY() - l.getY()) - limit; else limit = jumpHeight;
double distance = to.getY() - l.getY();
if(offset > 2D) vl = max(vl, Level.SEVERE); // Check if player isn't jumping too high
else if(offset > 0.5D) vl = max(vl, Level.WARNING); vlx = max(vlx, heightLimitCheck(limit, distance));
else vl = max(vl, Level.INFO);
} if(vlx < 0) {
else {
data.movingJumpPhase++; // Enter next phase of the flight data.movingJumpPhase++; // Enter next phase of the flight
// Setback point stays the same. IF we don't have one, take the "from" location as a setback point for now // 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) { if(data.movingSetBackPoint == null) {
@ -338,10 +320,10 @@ public class MovingCheck extends Check {
} }
} }
if(vl == null && (onGroundFrom || onGroundTo)) { if(vlx < 0 && (onGroundFrom || onGroundTo)) {
legitimateMove(data, event); legitimateMove(data, event);
} }
else if(vl != null) { else if(vlx >= 0) {
data.movingLastViolationTime = System.currentTimeMillis(); data.movingLastViolationTime = System.currentTimeMillis();
@ -350,35 +332,35 @@ public class MovingCheck extends Check {
data.movingSetBackPoint = event.getFrom().clone(); data.movingSetBackPoint = event.getFrom().clone();
} }
String actions = null; String action = null;
boolean log = true; boolean log = true;
// Find out with what actions to treat the violation(s) // Find out with what actions to treat the violation(s)
if(Level.INFO.equals(vl)) { if(vlx == 0) {
if(data.movingMinorViolationsInARow > 0) log = false; if(data.movingViolationsInARow[0] > 0) log = false;
data.movingMinorViolationsInARow++; data.movingViolationsInARow[0]++;
actions = actionLow; action = actions[0];
// after a set number of minor violations a normal violation gets thrown // after a set number of minor violations a normal violation gets thrown
if(data.movingMinorViolationsInARow % 40 == 0) { if(data.movingViolationsInARow[0] % 40 == 0) {
vl = Level.WARNING; vlx = 1;
log = true; log = true;
} }
} }
if(Level.WARNING.equals(vl)) { if(vlx == 1) {
if(data.movingNormalViolationsInARow > 0) log = false; if(data.movingViolationsInARow[1] > 0) log = false;
data.movingNormalViolationsInARow++; data.movingViolationsInARow[1]++;
actions = actionMed; action = actions[1];
} }
if(Level.SEVERE.equals(vl)) { if(vlx == 2) {
if(data.movingHeavyViolationsInARow > 0) log = false; if(data.movingViolationsInARow[2] > 0) log = false;
data.movingHeavyViolationsInARow++; data.movingViolationsInARow[2]++;
actions = actionHigh; action = actions[2];
} }
action(event, actions, log); action(event, action, log);
} }
} }
@ -427,28 +409,41 @@ public class MovingCheck extends Check {
data.movingLastViolationTime = 0; data.movingLastViolationTime = 0;
// Give some additional logs about now ending violations // Give some additional logs about now ending violations
if(data.movingHeavyViolationsInARow > 0) { if(data.movingViolationsInARow[2] > 0) {
plugin.logAction(actionHigh, "Moving violation ended: "+event.getPlayer().getName() + " total Events: "+ data.movingHeavyViolationsInARow); plugin.logAction(actions[2], "Moving violation ended: "+event.getPlayer().getName() + " total Events: "+ data.movingViolationsInARow[2]);
data.movingHeavyViolationsInARow = 0; data.movingViolationsInARow[2] = 0;
} }
if(data.movingNormalViolationsInARow > 0) { if(data.movingViolationsInARow[1] > 0) {
plugin.logAction(actionMed, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingNormalViolationsInARow); plugin.logAction(actions[1], "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingViolationsInARow[1]);
data.movingNormalViolationsInARow = 0; data.movingViolationsInARow[1] = 0;
} }
if(data.movingMinorViolationsInARow > 0) { if(data.movingViolationsInARow[0] > 0) {
plugin.logAction(actionLow, "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingMinorViolationsInARow); plugin.logAction(actions[0], "Moving violation ended: "+event.getPlayer().getName()+ " total Events: "+ data.movingViolationsInARow[0]);
data.movingMinorViolationsInARow = 0; data.movingViolationsInARow[0] = 0;
} }
data.movingMinorViolationsInARow = 0; data.movingViolationsInARow[0] = 0;
} }
} }
private int heightLimitCheck(double limit, double value) {
double offset = value - limit;
for(int i = heightLimits.length - 1; i >= 0; i--) {
if(offset > heightLimits[i]) {
return i;
}
}
private static Level max(Level l1, Level l2) { return -1;
if(l1 == null) return l2; }
if(l2 == null) return l1;
if(l1.intValue() > l2.intValue()) return l1; private static int max(int a, int b) {
else return l2; 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,