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; 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 { 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.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id; 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 class DropCheck extends InventoryCheck {
public DropCheck(NoCheat plugin) { public DropCheck(NoCheat plugin) {
@ -16,11 +21,13 @@ public class DropCheck extends InventoryCheck {
boolean cancel = false; 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) { if(data.dropLastTime + cc.dropTimeFrame <= time) {
data.dropLastTime = time; data.dropLastTime = time;
data.dropCount = 0; data.dropCount = 0;
data.dropVL = 0;
} }
// Security check, if the system time changes // Security check, if the system time changes
else if(data.dropLastTime > time) { else if(data.dropLastTime > time) {
@ -29,21 +36,25 @@ public class DropCheck extends InventoryCheck {
data.dropCount++; data.dropCount++;
// The player dropped more than he should
if(data.dropCount > cc.dropLimit) { if(data.dropCount > cc.dropLimit) {
// Set vl and increment statistics
data.dropVL = data.dropCount - cc.dropLimit; data.dropVL = data.dropCount - cc.dropLimit;
incrementStatistics(player, Id.INV_DROP, 1); 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); cancel = executeActions(player, cc.dropActions, data.dropVL);
} }
return cancel; return cancel;
} }
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) { public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS) if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", getData(player.getDataStore()).dropVL); return String.format(Locale.US, "%d", getData(player).dropVL);
else else
return super.getParameter(wildcard, player); 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.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id; 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 class InstantBowCheck extends InventoryCheck {
public InstantBowCheck(NoCheat plugin) { public InstantBowCheck(NoCheat plugin) {
@ -18,30 +22,38 @@ public class InstantBowCheck extends InventoryCheck {
boolean cancelled = false; boolean cancelled = false;
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
// How fast will the arrow be?
float bowForce = event.getForce(); float bowForce = event.getForce();
// Rough estimation of how long pulling the string should've taken
long expectedTimeWhenStringDrawn = data.lastBowInteractTime + (int) (bowForce * bowForce * 700F); long expectedTimeWhenStringDrawn = data.lastBowInteractTime + (int) (bowForce * bowForce * 700F);
if(expectedTimeWhenStringDrawn < time) { if(expectedTimeWhenStringDrawn < time) {
// Acceptable, reduce VL // The player was slow enough, reward him by lowering the vl
data.instantBowVL *= 0.90D; data.instantBowVL *= 0.90D;
} else if(data.lastBowInteractTime > time) { } else if(data.lastBowInteractTime > time) {
// Security, if time ran backwards, reset // Security check if time ran backwards, reset
data.lastBowInteractTime = 0; data.lastBowInteractTime = 0;
} else { } else {
// Seems fishy, increase violation level // Player was too fast, increase violation level and statistics
int vl = ((int) (expectedTimeWhenStringDrawn - time)) / 100; int vl = ((int) (expectedTimeWhenStringDrawn - time)) / 100;
data.instantBowVL += vl; data.instantBowVL += vl;
incrementStatistics(player, Id.INV_BOW, 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); cancelled = executeActions(player, cc.bowActions, data.instantBowVL);
} }
return cancelled; return cancelled;
} }
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) { public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS) 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 else
return super.getParameter(wildcard, player); 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.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id; 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 class InstantEatCheck extends InventoryCheck {
public InstantEatCheck(NoCheat plugin) { public InstantEatCheck(NoCheat plugin) {
@ -15,38 +18,43 @@ public class InstantEatCheck extends InventoryCheck {
public boolean check(NoCheatPlayer player, FoodLevelChangeEvent event, InventoryData data, InventoryConfig cc) { 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()) if(data.foodMaterial == null || event.getFoodLevel() <= player.getPlayer().getFoodLevel())
return false; return false;
boolean cancelled = false; boolean cancelled = false;
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
// rough estimation about how long it should take to eat
long expectedTimeWhenEatingFinished = data.lastEatInteractTime + 700; long expectedTimeWhenEatingFinished = data.lastEatInteractTime + 700;
if(expectedTimeWhenEatingFinished < time) { if(expectedTimeWhenEatingFinished < time) {
// Acceptable, reduce VL // Acceptable, reduce VL to reward the player
data.instantEatVL *= 0.98D; data.instantEatVL *= 0.60D;
} else if(data.lastEatInteractTime > time) { } else if(data.lastEatInteractTime > time) {
// Security, if time ran backwards, reset // Security test, if time ran backwards, reset
data.lastEatInteractTime = 0; data.lastEatInteractTime = 0;
} else { } else {
// Seems fishy, increase violation level // Player was too fast, increase violation level and statistics
int vl = ((int) (expectedTimeWhenEatingFinished - time)) / 100; int vl = ((int) (expectedTimeWhenEatingFinished - time)) / 100;
data.instantEatVL += vl; data.instantEatVL += vl;
incrementStatistics(player, Id.INV_EAT, 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); cancelled = executeActions(player, cc.eatActions, data.instantEatVL);
} }
return cancelled; return cancelled;
} }
@Override
public String getParameter(ParameterName wildcard, NoCheatPlayer player) { public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS) 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) else if(wildcard == ParameterName.FOOD)
return getData(player.getDataStore()).foodMaterial.toString(); return getData(player).foodMaterial.toString();
else else
return super.getParameter(wildcard, player); return super.getParameter(wildcard, player);
} }

View File

@ -1,10 +1,15 @@
package cc.co.evenprime.bukkit.nocheat.checks.inventory; package cc.co.evenprime.bukkit.nocheat.checks.inventory;
import cc.co.evenprime.bukkit.nocheat.NoCheat; 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.checks.Check;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore; import cc.co.evenprime.bukkit.nocheat.config.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.data.DataStore; 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 { public abstract class InventoryCheck extends Check {
private static final String id = "inventory"; private static final String id = "inventory";
@ -13,7 +18,15 @@ public abstract class InventoryCheck extends Check {
super(plugin, id, name); 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); InventoryData data = base.get(id);
if(data == null) { if(data == null) {
data = new InventoryData(); data = new InventoryData();
@ -22,6 +35,17 @@ public abstract class InventoryCheck extends Check {
return data; 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) { public static InventoryConfig getConfig(ConfigurationCacheStore cache) {
InventoryConfig config = cache.get(id); InventoryConfig config = cache.get(id);
if(config == null) { 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.ConfigurationCacheStore;
import cc.co.evenprime.bukkit.nocheat.config.Permissions; 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 { public class InventoryCheckListener implements Listener, EventManager {
private final DropCheck dropCheck; private final DropCheck dropCheck;
@ -36,6 +41,10 @@ public class InventoryCheckListener implements Listener, EventManager {
this.plugin = plugin; this.plugin = plugin;
} }
/**
* We listen to DropItem Event for the dropCheck
* @param event The PlayerDropItem Event
*/
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
protected void handlePlayerDropItemEvent(final PlayerDropItemEvent event) { protected void handlePlayerDropItemEvent(final PlayerDropItemEvent event) {
@ -45,8 +54,8 @@ public class InventoryCheckListener implements Listener, EventManager {
boolean cancelled = false; boolean cancelled = false;
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer()); final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final InventoryConfig cc = InventoryCheck.getConfig(player.getConfigurationStore()); final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player.getDataStore()); final InventoryData data = InventoryCheck.getData(player);
// If it should be executed, do it // If it should be executed, do it
if(cc.dropCheck && !player.hasPermission(Permissions.INVENTORY_DROP)) { if(cc.dropCheck && !player.hasPermission(Permissions.INVENTORY_DROP)) {
@ -54,62 +63,93 @@ public class InventoryCheckListener implements Listener, EventManager {
} }
if(cancelled) { if(cancelled) {
// Cancelling drop events is not save. So don't do it // Cancelling drop events is not save (in certain circumstances
// and kick players instead by default // items will disappear completely). So don't do it and kick
// players instead by default
// event.setCancelled(true); // event.setCancelled(true);
} }
} }
/**
* We listen to PlayerInteractEvent for the instantEat and instantBow
* checks
* @param event The PlayerInteractEvent
*/
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void interact(final PlayerInteractEvent event) { 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)) if(!event.hasItem() || !(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK))
return; return;
NoCheatPlayer player = plugin.getPlayer(event.getPlayer()); 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) { if(event.getItem().getType() == Material.BOW) {
// It was a bow, the player starts to pull the string
// Remember this time
data.lastBowInteractTime = System.currentTimeMillis(); data.lastBowInteractTime = System.currentTimeMillis();
} else if(CheckUtil.isFood(event.getItem())) { } 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.foodMaterial = event.getItem().getType();
data.lastEatInteractTime = System.currentTimeMillis(); data.lastEatInteractTime = System.currentTimeMillis();
} else { } else {
// Nothing that we are interested in, reset data
data.lastBowInteractTime = 0; data.lastBowInteractTime = 0;
data.lastEatInteractTime = 0; data.lastEatInteractTime = 0;
data.foodMaterial = null; 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) @EventHandler(priority = EventPriority.LOWEST)
public void foodchanged(final FoodLevelChangeEvent event) { public void foodchanged(final FoodLevelChangeEvent event) {
// Only if a player ate food
if(!event.isCancelled() && event.getEntity() instanceof Player) { if(!event.isCancelled() && event.getEntity() instanceof Player) {
final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity()); final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity());
final InventoryConfig cc = InventoryCheck.getConfig(player.getConfigurationStore()); final InventoryConfig cc = InventoryCheck.getConfig(player);
final InventoryData data = InventoryCheck.getData(player.getDataStore()); final InventoryData data = InventoryCheck.getData(player);
// Only if he should get checked
if(cc.eatCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTEAT)) { if(cc.eatCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTEAT)) {
boolean cancelled = instantEatCheck.check(player, event, data, cc); boolean cancelled = instantEatCheck.check(player, event, data, cc);
// The check requested the foodlevelchange to get cancelled
event.setCancelled(cancelled); event.setCancelled(cancelled);
} }
// Forget the food material, as the info is no longer needed
data.foodMaterial = null; data.foodMaterial = null;
} }
} }
/**
* We listen to EntityShootBowEvent for the instantbow check
*
* @param event The EntityShootBowEvent
*/
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void bowfired(final EntityShootBowEvent event) { public void bowfired(final EntityShootBowEvent event) {
// Only if a player shot the arrow
if(!event.isCancelled() && event.getEntity() instanceof Player) { if(!event.isCancelled() && event.getEntity() instanceof Player) {
final NoCheatPlayer player = plugin.getPlayer((Player) event.getEntity()); 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)) { 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); boolean cancelled = instantBowCheck.check(player, event, data, cc);
// The check requested the bowshooting to get cancelled
event.setCancelled(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.NoCheatConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.Permissions; 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 class InventoryConfig implements ConfigItem {
public final boolean dropCheck; public final boolean dropCheck;
@ -22,7 +28,7 @@ public class InventoryConfig implements ConfigItem {
public InventoryConfig(NoCheatConfiguration data) { public InventoryConfig(NoCheatConfiguration data) {
dropCheck = data.getBoolean(ConfPaths.INVENTORY_DROP_CHECK); 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); dropLimit = data.getInt(ConfPaths.INVENTORY_DROP_LIMIT);
dropActions = data.getActionList(ConfPaths.INVENTORY_DROP_ACTIONS, Permissions.INVENTORY_DROP); 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 org.bukkit.Material;
import cc.co.evenprime.bukkit.nocheat.DataItem; import cc.co.evenprime.bukkit.nocheat.DataItem;
/**
* Player specific data for the inventory checks
*
*/
public class InventoryData implements DataItem { public class InventoryData implements DataItem {
// Keep track of the violation levels of the three checks
public int dropVL; public int dropVL;
public int instantBowVL;
public double instantEatVL;
// Time and amount of dropped items
public long dropLastTime; public long dropLastTime;
public int dropCount; public int dropCount;
public int instantBowVL; // Times when bow shootinhg and eating started
public long lastBowInteractTime; public long lastBowInteractTime;
public double instantEatVL;
public long lastEatInteractTime; public long lastEatInteractTime;
// What the player is eating
public Material foodMaterial; public Material foodMaterial;
} }