And even more comments

This commit is contained in:
Evenprime 2012-03-01 21:23:06 +01:00
parent 2aedcd7515
commit f830defb5f
16 changed files with 190 additions and 77 deletions

View File

@ -86,7 +86,7 @@ public class NoCheat extends JavaPlugin implements Listener {
eventManagers = new ArrayList<EventManager>(8); // Big enough
// Then set up the event listeners
eventManagers.add(new MovingCheckListener(this));
eventManagers.add(new WorkaroundsListener(this));
eventManagers.add(new WorkaroundsListener());
eventManagers.add(new ChatCheckListener(this));
eventManagers.add(new BlockBreakCheckListener(this));
eventManagers.add(new BlockPlaceCheckListener(this));

View File

@ -17,6 +17,10 @@ import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The abstract Check class, providing some basic functionality
*
*/
public abstract class Check {
private final String name;
@ -41,13 +45,18 @@ public abstract class Check {
boolean special = false;
// Get the to be executed actions
Action[] actions = actionList.getActions(violationLevel);
final long time = System.currentTimeMillis() / 1000L;
// The configuration will be needed too
final ConfigurationCacheStore cc = player.getConfigurationStore();
for(Action ac : actions) {
if(player.getExecutionHistory().executeAction(groupId, ac, time)) {
// The executionHistory said it really is time to execute the
// action, find out what it is and do what is needed
if(ac instanceof LogAction && !player.hasPermission(actionList.permissionSilent)) {
executeLogAction((LogAction) ac, this, player, cc);
} else if(ac instanceof SpecialAction) {
@ -79,6 +88,7 @@ public abstract class Check {
if(!cc.logging.active)
return;
// Fire one of our custom "Log" Events
Bukkit.getServer().getPluginManager().callEvent(new NoCheatLogEvent(cc.logging.prefix, l.getLogMessage(player, check), cc.logging.toConsole && l.toConsole(), cc.logging.toChat && l.toChat(), cc.logging.toFile && l.toFile()));
}

View File

@ -12,7 +12,8 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
/**
* Some stuff that's used by different checks
* Some stuff that's used by different checks or just too complex to keep
* in other places
*
*/
public class CheckUtil {
@ -85,10 +86,11 @@ public class CheckUtil {
// All fences are solid - fences are treated specially due
// to being 1.5 blocks high
private static final int FENCE = 16 | SOLID | NONSOLID; // 0x00010010
private static final int FENCE = 16 | SOLID | NONSOLID; // 0x00010011
private static final int INGROUND = 128;
private static final int ONGROUND = 256;
// Until I can think of a better way to determine if a block is solid or
// not, this is what I'll do
private static final int types[];
@ -168,6 +170,8 @@ public class CheckUtil {
* }
* }
*/
// We need to know what is considered food for the instanteat check
foods.add(Material.APPLE);
foods.add(Material.BREAD);
foods.add(Material.COOKED_BEEF);
@ -202,7 +206,7 @@ public class CheckUtil {
final int lowerX = lowerBorder(location.x);
final int upperX = upperBorder(location.x);
final int Y = (int) Math.floor(location.y);
final int Y = (int) location.y;
final int lowerZ = lowerBorder(location.z);
final int upperZ = upperBorder(location.z);

View File

@ -8,7 +8,6 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
/**
@ -18,12 +17,7 @@ import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
*/
public class WorkaroundsListener implements Listener, EventManager {
//private final NoCheat plugin;
public WorkaroundsListener(NoCheat plugin) {
//this.plugin = plugin;
}
public WorkaroundsListener() {}
@EventHandler(priority = EventPriority.HIGHEST)
public void playerMove(final PlayerMoveEvent event) {
@ -39,12 +33,14 @@ public class WorkaroundsListener implements Listener, EventManager {
@EventHandler(priority = EventPriority.HIGHEST)
public void toggleSprint(final PlayerToggleSprintEvent event) {
// Some plugins cancel "sprinting", which makes no sense at all because
// it doesn't stop people from sprinting and rewards them by reducing
// their hunger bar as if they were walking instead of sprinting
if(event.isCancelled() && event.isSprinting()) {
event.setCancelled(false);
}
}
@Override
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
return Collections.emptyList();
}

View File

@ -19,23 +19,29 @@ public class FlyingCheck extends MovingCheck {
super(plugin, "moving.flying");
}
// Determined by trial and error, the flying movement speed of the creative
// mode
private static final double creativeSpeed = 0.60D;
public PreciseLocation check(NoCheatPlayer player, MovingData data, MovingConfig ccmoving) {
// The setBack is the location that players may get teleported to when
// they fail the check
final PreciseLocation setBack = data.runflySetBackPoint;
final PreciseLocation from = data.from;
final PreciseLocation to = data.to;
// If we have no setback, define one now
if(!setBack.isSet()) {
setBack.set(from);
}
// Used to store the location where the player gets teleported to
PreciseLocation newToLocation = null;
// Before doing anything, do a basic height check
// This is silent for now, will log messages later
// probably
// Before doing anything, do a basic height check to determine if
// players are flying too high
if(to.y - data.vertFreedom > ccmoving.flyingHeightLimit) {
newToLocation = new PreciseLocation();
newToLocation.set(setBack);
@ -43,33 +49,36 @@ public class FlyingCheck extends MovingCheck {
return newToLocation;
}
final double yDistance = to.y - from.y;
// Calculate some distances
final double yDistance = to.y - from.y;
final double xDistance = to.x - from.x;
final double zDistance = to.z - from.z;
// How far did the player move horizontally
final double horizontalDistance = Math.sqrt((xDistance * xDistance + zDistance * zDistance));
double resultHoriz = 0;
double resultVert = 0;
double result = 0;
// In case of creative gamemode, give at least 0.60 speed limit
// horizontal
// In case of creative game mode give at least 0.60 speed limit horizontal
double speedLimitHorizontal = player.isCreative() ? Math.max(creativeSpeed, ccmoving.flyingSpeedLimitHorizontal) : ccmoving.flyingSpeedLimitHorizontal;
// If the player is affected by potion of swiftness
speedLimitHorizontal *= player.getSpeedAmplifier();
// Finally, determine how far the player went beyond the set limits
resultHoriz = Math.max(0.0D, horizontalDistance - data.horizFreedom - speedLimitHorizontal);
boolean sprinting = player.isSprinting();
data.bunnyhopdelay--;
// Did he go too far?
if(resultHoriz > 0 && sprinting) {
// Try to treat it as a the "bunnyhop" problem
// The bunnyhop problem is that landing and immediatly jumping
// again leads to a player moving almost twice as far in that step
if(data.bunnyhopdelay <= 0 && resultHoriz < 0.4D) {
data.bunnyhopdelay = 9;
resultHoriz = 0;
@ -78,6 +87,9 @@ public class FlyingCheck extends MovingCheck {
resultHoriz *= 100;
// Is the player affected by the "jumping" potion
// This is really just a very, very crude estimation and far from
// reality
double jumpAmplifier = player.getJumpAmplifier();
if(jumpAmplifier > data.lastJumpAmplifier) {
data.lastJumpAmplifier = jumpAmplifier;
@ -89,14 +101,15 @@ public class FlyingCheck extends MovingCheck {
data.lastJumpAmplifier--;
}
// super simple, just check distance compared to max distance
// super simple, just check distance compared to max distance vertical
resultVert = Math.max(0.0D, yDistance - data.vertFreedom - speedLimitVertical) * 100;
result = resultHoriz + resultVert;
// The player went to far, either horizontal or vertical
if(result > 0) {
// Increment violation counter
// Increment violation counter and statistics
data.runflyVL += result;
if(resultHoriz > 0) {
incrementStatistics(player, Id.MOV_RUNNING, resultHoriz);
@ -106,6 +119,8 @@ public class FlyingCheck extends MovingCheck {
incrementStatistics(player, Id.MOV_FLYING, resultVert);
}
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
boolean cancel = executeActions(player, ccmoving.flyingActions, data.runflyVL);
// Was one of the actions a cancel? Then really do it
@ -114,10 +129,10 @@ public class FlyingCheck extends MovingCheck {
}
}
// Slowly reduce the level with each event
// Slowly reduce the violation level with each event
data.runflyVL *= 0.97;
// Some other cleanup 'n' stuff
// If the player did not get cancelled, define a new setback point
if(newToLocation == null) {
setBack.set(to);
}
@ -125,10 +140,11 @@ public class FlyingCheck extends MovingCheck {
return newToLocation;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).runflyVL);
return String.format(Locale.US, "%d", (int) getData(player).runflyVL);
else
return super.getParameter(wildcard, player);
}

View File

@ -19,6 +19,7 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class MorePacketsCheck extends MovingCheck {
// 20 would be for perfect internet connections, 22 is good enough
private final static int packetsPerTimeframe = 22;
public MorePacketsCheck(NoCheat plugin) {
@ -55,6 +56,8 @@ public class MorePacketsCheck extends MovingCheck {
data.packets = -data.morePacketsBuffer;
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
final boolean cancel = executeActions(player, cc.morePacketsActions, data.morePacketsVL);
if(cancel)
@ -100,9 +103,9 @@ public class MorePacketsCheck extends MovingCheck {
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).morePacketsVL);
return String.format(Locale.US, "%d", (int) getData(player).morePacketsVL);
else if(wildcard == ParameterName.PACKETS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).packets);
return String.format(Locale.US, "%d", (int) getData(player).packets);
else
return super.getParameter(wildcard, player);
}

View File

@ -9,6 +9,10 @@ import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
/**
* Abstract base class for Moving checks, provides some convenience
* methods for access to data and config that's relevant to this checktype
*/
public abstract class MovingCheck extends Check {
private static final String id = "moving";
@ -21,21 +25,29 @@ public abstract class MovingCheck extends Check {
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.LOCATION) {
PreciseLocation from = getData(player.getDataStore()).from;
PreciseLocation from = getData(player).from;
return String.format(Locale.US, "%.2f,%.2f,%.2f", from.x, from.y, from.z);
} else if(wildcard == ParameterName.MOVEDISTANCE) {
PreciseLocation from = getData(player.getDataStore()).from;
PreciseLocation to = getData(player.getDataStore()).to;
PreciseLocation from = getData(player).from;
PreciseLocation to = getData(player).to;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x - from.x, to.y - from.y, to.z - from.z);
} else if(wildcard == ParameterName.LOCATION_TO) {
PreciseLocation to = getData(player.getDataStore()).to;
PreciseLocation to = getData(player).to;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x, to.y, to.z);
} else
return super.getParameter(wildcard, player);
}
public static MovingData getData(DataStore base) {
/**
* Get the "MovingData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static MovingData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
MovingData data = base.get(id);
if(data == null) {
data = new MovingData();
@ -44,6 +56,17 @@ public abstract class MovingCheck extends Check {
return data;
}
/**
* Get the MovingConfig object that belongs to the world that the player
* currently resides in.
*
* @param player
* @return
*/
public static MovingConfig getConfig(NoCheatPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static MovingConfig getConfig(ConfigurationCacheStore cache) {
MovingConfig config = cache.get(id);
if(config == null) {

View File

@ -24,10 +24,8 @@ import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.PreciseLocation;
/**
* The only place that listens to and modifies player_move events if necessary
*
* Get the event, decide which checks should work on it and in what order,
* evaluate the check results and decide what to
* Central location to listen to events that are
* relevant for the moving checks
*
*/
public class MovingCheckListener implements Listener, EventManager {
@ -56,7 +54,7 @@ public class MovingCheckListener implements Listener, EventManager {
* was already on top of that block and should be allowed to stay
* there
*
* @param event
* @param event The BlockPlaceEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
public void blockPlace(final BlockPlaceEvent event) {
@ -66,7 +64,7 @@ public class MovingCheckListener implements Listener, EventManager {
return;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final MovingConfig config = MovingCheck.getConfig(player.getConfigurationStore());
final MovingConfig config = MovingCheck.getConfig(player);
// If the player is allowed to fly anyway, the workaround is not needed
// It's kind of expensive (looking up block types) therefore it makes
@ -76,7 +74,7 @@ public class MovingCheckListener implements Listener, EventManager {
}
// Get the player-specific stored data that applies here
final MovingData data = MovingCheck.getData(player.getDataStore());
final MovingData data = MovingCheck.getData(player);
final Block block = event.getBlockPlaced();
@ -109,15 +107,15 @@ public class MovingCheckListener implements Listener, EventManager {
* it was NoCheat or another plugin. If it was NoCheat, the target
* location should match the "data.teleportTo" value.
*
* On teleports, reset some movement related data
* On teleports, reset some movement related data that gets invalid
*
* @param event
* @param event The PlayerTeleportEvent
*/
@EventHandler(priority = EventPriority.HIGHEST)
public void teleport(final PlayerTeleportEvent event) {
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final MovingData data = MovingCheck.getData(player.getDataStore());
final MovingData data = MovingCheck.getData(player);
// If it was a teleport initialized by NoCheat, do it anyway
// even if another plugin said "no"
@ -141,14 +139,15 @@ public class MovingCheckListener implements Listener, EventManager {
/**
* Just for security, if a player switches between worlds, reset the
* runfly and morepackets checks.
* runfly and morepackets checks data, because it is definitely invalid
* now
*
* @param event
* @param event The PlayerChangedWorldEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
public void worldChange(final PlayerChangedWorldEvent event) {
// Maybe this helps with people teleporting through multiverse portals having problems?
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()).getDataStore());
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.teleportTo.reset();
data.clearRunFlyData();
data.clearMorePacketsData();
@ -162,7 +161,7 @@ public class MovingCheckListener implements Listener, EventManager {
*/
@EventHandler(priority = EventPriority.MONITOR)
public void portal(final PlayerPortalEvent event) {
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()).getDataStore());
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.clearMorePacketsData();
data.clearRunFlyData();
}
@ -175,7 +174,7 @@ public class MovingCheckListener implements Listener, EventManager {
*/
@EventHandler(priority = EventPriority.MONITOR)
public void respawn(final PlayerRespawnEvent event) {
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()).getDataStore());
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
data.clearMorePacketsData();
data.clearRunFlyData();
}
@ -184,22 +183,26 @@ public class MovingCheckListener implements Listener, EventManager {
* When a player moves, he will be checked for various
* suspicious behaviour.
*
* @param event
* @param event The PlayerMoveEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
public void move(final PlayerMoveEvent event) {
// Don't care for vehicles
if(event.isCancelled() || event.getPlayer().isInsideVehicle())
return;
// Don't care for movements that are very high distance or to another
// world (such that it is very likely the event data was modified by
// another plugin before we got it)
if(!event.getFrom().getWorld().equals(event.getTo().getWorld()) || event.getFrom().distanceSquared(event.getTo()) > 400) {
return;
}
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final MovingConfig cc = MovingCheck.getConfig(player.getConfigurationStore());
final MovingData data = MovingCheck.getData(player.getDataStore());
final MovingConfig cc = MovingCheck.getConfig(player);
final MovingData data = MovingCheck.getData(player);
// Advance various counters and values that change per movement
// tick. They are needed to decide on how fast a player may
@ -210,9 +213,6 @@ public class MovingCheckListener implements Listener, EventManager {
data.from.set(event.getFrom());
final Location to = event.getTo();
data.to.set(to);
PreciseLocation newTo = null;
@ -240,7 +240,8 @@ public class MovingCheckListener implements Listener, EventManager {
// Did one of the check(s) decide we need a new "to"-location?
if(newTo != null) {
// Compose a new location based on coordinates of "newTo" and
// viewing direction of "event.getTo()"
// viewing direction of "event.getTo()" to allow the player to
// look somewhere else despite getting pulled back by NoCheat
event.setTo(new Location(player.getPlayer().getWorld(), newTo.x, newTo.y, newTo.z, to.getYaw(), to.getPitch()));
// remember where we send the player to
@ -279,16 +280,16 @@ public class MovingCheckListener implements Listener, EventManager {
/**
* Player got a velocity packet. The server can't keep track
* of actual velocity values (by design), so we have to try
* and do that ourselves.
* and do that ourselves. Very rough estimates.
*
* @param event
* @param event The PlayerVelocityEvent
*/
@EventHandler(priority = EventPriority.MONITOR)
public void velocity(final PlayerVelocityEvent event) {
if(event.isCancelled())
return;
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()).getDataStore());
final MovingData data = MovingCheck.getData(plugin.getPlayer(event.getPlayer()));
final Vector v = event.getVelocity();

View File

@ -9,45 +9,61 @@ import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
*/
public class MovingData implements DataItem {
// Keep track of the violation levels of the checks
public double runflyVL;
public double nofallVL;
public double morePacketsVL;
// Count how long a player is in the air
public int jumpPhase;
// Remember how big the players last JumpAmplifier (potion effect) was
public double lastJumpAmplifier;
// Remember for a short time that the player was on ice and therefore
// should be allowed to move a bit faster
public int onIce;
// Where should a player be teleported back to when failing the check
public final PreciseLocation runflySetBackPoint = new PreciseLocation();
// Some values for estimating movement freedom
public double vertFreedom;
public double vertVelocity;
public int vertVelocityCounter;
public double horizFreedom;
public int horizVelocityCounter;
public float fallDistance;
public float lastAddedFallDistance;
public double horizontalBuffer;
public int bunnyhopdelay;
// Keep track of estimated fall distance to compare to real fall distance
public float fallDistance;
public float lastAddedFallDistance;
// Keep track of when "morePackets" last time checked and how much packets
// a player sent and may send before failing the check
public long morePacketsLastTime;
public int packets;
public int morePacketsBuffer = 50;
// Where to teleport the player that fails the "morepackets" check
public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation();
// When NoCheat does teleport the player, remember the target location to
// be able to distinguish "our" teleports from teleports of others
public final PreciseLocation teleportTo = new PreciseLocation();
// For logging and convenience, make copies of the events locations
public final PreciseLocation from = new PreciseLocation();
public final PreciseLocation to = new PreciseLocation();
// For convenience, remember if the locations are considered "on ground"
// by NoCheat
public boolean fromOnOrInGround;
public boolean toOnOrInGround;
public Id statisticCategory = Id.MOV_RUNNING;
public int packets;
public void clearRunFlyData() {
runflySetBackPoint.reset();
jumpPhase = 0;

View File

@ -41,6 +41,9 @@ public class NoFallCheck extends MovingCheck {
data.fallDistance = player.getPlayer().getFallDistance();
data.nofallVL += data.fallDistance;
incrementStatistics(player, Id.MOV_NOFALL, data.fallDistance);
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
final boolean cancel = executeActions(player, cc.nofallActions, data.nofallVL);
if(cancel) {
player.dealFallDamage();
@ -64,6 +67,8 @@ public class NoFallCheck extends MovingCheck {
data.nofallVL += difference;
incrementStatistics(player, Id.MOV_NOFALL, difference);
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
final boolean cancel = executeActions(player, cc.nofallActions, data.nofallVL);
// If "cancelled", the fall damage gets dealt in a way that's
@ -106,7 +111,7 @@ public class NoFallCheck extends MovingCheck {
}
// Reduce falldamage violation level
data.nofallVL *= 0.99D;
data.nofallVL *= 0.95D;
return;
}
@ -115,9 +120,9 @@ public class NoFallCheck extends MovingCheck {
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).nofallVL);
return String.format(Locale.US, "%d", (int) getData(player).nofallVL);
else if(wildcard == ParameterName.FALLDISTANCE)
return String.format(Locale.US, "%.2f", getData(player.getDataStore()).fallDistance);
return String.format(Locale.US, "%.2f", getData(player).fallDistance);
else
return super.getParameter(wildcard, player);
}

View File

@ -72,8 +72,8 @@ public class RunningCheck extends MovingCheck {
// Slowly reduce the level with each event
data.runflyVL *= 0.95;
// Did the player move in unexpected ways?
if(result > 0) {
// Increment violation counter
data.runflyVL += result;
@ -92,15 +92,24 @@ public class RunningCheck extends MovingCheck {
}
} else {
// Decide if we should create a new setBack point
// These are the result of a lot of bug reports, experience and
// trial and error
if((toInGround && from.y >= to.y) || CheckUtil.isLiquid(toType)) {
// Yes, if the player moved down "into" the ground or into liquid
setBack.set(to);
setBack.y = Math.ceil(setBack.y);
data.jumpPhase = 0;
} else if(toOnGround && (from.y >= to.y || setBack.y <= Math.floor(to.y))) {
// Yes, if the player moved down "onto" the ground and the new
// setback point is higher up than the old or at least at the
// same height
setBack.set(to);
setBack.y = Math.floor(setBack.y);
data.jumpPhase = 0;
} else if(fromOnGround || fromInGround || toOnGround || toInGround) {
// The player at least touched the ground somehow
data.jumpPhase = 0;
}
}
@ -134,7 +143,7 @@ public class RunningCheck extends MovingCheck {
Id statisticsCategory = null;
// Player on ice?
// Player on ice? Give him higher max speed
Block b = player.getPlayer().getLocation().getBlock();
if(b.getType() == Material.ICE || b.getRelative(0, -1, 0).getType() == Material.ICE) {
data.onIce = 20;
@ -208,6 +217,7 @@ public class RunningCheck extends MovingCheck {
// How much higher did the player move than expected??
double distanceAboveLimit = 0.0D;
// Potion effect "Jump"
double jumpAmplifier = player.getJumpAmplifier();
if(jumpAmplifier > data.lastJumpAmplifier) {
data.lastJumpAmplifier = jumpAmplifier;
@ -239,9 +249,9 @@ public class RunningCheck extends MovingCheck {
if(wildcard == ParameterName.CHECK)
// Workaround for something until I find a better way to do it
return getData(player.getDataStore()).statisticCategory.toString();
return getData(player).statisticCategory.toString();
else if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).runflyVL);
return String.format(Locale.US, "%d", (int) getData(player).runflyVL);
else
return super.getParameter(wildcard, player);
}

View File

@ -13,14 +13,19 @@ import org.bukkit.permissions.Permission;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Handle all NoCheat related commands in a common place
*/
public class CommandHandler {
private final List<Permission> perms;
public CommandHandler(NoCheat plugin) {
// Make a copy to allow sorting
perms = new LinkedList<Permission>(plugin.getDescription().getPermissions());
// Sort NoCheats permission by name and parent-child relation with
// a custom sorting method
Collections.sort(perms, new Comparator<Permission>() {
public int compare(Permission o1, Permission o2) {
@ -44,10 +49,19 @@ public class CommandHandler {
});
}
/**
* Handle a command that is directed at NoCheat
* @param plugin
* @param sender
* @param command
* @param label
* @param args
* @return
*/
public boolean handleCommand(NoCheat plugin, CommandSender sender, Command command, String label, String[] args) {
boolean result = false;
// Not our command
// Not our command, how did it get here?
if(!command.getName().equalsIgnoreCase("nocheat") || args.length == 0) {
result = false;
} else if(args[0].equalsIgnoreCase("permlist") && args.length >= 2) {
@ -60,7 +74,7 @@ public class CommandHandler {
}
else if(args[0].equalsIgnoreCase("playerinfo") && args.length >= 2) {
// performance command was used
// playerinfo command was used
result = handlePlayerInfoCommand(plugin, sender, args);
}
@ -117,9 +131,8 @@ public class CommandHandler {
sender.sendMessage("[NoCheat] Reloading configuration");
plugin.reloadConfiguration();
sender.sendMessage("[NoCheat] Configuration reloaded");
}
else {
sender.sendMessage("You lack the "+Permissions.ADMIN_RELOAD+ " permission to use 'reload'");
} else {
sender.sendMessage("You lack the " + Permissions.ADMIN_RELOAD + " permission to use 'reload'");
}
return true;

View File

@ -11,6 +11,10 @@ import cc.co.evenprime.bukkit.nocheat.actions.types.DummyAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
/**
* Helps with creating Actions out of text string definitions
*
*/
public class ActionFactory {
private static final Map<String, Object> lib = new HashMap<String, Object>();

View File

@ -2,6 +2,8 @@ package cc.co.evenprime.bukkit.nocheat.config;
/**
* Paths for the configuration options
* Making everything final static prevents accidentially modifying any
* of these
*
*/
public abstract class ConfPaths {

View File

@ -6,6 +6,10 @@ import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
/**
* Prints the list of active checks per world on startup, if requested
*
*/
public class ActiveCheckPrinter {
public static void printActiveChecks(NoCheat plugin, List<EventManager> eventManagers) {

View File

@ -3,6 +3,12 @@ package cc.co.evenprime.bukkit.nocheat.debug;
import org.bukkit.World;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
/**
* A task running in the background that measures tick time vs. real time
*
* @author Evenprime
*
*/
public class LagMeasureTask implements Runnable {
private int ingameseconds = 1;