Code Refactoring plus preparations for custom events

This commit is contained in:
Evenprime 2011-04-03 20:36:06 +02:00
parent 085cad8ee8
commit c47c2d98e8
12 changed files with 192 additions and 214 deletions

View File

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

View File

@ -1,20 +0,0 @@
package cc.co.evenprime.bukkit.nocheat;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
public class CustomAction implements Action {
private final int id;
private final String command;
public CustomAction(int id, String command) {
this.id = id;
this.command = command;
}
public void execute(Player player) {
// TODO: add command execution
}
}

View File

@ -117,16 +117,19 @@ public class NoCheatConfiguration {
String[] parts = string.split(" ");
for(String s : parts) {
s = s.trim();
if(s.equals("loglow"))
as.add(LogAction.logLow);
as.add(LogAction.loglow);
else if(s.equals("logmed"))
as.add(LogAction.logMed);
as.add(LogAction.logmed);
else if(s.equals("loghigh"))
as.add(LogAction.logHigh);
as.add(LogAction.loghigh);
else if(s.equals("deny"))
as.add(CancelAction.deny);
as.add(CancelAction.cancel);
else if(s.equals("reset"))
as.add(CancelAction.reset);
as.add(CancelAction.cancel);
else if(s.equals("cancel"))
as.add(CancelAction.cancel);
else if(s.startsWith("custom")) {
try {
// TODO: Implement Custom Action
@ -136,6 +139,9 @@ public class NoCheatConfiguration {
plugin.log(Level.WARNING, "Couldn't parse number of custom action '" + s + "'");
}
}
else {
plugin.log(Level.WARNING, "Can't parse action "+ s);
}
}

View File

@ -1,5 +1,7 @@
package cc.co.evenprime.bukkit.nocheat;
import java.util.logging.Level;
import org.bukkit.Location;
import org.bukkit.World;
@ -24,6 +26,7 @@ public class NoCheatData {
public Location movingSetBackPoint = null;
public Location movingLocation = null;
public Runnable movingRunnable = null;
public Level movingHighestLogLevel = null;
// WORKAROUND for changed PLAYER_MOVE logic
public Location movingTeleportTo = null;
@ -42,5 +45,6 @@ public class NoCheatData {
public NoCheatData() { }
}

View File

@ -15,6 +15,7 @@ import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.checks.AirbuildCheck;
import cc.co.evenprime.bukkit.nocheat.checks.BedteleportCheck;
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
@ -318,4 +319,9 @@ public class NoCheatPlugin extends JavaPlugin {
(!bedteleportCheck.isActive() ? bedteleportCheck.getName() + "* " : (hasPermission(p, "nocheat.bedteleport") ? bedteleportCheck.getName() + " " : "")) +
(hasPermission(p, "nocheat.notify") ? "notify " : ""));
}
public void handleCustomAction(Action a, Player player) {
// TODO Auto-generated method stub
}
}

View File

@ -1,5 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.actions;
public interface Action {
public abstract class Action {
public final int firstAfter;
public final boolean repeat;
public Action(int firstAfter, boolean repeat) {
this.firstAfter = firstAfter;
this.repeat = repeat;
}
}

View File

@ -1,9 +1,8 @@
package cc.co.evenprime.bukkit.nocheat.actions;
public class CancelAction implements Action {
public static final CancelAction deny = new CancelAction();
public static final CancelAction reset = new CancelAction();
public class CancelAction extends Action {
private CancelAction() { }
public final static CancelAction cancel = new CancelAction();
private CancelAction() { super(1, true); }
}

View File

@ -0,0 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.actions;
public class CustomAction extends Action {
public final String command;
public CustomAction(int firstAfter, boolean repeat, String command) {
super(firstAfter, repeat);
this.command = command;
}
}

View File

@ -2,27 +2,18 @@ package cc.co.evenprime.bukkit.nocheat.actions;
import java.util.logging.Level;
public class LogAction implements Action {
public class LogAction extends Action {
private final int index;
private final Level level;
public final Level level;
public final static LogAction logLow = new LogAction(0, Level.INFO);
public final static LogAction logMed = new LogAction(1, Level.WARNING);
public final static LogAction logHigh = new LogAction(2, Level.SEVERE);
public final static LogAction loglow = new LogAction(1, false, Level.INFO);
public final static LogAction logmed = new LogAction(1, false, Level.WARNING);
public final static LogAction loghigh = new LogAction(1, false, Level.SEVERE);
public final static LogAction log[] = { logLow, logMed, logHigh };
public final static LogAction[] log = { loglow, logmed, loghigh };
private LogAction(int index, Level level) {
this.index = index;
public LogAction(int firstAfter, boolean repeat, Level level) {
super(firstAfter, repeat);
this.level = level;
}
public Level getLevel() {
return level;
}
public int getIndex() {
return index;
}
}

View File

@ -9,6 +9,7 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
import cc.co.evenprime.bukkit.nocheat.actions.CustomAction;
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
@ -22,9 +23,9 @@ public class AirbuildCheck extends Check {
// How should airbuild violations be treated?
public final Action actions[][] = {
{ LogAction.logLow, CancelAction.deny },
{ LogAction.logMed, CancelAction.deny },
{ LogAction.logHigh, CancelAction.deny } };
{ LogAction.loglow, CancelAction.cancel },
{ LogAction.logmed, CancelAction.cancel },
{ LogAction.loghigh, CancelAction.cancel } };
public final int limits[] = { 1, 3, 10 };
@ -77,15 +78,31 @@ public class AirbuildCheck extends Check {
}
}
private void action(Action actions[], BlockPlaceEvent event, boolean log) {
private void action(Action actions[], BlockPlaceEvent event, boolean loggingAllowed) {
if(actions == null) return;
boolean cancelled = false;
// Prepare log message if needed
String logMessage = null;
if(loggingAllowed) {
final Location l = event.getBlockPlaced().getLocation();
logMessage = "Airbuild: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() +"," + l.getBlockZ();
}
// Execute actions in order
for(Action a : actions) {
if(log && a instanceof LogAction) {
final Location l = event.getBlockPlaced().getLocation();
plugin.log(((LogAction)a).getLevel(), "Airbuild: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() +"," + l.getBlockZ());
if(loggingAllowed && a instanceof LogAction) {
plugin.log(((LogAction)a).level, logMessage);
}
else if(a instanceof CancelAction)
else if(!cancelled && a instanceof CancelAction) {
event.setCancelled(true);
cancelled = true;
}
else if(a instanceof CustomAction) {
plugin.handleCustomAction(a, event.getPlayer());
}
}
}
@ -94,7 +111,7 @@ public class AirbuildCheck extends Check {
// Give a summary according to the highest violation level we encountered in that second
for(int i = limits.length-1; i >= 0; i--) {
if(data.airbuildPerSecond >= limits[i]) {
plugin.log(LogAction.log[i].getLevel(), "Airbuild summary: " +player.getName() + " total violations per second: " + data.airbuildPerSecond);
plugin.log(LogAction.log[i].level, "Airbuild summary: " +player.getName() + " total violations per second: " + data.airbuildPerSecond);
break;
}
}

View File

@ -11,6 +11,7 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
import cc.co.evenprime.bukkit.nocheat.actions.CustomAction;
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
/**
@ -36,17 +37,16 @@ public class MovingCheck extends Check {
private final double stepHeight = 0.501D;
// Limits
public final double moveLimits[] = { 0.0D, 0.5D, 2.0D };
public final double moveLimits[] = { 0.0D, 0.5D, 2.0D };
public final double heightLimits[] = { 0.0D, 0.5D, 2.0D };
public int ticksBeforeSummary = 100;
// How should moving violations be treated?
public final Action actions[][] = {
{ LogAction.logLow, CancelAction.reset },
{ LogAction.logMed, CancelAction.reset },
{ LogAction.logHigh, CancelAction.reset } };
{ LogAction.loglow, CancelAction.cancel },
{ LogAction.logmed, CancelAction.cancel },
{ LogAction.loghigh, CancelAction.cancel } };
private static final double magic = 0.30000001192092896D;
private static final double magic2 = 0.69999998807907103D;
@ -158,14 +158,13 @@ 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
@ -208,17 +207,16 @@ public class MovingCheck extends Check {
// The actual movingCheck starts here
// First check the distance the player has moved horizontally
double xDistance = from.getX()-to.getX();
double zDistance = from.getZ()-to.getZ();
double xDistance = Math.abs(from.getX()-to.getX());
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() && xDistance < 8.0D && zDistance < 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
}
// Calculate the horizontal distance
double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance)) - 0.6D ;
// Give additional movement based on velocity (not too precise, but still better than false positives)
Vector v = event.getPlayer().getVelocity();
@ -226,23 +224,8 @@ public class MovingCheck extends Check {
double tmp = Math.abs(v.getX()*5D) + Math.abs(v.getZ()*5D);
data.movingHorizFreedom = tmp > data.movingHorizFreedom * 0.9D ? tmp : data.movingHorizFreedom * 0.9D;
// subtract the additional freedom
combined -= data.movingHorizFreedom;
// Violation level
int vl1 = -1;
// How far are we off?
if(combined > moveLimits[2]) {
vl1 = max(vl1, 2);
}
else if(combined > moveLimits[1]) {
vl1 = max(vl1, 1);
}
else if(combined > moveLimits[0]) {
vl1 = max(vl1, 0);
}
int vl1 = limitCheck(combined - data.movingHorizFreedom - 0.6D, moveLimits);
// pre-calculate boundary values that are needed multiple times in the following checks
// the array each contains [lowerX, higherX, Y, lowerZ, higherZ]
@ -253,20 +236,18 @@ public class MovingCheck extends Check {
final boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from);
final boolean onGroundTo = playerIsOnGround(to.getWorld(), toValues, to);
// Handle 4 distinct cases: Walk, Jump, Land, Fly
int vl2 = -1;
// A halfway lag-resistant method of allowing vertical acceleration without allowing blatant cheating
// FACT: Minecraft server sends player "velocity" to the client and lets the client calculate the movement
// PROBLEM: There may be an arbitrary amount of other move events between the server sending the data
// and the client accepting it/reacting to it. The server can't know when the client starts to
// consider the sent "velocity" in its movement.
// SOLUTION: Give the client at least 10 events after sending "velocity" to actually use the velocity for
// its movement, plus additional events if the "velocity" was big and can cause longer flights
// The server sent the player a "velocity" a short time ago
if(v.getY() > 0.0D) {
if(data.movingVertFreedomCounter < 10)
@ -275,8 +256,8 @@ public class MovingCheck extends Check {
// Be generous with the height limit for the client
data.movingVertFreedom += v.getY()*3D;
// Set a top limit for how many events a client has to "consume" the sent velocity
if(data.movingVertFreedomCounter < 30)
// Set a top limit for how many events a client has to "consume" the added freedom
if(data.movingVertFreedomCounter < 40)
data.movingVertFreedomCounter++;
}
// If the server no longer has a positive velocity, start consuming the event counter for this client
@ -291,117 +272,99 @@ public class MovingCheck extends Check {
double limit = data.movingVertFreedom;
// Walk
if(onGroundFrom && onGroundTo)
Location newSetBack = null;
// Walk or start Jump
if(onGroundFrom)
{
limit += jumpHeight;
double distance = to.getY() - from.getY();
vl2 = heightLimitCheck(limit, distance);
vl2 = limitCheck(distance - limit, heightLimits);
if(vl1 < 0 && vl2 < 0)
if(vl2 < 0)
{
// reset jumping
data.movingJumpPhase = 0;
data.movingSetBackPoint = from.clone();
if(onGroundTo)
data.movingJumpPhase = 0; // Walk
else
data.movingJumpPhase = 1; // Jump
newSetBack = from.clone();
}
}
// Jump
else if(onGroundFrom && !onGroundTo)
{
limit += jumpHeight;
double distance = to.getY() - from.getY();
// Check if player isn't jumping too high
vl2 = heightLimitCheck(limit, distance);
if(vl1 < 0 && vl2 < 0) {
// Setup next phase of the jump
data.movingJumpPhase = 1;
data.movingSetBackPoint = from.clone();
}
}
// Land
else if(!onGroundFrom && onGroundTo)
// Land or Fly/Fall
else
{
Location l = data.movingSetBackPoint == null ? from : data.movingSetBackPoint;
if(data.movingJumpPhase > jumpingLimit)
limit += jumpHeight + stepHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
else limit += jumpHeight;
double distance = to.getY() - l.getY();
// Check if player isn't jumping too high
vl2 = heightLimitCheck(limit, distance);
if(vl1 < 0 && vl2 < 0) {
data.movingJumpPhase = 0; // He is on ground now, so reset the jump
data.movingSetBackPoint = to.clone();
}
}
// Player is moving through air (during jumping, falling)
else {
Location l = data.movingSetBackPoint == null ? from : data.movingSetBackPoint;
if(data.movingJumpPhase > jumpingLimit)
limit += jumpHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
else limit += jumpHeight;
if(onGroundTo) limit += stepHeight;
double distance = to.getY() - l.getY();
// Check if player isn't jumping too high
vl2 = heightLimitCheck(limit, distance);
vl2 = limitCheck(distance - limit, heightLimits);
if(vl1 < 0 && vl2 < 0) {
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
if(data.movingSetBackPoint == null) {
data.movingSetBackPoint = from.clone();
if(vl2 < 0) {
if(onGroundTo) { // Land
data.movingJumpPhase = 0; // He is on ground now, so reset the jump
newSetBack = to.clone();
}
else { // Fly
data.movingJumpPhase++; // Enter next phase of the flight
// If we have no setback point, create one now
if(data.movingSetBackPoint == null) {
newSetBack = from.clone();
}
}
}
}
int vl = max(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) {
final Player p = event.getPlayer();
final NoCheatData d = data;
setupSummaryTask(event.getPlayer(), data);
// Setup task to display summary later
if(data.movingRunnable == null) {
data.movingRunnable = new Runnable() {
@Override
public void run() {
summary(p, d);
// deleting its own reference
d.movingRunnable = null;
}
};
// Give a summary in x ticks. 20 ticks ~ 1 second
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.movingRunnable, ticksBeforeSummary);
}
// If we haven't already got a setback point, make this location the new setback point
if(data.movingSetBackPoint == null) {
data.movingSetBackPoint = event.getFrom().clone();
}
Action action[] = null;
boolean log = true;
// Find out with what actions to treat the violation(s)
if(data.movingViolationsInARow[vl] > 0) log = false; // only log the first violation of that level
boolean log = !(data.movingViolationsInARow[vl] > 0);
data.movingViolationsInARow[vl]++;
action = actions[vl];
action(event, event.getPlayer(), from, to, action, log);
action(event, event.getPlayer(), from, to, actions[vl], log, data);
}
}
private void setupSummaryTask(final Player player, final NoCheatData data) {
// Setup task to display summary later
if(data.movingRunnable == null) {
data.movingRunnable = new Runnable() {
@Override
public void run() {
summary(player, data);
// deleting its own reference
data.movingRunnable = null;
}
};
// Give a summary in x ticks. 20 ticks ~ 1 second
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.movingRunnable, ticksBeforeSummary);
}
}
public void teleported(PlayerMoveEvent event) {
NoCheatData data = plugin.getPlayerData(event.getPlayer());
@ -428,43 +391,43 @@ public class MovingCheck extends Check {
* @param event
* @param action
*/
private void action(PlayerMoveEvent event, Player player, Location from, Location to, Action[] actions, boolean log) {
private void action(PlayerMoveEvent event, Player player, Location from, Location to, Action[] actions, boolean loggingAllowed, NoCheatData data) {
if(actions == null) return;
boolean cancelled = false;
// prepare log message if neccessary
String logMessage = null;
if(loggingAllowed) {
logMessage = "Moving violation: "+player.getName()+" from " + String.format("%s (%.5f, %.5f, %.5f) to %s (%.5f, %.5f, %.5f)", from.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getWorld().getName(), to.getX(), to.getY(), to.getZ());
}
for(Action a : actions) {
if(a instanceof LogAction)
plugin.log(((LogAction)a).getLevel(), "Moving violation: "+player.getName()+" from " + String.format("%s (%.5f, %.5f, %.5f) to %s (%.5f, %.5f, %.5f)", from.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getWorld().getName(), to.getX(), to.getY(), to.getZ()));
else if(a.equals(CancelAction.reset))
if(a instanceof LogAction) {
plugin.log(((LogAction)a).level, logMessage);
data.movingHighestLogLevel = ((LogAction)a).level.intValue() > data.movingHighestLogLevel.intValue() ? ((LogAction)a).level : data.movingHighestLogLevel;
}
else if(!cancelled && a instanceof CancelAction) {
resetPlayer(event, from);
cancelled = true;
}
else if(a instanceof CustomAction)
plugin.handleCustomAction(a, player);
}
}
private void summary(Player p, NoCheatData data) {
LogAction log = null;
String logString = "Moving summary of last ~" + (ticksBeforeSummary/20) + " seconds: "+p.getName() + " total Violations: ("+ data.movingViolationsInARow[0] + "," + data.movingViolationsInARow[1] + "," + data.movingViolationsInARow[2] + ")";
// Find out the biggest applicable log level
for(int i = 0; i < data.movingViolationsInARow.length; i++) {
if(data.movingViolationsInARow[i] > 0)
for(Action a : actions[i])
if(a instanceof LogAction)
if(log == null || ((LogAction)a).getIndex() > log.getIndex())
log = (LogAction)a;
data.movingViolationsInARow[i] = 0;
}
if(log != null)
plugin.log(log.getLevel(), logString);
plugin.log(data.movingHighestLogLevel, logString);
}
private int heightLimitCheck(double limit, double value) {
private int limitCheck(double value, double limits[]) {
double offset = value - limit;
for(int i = heightLimits.length - 1; i >= 0; i--) {
if(offset > heightLimits[i]) {
for(int i = limits.length - 1; i >= 0; i--) {
if(value > limits[i]) {
return i;
}
}
@ -517,27 +480,15 @@ public class MovingCheck extends Check {
/**
* Check the four edges of the player's approximated Bounding Box for blocks or ladders,
* at his own height (values[2]) and below his feet (values[2]-1). Also, check at his "head"
* for ladders.
*
* If there is one, the player is considered as standing on it/hanging to it.
*
* Not perfect at all and will produce some false negatives. Probably will be refined
* later.
* Check if certain coordinates are considered "on ground" or in air
*
* @param w The world the coordinates belong to
* @param values The coordinates [lowerX, higherX, Y, lowerZ, higherZ]
* @param l The location that was used for calculation of "values"
* @return
*/
private static boolean playerIsOnGround(World w, int values[], Location l) {
// Completely revamped collision detection
// What it does:
// Check the blocks below the player. If they aren't not solid (sic!) and the blocks directly above
// them aren't solid, The player is considered to be standing on the lower block
// Plus the player can hang onto a ladder that is one field above him
// Check the four borders of the players hitbox for something he could be standing on
if(types[w.getBlockTypeIdAt(values[0], values[2]-1, values[3])] != BlockType.NONSOLID ||
types[w.getBlockTypeIdAt(values[1], values[2]-1, values[3])] != BlockType.NONSOLID ||
@ -548,7 +499,7 @@ public class MovingCheck extends Check {
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)
return true;
// check if he is standing "in" an 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)
else if(types[w.getBlockTypeIdAt(values[0], values[2], values[3])] != BlockType.NONSOLID ||
types[w.getBlockTypeIdAt(values[1], values[2], values[3])] != BlockType.NONSOLID||
@ -562,7 +513,7 @@ public class MovingCheck extends Check {
types[w.getBlockTypeIdAt(values[0], values[2]+1, values[4])] != BlockType.NONSOLID ||
types[w.getBlockTypeIdAt(values[1], values[2]+1, values[4])] != BlockType.NONSOLID)
return true;
// Allow using a bug called "water elevator"
// Allow using a bug called "water elevator" by checking northwest of the players location for liquids
else if(types[w.getBlockTypeIdAt(values[0]+1, values[2]-1, values[3]+1)] == BlockType.LIQUID ||
types[w.getBlockTypeIdAt(values[0]+1, values[2], values[3]+1)] == BlockType.LIQUID ||
types[w.getBlockTypeIdAt(values[0]+1, values[2]+1, values[3]+1)] == BlockType.LIQUID ||

View File

@ -7,6 +7,7 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
import cc.co.evenprime.bukkit.nocheat.actions.Action;
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
import cc.co.evenprime.bukkit.nocheat.actions.CustomAction;
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
/**
@ -30,9 +31,9 @@ public class SpeedhackCheck extends Check {
// How should speedhack violations be treated?
public Action actions[][] = {
{ LogAction.logLow, CancelAction.reset },
{ LogAction.logMed, CancelAction.reset },
{ LogAction.logHigh, CancelAction.reset } };
{ LogAction.loglow, CancelAction.cancel },
{ LogAction.logmed, CancelAction.cancel },
{ LogAction.loghigh, CancelAction.cancel } };
public void check(PlayerMoveEvent event) {
@ -100,11 +101,15 @@ public class SpeedhackCheck extends Check {
if(actions == null) return;
String logMessage = event.getPlayer().getName()+" sent "+ data.speedhackEventsSinceLastCheck + " move events, but only "+limits[0]+ " were allowed. Speedhack?";
for(Action a : actions) {
if(a instanceof LogAction)
plugin.log(((LogAction)a).getLevel(), event.getPlayer().getName()+" sent "+ data.speedhackEventsSinceLastCheck + " move events, but only "+limits[0]+ " were allowed. Speedhack?");
else if(a.equals(CancelAction.reset))
plugin.log(((LogAction)a).level, logMessage);
else if(a instanceof CancelAction)
resetPlayer(event, data);
else if(a instanceof CustomAction)
plugin.handleCustomAction(a, event.getPlayer());
}
}