Lag detection in seperate thread, bugfix for blockbreak direction

check and code refactoring to reduce complexity
This commit is contained in:
Evenprime 2011-10-19 17:34:59 +02:00
parent d917242683
commit ca2da0d6b4
23 changed files with 320 additions and 245 deletions

View File

@ -1,5 +1,6 @@
package cc.co.evenprime.bukkit.nocheat; package cc.co.evenprime.bukkit.nocheat;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -16,8 +17,11 @@ import cc.co.evenprime.bukkit.nocheat.actions.ActionManager;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager; import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions; import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache; import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.config.util.ActionList;
import cc.co.evenprime.bukkit.nocheat.data.BaseData; import cc.co.evenprime.bukkit.nocheat.data.BaseData;
import cc.co.evenprime.bukkit.nocheat.data.DataManager; import cc.co.evenprime.bukkit.nocheat.data.DataManager;
import cc.co.evenprime.bukkit.nocheat.data.ExecutionHistory;
import cc.co.evenprime.bukkit.nocheat.debug.LagMeasureTask;
import cc.co.evenprime.bukkit.nocheat.debug.Performance; import cc.co.evenprime.bukkit.nocheat.debug.Performance;
import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager; import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager;
import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type; import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type;
@ -42,19 +46,15 @@ import cc.co.evenprime.bukkit.nocheat.log.LogManager;
*/ */
public class NoCheat extends JavaPlugin { public class NoCheat extends JavaPlugin {
private ConfigurationManager conf; private ConfigurationManager conf;
private LogManager log; private LogManager log;
private DataManager data; private DataManager data;
private PerformanceManager performance; private PerformanceManager performance;
private ActionManager action; private ActionManager action;
private final List<EventManager> eventManagers = new LinkedList<EventManager>(); private List<EventManager> eventManagers;
private int taskId = -1; private LagMeasureTask lagMeasureTask;
private int ingameseconds = 0;
private long lastIngamesecondTime = 0L;
private long lastIngamesecondDuration = 0L;
private boolean skipCheck = false;
public NoCheat() { public NoCheat() {
@ -62,14 +62,17 @@ public class NoCheat extends JavaPlugin {
public void onDisable() { public void onDisable() {
if(taskId != -1) {
this.getServer().getScheduler().cancelTask(taskId);
taskId = -1;
}
PluginDescriptionFile pdfFile = this.getDescription(); PluginDescriptionFile pdfFile = this.getDescription();
if(conf != null) if(lagMeasureTask != null) {
lagMeasureTask.cancel();
lagMeasureTask = null;
}
if(conf != null) {
conf.cleanup(); conf.cleanup();
conf = null;
}
log.logToConsole(LogLevel.LOW, "[NoCheat] version [" + pdfFile.getVersion() + "] is disabled."); log.logToConsole(LogLevel.LOW, "[NoCheat] version [" + pdfFile.getVersion() + "] is disabled.");
} }
@ -93,6 +96,7 @@ public class NoCheat extends JavaPlugin {
// Then set up the Action Manager // Then set up the Action Manager
this.action = new ActionManager(this); this.action = new ActionManager(this);
eventManagers = new ArrayList<EventManager>(8); // Big enough
// Then set up the event listeners // Then set up the event listeners
eventManagers.add(new PlayerMoveEventManager(this)); eventManagers.add(new PlayerMoveEventManager(this));
eventManagers.add(new PlayerTeleportEventManager(this)); eventManagers.add(new PlayerTeleportEventManager(this));
@ -103,30 +107,9 @@ public class NoCheat extends JavaPlugin {
eventManagers.add(new EntityDamageEventManager(this)); eventManagers.add(new EntityDamageEventManager(this));
// Then set up a task to monitor server lag // Then set up a task to monitor server lag
if(taskId == -1) { if(lagMeasureTask == null) {
taskId = this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() { lagMeasureTask = new LagMeasureTask(this);
lagMeasureTask.start();
public void run() {
// If the previous second took to long, skip checks during
// this second
skipCheck = lastIngamesecondDuration > 1500;
long time = System.currentTimeMillis();
lastIngamesecondDuration = time - lastIngamesecondTime;
if(lastIngamesecondDuration < 1000)
lastIngamesecondDuration = 1000;
else if(lastIngamesecondDuration > 3600000) {
lastIngamesecondDuration = 3600000; // top limit of 1
// hour per "second"
}
lastIngamesecondTime = time;
ingameseconds++;
// Check if some data is outdated now and let it be removed
data.cleanDataMap();
}
}, 0, 20);
} }
// Then print a list of active checks per world // Then print a list of active checks per world
@ -136,23 +119,26 @@ public class NoCheat extends JavaPlugin {
log.logToConsole(LogLevel.LOW, "[NoCheat] version [" + this.getDescription().getVersion() + "] is enabled."); log.logToConsole(LogLevel.LOW, "[NoCheat] version [" + this.getDescription().getVersion() + "] is enabled.");
} }
public ConfigurationManager getConfigurationManager() { public ConfigurationCache getConfig(Player player) {
return conf; return conf.getConfigurationCacheForWorld(player.getWorld().getName());
} }
public void log(LogLevel level, String message, ConfigurationCache cc) { public void log(LogLevel level, String message, ConfigurationCache cc) {
log.log(level, message, cc); log.log(level, message, cc);
} }
public BaseData getPlayerData(Player player) { public BaseData getData(Player player) {
return data.getData(player); return data.getData(player);
} }
public void clearCriticalPlayerData(Player player) { public void clearCriticalData(Player player) {
data.clearCriticalData(player); data.clearCriticalData(player);
} }
public void playerLeft(Player player) { public void playerLeft(Player player) {
// Get rid of the critical data that's stored for player immediately
clearCriticalData(player);
data.queueForRemoval(player); data.queueForRemoval(player);
} }
@ -160,24 +146,13 @@ public class NoCheat extends JavaPlugin {
data.unqueueForRemoval(player); data.unqueueForRemoval(player);
} }
public PerformanceManager getPerformanceManager() { public Performance getPerformance(Type type) {
return performance; return performance.get(type);
} }
public ActionManager getActionManager() { public void cleanDataMap() {
return action; if(data != null)
} data.cleanDataMap();
public int getIngameSeconds() {
return ingameseconds;
}
public long getIngameSecondDuration() {
return lastIngamesecondDuration;
}
public boolean skipCheck() {
return skipCheck;
} }
/** /**
@ -197,119 +172,160 @@ public class NoCheat extends JavaPlugin {
ConfigurationCache cc = this.conf.getConfigurationCacheForWorld(world.getName()); ConfigurationCache cc = this.conf.getConfigurationCacheForWorld(world.getName());
if(cc.debug.showchecks) { if(!cc.debug.showchecks)
for(EventManager em : eventManagers) { continue;
List<String> checks = em.getActiveChecks(cc);
if(checks.size() > 0) {
for(String active : em.getActiveChecks(cc)) {
line.append(active).append(' ');
}
if(!introPrinted) { for(EventManager em : eventManagers) {
log.logToConsole(LogLevel.LOW, intro); if(em.getActiveChecks(cc).size() == 0)
introPrinted = true; continue;
}
log.logToConsole(LogLevel.LOW, line.toString()); for(String active : em.getActiveChecks(cc)) {
line.append(active).append(' ');
}
line = new StringBuilder(length); if(!introPrinted) {
log.logToConsole(LogLevel.LOW, intro);
introPrinted = true;
}
for(int i = 0; i < length; i++) { log.logToConsole(LogLevel.LOW, line.toString());
line.append(' ');
} line = new StringBuilder(length);
}
for(int i = 0; i < length; i++) {
line.append(' ');
} }
} }
} }
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if(command.getName().equalsIgnoreCase("nocheat") && args.length > 0) { // Not our command
if(args[0].equalsIgnoreCase("permlist") && args.length >= 2) { if(!command.getName().equalsIgnoreCase("nocheat") || args.length == 0)
// permlist command was used CORRECTLY return false;
// Does the sender have permission? if(args[0].equalsIgnoreCase("permlist") && args.length >= 2) {
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_PERMLIST)) { // permlist command was used
return false; return handlePermlistCommand(sender, args);
}
// Get the player names } else if(args[0].equalsIgnoreCase("reload")) {
Player player = this.getServer().getPlayerExact(args[1]); // reload command was used
if(player == null) { return handleReloadCommand(sender);
sender.sendMessage("Unknown player: " + args[1]); }
return true;
} else {
String prefix = "";
if(args.length == 3) {
prefix = args[2];
}
// Make a copy to allow sorting
List<Permission> perms = new LinkedList<Permission>(this.getDescription().getPermissions());
Collections.reverse(perms);
sender.sendMessage("Player " + player.getName() + " has the permission(s):"); else if(args[0].equalsIgnoreCase("performance")) {
for(Permission permission : perms) { // performance command was used
if(permission.getName().startsWith(prefix)) { return handlePerformanceCommand(sender);
sender.sendMessage(permission.getName() + ": " + player.hasPermission(permission)); }
}
}
return true;
}
} else if(args[0].equalsIgnoreCase("reload")) {
// reload command was used
// Does the sender have permission? return false;
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_RELOAD)) { }
return false;
}
sender.sendMessage("[NoCheat] Reloading configuration"); private boolean handlePermlistCommand(CommandSender sender, String[] args) {
// Does the sender have permission to use it?
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_PERMLIST)) {
return false;
}
this.conf.cleanup(); // Get the player by name
this.conf = new ConfigurationManager(this.getDataFolder().getPath()); Player player = this.getServer().getPlayerExact(args[1]);
this.data.clearCriticalData(); if(player == null) {
sender.sendMessage("Unknown player: " + args[1]);
return true;
}
sender.sendMessage("[NoCheat] Configuration reloaded"); // Should permissions be filtered by prefix?
String prefix = "";
if(args.length == 3) {
prefix = args[2];
}
return true; // Make a copy to allow sorting
List<Permission> perms = new LinkedList<Permission>(this.getDescription().getPermissions());
Collections.reverse(perms);
sender.sendMessage("Player " + player.getName() + " has the permission(s):");
for(Permission permission : perms) {
if(permission.getName().startsWith(prefix)) {
sender.sendMessage(permission.getName() + ": " + player.hasPermission(permission));
} }
}
return true;
}
else if(args[0].equalsIgnoreCase("performance")) { private boolean handleReloadCommand(CommandSender sender) {
// performance command was used // Does the sender have permission?
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_RELOAD)) {
return false;
}
// Does the sender have permission? sender.sendMessage("[NoCheat] Reloading configuration");
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_PERFORMANCE)) {
return false;
}
sender.sendMessage("[NoCheat] Retrieving performance statistics"); this.conf.cleanup();
this.conf = new ConfigurationManager(this.getDataFolder().getPath());
this.data.clearCriticalData();
PerformanceManager pm = this.getPerformanceManager(); sender.sendMessage("[NoCheat] Configuration reloaded");
long totalTime = 0;
for(Type type : Type.values()) { return true;
Performance p = pm.get(type); }
long total = p.getTotalTime(); private boolean handlePerformanceCommand(CommandSender sender) {
totalTime += total; // Does the sender have permission?
long relative = p.getRelativeTime(); if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_PERFORMANCE)) {
long events = p.getCounter(); return false;
}
StringBuilder string = new StringBuilder("").append(type.toString()); sender.sendMessage("[NoCheat] Retrieving performance statistics");
string.append(": total ").append(pm.convertToAppropriateUnit(total)).append(" ").append(pm.getAppropriateUnit(total));
string.append(", relative ").append(pm.convertToAppropriateUnit(relative)).append(" ").append(pm.getAppropriateUnit(relative));
string.append(" over ").append(events).append(" events.");
sender.sendMessage(string.toString()); long totalTime = 0;
}
sender.sendMessage("Total time spent: " + pm.convertToAppropriateUnit(totalTime) + " " + pm.getAppropriateUnit(totalTime)); for(Type type : Type.values()) {
Performance p = this.getPerformance(type);
return true; long total = p.getTotalTime();
} totalTime += total;
StringBuilder string = new StringBuilder("").append(type.toString());
string.append(": total ").append(Performance.toString(total));
string.append(", relative ").append(Performance.toString(p.getRelativeTime()));
string.append(" over ").append(p.getCounter()).append(" events.");
sender.sendMessage(string.toString());
}
sender.sendMessage("Total time spent: " + Performance.toString(totalTime) + " " + Performance.toString(totalTime));
return true;
}
public int getIngameSeconds() {
if(lagMeasureTask != null)
return lagMeasureTask.getIngameSeconds();
return 0;
}
public boolean skipCheck() {
if(lagMeasureTask != null)
return lagMeasureTask.skipCheck();
return false;
}
public long getIngameSecondDuration() {
if(lagMeasureTask != null)
return lagMeasureTask.getIngameSecondDuration();
return 1000L;
}
public boolean execute(Player player, ActionList actions, int violationLevel, ExecutionHistory history, ConfigurationCache cc) {
if(action != null) {
return action.executeActions(player, actions, violationLevel, history, cc);
} }
return false; return false;
} }
} }

View File

@ -30,7 +30,7 @@ public class ActionManager {
boolean special = false; boolean special = false;
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
// Always set this here "by hand" // Always set this here "by hand"
data.log.violationLevel = violationLevel; data.log.violationLevel = violationLevel;

View File

@ -23,7 +23,7 @@ public class DirectionCheck {
public boolean check(Player player, Block brokenBlock, ConfigurationCache cc) { public boolean check(Player player, Block brokenBlock, ConfigurationCache cc) {
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
// If the block is instabreak and we don't check instabreak, return // If the block is instabreak and we don't check instabreak, return
if(!cc.blockbreak.checkinstabreakblocks && brokenBlock.getLocation().equals(data.blockbreak.instaBrokeBlockLocation)) { if(!cc.blockbreak.checkinstabreakblocks && brokenBlock.getLocation().equals(data.blockbreak.instaBrokeBlockLocation)) {
@ -48,11 +48,11 @@ public class DirectionCheck {
// Prepare some event-specific values for logging and custom actions // Prepare some event-specific values for logging and custom actions
data.log.check = "blockbreak.direction"; data.log.check = "blockbreak.direction";
cancel = plugin.getActionManager().executeActions(player, cc.blockbreak.directionActions, (int) data.blockbreak.directionViolationLevel, data.blockbreak.history, cc); cancel = plugin.execute(player, cc.blockbreak.directionActions, (int) data.blockbreak.directionViolationLevel, data.blockbreak.history, cc);
if(cancel) { if(cancel) {
// Needed to calculate penalty times // Needed to calculate penalty times
data.fight.directionLastViolationTime = time; data.blockbreak.directionLastViolationTime = time;
} }
} }

View File

@ -30,7 +30,7 @@ public class ReachCheck {
double distance = CheckUtil.reachCheck(player, brokenBlock.getX() + 0.5D, brokenBlock.getY() + 0.5D, brokenBlock.getZ() + 0.5D, player.getGameMode() == GameMode.CREATIVE ? cc.blockbreak.reachDistance + 2 : cc.blockbreak.reachDistance); double distance = CheckUtil.reachCheck(player, brokenBlock.getX() + 0.5D, brokenBlock.getY() + 0.5D, brokenBlock.getZ() + 0.5D, player.getGameMode() == GameMode.CREATIVE ? cc.blockbreak.reachDistance + 2 : cc.blockbreak.reachDistance);
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(distance > 0D) { if(distance > 0D) {
// Player failed the check // Player failed the check
@ -42,7 +42,7 @@ public class ReachCheck {
data.log.check = "blockbreak.reach"; data.log.check = "blockbreak.reach";
data.log.reachdistance = distance; data.log.reachdistance = distance;
cancel = plugin.getActionManager().executeActions(player, cc.blockbreak.reachActions, (int) data.blockbreak.reachViolationLevel, data.blockbreak.history, cc); cancel = plugin.execute(player, cc.blockbreak.reachActions, (int) data.blockbreak.reachViolationLevel, data.blockbreak.history, cc);
} else { } else {
data.blockbreak.reachViolationLevel *= 0.9D; data.blockbreak.reachViolationLevel *= 0.9D;
} }

View File

@ -26,7 +26,7 @@ public class OnLiquidCheck {
boolean cancel = false; boolean cancel = false;
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(blockPlaced == null || blockPlaced.isEmpty() || (blockPlacedAgainst != null && isSolid(blockPlacedAgainst.getTypeId()))) { if(blockPlaced == null || blockPlaced.isEmpty() || (blockPlacedAgainst != null && isSolid(blockPlacedAgainst.getTypeId()))) {
// all ok // all ok
@ -38,7 +38,7 @@ public class OnLiquidCheck {
data.log.placed = blockPlaced; data.log.placed = blockPlaced;
data.log.placedAgainst = blockPlacedAgainst; data.log.placedAgainst = blockPlacedAgainst;
cancel = plugin.getActionManager().executeActions(player, cc.blockplace.onliquidActions, (int) data.blockplace.onliquidViolationLevel, data.blockplace.history, cc); cancel = plugin.execute(player, cc.blockplace.onliquidActions, (int) data.blockplace.onliquidViolationLevel, data.blockplace.history, cc);
} }
data.blockplace.onliquidViolationLevel *= 0.95D; // Reduce level over data.blockplace.onliquidViolationLevel *= 0.95D; // Reduce level over

View File

@ -29,7 +29,7 @@ public class ReachCheck {
double distance = CheckUtil.reachCheck(player, placedAgainstBlock.getX() + 0.5D, placedAgainstBlock.getY() + 0.5D, placedAgainstBlock.getZ() + 0.5D, cc.blockplace.reachDistance); double distance = CheckUtil.reachCheck(player, placedAgainstBlock.getX() + 0.5D, placedAgainstBlock.getY() + 0.5D, placedAgainstBlock.getZ() + 0.5D, cc.blockplace.reachDistance);
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(distance > 0D) { if(distance > 0D) {
// Player failed the check // Player failed the check
@ -41,7 +41,7 @@ public class ReachCheck {
data.log.check = "blockplace.reach"; data.log.check = "blockplace.reach";
data.log.reachdistance = distance; data.log.reachdistance = distance;
cancel = plugin.getActionManager().executeActions(player, cc.blockplace.reachActions, (int) data.blockplace.reachViolationLevel, data.blockplace.history, cc); cancel = plugin.execute(player, cc.blockplace.reachActions, (int) data.blockplace.reachViolationLevel, data.blockplace.history, cc);
} else { } else {
data.blockplace.reachViolationLevel *= 0.9D; data.blockplace.reachViolationLevel *= 0.9D;
} }

View File

@ -37,7 +37,7 @@ public class ChatCheck {
int time = plugin.getIngameSeconds(); int time = plugin.getIngameSeconds();
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(data.chat.spamLasttime + cc.chat.spamTimeframe <= time) { if(data.chat.spamLasttime + cc.chat.spamTimeframe <= time) {
data.chat.spamLasttime = time; data.chat.spamLasttime = time;
@ -54,7 +54,7 @@ public class ChatCheck {
data.log.check = "chat.spam"; data.log.check = "chat.spam";
data.log.text = message; data.log.text = message;
cancel = plugin.getActionManager().executeActions(player, cc.chat.spamActions, data.chat.messageCount - cc.chat.spamLimit, data.chat.history, cc); cancel = plugin.execute(player, cc.chat.spamActions, data.chat.messageCount - cc.chat.spamLimit, data.chat.history, cc);
} }
} }

View File

@ -44,7 +44,7 @@ public class FightCheck {
// height to get the "center" of the hitbox // height to get the "center" of the hitbox
double off = CheckUtil.directionCheck(player, entity.locX, entity.locY + 1.0D, entity.locZ, width, 2.0D, cc.fight.directionPrecision); double off = CheckUtil.directionCheck(player, entity.locX, entity.locY + 1.0D, entity.locZ, width, 2.0D, cc.fight.directionPrecision);
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(off < 0.1D) { if(off < 0.1D) {
// Player did probably nothing wrong // Player did probably nothing wrong
@ -61,7 +61,7 @@ public class FightCheck {
// actions // actions
data.log.check = "fight.direction"; data.log.check = "fight.direction";
cancel = plugin.getActionManager().executeActions(player, cc.fight.directionActions, (int) data.fight.violationLevel, data.fight.history, cc); cancel = plugin.execute(player, cc.fight.directionActions, (int) data.fight.violationLevel, data.fight.history, cc);
if(cancel) { if(cancel) {
// Needed to calculate penalty times // Needed to calculate penalty times

View File

@ -29,7 +29,7 @@ public class FlyingCheck {
public Location check(Player player, Location from, Location to, ConfigurationCache cc) { public Location check(Player player, Location from, Location to, ConfigurationCache cc) {
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(data.moving.runflySetBackPoint == null) { if(data.moving.runflySetBackPoint == null) {
data.moving.runflySetBackPoint = player.getLocation().clone(); data.moving.runflySetBackPoint = player.getLocation().clone();
@ -83,7 +83,7 @@ public class FlyingCheck {
data.log.toLocation = to; data.log.toLocation = to;
data.log.check = "flying/toofast"; data.log.check = "flying/toofast";
boolean cancel = plugin.getActionManager().executeActions(player, cc.moving.flyingActions, (int) data.moving.runflyViolationLevel, data.moving.history, cc); boolean cancel = plugin.execute(player, cc.moving.flyingActions, (int) data.moving.runflyViolationLevel, data.moving.history, cc);
// Was one of the actions a cancel? Then really do it // Was one of the actions a cancel? Then really do it
if(cancel) { if(cancel) {

View File

@ -85,7 +85,7 @@ public class MorePacketsCheck {
Location newToLocation = null; Location newToLocation = null;
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
data.moving.morePacketsCounter++; data.moving.morePacketsCounter++;
if(data.moving.morePacketsSetbackPoint == null) { if(data.moving.morePacketsSetbackPoint == null) {
@ -122,7 +122,7 @@ public class MorePacketsCheck {
data.log.check = "moving/morepackets"; data.log.check = "moving/morepackets";
boolean cancel = false; boolean cancel = false;
cancel = plugin.getActionManager().executeActions(player, cc.moving.morePacketsActions, (int) data.moving.morePacketsViolationLevel, data.moving.history, cc); cancel = plugin.execute(player, cc.moving.morePacketsActions, (int) data.moving.morePacketsViolationLevel, data.moving.history, cc);
// Only do the cancel if the player didn't change worlds // Only do the cancel if the player didn't change worlds
// inbetween // inbetween

View File

@ -31,7 +31,7 @@ public class NoFallCheck {
double oldY = from.getY(); double oldY = from.getY();
double newY = to.getY(); double newY = to.getY();
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
// This check is pretty much always a step behind for technical reasons. // This check is pretty much always a step behind for technical reasons.
if(fromOnOrInGround) { if(fromOnOrInGround) {
@ -58,7 +58,7 @@ public class NoFallCheck {
data.log.falldistance = data.moving.fallDistance; data.log.falldistance = data.moving.fallDistance;
data.log.check = "moving/nofall"; data.log.check = "moving/nofall";
boolean cancel = plugin.getActionManager().executeActions(player, cc.moving.nofallActions, (int) data.moving.nofallViolationLevel, data.moving.history, cc); boolean cancel = plugin.execute(player, cc.moving.nofallActions, (int) data.moving.nofallViolationLevel, data.moving.history, cc);
// If "cancelled", the fall damage gets dealt in a way that's // If "cancelled", the fall damage gets dealt in a way that's
// visible to other plugins // visible to other plugins

View File

@ -54,7 +54,7 @@ public class RunFlyCheck {
*/ */
Location newToLocation = null; Location newToLocation = null;
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
/******** DO GENERAL DATA MODIFICATIONS ONCE FOR EACH EVENT *****/ /******** DO GENERAL DATA MODIFICATIONS ONCE FOR EACH EVENT *****/
if(data.moving.horizVelocityCounter > 0) { if(data.moving.horizVelocityCounter > 0) {
@ -102,7 +102,7 @@ public class RunFlyCheck {
*/ */
public void blockPlaced(Player player, Block blockPlaced) { public void blockPlaced(Player player, Block blockPlaced) {
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(blockPlaced == null || data.moving.runflySetBackPoint == null) { if(blockPlaced == null || data.moving.runflySetBackPoint == null) {
return; return;

View File

@ -43,7 +43,7 @@ public class RunningCheck {
final double zDistance = to.getZ() - from.getZ(); final double zDistance = to.getZ() - from.getZ();
final double horizontalDistance = Math.sqrt((xDistance * xDistance + zDistance * zDistance)); final double horizontalDistance = Math.sqrt((xDistance * xDistance + zDistance * zDistance));
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(data.moving.runflySetBackPoint == null) { if(data.moving.runflySetBackPoint == null) {
data.moving.runflySetBackPoint = from.clone(); data.moving.runflySetBackPoint = from.clone();
@ -84,7 +84,7 @@ public class RunningCheck {
else if(resultVert > 0) else if(resultVert > 0)
data.log.check = "runfly/vertical"; data.log.check = "runfly/vertical";
boolean cancel = plugin.getActionManager().executeActions(player, cc.moving.actions, (int) data.moving.runflyViolationLevel, data.moving.history, cc); boolean cancel = plugin.execute(player, cc.moving.actions, (int) data.moving.runflyViolationLevel, data.moving.history, cc);
// Was one of the actions a cancel? Then do it // Was one of the actions a cancel? Then do it
if(cancel) { if(cancel) {
@ -130,7 +130,7 @@ public class RunningCheck {
e.printStackTrace(); e.printStackTrace();
} }
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
if(cc.moving.sneakingCheck && player.isSneaking() && !player.hasPermission(Permissions.MOVE_SNEAK)) { if(cc.moving.sneakingCheck && player.isSneaking() && !player.hasPermission(Permissions.MOVE_SNEAK)) {
distanceAboveLimit = totalDistance - cc.moving.sneakingSpeedLimit - data.moving.horizFreedom; distanceAboveLimit = totalDistance - cc.moving.sneakingSpeedLimit - data.moving.horizFreedom;
@ -183,7 +183,7 @@ public class RunningCheck {
final double toY = to.getY(); final double toY = to.getY();
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
double limit = data.moving.vertFreedom + cc.moving.jumpheight; double limit = data.moving.vertFreedom + cc.moving.jumpheight;

View File

@ -0,0 +1,66 @@
package cc.co.evenprime.bukkit.nocheat.debug;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
public class LagMeasureTask implements Runnable {
private int ingameseconds = 0;
private long lastIngamesecondTime = 0L;
private long lastIngamesecondDuration = 0L;
private boolean skipCheck = true;
private int lagMeasureTaskId = -1;
private final NoCheat plugin;
public LagMeasureTask(NoCheat plugin) {
this.plugin = plugin;
}
public void start() {
lagMeasureTaskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this, 0, 20);
}
public void run() {
// If the previous second took to long, skip checks during
// this second
skipCheck = lastIngamesecondDuration > 1500;
long time = System.currentTimeMillis();
lastIngamesecondDuration = time - lastIngamesecondTime;
if(lastIngamesecondDuration < 1000)
lastIngamesecondDuration = 1000;
else if(lastIngamesecondDuration > 3600000) {
lastIngamesecondDuration = 3600000; // top limit of 1
// hour per "second"
}
lastIngamesecondTime = time;
ingameseconds++;
// Check if some data is outdated now and let it be removed
plugin.cleanDataMap();
}
public void cancel() {
if(lagMeasureTaskId != -1) {
try {
plugin.getServer().getScheduler().cancelTask(lagMeasureTaskId);
} catch(Exception e) {
System.out.println("NoCheat: Couldn't cancel LagMeasureTask: " + e.getMessage());
}
lagMeasureTaskId = -1;
}
}
public int getIngameSeconds() {
return ingameseconds;
}
public long getIngameSecondDuration() {
return lastIngamesecondDuration;
}
public boolean skipCheck() {
return skipCheck;
}
}

View File

@ -7,6 +7,12 @@ public class Performance {
private long counter = 1; // start with 1 to avoid DIV/0 errors private long counter = 1; // start with 1 to avoid DIV/0 errors
private final boolean enabled; private final boolean enabled;
private static final long NANO = 1;
private static final long MICRO = NANO * 1000;
private static final long MILLI = MICRO * 1000;
private static final long SECOND = MILLI * 1000;
private static final long MINUTE = SECOND * 60;
public Performance(boolean enabled) { public Performance(boolean enabled) {
this.enabled = enabled; this.enabled = enabled;
@ -34,4 +40,51 @@ public class Performance {
public boolean isEnabled() { public boolean isEnabled() {
return enabled; return enabled;
} }
private static String getAppropriateUnit(long timeInNanoseconds) {
// more than 10 minutes
if(timeInNanoseconds > MINUTE * 10) {
return "minutes";
}
// more than 10 seconds
else if(timeInNanoseconds > SECOND * 10) {
return "seconds";
}
// more than 10 milliseconds
else if(timeInNanoseconds > MILLI * 10) {
return "milliseconds";
}
// more than 10 microseconds
else if(timeInNanoseconds > MICRO * 10) {
return "microseconds";
} else {
return "nanoseconds";
}
}
private static long convertToAppropriateUnit(long timeInNanoseconds) {
// more than 10 minutes
if(timeInNanoseconds > MINUTE * 10) {
return timeInNanoseconds / MINUTE;
}
// more than 10 seconds
else if(timeInNanoseconds > SECOND * 10) {
return timeInNanoseconds / SECOND;
}
// more than 10 milliseconds
else if(timeInNanoseconds > MILLI * 10) {
return timeInNanoseconds / MILLI;
}
// more than 10 microseconds
else if(timeInNanoseconds > MICRO * 10) {
return timeInNanoseconds / MICRO;
} else {
return timeInNanoseconds / NANO;
}
}
public static String toString(long timeInNanoseconds) {
return convertToAppropriateUnit(timeInNanoseconds) + " " + getAppropriateUnit(timeInNanoseconds);
}
} }

View File

@ -9,11 +9,7 @@ public class PerformanceManager {
BLOCKBREAK, BLOCKDAMAGE, BLOCKPLACE, CHAT, MOVING, VELOCITY, FIGHT BLOCKBREAK, BLOCKDAMAGE, BLOCKPLACE, CHAT, MOVING, VELOCITY, FIGHT
} }
private static final long NANO = 1;
private static final long MICRO = NANO * 1000;
private static final long MILLI = MICRO * 1000;
private static final long SECOND = MILLI * 1000;
private static final long MINUTE = SECOND * 60;
private final Map<Type, Performance> map; private final Map<Type, Performance> map;
@ -29,47 +25,4 @@ public class PerformanceManager {
public Performance get(Type type) { public Performance get(Type type) {
return map.get(type); return map.get(type);
} }
public String getAppropriateUnit(long timeInNanoseconds) {
// more than 10 minutes
if(timeInNanoseconds > MINUTE * 10) {
return "minutes";
}
// more than 10 seconds
else if(timeInNanoseconds > SECOND * 10) {
return "seconds";
}
// more than 10 milliseconds
else if(timeInNanoseconds > MILLI * 10) {
return "milliseconds";
}
// more than 10 microseconds
else if(timeInNanoseconds > MICRO * 10) {
return "microseconds";
} else {
return "nanoseconds";
}
}
public long convertToAppropriateUnit(long timeInNanoseconds) {
// more than 10 minutes
if(timeInNanoseconds > MINUTE * 10) {
return timeInNanoseconds / MINUTE;
}
// more than 10 seconds
else if(timeInNanoseconds > SECOND * 10) {
return timeInNanoseconds / SECOND;
}
// more than 10 milliseconds
else if(timeInNanoseconds > MILLI * 10) {
return timeInNanoseconds / MILLI;
}
// more than 10 microseconds
else if(timeInNanoseconds > MICRO * 10) {
return timeInNanoseconds / MICRO;
} else {
return timeInNanoseconds / NANO;
}
}
} }

View File

@ -24,8 +24,6 @@ import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type;
* Central location to listen to player-interact events and dispatch them to * Central location to listen to player-interact events and dispatch them to
* relevant checks * relevant checks
* *
* @author Evenprime
*
*/ */
public class BlockBreakEventManager extends BlockListener implements EventManager { public class BlockBreakEventManager extends BlockListener implements EventManager {
@ -38,8 +36,8 @@ public class BlockBreakEventManager extends BlockListener implements EventManage
this.plugin = plugin; this.plugin = plugin;
this.blockBreakCheck = new BlockBreakCheck(plugin); this.blockBreakCheck = new BlockBreakCheck(plugin);
this.blockBreakPerformance = plugin.getPerformanceManager().get(Type.BLOCKBREAK); this.blockBreakPerformance = plugin.getPerformance(Type.BLOCKBREAK);
this.blockDamagePerformance = plugin.getPerformanceManager().get(Type.BLOCKDAMAGE); this.blockDamagePerformance = plugin.getPerformance(Type.BLOCKDAMAGE);
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
@ -62,7 +60,7 @@ public class BlockBreakEventManager extends BlockListener implements EventManage
nanoTimeStart = System.nanoTime(); nanoTimeStart = System.nanoTime();
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName()); final ConfigurationCache cc = plugin.getConfig(player);
// Find out if checks need to be done for that player // Find out if checks need to be done for that player
if(cc.blockbreak.check && !player.hasPermission(Permissions.BLOCKBREAK)) { if(cc.blockbreak.check && !player.hasPermission(Permissions.BLOCKBREAK)) {
@ -98,7 +96,7 @@ public class BlockBreakEventManager extends BlockListener implements EventManage
final Player player = event.getPlayer(); final Player player = event.getPlayer();
// Get the player-specific stored data that applies here // Get the player-specific stored data that applies here
final BaseData data = plugin.getPlayerData(player); final BaseData data = plugin.getData(player);
// Remember this location. We ignore block breaks in the block-break // Remember this location. We ignore block breaks in the block-break
// direction check that are insta-breaks // direction check that are insta-breaks

View File

@ -23,8 +23,6 @@ import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type;
* Central location to listen to Block-related events and dispatching them to * Central location to listen to Block-related events and dispatching them to
* checks * checks
* *
* @author Evenprime
*
*/ */
public class BlockPlaceEventManager extends BlockListener implements EventManager { public class BlockPlaceEventManager extends BlockListener implements EventManager {
@ -41,7 +39,7 @@ public class BlockPlaceEventManager extends BlockListener implements EventManage
this.movingCheck = new RunFlyCheck(plugin); this.movingCheck = new RunFlyCheck(plugin);
this.blockPlaceCheck = new BlockPlaceCheck(plugin); this.blockPlaceCheck = new BlockPlaceCheck(plugin);
this.blockPlacePerformance = p.getPerformanceManager().get(Type.BLOCKPLACE); this.blockPlacePerformance = p.getPerformance(Type.BLOCKPLACE);
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
@ -79,7 +77,7 @@ public class BlockPlaceEventManager extends BlockListener implements EventManage
boolean cancel = false; boolean cancel = false;
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName()); final ConfigurationCache cc = plugin.getConfig(player);
// Find out if checks need to be done for that player // Find out if checks need to be done for that player
if(cc.blockplace.check && !player.hasPermission(Permissions.BLOCKPLACE)) { if(cc.blockplace.check && !player.hasPermission(Permissions.BLOCKPLACE)) {

View File

@ -32,7 +32,7 @@ public class EntityDamageEventManager extends EntityListener implements EventMan
this.plugin = plugin; this.plugin = plugin;
this.fightCheck = new FightCheck(plugin); this.fightCheck = new FightCheck(plugin);
this.fightPerformance = plugin.getPerformanceManager().get(Type.FIGHT); this.fightPerformance = plugin.getPerformance(Type.FIGHT);
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
@ -64,7 +64,7 @@ public class EntityDamageEventManager extends EntityListener implements EventMan
// possibilities above // possibilities above
final Player player = (Player) ((EntityDamageByEntityEvent) event).getDamager(); final Player player = (Player) ((EntityDamageByEntityEvent) event).getDamager();
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName()); final ConfigurationCache cc = plugin.getConfig(player);
// Find out if checks need to be done for that player // Find out if checks need to be done for that player
if(cc.fight.check && !player.hasPermission(Permissions.FIGHT)) { if(cc.fight.check && !player.hasPermission(Permissions.FIGHT)) {

View File

@ -20,8 +20,6 @@ import cc.co.evenprime.bukkit.nocheat.debug.Performance;
import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type; import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type;
/** /**
*
* @author Evenprime
* *
*/ */
public class PlayerChatEventManager extends PlayerListener implements EventManager { public class PlayerChatEventManager extends PlayerListener implements EventManager {
@ -35,7 +33,7 @@ public class PlayerChatEventManager extends PlayerListener implements EventManag
this.plugin = plugin; this.plugin = plugin;
this.chatCheck = new ChatCheck(plugin); this.chatCheck = new ChatCheck(plugin);
this.chatPerformance = plugin.getPerformanceManager().get(Type.CHAT); this.chatPerformance = plugin.getPerformance(Type.CHAT);
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
@ -58,7 +56,7 @@ public class PlayerChatEventManager extends PlayerListener implements EventManag
nanoTimeStart = System.nanoTime(); nanoTimeStart = System.nanoTime();
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName()); final ConfigurationCache cc = plugin.getConfig(player);
// Find out if checks need to be done for that player // Find out if checks need to be done for that player
if(cc.chat.check && !player.hasPermission(Permissions.CHAT)) { if(cc.chat.check && !player.hasPermission(Permissions.CHAT)) {

View File

@ -28,8 +28,6 @@ import cc.co.evenprime.bukkit.nocheat.debug.PerformanceManager.Type;
* Get the event, decide which checks should work on it and in what order, * Get the event, decide which checks should work on it and in what order,
* evaluate the check results and decide what to * evaluate the check results and decide what to
* *
* @author Evenprime
*
*/ */
public class PlayerMoveEventManager extends PlayerListener implements EventManager { public class PlayerMoveEventManager extends PlayerListener implements EventManager {
@ -44,8 +42,8 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
this.plugin = plugin; this.plugin = plugin;
this.movingCheck = new RunFlyCheck(plugin); this.movingCheck = new RunFlyCheck(plugin);
this.movePerformance = plugin.getPerformanceManager().get(Type.MOVING); this.movePerformance = plugin.getPerformance(Type.MOVING);
this.velocityPerformance = plugin.getPerformanceManager().get(Type.VELOCITY); this.velocityPerformance = plugin.getPerformance(Type.VELOCITY);
PluginManager pm = Bukkit.getServer().getPluginManager(); PluginManager pm = Bukkit.getServer().getPluginManager();
@ -69,7 +67,7 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
// Get the world-specific configuration that applies here // Get the world-specific configuration that applies here
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName()); final ConfigurationCache cc = plugin.getConfig(player);
// Find out if checks need to be done for that player // Find out if checks need to be done for that player
if(cc.moving.check && !player.hasPermission(Permissions.MOVE)) { if(cc.moving.check && !player.hasPermission(Permissions.MOVE)) {
@ -95,7 +93,7 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
event.setTo(l); event.setTo(l);
// Get the player-specific stored data that applies here // Get the player-specific stored data that applies here
final BaseData data = plugin.getPlayerData(player); final BaseData data = plugin.getData(player);
data.moving.teleportTo = l; data.moving.teleportTo = l;
} }
@ -120,7 +118,7 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
Player player = event.getPlayer(); Player player = event.getPlayer();
BaseData data = plugin.getPlayerData(player); BaseData data = plugin.getData(player);
Vector v = event.getVelocity(); Vector v = event.getVelocity();

View File

@ -29,9 +29,6 @@ public class PlayerQuitEventManager extends PlayerListener implements EventManag
@Override @Override
public void onPlayerQuit(PlayerQuitEvent event) { public void onPlayerQuit(PlayerQuitEvent event) {
// Get rid of the critical data that's stored for player immediately
plugin.clearCriticalPlayerData(event.getPlayer());
// But only after a certain time, get rid of the rest of the data // But only after a certain time, get rid of the rest of the data
plugin.playerLeft(event.getPlayer()); plugin.playerLeft(event.getPlayer());
} }

View File

@ -23,8 +23,6 @@ import cc.co.evenprime.bukkit.nocheat.data.BaseData;
* Only place that listens to Player-teleport related events and dispatches them * Only place that listens to Player-teleport related events and dispatches them
* to relevant checks * to relevant checks
* *
* @author Evenprime
*
*/ */
public class PlayerTeleportEventManager extends PlayerListener implements EventManager { public class PlayerTeleportEventManager extends PlayerListener implements EventManager {
@ -52,7 +50,7 @@ public class PlayerTeleportEventManager extends PlayerListener implements EventM
return; return;
} }
final BaseData data = plugin.getPlayerData(event.getPlayer()); final BaseData data = plugin.getData(event.getPlayer());
if(data.moving.teleportTo != null && data.moving.teleportTo.equals(event.getTo())) { if(data.moving.teleportTo != null && data.moving.teleportTo.equals(event.getTo())) {
event.setCancelled(false); event.setCancelled(false);
@ -91,7 +89,7 @@ public class PlayerTeleportEventManager extends PlayerListener implements EventM
private void handleTeleportation(Player player, Location newLocation) { private void handleTeleportation(Player player, Location newLocation) {
plugin.clearCriticalPlayerData(player); plugin.clearCriticalData(player);
} }
public List<String> getActiveChecks(ConfigurationCache cc) { public List<String> getActiveChecks(ConfigurationCache cc) {