Again, more comments

This commit is contained in:
Evenprime 2012-03-01 20:35:41 +01:00
parent 32d09868d9
commit 2aedcd7515
8 changed files with 142 additions and 32 deletions

View File

@ -7,8 +7,8 @@ import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
/**
* Check various things related to fighting players/entities
*
* Abstract base class for Fight checks, provides some convenience
* methods for access to data and config that's relevant to this checktype
*/
public abstract class FightCheck extends Check {

View File

@ -6,6 +6,11 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The DropCheck will find out if a player drops too many items within a short
* amount of time
*
*/
public class DropCheck extends InventoryCheck {
public DropCheck(NoCheat plugin) {
@ -16,11 +21,13 @@ public class DropCheck extends InventoryCheck {
boolean cancel = false;
final long time = System.currentTimeMillis() / 1000;
final long time = System.currentTimeMillis();
// Has the configured time passed? If so, reset the counter
if(data.dropLastTime + cc.dropTimeFrame <= time) {
data.dropLastTime = time;
data.dropCount = 0;
data.dropVL = 0;
}
// Security check, if the system time changes
else if(data.dropLastTime > time) {
@ -29,21 +36,25 @@ public class DropCheck extends InventoryCheck {
data.dropCount++;
// The player dropped more than he should
if(data.dropCount > cc.dropLimit) {
// Set vl and increment statistics
data.dropVL = data.dropCount - cc.dropLimit;
incrementStatistics(player, Id.INV_DROP, 1);
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
cancel = executeActions(player, cc.dropActions, data.dropVL);
}
return cancel;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player.getDataStore()).dropVL);
return String.format(Locale.US, "%d", getData(player).dropVL);
else
return super.getParameter(wildcard, player);
}

View File

@ -7,6 +7,10 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The InstantBowCheck will find out if a player pulled the string of his bow
* too fast
*/
public class InstantBowCheck extends InventoryCheck {
public InstantBowCheck(NoCheat plugin) {
@ -18,30 +22,38 @@ public class InstantBowCheck extends InventoryCheck {
boolean cancelled = false;
long time = System.currentTimeMillis();
// How fast will the arrow be?
float bowForce = event.getForce();
// Rough estimation of how long pulling the string should've taken
long expectedTimeWhenStringDrawn = data.lastBowInteractTime + (int) (bowForce * bowForce * 700F);
if(expectedTimeWhenStringDrawn < time) {
// Acceptable, reduce VL
// The player was slow enough, reward him by lowering the vl
data.instantBowVL *= 0.90D;
} else if(data.lastBowInteractTime > time) {
// Security, if time ran backwards, reset
// Security check if time ran backwards, reset
data.lastBowInteractTime = 0;
} else {
// Seems fishy, increase violation level
// Player was too fast, increase violation level and statistics
int vl = ((int) (expectedTimeWhenStringDrawn - time)) / 100;
data.instantBowVL += vl;
incrementStatistics(player, Id.INV_BOW, vl);
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
cancelled = executeActions(player, cc.bowActions, data.instantBowVL);
}
return cancelled;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).instantBowVL);
return String.format(Locale.US, "%d", (int) getData(player).instantBowVL);
else
return super.getParameter(wildcard, player);
}

View File

@ -7,6 +7,9 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
/**
* The InstantEatCheck will find out if a player eats his food too fast
*/
public class InstantEatCheck extends InventoryCheck {
public InstantEatCheck(NoCheat plugin) {
@ -15,38 +18,43 @@ public class InstantEatCheck extends InventoryCheck {
public boolean check(NoCheatPlayer player, FoodLevelChangeEvent event, InventoryData data, InventoryConfig cc) {
// Seems to be not the result of eating
// Hunger level change seems to not be the result of eating
if(data.foodMaterial == null || event.getFoodLevel() <= player.getPlayer().getFoodLevel())
return false;
boolean cancelled = false;
long time = System.currentTimeMillis();
// rough estimation about how long it should take to eat
long expectedTimeWhenEatingFinished = data.lastEatInteractTime + 700;
if(expectedTimeWhenEatingFinished < time) {
// Acceptable, reduce VL
data.instantEatVL *= 0.98D;
// Acceptable, reduce VL to reward the player
data.instantEatVL *= 0.60D;
} else if(data.lastEatInteractTime > time) {
// Security, if time ran backwards, reset
// Security test, if time ran backwards, reset
data.lastEatInteractTime = 0;
} else {
// Seems fishy, increase violation level
// Player was too fast, increase violation level and statistics
int vl = ((int) (expectedTimeWhenEatingFinished - time)) / 100;
data.instantEatVL += vl;
incrementStatistics(player, Id.INV_EAT, vl);
// Execute whatever actions are associated with this check and the
// violation level and find out if we should cancel the event
cancelled = executeActions(player, cc.eatActions, data.instantEatVL);
}
return cancelled;
}
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).instantEatVL);
return String.format(Locale.US, "%d", (int) getData(player).instantEatVL);
else if(wildcard == ParameterName.FOOD)
return getData(player.getDataStore()).foodMaterial.toString();
return getData(player).foodMaterial.toString();
else
return super.getParameter(wildcard, player);
}

View File

@ -1,10 +1,15 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore;
/**
* Abstract base class for Inventory checks, provides some convenience
* methods for access to data and config that's relevant to this checktype
*/
public abstract class InventoryCheck extends Check {
private static final String id = "inventory";
@ -13,7 +18,15 @@ public abstract class InventoryCheck extends Check {
super(plugin, id, name);
}
public static InventoryData getData(DataStore base) {
/**
* Get the "InventoryData" object that belongs to the player. Will ensure
* that such a object exists and if not, create one
*
* @param player
* @return
*/
public static InventoryData getData(NoCheatPlayer player) {
DataStore base = player.getDataStore();
InventoryData data = base.get(id);
if(data == null) {
data = new InventoryData();
@ -22,6 +35,17 @@ public abstract class InventoryCheck extends Check {
return data;
}
/**
* Get the InventoryConfig object that belongs to the world that the player
* currently resides in.
*
* @param player
* @return
*/
public static InventoryConfig getConfig(NoCheatPlayer player) {
return getConfig(player.getConfigurationStore());
}
public static InventoryConfig getConfig(ConfigurationCacheStore cache) {
InventoryConfig config = cache.get(id);
if(config == null) {

View File

@ -19,6 +19,11 @@ import cc.co.evenprime.bukkit.nocheat.checks.CheckUtil;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Central location to listen to events that are
* relevant for the inventory checks
*
*/
public class InventoryCheckListener implements Listener, EventManager {
private final DropCheck dropCheck;
@ -36,6 +41,10 @@ public class InventoryCheckListener implements Listener, EventManager {
this.plugin = plugin;
}
/**
* We listen to DropItem Event for the dropCheck
* @param event The PlayerDropItem Event
*/
@EventHandler(priority = EventPriority.LOWEST)
protected void handlePlayerDropItemEvent(final PlayerDropItemEvent event) {
@ -45,8 +54,8 @@ public class InventoryCheckListener implements Listener, EventManager {
boolean cancelled = false;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryConfig cc = InventoryCheck.getConfig(player.getConfigurationStore());
final InventoryData data = InventoryCheck.getData(player.getDataStore());
final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player);
// If it should be executed, do it
if(cc.dropCheck && !player.hasPermission(Permissions.INVENTORY_DROP)) {
@ -54,62 +63,93 @@ public class InventoryCheckListener implements Listener, EventManager {
}
if(cancelled) {
// Cancelling drop events is not save. So don't do it
// and kick players instead by default
//event.setCancelled(true);
// Cancelling drop events is not save (in certain circumstances
// items will disappear completely). So don't do it and kick
// players instead by default
// event.setCancelled(true);
}
}
/**
* We listen to PlayerInteractEvent for the instantEat and instantBow
* checks
* @param event The PlayerInteractEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
public void interact(final PlayerInteractEvent event) {
// Only interested in right-clicks while holding an item
if(!event.hasItem() || !(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK))
return;
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryData data = InventoryCheck.getData(player.getDataStore());
final InventoryData data = InventoryCheck.getData(player);
if(event.getItem().getType() == Material.BOW) {
// It was a bow, the player starts to pull the string
// Remember this time
data.lastBowInteractTime = System.currentTimeMillis();
} else if(CheckUtil.isFood(event.getItem())) {
// Remember food Material, because we don't have that info in the other event
// It was food, the player starts to eat some food
// Remember this time and the type of food
data.foodMaterial = event.getItem().getType();
data.lastEatInteractTime = System.currentTimeMillis();
} else {
// Nothing that we are interested in, reset data
data.lastBowInteractTime = 0;
data.lastEatInteractTime = 0;
data.foodMaterial = null;
}
}
/**
* We listen to FoodLevelChange Event because Bukkit doesn't provide a
* PlayerFoodEating Event (or whatever it would be called).
*
* @param event The FoodLevelChangeEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
public void foodchanged(final FoodLevelChangeEvent event) {
// Only if a player ate food
if(!event.isCancelled() && event.getEntity() instanceof Player) {
final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity());
final InventoryConfig cc = InventoryCheck.getConfig(player.getConfigurationStore());
final InventoryData data = InventoryCheck.getData(player.getDataStore());
final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player);
// Only if he should get checked
if(cc.eatCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTEAT)) {
boolean cancelled = instantEatCheck.check(player, event, data, cc);
// The check requested the foodlevelchange to get cancelled
event.setCancelled(cancelled);
}
// Forget the food material, as the info is no longer needed
data.foodMaterial = null;
}
}
/**
* We listen to EntityShootBowEvent for the instantbow check
*
* @param event The EntityShootBowEvent
*/
@EventHandler(priority = EventPriority.LOWEST)
public void bowfired(final EntityShootBowEvent event) {
// Only if a player shot the arrow
if(!event.isCancelled() && event.getEntity() instanceof Player) {
final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity());
final InventoryConfig cc = InventoryCheck.getConfig(player.getConfigurationStore());
final InventoryConfig cc = InventoryCheck.getConfig(player);
// Only if he should get checked
if(cc.bowCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTBOW)) {
final InventoryData data = InventoryCheck.getData(player.getDataStore());
final InventoryData data = InventoryCheck.getData(player);
boolean cancelled = instantBowCheck.check(player, event, data, cc);
// The check requested the bowshooting to get cancelled
event.setCancelled(cancelled);
}
}

View File

@ -6,6 +6,12 @@ import cc.co.evenprime.bukkit.nocheat.config.ConfPaths;
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
/**
* Configurations specific for the "Inventory" checks
* Every world gets one of these assigned to it, or if a world doesn't get
* it's own, it will use the "global" version
*
*/
public class InventoryConfig implements ConfigItem {
public final boolean dropCheck;
@ -22,7 +28,7 @@ public class InventoryConfig implements ConfigItem {
public InventoryConfig(NoCheatConfiguration data) {
dropCheck = data.getBoolean(ConfPaths.INVENTORY_DROP_CHECK);
dropTimeFrame = data.getInt(ConfPaths.INVENTORY_DROP_TIMEFRAME);
dropTimeFrame = data.getInt(ConfPaths.INVENTORY_DROP_TIMEFRAME) * 1000;
dropLimit = data.getInt(ConfPaths.INVENTORY_DROP_LIMIT);
dropActions = data.getActionList(ConfPaths.INVENTORY_DROP_ACTIONS, Permissions.INVENTORY_DROP);

View File

@ -3,16 +3,25 @@ package cc.co.evenprime.bukkit.nocheat.checks.inventory;
import org.bukkit.Material;
import cc.co.evenprime.bukkit.nocheat.DataItem;
/**
* Player specific data for the inventory checks
*
*/
public class InventoryData implements DataItem {
// Keep track of the violation levels of the three checks
public int dropVL;
public int instantBowVL;
public double instantEatVL;
// Time and amount of dropped items
public long dropLastTime;
public int dropCount;
public int instantBowVL;
// Times when bow shootinhg and eating started
public long lastBowInteractTime;
public double instantEatVL;
public long lastEatInteractTime;
// What the player is eating
public Material foodMaterial;
}