Add yawrate check to fight/combined. Adjust angle check.

This commit is contained in:
asofold 2012-09-18 17:25:23 +02:00
parent 5e2d4fe57f
commit 66fe28dd93
11 changed files with 172 additions and 48 deletions

View File

@ -0,0 +1,105 @@
package fr.neatmonster.nocheatplus.checks.combined;
import org.bukkit.entity.Player;
/**
* Static access API for shared use. This is actually not really a check, but access to combined or shared data.
* @author mc_dev
*
*/
public class Combined {
/**
* Check if a penalty is set by changing horizontal facing dierection too often.
* @param player
* @param yaw
* @param now
* @param worldName
* @return
*/
public static final boolean checkYaw(final Player player, final float yaw, final long now, final String worldName){
return checkYaw(player, yaw, now, worldName, CombinedData.getData(player));
}
/**
* Feed horizontal facing direction.
* @param player
* @param yaw
* @param now
* @param worldName
*/
public static final void feedYaw(final Player player, final float yaw, final long now, final String worldName){
feedYaw(player, yaw, now, worldName, CombinedData.getData(player));
}
/**
* Update the yaw change data.
* @param player
* @param yaw
* @param now
* @param worldName
* @param data
*/
private static final void feedYaw(final Player player, final float yaw, final long now, final String worldName, final CombinedData data) {
// Reset on world change or timeout.
if (now - data.lastYawTime > 999 || !worldName.equals(data.lastWorld)){
data.lastYaw = yaw;
data.lastYawTime = now;
data.lastWorld = worldName;
}
final float yawDiff = (yaw - data.lastYaw) % 180;
final long elapsed = now - data.lastYawTime;
// Set data to current state.
data.lastYaw = yaw;
data.lastYawTime = now;
final float dAbs = Math.abs(yawDiff);
final float dNorm = (float) dAbs / (float) (1 + elapsed);
data.yawFreq.add(now, dNorm);
}
/**
* This calls feedLastYaw and does nothing but set the freezing time to be used by whatever check.
* @param player
* @param yaw
* @param now
* @param worldName
* @return
*/
private static final boolean checkYaw(Player player, float yaw, long now, final String worldName, final CombinedData data) {
feedYaw(player, yaw, now, worldName, data);
final CombinedConfig cc = CombinedConfig.getConfig(player);
// Angle diff per second
final float total = Math.max(data.yawFreq.getScore(1f), data.yawFreq.getScore(0) * 3f);
final float threshold = cc.lastYawRate;
if (total > threshold){
// Add time
data.timeFreeze = Math.max(data.timeFreeze, now + (long) ((total - threshold) / threshold * 1000f));
}
return now < data.timeFreeze;
}
/**
* Allow to pass a config flag if to check or only to feed.
* @param player
* @param yaw
* @param now
* @param worldName
* @param yawRateCheck If to actually check the yaw rate, or just feed.
* @return
*/
public static final boolean checkYaw(final Player player, final float yaw, final long now, final String worldName, final boolean yawRateCheck) {
if (yawRateCheck) return checkYaw(player, yaw, now, worldName);
else {
feedYaw(player, yaw, now, worldName);
return false;
}
}
}

View File

@ -37,14 +37,20 @@ public class CombinedConfig extends ACheckConfig {
return cc;
}
/** Do mind that this flag is not used by all compinents. */
public final boolean improbableCheck;
public final float improbableLevel;
public final ActionList improbableActions;
// Last yaw tracking
public final float lastYawRate;
public CombinedConfig(final ConfigFile config) {
improbableCheck = config.getBoolean(ConfPaths.COMBINED_IMPROBABLE_CHECK, false);
improbableLevel = (float) config.getDouble(ConfPaths.COMBINED_IMPROBABLE_LEVEL, 300);
improbableActions = config.getActionList(ConfPaths.COMBINED_IMPROBABLE_ACTIONS, Permissions.COMBINED_IMPROBABLE);
lastYawRate = config.getInt(ConfPaths.COMBINED_YAWRATE_RATE);
}
@Override

View File

@ -46,11 +46,13 @@ public class CombinedData extends ACheckData {
public float lastYaw;
public long lastYawTime;
public final ActionFrequency yawFreq = new ActionFrequency(4, 500);
public final ActionFrequency yawFreq = new ActionFrequency(3, 333);
public long timeFreeze = 0;
public final ActionFrequency improbableCount = new ActionFrequency(20, 3000);
public String lastWorld = "";
public CombinedData(final Player player){
// final CombinedConfig cc = CombinedConfig.getConfig(player);

View File

@ -1,10 +1,13 @@
package fr.neatmonster.nocheatplus.checks.combined;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerToggleSneakEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
/**
*
@ -19,23 +22,26 @@ public class CombinedListener implements Listener {
this.improbable = new Improbable();
}
// @EventHandler(priority=EventPriority.LOW)
// public void onPlayerToggleSneak(final PlayerToggleSneakEvent event){
// // Check also in case of cancelled events.
// if (Improbable.check(event.getPlayer(), 0.35f, System.currentTimeMillis())) event.setCancelled(true);
// }
//
// @EventHandler(priority=EventPriority.LOW)
// public void onPlayerToggleSprint(final PlayerToggleSprintEvent event){
// // Check also in case of cancelled events.
// if (Improbable.check(event.getPlayer(), 0.35f, System.currentTimeMillis())) event.setCancelled(true);
// }
@EventHandler(priority=EventPriority.LOW)
public void onPlayerToggleSneak(final PlayerToggleSneakEvent event){
// Check also in case of cancelled events.
if (Improbable.check(event.getPlayer(), 0.35f, System.currentTimeMillis())) event.setCancelled(true);
}
@EventHandler(priority=EventPriority.MONITOR)
@EventHandler(priority=EventPriority.LOW)
public void onPlayerToggleSprint(final PlayerToggleSprintEvent event){
// Check also in case of cancelled events.
if (Improbable.check(event.getPlayer(), 0.35f, System.currentTimeMillis())) event.setCancelled(true);
}
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled = false)
public final void onPlayerMove(final PlayerMoveEvent event){
final Player player =event.getPlayer();
// Experimental
final Player player = event.getPlayer();
// Just add the yaw to the list.
Improbable.checkYaw(player, player.getLocation().getYaw(), System.currentTimeMillis());
final Location loc = player.getLocation();
final String worldName = loc.getWorld().getName();
Combined.feedYaw(player, loc.getYaw(), System.currentTimeMillis(), worldName);
}
// (possibly other types of events, but these combine with fighting).

View File

@ -26,10 +26,6 @@ public class Improbable extends Check {
public static final boolean check(final Player player, final float weight, final long now){
return instance.checkImprobable(player, weight, now);
}
public static final boolean checkYaw(final Player player, final float yaw, final long now){
return instance.checkLastYaw(player, yaw, now);
}
////////////////////////////////////
// Instance methods.
@ -67,28 +63,5 @@ public class Improbable extends Check {
data.improbableVL *= 0.95;
return cancel;
}
private boolean checkLastYaw(Player player, float yaw, long now) {
if (!isEnabled(player)) return false;
final CombinedData data = CombinedData.getData(player);
// final CombinedConfig cc = CombinedConfig.getConfig(player);
final float yawDiff = (yaw - data.lastYaw) % 180;
// final long elapsed = now - data.lastYawTime;
boolean cancel = false;
if (now < data.timeFreeze) cancel = true;
final float dAbs = Math.abs(yawDiff);
data.yawFreq.add(now, (float) dAbs); // *3f / ((float) (elapsed + 1)) );
if (dAbs > 30) data.timeFreeze = now + (long) dAbs * 3;
// System.out.println("yawDiff " + player.getName() + ": " + yawDiff + " (" + elapsed+ ") - " + data.yawFreq.getScore(1f));
// Set data to current state.
data.lastYaw = yaw;
data.lastYawTime = now;
return cancel;
}
}

View File

@ -38,11 +38,17 @@ public class Angle extends Check {
*
* @param player
* the player
* @param worldChanged
* @return true, if successful
*/
public boolean check(final Player player) {
public boolean check(final Player player, final boolean worldChanged) {
final FightConfig cc = FightConfig.getConfig(player);
final FightData data = FightData.getData(player);
if (worldChanged){
// TODO: clear some data.
data.angleHits.clear();
}
boolean cancel = false;
@ -69,13 +75,15 @@ public class Angle extends Check {
for (final long time : data.angleHits.descendingKeySet()) {
final Location location = data.angleHits.get(time);
// We need a previous location to calculate deltas.
if (previousLocation != null && location.getWorld().getName().equals(previousLocation.getWorld().getName())) {
if (previousLocation != null){ // && location.getWorld().getName().equals(previousLocation.getWorld().getName())) {
// (Risks exceptions on reloading).
// Calculate the distance between the two locations.
deltaMove += previousLocation.distanceSquared(location);
// Calculate the time elapsed between the two hits.
deltaTime += previousTime - time;
// Calculate the difference of the yaw between the two locations.
deltaYaw += (previousLocation.getYaw() - location.getYaw()) % 360f;
final float dYaw = (previousLocation.getYaw() - location.getYaw()) % 180;
deltaYaw += Math.abs(dYaw);
}
// Remember the current time and location.
previousTime = time;

View File

@ -99,6 +99,8 @@ public class FightConfig extends ACheckConfig {
public final boolean speedCheck;
public final int speedLimit;
public final ActionList speedActions;
public final boolean yawRateCheck;
/**
* Instantiates a new fight configuration.
@ -143,6 +145,8 @@ public class FightConfig extends ACheckConfig {
speedCheck = data.getBoolean(ConfPaths.FIGHT_SPEED_CHECK);
speedLimit = data.getInt(ConfPaths.FIGHT_SPEED_LIMIT);
speedActions = data.getActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED);
yawRateCheck = data.getBoolean(ConfPaths.FIGHT_YAWRATE_CHECK, true);
}
/* (non-Javadoc)

View File

@ -72,6 +72,10 @@ public class FightData extends ACheckData {
public double speedVL;
public boolean skipNext;
// Shared
public String lastWorld = "";
// Data of the angle check.
public TreeMap<Long, Location> angleHits = new TreeMap<Long, Location>();

View File

@ -15,6 +15,7 @@ import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.player.PlayerAnimationEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
import fr.neatmonster.nocheatplus.checks.combined.Combined;
import fr.neatmonster.nocheatplus.checks.combined.Improbable;
import fr.neatmonster.nocheatplus.players.Permissions;
@ -98,6 +99,8 @@ public class FightListener implements Listener {
boolean cancelled = false;
final String worldName = player.getWorld().getName();
// Check for self hit exploits (mind that projectiles should be excluded)
final Entity cbEntity = event.getEntity();
if (cbEntity instanceof Player){
@ -113,10 +116,11 @@ public class FightListener implements Listener {
final long now = System.currentTimeMillis();
final boolean worldChanged = !worldName.equals(data.lastWorld);
// Improbable yaw:
if (Improbable.checkYaw(player, player.getLocation().getYaw(), now)){
if (Combined.checkYaw(player, player.getLocation().getYaw(), now, worldName, cc.yawRateCheck)){
cancelled = true;
// System.out.println(player.getName() + " <- cancelled attack by yaw.");
}
// Combined speed:
@ -127,7 +131,7 @@ public class FightListener implements Listener {
final net.minecraft.server.Entity damaged = ((CraftEntity) cbEntity).getHandle();
// Run through the main checks.
if (!cancelled && angle.isEnabled(player) && angle.check(player))
if (!cancelled && angle.isEnabled(player) && angle.check(player, worldChanged))
cancelled = true;
if (!cancelled && critical.isEnabled(player) && critical.check(player))
@ -154,6 +158,8 @@ public class FightListener implements Listener {
// One of the checks requested the event to be cancelled, so do it.
if (cancelled)
event.setCancelled(cancelled);
data.lastWorld = worldName;
}
/**

View File

@ -301,6 +301,9 @@ public abstract class ConfPaths {
public static final String COMBINED_IMPROBABLE_ACTIONS = COMBINED_IMPROBABLE + "actions";
private static final String COMBINED_YAWRATE = COMBINED + "yawrate.";
public static final String COMBINED_YAWRATE_RATE = COMBINED_YAWRATE + "rate";
/*
* 888'Y88 ,e, 888 d8
* 888 ,'Y " e88 888 888 ee d88
@ -359,6 +362,9 @@ public abstract class ConfPaths {
public static final String FIGHT_SPEED_CHECK = FIGHT_SPEED + "active";
public static final String FIGHT_SPEED_LIMIT = FIGHT_SPEED + "limit";
public static final String FIGHT_SPEED_ACTIONS = FIGHT_SPEED + "actions";
private static final String FIGHT_YAWRATE = FIGHT + "yawrate.";
public static final String FIGHT_YAWRATE_CHECK = FIGHT_YAWRATE + "active";
/*
* 888 d8

View File

@ -228,6 +228,8 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.COMBINED_IMPROBABLE_FASTBREAK_CHECK, false);
set(ConfPaths.COMBINED_IMPROBABLE_ACTIONS, "cancel log:improbable:2:8:if");
set(ConfPaths.COMBINED_YAWRATE_RATE , "380");
/*
* 888'Y88 ,e, 888 d8
* 888 ,'Y " e88 888 888 ee d88
@ -237,6 +239,8 @@ public class DefaultConfig extends ConfigFile {
* , 88P
* "8",P"
*/
set(ConfPaths.FIGHT_YAWRATE_CHECK, true);
set(ConfPaths.FIGHT_ANGLE_CHECK, true);
set(ConfPaths.FIGHT_ANGLE_THRESHOLD, 50);
set(ConfPaths.FIGHT_ANGLE_ACTIONS, "cancel vl>100 log:angle:3:5:f cancel vl>250 log:angle:0:5:cif cancel");