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.Check;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData; import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/* /*
@ -28,53 +29,88 @@ public class FastClick extends Check {
super(CheckType.INVENTORY_FASTCLICK); super(CheckType.INVENTORY_FASTCLICK);
} }
/** // /**
* Checks a player. // * Checks a player.
* // *
* @param player // * @param player
* the player // * the player
* @param cc // * @param cc
* @return true, if successful // * @return true, if successful
*/ // */
public boolean check(final Player player) { // 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. // Take time once.
final long time = System.currentTimeMillis();
data.fastClickFreq.add(now, 1f);
final InventoryData data = InventoryData.getData(player);
float shortTerm = data.fastClickFreq.bucketScore(0);
boolean cancel = false; if (shortTerm > cc.fastClickShortTermLimit){
// Check for lag.
// If the last inventory click has been made within 45 milliseconds. shortTerm /= (float) TickTask.getLag(data.fastClickFreq.bucketDuration());
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;
} }
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 final double violation = Math.max(shortTerm, normal);
data.fastClickLastTime = time;
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; return cancel;
} }
} }

View File

@ -52,7 +52,7 @@ public class InstantEat extends Check {
return false; return false;
// Rough estimation about how long it should take to eat // 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){ if (data.instantEatInteract > 0 && expectedTimeWhenEatingFinished < time){
// Acceptable, reduce VL to reward the player. // 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 fastClickCheck;
public final boolean fastClickSpareCreative; public final boolean fastClickSpareCreative;
public final float fastClickShortTermLimit;
public final float fastClickNormalLimit;
public final ActionList fastClickActions; public final ActionList fastClickActions;
public final boolean instantBowCheck; public final boolean instantBowCheck;
@ -108,6 +110,8 @@ public class InventoryConfig extends ACheckConfig {
fastClickCheck = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_CHECK); fastClickCheck = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_CHECK);
fastClickSpareCreative = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_SPARECREATIVE); 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( fastClickActions = data.getOptimizedActionList(
ConfPaths.INVENTORY_FASTCLICK_ACTIONS, ConfPaths.INVENTORY_FASTCLICK_ACTIONS,
Permissions.INVENTORY_FASTCLICK); 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.ACheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory; import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData; import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.utilities.ActionFrequency;
/* /*
* M""M dP M""""""'YMM dP * M""M dP M""""""'YMM dP
@ -72,14 +73,17 @@ public class InventoryData extends ACheckData {
public double fastClickVL; public double fastClickVL;
public double instantBowVL; public double instantBowVL;
public double instantEatVL; public double instantEatVL;
// General.
public long lastClickTime = 0;;
// Data of the drop check. // Data of the drop check.
public int dropCount; public int dropCount;
public long dropLastTime; public long dropLastTime;
// Data of the fast click check. // Data of the fast click check.
public boolean fastClickLastCancelled; // public boolean fastClickLastCancelled;
public long fastClickLastTime; public final ActionFrequency fastClickFreq = new ActionFrequency(5, 200L);
// Data of the instant bow check. // Data of the instant bow check.
public long instantBowInteract; public long instantBowInteract;

View File

@ -153,6 +153,7 @@ public class InventoryListener extends CheckListener {
* |___/ * |___/
*/ */
if (event.getWhoClicked() instanceof Player) { if (event.getWhoClicked() instanceof Player) {
final long now = System.currentTimeMillis();
final Player player = (Player) event.getWhoClicked(); final Player player = (Player) event.getWhoClicked();
// Illegal enchantment checks. // Illegal enchantment checks.
@ -165,10 +166,14 @@ public class InventoryListener extends CheckListener {
} }
catch(final ArrayIndexOutOfBoundsException e){} // Hotfix (CB) catch(final ArrayIndexOutOfBoundsException e){} // Hotfix (CB)
final InventoryData data = InventoryData.getData(player);
// Fast inventory manipulation check. // Fast inventory manipulation check.
if (fastClick.isEnabled(player)){ 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. // The check requested the event to be cancelled.
event.setCancelled(true); event.setCancelled(true);
} }
@ -176,6 +181,7 @@ public class InventoryListener extends CheckListener {
Improbable.feed(player, 0.7f, System.currentTimeMillis()); 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."; private static final String INVENTORY_FASTCLICK = INVENTORY + "fastclick.";
public static final String INVENTORY_FASTCLICK_CHECK = INVENTORY_FASTCLICK + "active"; public static final String INVENTORY_FASTCLICK_CHECK = INVENTORY_FASTCLICK + "active";
public static final String INVENTORY_FASTCLICK_SPARECREATIVE = INVENTORY_FASTCLICK + "sparecreative"; 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"; public static final String INVENTORY_FASTCLICK_ACTIONS = INVENTORY_FASTCLICK + "actions";
private static final String INVENTORY_INSTANTBOW = INVENTORY + "instantbow."; 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_CHECK, true);
set(ConfPaths.INVENTORY_FASTCLICK_SPARECREATIVE, 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_FASTCLICK_ACTIONS, "cancel vl>50 log:fastclick:3:5:cif cancel");
set(ConfPaths.INVENTORY_INSTANTBOW_CHECK, true); set(ConfPaths.INVENTORY_INSTANTBOW_CHECK, true);

View File

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