[Bleeding] Add FastHeal check.

Might need lower interval and higher buffer in the default config,
subject to testing.
This commit is contained in:
asofold 2013-02-20 17:02:48 +01:00
parent 4a2dfc853e
commit db5a71d6d2
8 changed files with 119 additions and 1 deletions

View File

@ -78,6 +78,7 @@ public enum CheckType {
FIGHT_ANGLE(FIGHT, Permissions.FIGHT_ANGLE),
FIGHT_CRITICAL(FIGHT, Permissions.FIGHT_CRITICAL),
FIGHT_DIRECTION(FIGHT, Permissions.FIGHT_DIRECTION),
FIGHT_FASTHEAL(FIGHT, Permissions.FIGHT_FASTHEAL),
FIGHT_GODMODE(FIGHT, Permissions.FIGHT_GODMODE),
FIGHT_KNOCKBACK(FIGHT, Permissions.FIGHT_KNOCKBACK),
FIGHT_NOSWING(FIGHT, Permissions.FIGHT_NOSWING),

View File

@ -0,0 +1,55 @@
package fr.neatmonster.nocheatplus.checks.fight;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.TickTask;
/**
*
* @author mc_dev
*
*/
public class FastHeal extends Check {
public FastHeal(){
super(CheckType.FIGHT_FASTHEAL);
}
public boolean check(final Player player){
final long time = System.currentTimeMillis();
final FightConfig cc = FightConfig.getConfig(player);
final FightData data = FightData.getData(player);
boolean cancel = false;
if (time < data.fastHealRefTime || time - data.fastHealRefTime >= cc.fastHealInterval){
// Reset.
data.fastHealVL *= 0.96;
// Only add a predefined amount to the buffer.
data.fastHealBuffer = Math.min(cc.fastHealBuffer, data.fastHealBuffer + 50L);
}
else{
// Violation.
final double correctedDiff = ((double) time - data.fastHealRefTime) * TickTask.getLag(cc.fastHealInterval);
// TODO: Consider using a simple buffer as well (to get closer to the correct interva).
if (correctedDiff < cc.fastHealInterval){
data.fastHealBuffer -= (cc.fastHealInterval - correctedDiff);
if (data.fastHealBuffer <= 0){
final double violation = ((double) cc.fastHealInterval - correctedDiff) / 1000.0;
data.fastHealVL += violation;
if (executeActions(player, data.fastHealVL, violation, cc.fastHealActions)){
cancel = true;
}
}
}
}
if (cc.debug && player.hasPermission(Permissions.ADMINISTRATION_DEBUG)){
player.sendMessage("Regain health(SATIATED): " + (time - data.fastHealRefTime) + " ms "+ "(buffer=" + data.fastHealBuffer + ")" +" , cancel=" + cancel);
}
data.fastHealRefTime = time;
return cancel;
}
}

View File

@ -75,6 +75,11 @@ public class FightConfig extends ACheckConfig {
public final boolean directionCheck;
public final long directionPenalty;
public final ActionList directionActions;
public final boolean fastHealCheck;
public final long fastHealInterval;
public final long fastHealBuffer;
public final ActionList fastHealActions;
public final boolean godModeCheck;
public final long godModeLagMinAge;
@ -131,6 +136,11 @@ public class FightConfig extends ACheckConfig {
directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK);
directionPenalty = data.getLong(ConfPaths.FIGHT_DIRECTION_PENALTY);
directionActions = data.getOptimizedActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION);
fastHealCheck = data.getBoolean(ConfPaths.FIGHT_FASTHEAL_CHECK);;
fastHealInterval = data.getLong(ConfPaths.FIGHT_FASTHEAL_INTERVAL);
fastHealBuffer = data.getLong(ConfPaths.FIGHT_FASTHEAL_BUFFER);
fastHealActions = data.getOptimizedActionList(ConfPaths.FIGHT_FASTHEAL_ACTIONS, Permissions.FIGHT_FASTHEAL);
godModeCheck = data.getBoolean(ConfPaths.FIGHT_GODMODE_CHECK);
godModeLagMinAge = data.getLong(ConfPaths.FIGHT_GODMODE_LAGMINAGE);
@ -191,6 +201,8 @@ public class FightConfig extends ACheckConfig {
return speedCheck;
case FIGHT_SELFHIT:
return selfHitCheck;
case FIGHT_FASTHEAL:
return fastHealCheck;
default:
return true;
}

View File

@ -73,6 +73,7 @@ public class FightData extends ACheckData {
public double angleVL;
public double criticalVL;
public double directionVL;
public double fastHealVL;
public double godModeVL;
public double knockbackVL;
public double noSwingVL;
@ -85,6 +86,7 @@ public class FightData extends ACheckData {
public double lastAttackedX = Integer.MAX_VALUE;
public double lastAttackedY;
public double lastAttackedZ;
/** Any kind of health regeneration. */
public long regainHealthTime = 0;
// public double lastAttackedDist = 0.0;
public long damageTakenByEntityTick;
@ -93,7 +95,12 @@ public class FightData extends ACheckData {
public TreeMap<Long, Location> angleHits = new TreeMap<Long, Location>();
// Data of the direction check.
public long directionLastViolationTime;
public long directionLastViolationTime = 0;
// FastHeal
public long fastHealRefTime = 0;
/** Buffer has to be initialized in constructor. */
public long fastHealBuffer = 0;
// Old god mode check.
public int godModeBuffer;
@ -129,5 +136,7 @@ public class FightData extends ACheckData {
public FightData(final FightConfig cc){
speedBuckets = new ActionFrequency(cc.speedBuckets, cc.speedBucketDur);
// Start with full fast-heal buffer.
fastHealBuffer = cc.fastHealBuffer;
}
}

View File

@ -10,6 +10,7 @@ import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
import org.bukkit.event.player.PlayerAnimationEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
import org.bukkit.inventory.ItemStack;
@ -48,6 +49,9 @@ public class FightListener extends CheckListener {
/** The direction check. */
private final Direction direction = addCheck(new Direction());
/** Faster health regeneration check. */
private final FastHeal fastHeal = addCheck(new FastHeal());
/** The god mode check. */
private final GodMode godMode = addCheck(new GodMode());
@ -223,6 +227,16 @@ public class FightListener extends CheckListener {
// It requested to "cancel" the players invulnerability, so set his noDamageTicks to 0.
player.setNoDamageTicks(0);
}
if (player.getHealth() == player.getMaxHealth()){
final FightData data = FightData.getData(player);
// TODO: Might use the same FightData instance for GodMode.
if (data.fastHealBuffer < 0){
// Reduce negative buffer with each full health.
data.fastHealBuffer /= 2;
}
// Set reference time.
data.fastHealRefTime = System.currentTimeMillis();
}
}
// Attacking entities.
if (event instanceof EntityDamageByEntityEvent) {
@ -318,12 +332,27 @@ public class FightListener extends CheckListener {
if (event.isSprinting()) FightData.getData(event.getPlayer()).knockbackSprintTime = System.currentTimeMillis();
}
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onEntityRegainHealthLow(final EntityRegainHealthEvent event){
final Entity entity = event.getEntity();
if (!(entity instanceof Player)) return;
final Player player = (Player) entity;
if (event.getRegainReason() != RegainReason.SATIATED){
return;
}
if (fastHeal.isEnabled(player) && fastHeal.check(player)){
// TODO: Can clients force events with 0-re-gain ?
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onEntityRegainHealth(final EntityRegainHealthEvent event){
final Entity entity = event.getEntity();
if (!(entity instanceof Player)) return;
final Player player = (Player) entity;
final FightData data = FightData.getData(player);
// Adjust god mode data:
// Remember the time.
data.regainHealthTime = System.currentTimeMillis();
// Set god-mode health to maximum.

View File

@ -376,6 +376,12 @@ public abstract class ConfPaths {
public static final String FIGHT_DIRECTION_CHECK = FIGHT_DIRECTION + "active";
public static final String FIGHT_DIRECTION_PENALTY = FIGHT_DIRECTION + "penalty";
public static final String FIGHT_DIRECTION_ACTIONS = FIGHT_DIRECTION + "actions";
private static final String FIGHT_FASTHEAL = FIGHT + "fastheal.";
public static final String FIGHT_FASTHEAL_CHECK = FIGHT_FASTHEAL + "active";
public static final String FIGHT_FASTHEAL_INTERVAL = FIGHT_FASTHEAL + "interval";
public static final String FIGHT_FASTHEAL_BUFFER = FIGHT_FASTHEAL + "buffer";
public static final String FIGHT_FASTHEAL_ACTIONS = FIGHT_FASTHEAL + "actions";
private static final String FIGHT_GODMODE = FIGHT + "godmode.";
public static final String FIGHT_GODMODE_CHECK = FIGHT_GODMODE + "active";

View File

@ -300,6 +300,11 @@ public class DefaultConfig extends ConfigFile {
set(ConfPaths.FIGHT_DIRECTION_ACTIONS,
"cancel vl>5 log:fdirection:3:5:f cancel vl>20 log:fdirection:0:5:if cancel vl>50 log:fdirection:0:5:cif cancel");
set(ConfPaths.FIGHT_FASTHEAL_CHECK, true);
set(ConfPaths.FIGHT_FASTHEAL_INTERVAL, 4000L);
set(ConfPaths.FIGHT_FASTHEAL_BUFFER, 1000L);
set(ConfPaths.FIGHT_FASTHEAL_ACTIONS, "cancel vl>10 cancel log:fastheal:0:10");
set(ConfPaths.FIGHT_GODMODE_CHECK, true);
set(ConfPaths.FIGHT_GODMODE_LAGMINAGE, 1100); // TODO: ndt/2 => 500-600.
set(ConfPaths.FIGHT_GODMODE_LAGMAXAGE, 5000);

View File

@ -140,6 +140,7 @@ public class Permissions {
public static final String FIGHT_ANGLE = FIGHT + ".angle";
public static final String FIGHT_CRITICAL = FIGHT + ".critical";
public static final String FIGHT_DIRECTION = FIGHT + ".direction";
public static final String FIGHT_FASTHEAL = FIGHT + ".fastheal";
public static final String FIGHT_GODMODE = FIGHT + ".godmode";
public static final String FIGHT_KNOCKBACK = FIGHT + ".knockback";
public static final String FIGHT_NOSWING = FIGHT + ".noswing";