More refactoring + seperate data objects for each check, only created

on demand + some whitespace code formatting
This commit is contained in:
Evenprime 2011-04-25 22:44:54 +02:00
parent d9b73cbb67
commit 18cb95ab5e
22 changed files with 330 additions and 245 deletions

View File

@ -18,6 +18,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.BedteleportCheck;
import cc.co.evenprime.bukkit.nocheat.checks.ItemdupeCheck;
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
import cc.co.evenprime.bukkit.nocheat.checks.SpeedhackCheck;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import com.ensifera.animosity.craftirc.CraftIRC;
import com.nijikokun.bukkit.Permissions.Permissions;
@ -60,7 +61,7 @@ public class NoCheat extends JavaPlugin {
public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args)
{
if(sender instanceof Player) {
if(!hasPermission((Player)sender, NoCheatData.PERMISSION_P)) {
if(!hasPermission((Player)sender, PermissionData.PERMISSION_P)) {
sender.sendMessage("NC: You are not allowed to use this command.");
return false;
}
@ -111,7 +112,7 @@ public class NoCheat extends JavaPlugin {
}
public void onEnable() {
movingCheck = new MovingCheck(this);
bedteleportCheck = new BedteleportCheck(this);
speedhackCheck = new SpeedhackCheck(this);
@ -120,7 +121,7 @@ public class NoCheat extends JavaPlugin {
// parse the nocheat.yml config file
setupConfig();
PluginDescriptionFile pdfFile = this.getDescription();
@ -212,7 +213,7 @@ public class NoCheat extends JavaPlugin {
private void logToChat(Level l, String message) {
if(config.chatLevel.intValue() <= l.intValue()) {
for(Player player : getServer().getOnlinePlayers()) {
if(hasPermission(player, NoCheatData.PERMISSION_NOTIFY)) {
if(hasPermission(player, PermissionData.PERMISSION_NOTIFY)) {
player.sendMessage("["+l.getName()+"] " + message);
}
}
@ -234,15 +235,13 @@ public class NoCheat extends JavaPlugin {
public boolean hasPermission(Player player, int permission) {
if(player == null) {
return false;
}
if(player == null) return false;
try {
if(permissions == null)
return player.isOp();
else {
NoCheatData data = NoCheatData.getPlayerData(player);
PermissionData data = PermissionData.get(player);
if(data.permissionsLastUpdate + 10000 < System.currentTimeMillis()) {
data.permissionsLastUpdate = System.currentTimeMillis();
updatePermissions(player, data);
@ -265,16 +264,16 @@ public class NoCheat extends JavaPlugin {
}
}
private void updatePermissions(Player player, NoCheatData data) {
private void updatePermissions(Player player, PermissionData data) {
data.permissionsCache[NoCheatData.PERMISSION_AIRBUILD] = permissions.has(player, "nocheat.airbuild");
data.permissionsCache[NoCheatData.PERMISSION_BEDTELEPORT] = permissions.has(player, "nocheat.bedteleport");
data.permissionsCache[NoCheatData.PERMISSION_FLYING] = permissions.has(player, "nocheat.flying");
data.permissionsCache[NoCheatData.PERMISSION_MOVING] = permissions.has(player, "nocheat.moving");
data.permissionsCache[NoCheatData.PERMISSION_P] = permissions.has(player, "nocheat.p");
data.permissionsCache[NoCheatData.PERMISSION_SPEEDHACK] = permissions.has(player, "nocheat.speedhack");
data.permissionsCache[NoCheatData.PERMISSION_NOTIFY] = permissions.has(player, "nocheat.notify");
data.permissionsCache[NoCheatData.PERMISSION_ITEMDUPE] = permissions.has(player, "nocheat.itemdupe");
data.permissionsCache[PermissionData.PERMISSION_AIRBUILD] = permissions.has(player, "nocheat.airbuild");
data.permissionsCache[PermissionData.PERMISSION_BEDTELEPORT] = permissions.has(player, "nocheat.bedteleport");
data.permissionsCache[PermissionData.PERMISSION_FLYING] = permissions.has(player, "nocheat.flying");
data.permissionsCache[PermissionData.PERMISSION_MOVING] = permissions.has(player, "nocheat.moving");
data.permissionsCache[PermissionData.PERMISSION_P] = permissions.has(player, "nocheat.p");
data.permissionsCache[PermissionData.PERMISSION_SPEEDHACK] = permissions.has(player, "nocheat.speedhack");
data.permissionsCache[PermissionData.PERMISSION_NOTIFY] = permissions.has(player, "nocheat.notify");
data.permissionsCache[PermissionData.PERMISSION_ITEMDUPE] = permissions.has(player, "nocheat.itemdupe");
}
@ -300,13 +299,13 @@ public class NoCheat extends JavaPlugin {
private String getPermissionsForPlayerAsString(Player p) {
return (!movingCheck.isActive() ? movingCheck.getName() + "* " : (hasPermission(p, NoCheatData.PERMISSION_MOVING) ? movingCheck.getName() + " " : "") +
(!movingCheck.isActive() || movingCheck.allowFlying ? "flying* " : (hasPermission(p, NoCheatData.PERMISSION_FLYING) ? "flying " : "")) +
(!speedhackCheck.isActive() ? speedhackCheck.getName() + "* " : (hasPermission(p, NoCheatData.PERMISSION_SPEEDHACK) ? speedhackCheck.getName() + " " : "")) +
(!airbuildCheck.isActive() ? airbuildCheck.getName() + "* " : (hasPermission(p, NoCheatData.PERMISSION_AIRBUILD) ? airbuildCheck.getName() + " " : "")) +
(!bedteleportCheck.isActive() ? bedteleportCheck.getName() + "* " : (hasPermission(p, NoCheatData.PERMISSION_BEDTELEPORT) ? bedteleportCheck.getName() + " " : "")) +
(!itemdupeCheck.isActive() ? itemdupeCheck.getName() + "* " : (hasPermission(p, NoCheatData.PERMISSION_ITEMDUPE) ? itemdupeCheck.getName() + " " : "")) +
(hasPermission(p, NoCheatData.PERMISSION_NOTIFY) ? "notify " : ""));
return (!movingCheck.isActive() ? movingCheck.getName() + "* " : (hasPermission(p, PermissionData.PERMISSION_MOVING) ? movingCheck.getName() + " " : "") +
(!movingCheck.isActive() || movingCheck.allowFlying ? "flying* " : (hasPermission(p, PermissionData.PERMISSION_FLYING) ? "flying " : "")) +
(!speedhackCheck.isActive() ? speedhackCheck.getName() + "* " : (hasPermission(p, PermissionData.PERMISSION_SPEEDHACK) ? speedhackCheck.getName() + " " : "")) +
(!airbuildCheck.isActive() ? airbuildCheck.getName() + "* " : (hasPermission(p, PermissionData.PERMISSION_AIRBUILD) ? airbuildCheck.getName() + " " : "")) +
(!bedteleportCheck.isActive() ? bedteleportCheck.getName() + "* " : (hasPermission(p, PermissionData.PERMISSION_BEDTELEPORT) ? bedteleportCheck.getName() + " " : "")) +
(!itemdupeCheck.isActive() ? itemdupeCheck.getName() + "* " : (hasPermission(p, PermissionData.PERMISSION_ITEMDUPE) ? itemdupeCheck.getName() + " " : "")) +
(hasPermission(p, PermissionData.PERMISSION_NOTIFY) ? "notify " : ""));
}
public void handleCustomAction(Action a, Player player) {

View File

@ -124,7 +124,7 @@ public class NoCheatConfiguration {
plugin.bedteleportCheck.setActive(c.getBoolean("active.bedteleport", true));
plugin.itemdupeCheck.setActive(c.getBoolean("active.itemdupe", false));
}
public void cleanup() {
if(fh != null) {

View File

@ -3,13 +3,16 @@ package cc.co.evenprime.bukkit.nocheat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.data.AirbuildData;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.data.SpeedhackData;
/**
* Storage for data persistence between events
* per player storage for data persistence between events
*
* @author Evenprime
*
@ -19,46 +22,13 @@ public class NoCheatData {
/**
* Don't rely on any of these yet, they are likely going to change their name/functionality
*/
public MovingData moving;
public SpeedhackData speedhack;
public AirbuildData airbuild;
public int movingJumpPhase = 0;
public int movingViolationsInARow[] = { 0, 0, 0 };
public double movingHorizFreedom = 0.0D;
public int movingHorizFreedomCounter = 0;
public double movingVertFreedom = 0.0D;
public int movingVertFreedomCounter = 0;
public Location movingSetBackPoint = null;
public Runnable movingSummaryTask = null;
public Level movingHighestLogLevel = null;
// WORKAROUND for changed PLAYER_MOVE logic
public Location movingTeleportTo = null;
public Location movingLastLocation = null;
public Location teleportInitializedByMe = null;
public boolean worldChanged = false;
public boolean respawned = false;
public long speedhackLastCheck = System.currentTimeMillis(); // timestamp of last check for speedhacks
public Location speedhackSetBackPoint = null;
public int speedhackEventsSinceLastCheck = 0; // used to identify speedhacks
public int speedhackViolationsInARow = 0;
public int airbuildPerSecond = 0;
public Runnable airbuildSummaryTask = null;
public double maxYVelocity = 0.0D;
public long permissionsLastUpdate = 0;
public boolean permissionsCache[] = new boolean[8];
public PermissionData permission;
public static final int PERMISSION_MOVING = 0;
public static final int PERMISSION_FLYING = 1;
public static final int PERMISSION_SPEEDHACK = 2;
public static final int PERMISSION_AIRBUILD = 3;
public static final int PERMISSION_BEDTELEPORT = 4;
public static final int PERMISSION_P = 5;
public static final int PERMISSION_NOTIFY = 6;
public static final int PERMISSION_ITEMDUPE = 7;
// Store data between Events
private static final Map<Player, NoCheatData> playerData = new HashMap<Player, NoCheatData>();
@ -72,17 +42,12 @@ public class NoCheatData {
* @return
*/
public static NoCheatData getPlayerData(Player p) {
NoCheatData data = null;
NoCheatData data = playerData.get(p);
if((data = playerData.get(p)) == null ) {
synchronized(playerData) {
data = playerData.get(p);
if(data == null) {
// If we have no data for the player, create some
data = new NoCheatData();
playerData.put(p, data);
}
}
if(data == null) {
// If we have no data for the player, create some
data = new NoCheatData();
playerData.put(p, data);
}
return data;

View File

@ -10,11 +10,11 @@ public abstract class Action {
public final int firstAfter;
public final boolean repeat;
public Action(int firstAfter, boolean repeat) {
this.firstAfter = firstAfter;
this.repeat = repeat;
}
public abstract String getName();
}

View File

@ -6,11 +6,11 @@ package cc.co.evenprime.bukkit.nocheat.actions;
*
*/
public class CancelAction extends Action {
public final static CancelAction cancel = new CancelAction();
private CancelAction() { super(1, true); }
public String getName() {
return "cancel";
}

View File

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

View File

@ -10,18 +10,18 @@ import java.util.logging.Level;
public class LogAction extends Action {
public final Level level;
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 LogAction(int firstAfter, boolean repeat, Level level) {
super(firstAfter, repeat);
this.level = level;
}
public String getName() {
if(level.equals(Level.INFO))
return "loglow";

View File

@ -9,12 +9,13 @@ import org.bukkit.event.Event.Priority;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
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;
import cc.co.evenprime.bukkit.nocheat.data.AirbuildData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.listeners.AirbuildBlockListener;
@ -35,7 +36,7 @@ public class AirbuildCheck extends Check {
public final int limits[] = { 1, 3, 10 };
public AirbuildCheck(NoCheat plugin) {
super(plugin, "airbuild", NoCheatData.PERMISSION_AIRBUILD);
super(plugin, "airbuild", PermissionData.PERMISSION_AIRBUILD);
}
public void check(BlockPlaceEvent event) {
@ -45,31 +46,31 @@ public class AirbuildCheck extends Check {
// Are all 6 sides "air-blocks" -> cancel the event
if(event.getBlockAgainst().getType() == Material.AIR) {
final NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
final AirbuildData data = AirbuildData.get(event.getPlayer());
final Player p = event.getPlayer();
if(data.airbuildSummaryTask == null) {
data.airbuildSummaryTask = new Runnable() {
if(data.summaryTask == null) {
data.summaryTask = new Runnable() {
@Override
public void run() {
summary(p, data);
// deleting its own reference
data.airbuildSummaryTask = null;
data.summaryTask = null;
}
};
// Give a summary in 20 ticks ~ 1 second
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.airbuildSummaryTask, 20);
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.summaryTask, 20);
}
data.airbuildPerSecond++;
data.perSecond++;
// which limit has been reached
for(int i = limits.length-1; i >= 0; i--) {
if(data.airbuildPerSecond >= limits[i]) {
if(data.perSecond >= limits[i]) {
// Only explicitly log certain "milestones"
if(data.airbuildPerSecond == limits[i]) {
if(data.perSecond == limits[i]) {
action(actions[i], event, true);
}
else {
@ -109,25 +110,25 @@ public class AirbuildCheck extends Check {
}
}
private void summary(Player player, NoCheatData data) {
private void summary(Player player, AirbuildData data) {
// 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].level, "Airbuild summary: " +player.getName() + " total violations per second: " + data.airbuildPerSecond);
if(data.perSecond >= limits[i]) {
plugin.log(LogAction.log[i].level, "Airbuild summary: " +player.getName() + " total violations per second: " + data.perSecond);
break;
}
}
data.airbuildPerSecond = 0;
data.perSecond = 0;
}
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
// Register listeners for airbuild check
pm.registerEvent(Event.Type.BLOCK_PLACE, new AirbuildBlockListener(this), Priority.Low, plugin);
}
}

View File

@ -7,7 +7,7 @@ import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.listeners.BedteleportPlayerListener;
/**
@ -19,7 +19,7 @@ import cc.co.evenprime.bukkit.nocheat.listeners.BedteleportPlayerListener;
public class BedteleportCheck extends Check {
public BedteleportCheck(NoCheat plugin) {
super(plugin, "bedteleport", NoCheatData.PERMISSION_BEDTELEPORT);
super(plugin, "bedteleport", PermissionData.PERMISSION_BEDTELEPORT);
}
public void check(PlayerMoveEvent event) {
@ -35,9 +35,9 @@ public class BedteleportCheck extends Check {
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
// Register listeners for bedteleport check
pm.registerEvent(Event.Type.PLAYER_TELEPORT, new BedteleportPlayerListener(this), Priority.Lowest, plugin);
}
}

View File

@ -30,7 +30,7 @@ public abstract class Check {
}
protected abstract void registerListeners();
public boolean isActive() {
return active;
}
@ -42,7 +42,7 @@ public abstract class Check {
registerListeners();
}
}
// There is no way to unregister listeners ...
this.active = active;
}

View File

@ -13,20 +13,20 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.listeners.ItemdupePlayerListener;
public class ItemdupeCheck extends Check {
public ItemdupeCheck(NoCheat plugin){
super(plugin, "itemdupe", NoCheatData.PERMISSION_ITEMDUPE);
super(plugin, "itemdupe", PermissionData.PERMISSION_ITEMDUPE);
}
public void check(PlayerPickupItemEvent event) {
// Should we check at all?
if(hasPermission(event.getPlayer())) return;
Item i = event.getItem();
if(i != null) {
ItemStack s = i.getItemStack();
@ -39,12 +39,11 @@ public class ItemdupeCheck extends Check {
}
}
}
public void check(PlayerInteractEvent event) {
if(plugin.hasPermission(event.getPlayer(), NoCheatData.PERMISSION_ITEMDUPE))
return;
if(hasPermission(event.getPlayer())) return;
if(event.hasItem() && event.getItem().getAmount() <= 0) {// buggy item
event.setCancelled(true);
plugin.log(Level.WARNING, event.getPlayer().getName() + " tried to use an invalid item. Item will be removed now.");
@ -55,14 +54,14 @@ public class ItemdupeCheck extends Check {
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
// Register listeners for itemdupe check
Listener itemdupePlayerListener = new ItemdupePlayerListener(this);
// Register listeners for itemdupe check
pm.registerEvent(Event.Type.PLAYER_PICKUP_ITEM, itemdupePlayerListener, Priority.Lowest, plugin);
pm.registerEvent(Event.Type.PLAYER_INTERACT, itemdupePlayerListener, Priority.Lowest, plugin);
}
}

View File

@ -16,12 +16,13 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
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;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.listeners.MovingEntityListener;
import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerListener;
import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerMonitor;
@ -35,7 +36,7 @@ import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerMonitor;
public class MovingCheck extends Check {
public MovingCheck(NoCheat plugin) {
super(plugin, "moving", NoCheatData.PERMISSION_MOVING);
super(plugin, "moving", PermissionData.PERMISSION_MOVING);
}
// How many move events can a player have in air before he is expected to lose altitude (or land somewhere)
@ -187,22 +188,22 @@ public class MovingCheck extends Check {
}
final boolean canFly;
if(allowFlying || plugin.hasPermission(player, NoCheatData.PERMISSION_FLYING))
if(allowFlying || plugin.hasPermission(player, PermissionData.PERMISSION_FLYING))
canFly = true;
else
canFly = false;
// Get the player-specific data
final NoCheatData data = NoCheatData.getPlayerData(player);
final MovingData data = MovingData.get(player);
// Get the two locations of the event
final Location to = event.getTo();
Location from = event.getFrom();
// WORKAROUND for changed PLAYER_MOVE logic
if(data.movingTeleportTo != null) {
from = data.movingTeleportTo;
data.movingTeleportTo = null;
if(data.teleportTo != null) {
from = data.teleportTo;
data.teleportTo = null;
}
// The use of event.getFrom() is intentional
@ -235,12 +236,12 @@ public class MovingCheck extends Check {
//if(player.isSneaking())
if(false) // Currently disabled, still needs some additional work
vl1 = limitCheck(combined - (data.movingHorizFreedom + sneakStepWidth), moveLimits);
vl1 = limitCheck(combined - (data.horizFreedom + sneakStepWidth), moveLimits);
else
vl1 = limitCheck(combined - (data.movingHorizFreedom + stepWidth), moveLimits);
vl1 = limitCheck(combined - (data.horizFreedom + stepWidth), moveLimits);
// Reduce horiz moving freedom with each event
data.movingHorizFreedom *= 0.9;
data.horizFreedom *= 0.9;
/**** Horizontal movement check END ****/
@ -267,30 +268,30 @@ public class MovingCheck extends Check {
// The server sent the player a "velocity" packet a short time ago
if(data.maxYVelocity > 0.0D) {
data.movingVertFreedomCounter = 30;
data.vertFreedomCounter = 30;
// Be generous with the height limit for the client
data.movingVertFreedom += data.maxYVelocity*2D;
data.vertFreedom += data.maxYVelocity*2D;
data.maxYVelocity = 0.0D;
}
// consume a counter for this client
if(data.movingVertFreedomCounter > 0) {
data.movingVertFreedomCounter--;
if(data.vertFreedomCounter > 0) {
data.vertFreedomCounter--;
}
double limit = data.movingVertFreedom;
double limit = data.vertFreedom;
// If the event counter has been consumed, remove the vertical movement limit increase when landing the next time
if(data.movingVertFreedomCounter <= 0 && (onGroundFrom || onGroundTo)) {
data.movingVertFreedom = 0.0D;
if(data.vertFreedomCounter <= 0 && (onGroundFrom || onGroundTo)) {
data.vertFreedom = 0.0D;
}
// The location we'd use as a new setback if there are no violations
Location newSetBack = null;
// there's no use for counting this
if(canFly) data.movingJumpPhase = 0;
if(canFly) data.jumpPhase = 0;
// Handle 4 distinct cases: Walk, Jump, Land, Fly
@ -306,9 +307,9 @@ public class MovingCheck extends Check {
{
// reset jumping
if(onGroundTo)
data.movingJumpPhase = 0; // Walk
data.jumpPhase = 0; // Walk
else
data.movingJumpPhase = 1; // Jump
data.jumpPhase = 1; // Jump
newSetBack = from.clone();
}
@ -318,13 +319,13 @@ public class MovingCheck extends Check {
{
Location l = null;
if(data.movingSetBackPoint == null || canFly)
if(data.setBackPoint == null || canFly)
l = from;
else
l = data.movingSetBackPoint;
l = data.setBackPoint;
if(!canFly && data.movingJumpPhase > jumpingLimit)
limit += jumpHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
if(!canFly && data.jumpPhase > jumpingLimit)
limit += jumpHeight - (data.jumpPhase-jumpingLimit) * 0.2D;
else limit += jumpHeight;
if(onGroundTo) limit += stepHeight;
@ -336,13 +337,13 @@ public class MovingCheck extends Check {
if(vl2 < 0) {
if(onGroundTo) { // Land
data.movingJumpPhase = 0; // He is on ground now, so reset the jump
data.jumpPhase = 0; // He is on ground now, so reset the jump
newSetBack = to.clone();
}
else { // Fly
data.movingJumpPhase++; // Enter next phase of the flight
data.jumpPhase++; // Enter next phase of the flight
// If we have no setback point, create one now
if(data.movingSetBackPoint == null) {
if(data.setBackPoint == null) {
newSetBack = from.clone();
}
}
@ -352,19 +353,19 @@ public class MovingCheck extends Check {
int vl = vl1 > vl2 ? vl1 : vl2;
if(vl < 0 && newSetBack != null) {
data.movingSetBackPoint = newSetBack;
data.setBackPoint = 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 = from.clone();
if(data.setBackPoint == null) {
data.setBackPoint = from.clone();
}
if(vl >= 0) {
setupSummaryTask(event.getPlayer(), data);
boolean log = !(data.movingViolationsInARow[vl] > 0);
data.movingViolationsInARow[vl]++;
boolean log = !(data.violationsInARow[vl] > 0);
data.violationsInARow[vl]++;
action(event, event.getPlayer(), from, to, actions[vl], log, data);
}
@ -373,10 +374,10 @@ public class MovingCheck extends Check {
statisticTotalEvents++;
}
private boolean shouldBeIgnored(Player player, NoCheatData data, Location from, Location to) {
private boolean shouldBeIgnored(Player player, MovingData data, Location from, Location to) {
if(from.equals(to)) // Both locations are perfectly identical
return true;
else if(!from.equals(data.movingLastLocation)) { // The player was moved somehow without causing a move event
else if(!from.equals(data.lastLocation)) { // The player was moved somehow without causing a move event
resetData(data, to);
return true;
}
@ -396,28 +397,28 @@ public class MovingCheck extends Check {
}
private void setupSummaryTask(final Player p, final NoCheatData data) {
private void setupSummaryTask(final Player p, final MovingData data) {
// Setup task to display summary later
if(data.movingSummaryTask == null) {
data.movingSummaryTask = new Runnable() {
if(data.summaryTask == null) {
data.summaryTask = new Runnable() {
@Override
public void run() {
if(data.movingHighestLogLevel != null) {
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.movingViolationsInARow[0], data.movingViolationsInARow[1],data.movingViolationsInARow[2]);
plugin.log(data.movingHighestLogLevel, logString);
if(data.highestLogLevel != null) {
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.violationsInARow[0], data.violationsInARow[1],data.violationsInARow[2]);
plugin.log(data.highestLogLevel, logString);
}
// deleting its own reference
data.movingSummaryTask = null;
data.summaryTask = null;
data.movingViolationsInARow[0] = 0;
data.movingViolationsInARow[1] = 0;
data.movingViolationsInARow[2] = 0;
data.violationsInARow[0] = 0;
data.violationsInARow[1] = 0;
data.violationsInARow[2] = 0;
}
};
// Give a summary in x ticks. 20 ticks ~ 1 second
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.movingSummaryTask, ticksBeforeSummary);
plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, data.summaryTask, ticksBeforeSummary);
}
}
@ -429,7 +430,7 @@ public class MovingCheck extends Check {
*/
public void teleported(PlayerTeleportEvent event) {
NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
MovingData data = MovingData.get(event.getPlayer());
if(event.getTo().equals(data.teleportInitializedByMe)) { // My plugin requested this teleport while handling another event
@ -448,7 +449,7 @@ public class MovingCheck extends Check {
if(event.getFrom().getWorld().equals(event.getTo().getWorld())) {
// 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.teleportTo = event.getTo();
}
else
data.worldChanged = true;
@ -456,18 +457,18 @@ public class MovingCheck extends Check {
}
public void respawned(PlayerRespawnEvent event) {
NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
MovingData data = MovingData.get(event.getPlayer());
data.respawned = true;
}
public static void updateVelocity(Vector v, NoCheatData data) {
public void updateVelocity(Vector v, MovingData data) {
// Compare the velocity vector to the existing movement freedom that we've from previous events
double tmp = (Math.abs(v.getX()) + Math.abs(v.getZ())) * 2D;
if(tmp > data.movingHorizFreedom)
data.movingHorizFreedom = tmp;
if(tmp > data.horizFreedom)
data.horizFreedom = tmp;
if(v.getY() > data.maxYVelocity) {
data.maxYVelocity = v.getY();
@ -478,7 +479,7 @@ public class MovingCheck extends Check {
* @param event
* @param action
*/
private void action(PlayerMoveEvent event, Player player, Location from, Location to, Action[] actions, boolean loggingAllowed, NoCheatData data) {
private void action(PlayerMoveEvent event, Player player, Location from, Location to, Action[] actions, boolean loggingAllowed, MovingData data) {
if(actions == null) return;
boolean cancelled = false;
@ -493,8 +494,8 @@ public class MovingCheck extends Check {
for(Action a : actions) {
if(loggingAllowed && a instanceof LogAction) {
plugin.log(((LogAction)a).level, log);
if(data.movingHighestLogLevel == null) data.movingHighestLogLevel = Level.ALL;
if(data.movingHighestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.movingHighestLogLevel = ((LogAction)a).level;
if(data.highestLogLevel == null) data.highestLogLevel = Level.ALL;
if(data.highestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.highestLogLevel = ((LogAction)a).level;
}
else if(!cancelled && a instanceof CancelAction) {
resetPlayer(event, from);
@ -524,18 +525,18 @@ public class MovingCheck extends Check {
*/
private void resetPlayer(PlayerMoveEvent event, Location from) {
NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
MovingData data = MovingData.get(event.getPlayer());
// Reset the jumpphase. We choose the setback-point such that it should be
// 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
if(data.movingSetBackPoint == null) data.movingSetBackPoint = from.clone();
if(data.setBackPoint == null) data.setBackPoint = from.clone();
// Set a flag that gets used while handling teleport events (to determine if
// it was my teleport or someone else'
Location t = data.movingSetBackPoint;
Location t = data.setBackPoint;
t = new Location(t.getWorld(), t.getX(), t.getY(), t.getZ(), event.getTo().getYaw(), event.getTo().getPitch());
data.teleportInitializedByMe = t;
@ -633,19 +634,19 @@ public class MovingCheck extends Check {
return (int) (floor - d4);
}
private void resetData(NoCheatData data, Location l) {
private void resetData(MovingData data, Location l) {
// If it wasn't our plugin that ordered the teleport, forget (almost) all our information and start from scratch
data.movingSetBackPoint = l;
data.movingJumpPhase = 0;
data.movingTeleportTo = null;
data.setBackPoint = l;
data.jumpPhase = 0;
data.teleportTo = null;
}
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
Listener movingPlayerMonitor = new MovingPlayerMonitor(this);
// Register listeners for moving check
pm.registerEvent(Event.Type.PLAYER_MOVE, new MovingPlayerListener(this), Priority.Lowest, plugin);
pm.registerEvent(Event.Type.PLAYER_INTERACT, movingPlayerMonitor, Priority.Monitor, plugin);

View File

@ -8,12 +8,13 @@ import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
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;
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
import cc.co.evenprime.bukkit.nocheat.data.SpeedhackData;
import cc.co.evenprime.bukkit.nocheat.listeners.SpeedhackPlayerListener;
/**
@ -25,21 +26,21 @@ import cc.co.evenprime.bukkit.nocheat.listeners.SpeedhackPlayerListener;
public class SpeedhackCheck extends Check {
public SpeedhackCheck(NoCheat plugin) {
super(plugin, "speedhack", NoCheatData.PERMISSION_SPEEDHACK);
super(plugin, "speedhack", PermissionData.PERMISSION_SPEEDHACK);
}
private static final long interval = 1000;
private static final int violationsLimit = 3;
// Limits for the speedhack check
public int limits[] = { 30, 45, 60 };
// How should speedhack violations be treated?
public Action actions[][] = {
{ LogAction.loglow, CancelAction.cancel },
{ LogAction.logmed, CancelAction.cancel },
{ LogAction.loghigh, CancelAction.cancel } };
public String logMessage = "%1$s sent %2$d move events, but only %3$d were allowed. Speedhack?";
public void check(PlayerMoveEvent event) {
@ -48,67 +49,67 @@ public class SpeedhackCheck extends Check {
if(hasPermission(event.getPlayer())) return;
// Get the player-specific data
NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
SpeedhackData data = SpeedhackData.get(event.getPlayer());
// Ignore events if the player has positive y-Velocity (these can be the cause of event spam between server and client)
if(event.getPlayer().getVelocity().getY() > 0.0D) {
return;
}
// Ignore events of players in vehicles (these can be the cause of event spam between server and client)
if(event.getPlayer().isInsideVehicle()) {
return;
}
// Get the time of the server
long time = System.currentTimeMillis();
// Is it time for a speedhack check now?
if(time > interval + data.speedhackLastCheck ) {
if(time > interval + data.lastCheck ) {
// Yes
// TODO: Needs some better handling for server lag
Action action[] = null;
int low = (int)((limits[0] * (time - data.speedhackLastCheck)) / interval);
int med = (int)((limits[1] * (time - data.speedhackLastCheck)) / interval);
int high = (int)((limits[2] * (time - data.speedhackLastCheck)) / interval);
int low = (int)((limits[0] * (time - data.lastCheck)) / interval);
int med = (int)((limits[1] * (time - data.lastCheck)) / interval);
int high = (int)((limits[2] * (time - data.lastCheck)) / interval);
if(data.speedhackEventsSinceLastCheck > high) action = actions[2];
else if(data.speedhackEventsSinceLastCheck > med) action = actions[1];
else if(data.speedhackEventsSinceLastCheck > low) action = actions[0];
if(data.eventsSinceLastCheck > high) action = actions[2];
else if(data.eventsSinceLastCheck > med) action = actions[1];
else if(data.eventsSinceLastCheck > low) action = actions[0];
if(action == null) {
data.speedhackSetBackPoint = event.getFrom().clone();
data.speedhackViolationsInARow = 0;
data.setBackPoint = event.getFrom().clone();
data.violationsInARow = 0;
}
else {
// If we haven't already got a setback point, create one now
if(data.speedhackSetBackPoint == null) {
data.speedhackSetBackPoint = event.getFrom().clone();
if(data.setBackPoint == null) {
data.setBackPoint = event.getFrom().clone();
}
data.speedhackViolationsInARow++;
data.violationsInARow++;
}
if(data.speedhackViolationsInARow >= violationsLimit) {
if(data.violationsInARow >= violationsLimit) {
action(action, event, data);
}
// Reset values for next check
data.speedhackEventsSinceLastCheck = 0;
data.speedhackLastCheck = time;
data.eventsSinceLastCheck = 0;
data.lastCheck = time;
}
data.speedhackEventsSinceLastCheck++;
data.eventsSinceLastCheck++;
}
private void action(Action actions[], PlayerMoveEvent event, NoCheatData data) {
private void action(Action actions[], PlayerMoveEvent event, SpeedhackData data) {
if(actions == null) return;
String log = String.format(logMessage, event.getPlayer().getName(), data.speedhackEventsSinceLastCheck, limits[0]);
String log = String.format(logMessage, event.getPlayer().getName(), data.eventsSinceLastCheck, limits[0]);
for(Action a : actions) {
if(a instanceof LogAction)
plugin.log(((LogAction)a).level, log);
@ -119,17 +120,15 @@ public class SpeedhackCheck extends Check {
}
}
private static void resetPlayer(PlayerMoveEvent event, NoCheatData data) {
private static void resetPlayer(PlayerMoveEvent event, SpeedhackData data) {
if(data.speedhackSetBackPoint == null) data.speedhackSetBackPoint = event.getFrom().clone();
if(data.setBackPoint == null) data.setBackPoint = event.getFrom().clone();
data.teleportInitializedByMe = data.speedhackSetBackPoint;
// If we have stored a location for the player, we put him back there
if(event.getPlayer().teleport(data.speedhackSetBackPoint)) {
event.setFrom(data.speedhackSetBackPoint);
event.setTo(data.speedhackSetBackPoint);
if(event.getPlayer().teleport(data.setBackPoint)) {
event.setFrom(data.setBackPoint);
event.setTo(data.setBackPoint);
event.setCancelled(true);
}
}
@ -137,19 +136,19 @@ public class SpeedhackCheck extends Check {
@Override
protected void registerListeners() {
PluginManager pm = Bukkit.getServer().getPluginManager();
Listener speedhackPlayerListener = new SpeedhackPlayerListener(this);
// Register listeners for speedhack check
pm.registerEvent(Event.Type.PLAYER_MOVE, speedhackPlayerListener, Priority.High, plugin);
pm.registerEvent(Event.Type.PLAYER_TELEPORT, speedhackPlayerListener, Priority.Monitor, plugin);
}
public void teleported(PlayerTeleportEvent event) {
NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
data.speedhackSetBackPoint = event.getTo();
data.speedhackEventsSinceLastCheck = 0;
SpeedhackData data = SpeedhackData.get(event.getPlayer());
data.setBackPoint = event.getTo();
data.eventsSinceLastCheck = 0;
}
}

View File

@ -0,0 +1,21 @@
package cc.co.evenprime.bukkit.nocheat.data;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
public class AirbuildData {
public int perSecond = 0;
public Runnable summaryTask = null;
public static AirbuildData get(Player p) {
NoCheatData data = NoCheatData.getPlayerData(p);
if(data.airbuild == null) {
data.airbuild = new AirbuildData();
}
return data.airbuild;
}
}

View File

@ -0,0 +1,42 @@
package cc.co.evenprime.bukkit.nocheat.data;
import java.util.logging.Level;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
public class MovingData {
public int jumpPhase = 0;
public int violationsInARow[] = { 0, 0, 0 };
public double horizFreedom = 0.0D;
public int horizFreedomCounter = 0;
public double vertFreedom = 0.0D;
public int vertFreedomCounter = 0;
public Location setBackPoint = null;
public Runnable summaryTask = null;
public Level highestLogLevel = null;
public double maxYVelocity = 0.0D;
public boolean worldChanged = false;
public boolean respawned = false;
// WORKAROUND for changed PLAYER_MOVE logic
public Location teleportTo = null;
public Location lastLocation = null;
public Location teleportInitializedByMe = null;
public static MovingData get(Player p) {
NoCheatData data = NoCheatData.getPlayerData(p);
if(data.moving == null) {
data.moving = new MovingData();
}
return data.moving;
}
}

View File

@ -0,0 +1,32 @@
package cc.co.evenprime.bukkit.nocheat.data;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
public class PermissionData {
public long permissionsLastUpdate = 0;
public boolean permissionsCache[] = new boolean[8];
public static final int PERMISSION_MOVING = 0;
public static final int PERMISSION_FLYING = 1;
public static final int PERMISSION_SPEEDHACK = 2;
public static final int PERMISSION_AIRBUILD = 3;
public static final int PERMISSION_BEDTELEPORT = 4;
public static final int PERMISSION_P = 5;
public static final int PERMISSION_NOTIFY = 6;
public static final int PERMISSION_ITEMDUPE = 7;
public static PermissionData get(Player p) {
NoCheatData data = NoCheatData.getPlayerData(p);
if(data.permission == null) {
data.permission = new PermissionData();
}
return data.permission;
}
}

View File

@ -0,0 +1,25 @@
package cc.co.evenprime.bukkit.nocheat.data;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
public class SpeedhackData {
public long lastCheck = System.currentTimeMillis(); // timestamp of last check for speedhacks
public Location setBackPoint = null;
public int eventsSinceLastCheck = 0; // used to identify speedhacks
public int violationsInARow = 0;
public static SpeedhackData get(Player p) {
NoCheatData data = NoCheatData.getPlayerData(p);
if(data.speedhack == null) {
data.speedhack = new SpeedhackData();
}
return data.speedhack;
}
}

View File

@ -9,20 +9,20 @@ import cc.co.evenprime.bukkit.nocheat.checks.ItemdupeCheck;
public class ItemdupePlayerListener extends PlayerListener {
ItemdupeCheck check;
public ItemdupePlayerListener(ItemdupeCheck itemdupeCheck) {
check = itemdupeCheck;
}
@Override
public void onPlayerPickupItem(PlayerPickupItemEvent event) {
if(!event.isCancelled()) check.check(event);
}
@Override
public void onPlayerInteract(PlayerInteractEvent event) {
if(!event.isCancelled()) check.check(event);
}
}

View File

@ -4,22 +4,22 @@ import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityListener;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
public class MovingEntityListener extends EntityListener {
private MovingCheck check;
public MovingEntityListener(MovingCheck check) {
this.check = check;
}
@Override
public void onEntityDamage(EntityDamageEvent event) {
if(event.getEntity() instanceof Player) {
MovingCheck.updateVelocity(event.getEntity().getVelocity(), NoCheatData.getPlayerData((Player)event.getEntity()));
check.updateVelocity(event.getEntity().getVelocity(), MovingData.get((Player)event.getEntity()));
}
}
}

View File

@ -19,6 +19,7 @@ public class MovingPlayerListener extends PlayerListener {
public MovingPlayerListener(MovingCheck check) {
this.check = check;
}
@Override
public void onPlayerMove(PlayerMoveEvent event) {

View File

@ -6,8 +6,8 @@ import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
*
@ -26,21 +26,21 @@ public class MovingPlayerMonitor extends PlayerListener {
public void onPlayerRespawn(PlayerRespawnEvent event) {
check.respawned(event);
}
@Override
public void onPlayerTeleport(PlayerTeleportEvent event) {
check.teleported(event);
}
@Override
public void onPlayerInteract(PlayerInteractEvent event) {
MovingCheck.updateVelocity(event.getPlayer().getVelocity(), NoCheatData.getPlayerData(event.getPlayer()));
check.updateVelocity(event.getPlayer().getVelocity(), MovingData.get(event.getPlayer()));
}
@Override
public void onPlayerMove(PlayerMoveEvent event) {
NoCheatData data = NoCheatData.getPlayerData(event.getPlayer());
data.movingLastLocation = event.getTo();
MovingCheck.updateVelocity(event.getPlayer().getVelocity(), data);
MovingData data = MovingData.get(event.getPlayer());
data.lastLocation = event.getTo();
check.updateVelocity(event.getPlayer().getVelocity(), data);
}
}

View File

@ -24,10 +24,10 @@ public class SpeedhackPlayerListener extends PlayerListener {
if(!event.isCancelled()) check.check(event);
}
@Override
public void onPlayerTeleport(PlayerTeleportEvent event) {
if(!event.isCancelled()) check.teleported(event);
}
}