New FastClick (inventory) check.

This check is less strict on short term but more strict on medium term.
Keeps track of one second (200 ms resolution).
This commit is contained in:
asofold 2013-03-14 10:44:29 +01:00
parent 0abca20dd9
commit 9de6175874
8 changed files with 105 additions and 50 deletions

View File

@ -5,6 +5,7 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.TickTask;
/*
@ -28,53 +29,88 @@ public class FastClick extends Check {
super(CheckType.INVENTORY_FASTCLICK);
}
/**
* Checks a player.
*
* @param player
* the player
* @param cc
* @return true, if successful
*/
public boolean check(final Player player) {
// /**
// * Checks a player.
// *
// * @param player
// * the player
// * @param cc
// * @return true, if successful
// */
// public boolean check(final Player player) {
// // Take time once.
// final long time = System.currentTimeMillis();
//
// final InventoryData data = InventoryData.getData(player);
//
// boolean cancel = false;
//
// // If the last inventory click has been made within 45 milliseconds.
// if (time - data.fastClickLastTime < 45L) {
// if (data.fastClickLastCancelled) {
//
// // Calculate the difference between the limit and the time elapsed.
// final double difference = 45L - time + data.fastClickLastTime;
// final InventoryConfig cc = InventoryConfig.getConfig(player);
// final ViolationData vd = new ViolationData(this, player, data.fastClickVL + difference, difference, cc.fastClickActions);
// if (TickTask.getLag(150) > 1.7f){
// // Don't increase vl here.
// cancel = vd.hasCancel();
// }
// else{
// // Increment the violation level.
// data.fastClickVL += difference;
//
// // Find out if we need to cancel the event.
// cancel = executeActions(vd);
// }
// } else
// data.fastClickLastCancelled = true;
// } else {
// data.fastClickLastCancelled = false;
//
// // Reduce the violation level.
// data.fastClickVL *= 0.98D;
// }
//
// // Remember the current time.s
// data.fastClickLastTime = time;
//
// return cancel;
// }
public boolean check(final Player player, final long now, final InventoryData data, final InventoryConfig cc) {
// Take time once.
final long time = System.currentTimeMillis();
final InventoryData data = InventoryData.getData(player);
boolean cancel = false;
// If the last inventory click has been made within 45 milliseconds.
if (time - data.fastClickLastTime < 45L) {
if (data.fastClickLastCancelled) {
// Calculate the difference between the limit and the time elapsed.
final double difference = 45L - time + data.fastClickLastTime;
final InventoryConfig cc = InventoryConfig.getConfig(player);
final ViolationData vd = new ViolationData(this, player, data.fastClickVL + difference, difference, cc.fastClickActions);
if (TickTask.getLag(150) > 1.7f){
// Don't increase vl here.
cancel = vd.hasCancel();
}
else{
// Increment the violation level.
data.fastClickVL += difference;
// Find out if we need to cancel the event.
cancel = executeActions(vd);
}
} else
data.fastClickLastCancelled = true;
} else {
data.fastClickLastCancelled = false;
// Reduce the violation level.
data.fastClickVL *= 0.98D;
data.fastClickFreq.add(now, 1f);
float shortTerm = data.fastClickFreq.bucketScore(0);
if (shortTerm > cc.fastClickShortTermLimit){
// Check for lag.
shortTerm /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration());
}
shortTerm -= cc.fastClickShortTermLimit;
float normal = data.fastClickFreq.score(1f);
if (normal > cc.fastClickNormalLimit){
// Check for lag.
normal /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration() * data.fastClickFreq.numberOfBuckets());
}
normal -= cc.fastClickNormalLimit;
// Remember the current time.s
data.fastClickLastTime = time;
final double violation = Math.max(shortTerm, normal);
boolean cancel = false;
if (violation > 0){
final ViolationData vd = new ViolationData(this, player, data.fastClickVL + violation, violation, cc.fastClickActions);
cancel = executeActions(vd);
}
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
player.sendMessage("FastClick: " + ((int) data.fastClickFreq.bucketScore(0)) + " / " + ((int) data.fastClickFreq.score(1f)));
}
return cancel;
}
}

View File

@ -52,7 +52,7 @@ public class InstantEat extends Check {
return false;
// Rough estimation about how long it should take to eat
final long expectedTimeWhenEatingFinished = Math.max(data.instantEatInteract, data.fastClickLastTime) + 700L;
final long expectedTimeWhenEatingFinished = Math.max(data.instantEatInteract, data.lastClickTime) + 700L;
if (data.instantEatInteract > 0 && expectedTimeWhenEatingFinished < time){
// Acceptable, reduce VL to reward the player.

View File

@ -80,6 +80,8 @@ public class InventoryConfig extends ACheckConfig {
public final boolean fastClickCheck;
public final boolean fastClickSpareCreative;
public final float fastClickShortTermLimit;
public final float fastClickNormalLimit;
public final ActionList fastClickActions;
public final boolean instantBowCheck;
@ -108,6 +110,8 @@ public class InventoryConfig extends ACheckConfig {
fastClickCheck = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_CHECK);
fastClickSpareCreative = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_SPARECREATIVE);
fastClickShortTermLimit = (float) data.getDouble(ConfPaths.INVENTORY_FASTCLICK_LIMIT_SHORTTERM);
fastClickNormalLimit = (float) data.getDouble(ConfPaths.INVENTORY_FASTCLICK_LIMIT_NORMAL);
fastClickActions = data.getOptimizedActionList(
ConfPaths.INVENTORY_FASTCLICK_ACTIONS,
Permissions.INVENTORY_FASTCLICK);

View File

@ -9,6 +9,7 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.access.ACheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.utilities.ActionFrequency;
/*
* M""M dP M""""""'YMM dP
@ -72,14 +73,17 @@ public class InventoryData extends ACheckData {
public double fastClickVL;
public double instantBowVL;
public double instantEatVL;
// General.
public long lastClickTime = 0;;
// Data of the drop check.
public int dropCount;
public long dropLastTime;
// Data of the fast click check.
public boolean fastClickLastCancelled;
public long fastClickLastTime;
// public boolean fastClickLastCancelled;
public final ActionFrequency fastClickFreq = new ActionFrequency(5, 200L);
// Data of the instant bow check.
public long instantBowInteract;

View File

@ -153,6 +153,7 @@ public class InventoryListener extends CheckListener {
* |___/
*/
if (event.getWhoClicked() instanceof Player) {
final long now = System.currentTimeMillis();
final Player player = (Player) event.getWhoClicked();
// Illegal enchantment checks.
@ -165,10 +166,14 @@ public class InventoryListener extends CheckListener {
}
catch(final ArrayIndexOutOfBoundsException e){} // Hotfix (CB)
final InventoryData data = InventoryData.getData(player);
// Fast inventory manipulation check.
if (fastClick.isEnabled(player)){
if (player.getGameMode() != GameMode.CREATIVE || !InventoryConfig.getConfig(player).fastClickSpareCreative){
if (fastClick.check(player)){
final InventoryConfig cc = InventoryConfig.getConfig(player);
if (player.getGameMode() != GameMode.CREATIVE || !cc.fastClickSpareCreative){
if (fastClick.check(player, now, data, cc)){
// The check requested the event to be cancelled.
event.setCancelled(true);
}
@ -176,6 +181,7 @@ public class InventoryListener extends CheckListener {
Improbable.feed(player, 0.7f, System.currentTimeMillis());
}
}
data.lastClickTime = now;
}
}

View File

@ -468,6 +468,9 @@ public abstract class ConfPaths {
private static final String INVENTORY_FASTCLICK = INVENTORY + "fastclick.";
public static final String INVENTORY_FASTCLICK_CHECK = INVENTORY_FASTCLICK + "active";
public static final String INVENTORY_FASTCLICK_SPARECREATIVE = INVENTORY_FASTCLICK + "sparecreative";
private static final String INVENTORY_FASTCLICK_LIMIT = INVENTORY_FASTCLICK + "limit.";
public static final String INVENTORY_FASTCLICK_LIMIT_SHORTTERM = INVENTORY_FASTCLICK_LIMIT + "shortterm";
public static final String INVENTORY_FASTCLICK_LIMIT_NORMAL = INVENTORY_FASTCLICK_LIMIT + "normal";
public static final String INVENTORY_FASTCLICK_ACTIONS = INVENTORY_FASTCLICK + "actions";
private static final String INVENTORY_INSTANTBOW = INVENTORY + "instantbow.";

View File

@ -360,6 +360,8 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.INVENTORY_FASTCLICK_CHECK, true);
set(ConfPaths.INVENTORY_FASTCLICK_SPARECREATIVE, true);
set(ConfPaths.INVENTORY_FASTCLICK_LIMIT_SHORTTERM, 4);
set(ConfPaths.INVENTORY_FASTCLICK_LIMIT_NORMAL, 15);
set(ConfPaths.INVENTORY_FASTCLICK_ACTIONS, "cancel vl>50 log:fastclick:3:5:cif cancel");
set(ConfPaths.INVENTORY_INSTANTBOW_CHECK, true);

View File

@ -476,7 +476,7 @@ public class CheckUtils {
ref = Math.max(ref, CombinedData.getData(player).lastMoveTime);
// Inventory.
final InventoryData iData = InventoryData.getData(player);
ref = Math.max(ref, iData.fastClickLastTime);
ref = Math.max(ref, iData.lastClickTime);
ref = Math.max(ref, iData.instantEatInteract);
// BlcokBreak/interact.
final BlockBreakData bbData = BlockBreakData.getData(player);