mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-29 23:17:41 +02:00
Add check: net/AttackFrequency (without improbable).
This commit is contained in:
parent
d899334d8f
commit
8ff29c2575
@ -0,0 +1,94 @@
|
||||
package fr.neatmonster.nocheatplus.checks.net.protocollib;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.checks.Check;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationData;
|
||||
import fr.neatmonster.nocheatplus.checks.net.NetConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.net.NetData;
|
||||
|
||||
public class AttackFrequency extends Check {
|
||||
|
||||
public AttackFrequency() {
|
||||
super(CheckType.NET_ATTACKFREQUENCY);
|
||||
}
|
||||
|
||||
public boolean check(final Player player, final long time, final NetData data, final NetConfig cc) {
|
||||
// Update frequency.
|
||||
data.attackFrequencySeconds.add(time, 1f);
|
||||
double maxVL = 0.0;
|
||||
float maxLimit = 0f;
|
||||
String tags = null;
|
||||
// TODO: option to normalize the vl / stats to per second?
|
||||
// HALF
|
||||
float sum = data.attackFrequencySeconds.bucketScore(0); // HALF
|
||||
float limit = cc.attackFrequencyLimitSecondsHalf;
|
||||
if (sum - limit > maxVL) {
|
||||
maxVL = sum - limit;
|
||||
maxLimit = limit;
|
||||
tags = "sec_half";
|
||||
}
|
||||
// ONE (update sum).
|
||||
sum += data.attackFrequencySeconds.bucketScore(1);
|
||||
limit = cc.attackFrequencyLimitSecondsOne;
|
||||
if (sum - limit > maxVL) {
|
||||
maxVL = sum - limit;
|
||||
maxLimit = limit;
|
||||
tags = "sec_one";
|
||||
}
|
||||
// TWO (update sum).
|
||||
sum += data.attackFrequencySeconds.sliceScore(2, 4, 1f);
|
||||
limit = cc.attackFrequencyLimitSecondsTwo;
|
||||
if (sum - limit > maxVL) {
|
||||
maxVL = sum - limit;
|
||||
maxLimit = limit;
|
||||
tags = "sec_two";
|
||||
}
|
||||
// FOUR (update sum).
|
||||
sum += data.attackFrequencySeconds.sliceScore(4, 8, 1f);
|
||||
limit = cc.attackFrequencyLimitSecondsFour;
|
||||
if (sum - limit > maxVL) {
|
||||
maxVL = sum - limit;
|
||||
maxLimit = limit;
|
||||
tags = "sec_four";
|
||||
}
|
||||
// EIGHT (update sum).
|
||||
sum += data.attackFrequencySeconds.sliceScore(8, 16, 1f);
|
||||
limit = cc.attackFrequencyLimitSecondsEight;
|
||||
if (sum - limit > maxVL) {
|
||||
maxVL = sum - limit;
|
||||
maxLimit = limit;
|
||||
tags = "sec_eight";
|
||||
}
|
||||
|
||||
// if (data.debug) {
|
||||
// player.sendMessage("AttackFrequency: " + data.attackFrequencySeconds.toLine());
|
||||
// }
|
||||
|
||||
boolean cancel = false;
|
||||
if (maxVL > 0.0) {
|
||||
// Trigger a violation.
|
||||
final ViolationData vd = new ViolationData(this, player, maxVL, 1.0, cc.attackFrequencyActions);
|
||||
if (data.debug || vd.needsParameters()) {
|
||||
vd.setParameter(ParameterName.PACKETS, Integer.toString((int) sum));
|
||||
vd.setParameter(ParameterName.LIMIT, Integer.toString((int) maxLimit));
|
||||
vd.setParameter(ParameterName.TAGS, tags);
|
||||
}
|
||||
if (executeActions(vd)) {
|
||||
cancel = true;
|
||||
}
|
||||
// // TODO: Still feed the improbable (needs TickTask extension ...)
|
||||
// if (data.speedVL > 50){
|
||||
// Improbable.check(player, 2f, now, "fight.speed");
|
||||
// }
|
||||
// else{
|
||||
// Improbable.feed(player, 2f, now);
|
||||
// }
|
||||
}
|
||||
|
||||
return cancel;
|
||||
}
|
||||
|
||||
}
|
@ -62,10 +62,10 @@ public class ProtocolLibComponent implements DisableListener, INotifyReload, Joi
|
||||
register("fr.neatmonster.nocheatplus.checks.net.protocollib.DebugAdapter", plugin);
|
||||
}
|
||||
// Actual checks.
|
||||
// if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE)) {
|
||||
// // (Also sets lastKeepAliveTime, if enabled.)
|
||||
// register("fr.neatmonster.nocheatplus.checks.net.protocollib.UseEntityAdapter", plugin);
|
||||
// }
|
||||
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE)) {
|
||||
// (Also sets lastKeepAliveTime, if enabled.)
|
||||
register("fr.neatmonster.nocheatplus.checks.net.protocollib.UseEntityAdapter", plugin);
|
||||
}
|
||||
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE)) {
|
||||
// (Also sets lastKeepAliveTime, if enabled.)
|
||||
register("fr.neatmonster.nocheatplus.checks.net.protocollib.FlyingFrequency", plugin);
|
||||
|
@ -0,0 +1,70 @@
|
||||
package fr.neatmonster.nocheatplus.checks.net.protocollib;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.events.PacketEvent;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.EntityUseAction;
|
||||
|
||||
import fr.neatmonster.nocheatplus.NCPAPIProvider;
|
||||
import fr.neatmonster.nocheatplus.checks.net.NetConfig;
|
||||
import fr.neatmonster.nocheatplus.checks.net.NetData;
|
||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||
|
||||
public class UseEntityAdapter extends BaseAdapter {
|
||||
|
||||
private final AttackFrequency attackFrequency;
|
||||
|
||||
public UseEntityAdapter(Plugin plugin) {
|
||||
super(plugin, PacketType.Play.Client.USE_ENTITY);
|
||||
|
||||
// Add feature tags for checks.
|
||||
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE)) {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(AttackFrequency.class.getSimpleName()));
|
||||
}
|
||||
attackFrequency = new AttackFrequency();
|
||||
NCPAPIProvider.getNoCheatPlusAPI().addComponent(attackFrequency);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPacketReceiving(final PacketEvent event) {
|
||||
final long time = System.currentTimeMillis();
|
||||
final Player player = event.getPlayer();
|
||||
final NetConfig cc = configFactory.getConfig(player);
|
||||
final NetData data = dataFactory.getData(player);
|
||||
|
||||
// Always set last received time.
|
||||
data.lastKeepAliveTime = time;
|
||||
|
||||
// Quick return, if no checks are active.
|
||||
if (!cc.attackFrequencyActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PacketContainer packet = event.getPacket();
|
||||
final StructureModifier<EntityUseAction> actions = packet.getEntityUseActions();
|
||||
if (actions.size() != 1) {
|
||||
// TODO: Log warning once.
|
||||
return;
|
||||
}
|
||||
final EntityUseAction action = actions.read(0);
|
||||
|
||||
boolean cancel = false;
|
||||
if (action == EntityUseAction.ATTACK && attackFrequency.isEnabled(player, data, cc) && attackFrequency.check(player, time, data, cc)) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
// MIGHT: use entity, use block both on packet level?
|
||||
|
||||
if (cancel) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -213,6 +213,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
|
||||
cancelled = true;
|
||||
}
|
||||
}
|
||||
// TODO: Consider to always check improbable (first?). At least if config.always or speed or net.attackfrequency are enabled.
|
||||
|
||||
if (!cancelled && critical.isEnabled(player) && critical.check(player, loc, data, cc)) {
|
||||
cancelled = true;
|
||||
|
@ -16,6 +16,12 @@ import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
public class NetConfig extends ACheckConfig {
|
||||
|
||||
public final boolean attackFrequencyActive;
|
||||
public final float attackFrequencyLimitSecondsHalf;
|
||||
public final float attackFrequencyLimitSecondsOne;
|
||||
public final float attackFrequencyLimitSecondsTwo;
|
||||
public final float attackFrequencyLimitSecondsFour;
|
||||
public final float attackFrequencyLimitSecondsEight;
|
||||
public final ActionList attackFrequencyActions;
|
||||
|
||||
public final boolean flyingFrequencyActive;
|
||||
public final int flyingFrequencySeconds;
|
||||
@ -43,7 +49,12 @@ public class NetConfig extends ACheckConfig {
|
||||
final ConfigFile globalConfig = ConfigManager.getConfigFile();
|
||||
|
||||
attackFrequencyActive = config.getBoolean(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE);
|
||||
// TODO: Others.
|
||||
attackFrequencyLimitSecondsHalf = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_HALF);
|
||||
attackFrequencyLimitSecondsOne = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_ONE);
|
||||
attackFrequencyLimitSecondsTwo = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_TWO);
|
||||
attackFrequencyLimitSecondsFour= config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_FOUR);
|
||||
attackFrequencyLimitSecondsEight = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_EIGHT);
|
||||
attackFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_ATTACKFREQUENCY_ACTIONS, Permissions.NET_ATTACKFREQUENCY);
|
||||
|
||||
flyingFrequencyActive = config.getBoolean(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE);
|
||||
flyingFrequencySeconds = Math.max(1, globalConfig.getInt(ConfPaths.NET_FLYINGFREQUENCY_SECONDS));
|
||||
|
@ -16,6 +16,10 @@ import fr.neatmonster.nocheatplus.utilities.ActionFrequency;
|
||||
*/
|
||||
public class NetData extends ACheckData {
|
||||
|
||||
// AttackFrequency
|
||||
public ActionFrequency attackFrequencySeconds = new ActionFrequency(16, 500);
|
||||
|
||||
// FlyingFrequency
|
||||
/** All flying packets, use System.currentTimeMillis() for time. */
|
||||
public final ActionFrequency flyingFrequencyAll;
|
||||
public boolean flyingFrequencyOnGround = false;
|
||||
@ -27,6 +31,7 @@ public class NetData extends ACheckData {
|
||||
*/
|
||||
public final ActionFrequency flyingFrequencyRedundantFreq;
|
||||
|
||||
// KeepAliveFrequency
|
||||
/**
|
||||
* Last 20 seconds keep alive packets counting. Use lastUpdate() for the
|
||||
* time of the last event. System.currentTimeMillis() is used.
|
||||
@ -34,7 +39,10 @@ public class NetData extends ACheckData {
|
||||
public ActionFrequency keepAliveFreq = new ActionFrequency(20, 1000);
|
||||
|
||||
// Shared.
|
||||
/** Last time some action was received (keep alive or flying). Also maintained for fight.godmode. */
|
||||
/**
|
||||
* Last time some action was received (keep alive/flying/interaction). Also
|
||||
* maintained for fight.godmode.
|
||||
*/
|
||||
public long lastKeepAliveTime = 0L;
|
||||
|
||||
public final TeleportQueue teleportQueue = new TeleportQueue(); // TODO: Consider using one lock per data instance and pass here.
|
||||
|
@ -614,7 +614,14 @@ public abstract class ConfPaths {
|
||||
|
||||
private static final String NET_ATTACKFREQUENCY = NET + "attackfrequency.";
|
||||
public static final String NET_ATTACKFREQUENCY_ACTIVE = NET_ATTACKFREQUENCY + "active";
|
||||
// TODO: Parameters / concept.
|
||||
// TODO: Generic config for seconds.
|
||||
public static final String NET_ATTACKFREQUENCY_SECONDS = NET_ATTACKFREQUENCY + "limitforseconds.";
|
||||
public static final String NET_ATTACKFREQUENCY_SECONDS_HALF = NET_ATTACKFREQUENCY_SECONDS + "half";
|
||||
public static final String NET_ATTACKFREQUENCY_SECONDS_ONE = NET_ATTACKFREQUENCY_SECONDS + "one";
|
||||
public static final String NET_ATTACKFREQUENCY_SECONDS_TWO = NET_ATTACKFREQUENCY_SECONDS + "two";
|
||||
public static final String NET_ATTACKFREQUENCY_SECONDS_FOUR = NET_ATTACKFREQUENCY_SECONDS + "four";
|
||||
public static final String NET_ATTACKFREQUENCY_SECONDS_EIGHT = NET_ATTACKFREQUENCY_SECONDS + "eight";
|
||||
public static final String NET_ATTACKFREQUENCY_ACTIONS = NET_ATTACKFREQUENCY + "actions";
|
||||
|
||||
private static final String NET_FLYINGFREQUENCY = NET + "flyingfrequency.";
|
||||
public static final String NET_FLYINGFREQUENCY_ACTIVE = NET_FLYINGFREQUENCY + "active";
|
||||
|
@ -447,6 +447,12 @@ public class DefaultConfig extends ConfigFile {
|
||||
|
||||
// AttackFrequency
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE, true);
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_HALF, 10);
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_ONE, 15);
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_TWO, 30);
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_FOUR, 60);
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_EIGHT, 100);
|
||||
set(ConfPaths.NET_ATTACKFREQUENCY_ACTIONS, "cancel vl>30 cancel log:attackfrequency:0:5:if vl>160 cancel log:attackfrequency:0:0:cif cmd:kickattackfrequency");
|
||||
|
||||
// FlyingFrequency
|
||||
set(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE, true);
|
||||
@ -472,6 +478,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
final String end = ". VL [violations].";
|
||||
final String tell = "ncp tell [player] ";
|
||||
set(ConfPaths.STRINGS + ".angle", start + "tried to hit multiple entities at the same time" + end);
|
||||
set(ConfPaths.STRINGS + ".attackfrequency", start + "attacks with too high a frequency ([packets]/[limit], [tags])" + end);
|
||||
set(ConfPaths.STRINGS + ".ban", "ban [player]");
|
||||
set(ConfPaths.STRINGS + ".ban-ip", "ban-ip [ip]");
|
||||
set(ConfPaths.STRINGS + ".bautosign", start + "failed autosign with [tags]" + end);
|
||||
@ -511,6 +518,7 @@ public class DefaultConfig extends ConfigFile {
|
||||
set(ConfPaths.STRINGS + ".keepalive", start + "spams keep-alive packets (god/freecam?)" + end);
|
||||
set(ConfPaths.STRINGS + ".kick", "kick [player]");
|
||||
set(ConfPaths.STRINGS + ".kickalive", "ncp kick [player] Too many keep-alive packets.");
|
||||
set(ConfPaths.STRINGS + ".kickattackfrequency", "ncp kick [player] Unlikely fast clicking.");
|
||||
set(ConfPaths.STRINGS + ".kickbedleave", "ncp delay ncp kick [player] Go find a bed!");
|
||||
set(ConfPaths.STRINGS + ".kickbspeed", "ncp kick [player] You interacted too fast!");
|
||||
set(ConfPaths.STRINGS + ".kickcaptcha", "ncp kick [player] Enter the captcha!");
|
||||
|
Loading…
Reference in New Issue
Block a user