mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-07-05 10:44:40 +02:00
[BLEEDING] Net checks: Cancel redundant flying packets. Better config.
FlyingFrequency: if frequency is above 20/sec, redundant packets will be cancelled (experimental, configurable).
This commit is contained in:
parent
03eb652dd9
commit
dd87ab7ccd
|
@ -1,5 +1,6 @@
|
||||||
package fr.neatmonster.nocheatplus.net.protocollib;
|
package fr.neatmonster.nocheatplus.net.protocollib;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
@ -7,13 +8,13 @@ import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.protocol.PacketType;
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
import com.comphenix.protocol.events.PacketAdapter;
|
||||||
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
|
||||||
import fr.neatmonster.nocheatplus.NCPAPIProvider;
|
import fr.neatmonster.nocheatplus.NCPAPIProvider;
|
||||||
import fr.neatmonster.nocheatplus.components.JoinLeaveListener;
|
import fr.neatmonster.nocheatplus.components.JoinLeaveListener;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
import fr.neatmonster.nocheatplus.net.NetConfig;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
import fr.neatmonster.nocheatplus.net.NetConfigCache;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
|
||||||
import fr.neatmonster.nocheatplus.stats.Counters;
|
import fr.neatmonster.nocheatplus.stats.Counters;
|
||||||
import fr.neatmonster.nocheatplus.utilities.ActionFrequency;
|
import fr.neatmonster.nocheatplus.utilities.ActionFrequency;
|
||||||
import fr.neatmonster.nocheatplus.utilities.ds.corw.LinkedHashMapCOW;
|
import fr.neatmonster.nocheatplus.utilities.ds.corw.LinkedHashMapCOW;
|
||||||
|
@ -27,30 +28,44 @@ import fr.neatmonster.nocheatplus.utilities.ds.corw.LinkedHashMapCOW;
|
||||||
*/
|
*/
|
||||||
public class FlyingFrequency extends PacketAdapter implements JoinLeaveListener {
|
public class FlyingFrequency extends PacketAdapter implements JoinLeaveListener {
|
||||||
|
|
||||||
// TODO: Silent cancel count.
|
// TODO: Most efficient registration + optimize (primary thread or asynchronous).
|
||||||
// TODO: Configuration.
|
|
||||||
// TODO: Optimized options (receive only, other?).
|
|
||||||
// TODO: Forced async version ?
|
|
||||||
|
|
||||||
private final Map<String, ActionFrequency> freqMap = new LinkedHashMapCOW<String, ActionFrequency>();
|
private class FFData {
|
||||||
|
public static final int numBooleans = 3;
|
||||||
|
public static final int indexOnGround = 0;
|
||||||
|
public static final int indexhasPos = 1;
|
||||||
|
public static final int indexhasLook = 2;
|
||||||
|
|
||||||
|
public final ActionFrequency all;
|
||||||
|
// Last move.
|
||||||
|
public final double[] doubles = new double[3]; // x, y, z
|
||||||
|
public final float[] floats = new float[2]; // yaw, pitch
|
||||||
|
//public final boolean[] booleans = new boolean[3]; // ground, hasPos, hasLook
|
||||||
|
public boolean onGround = false;
|
||||||
|
public FFData(int seconds) {
|
||||||
|
all = new ActionFrequency(seconds, 1000L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Map<String, FFData> freqMap = new LinkedHashMapCOW<String, FFData>();
|
||||||
private final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class);
|
private final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class);
|
||||||
private final int idSilent = counters.registerKey("packet.flying.silentcancel");
|
private final int idSilent = counters.registerKey("packet.flying.silentcancel");
|
||||||
|
private final int idRedundant = counters.registerKey("packet.flying.silentcancel.redundant");
|
||||||
private final int idNullPlayer = counters.registerKey("packet.flying.nullplayer");
|
private final int idNullPlayer = counters.registerKey("packet.flying.nullplayer");
|
||||||
|
|
||||||
private final int seconds;
|
private boolean cancelRedundant = true;
|
||||||
private final float maxPackets;
|
|
||||||
|
|
||||||
public FlyingFrequency(Plugin plugin) {
|
private final NetConfigCache configs;
|
||||||
|
|
||||||
|
public FlyingFrequency(NetConfigCache configs, Plugin plugin) {
|
||||||
// PacketPlayInFlying[3, legacy: 10]
|
// PacketPlayInFlying[3, legacy: 10]
|
||||||
super(plugin, PacketType.Play.Client.FLYING); // TODO: How does POS and POS_LOOK relate/translate?
|
super(plugin, PacketType.Play.Client.FLYING); // TODO: How does POS and POS_LOOK relate/translate?
|
||||||
ConfigFile config = ConfigManager.getConfigFile();
|
this.configs = configs;
|
||||||
seconds = Math.max(1, config.getInt(ConfPaths.NET_FLYINGFREQUENCY_SECONDS));
|
|
||||||
maxPackets = Math.max(1, config.getInt(ConfPaths.NET_FLYINGFREQUENCY_MAXPACKETS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playerJoins(Player player) {
|
public void playerJoins(Player player) {
|
||||||
getFreq(player.getName());
|
// Ignore.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,12 +73,12 @@ public class FlyingFrequency extends PacketAdapter implements JoinLeaveListener
|
||||||
freqMap.remove(player.getName());
|
freqMap.remove(player.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionFrequency getFreq(final String name) {
|
private FFData getFreq(final String name, final NetConfig cc) {
|
||||||
final ActionFrequency freq = this.freqMap.get(name);
|
final FFData freq = this.freqMap.get(name);
|
||||||
if (freq != null) {
|
if (freq != null) {
|
||||||
return freq;
|
return freq;
|
||||||
} else {
|
} else {
|
||||||
final ActionFrequency newFreq = new ActionFrequency(seconds, 1000);
|
final FFData newFreq = new FFData(cc.flyingFrequencySeconds);
|
||||||
this.freqMap.put(name, newFreq);
|
this.freqMap.put(name, newFreq);
|
||||||
return newFreq;
|
return newFreq;
|
||||||
}
|
}
|
||||||
|
@ -71,40 +86,84 @@ public class FlyingFrequency extends PacketAdapter implements JoinLeaveListener
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketReceiving(final PacketEvent event) {
|
public void onPacketReceiving(final PacketEvent event) {
|
||||||
|
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
if (onNullPlayer(event)) {
|
// TODO: Need config?
|
||||||
event.setCancelled(true);
|
counters.add(idNullPlayer, 1);
|
||||||
}
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: Consider using similar heuristic as CB does for when to count.
|
|
||||||
// TODO: Consider detecting "untracked moves" early.
|
final NetConfig cc = configs.getConfig(player.getWorld());
|
||||||
// TODO: Add more counters/cases (at least has look + has pos individually, maybe none/onground)
|
if (!cc.flyingFrequencyActive) {
|
||||||
final ActionFrequency freq = getFreq(player.getName());
|
return;
|
||||||
freq.add(System.currentTimeMillis(), 1f);
|
}
|
||||||
if (freq.score(1f) > maxPackets) {
|
|
||||||
if (onViolation(player)) {
|
final FFData freq = getFreq(player.getName(), cc);
|
||||||
|
final long t = System.currentTimeMillis();
|
||||||
|
// Counting all packets.
|
||||||
|
freq.all.add(t, 1f);
|
||||||
|
final float allScore = freq.all.score(1f);
|
||||||
|
if (allScore > cc.flyingFrequencyMaxPackets) {
|
||||||
|
counters.add(idSilent, 1); // Until it is sure if we can get these async.
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel redundant packets, when frequency is high anyway.
|
||||||
|
if (!cancelRedundant || !cc.flyingFrequencyCancelRedundant) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: Consider to detect if a moving event would fire (...).
|
||||||
|
boolean redundant = true;
|
||||||
|
final PacketContainer packet = event.getPacket();
|
||||||
|
final List<Boolean> booleans = packet.getBooleans().getValues();
|
||||||
|
if (booleans.size() != FFData.numBooleans) {
|
||||||
|
cancelRedundant = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final boolean onGround = booleans.get(FFData.indexOnGround).booleanValue();
|
||||||
|
if (onGround != freq.onGround) {
|
||||||
|
redundant = false;
|
||||||
|
}
|
||||||
|
freq.onGround = onGround;
|
||||||
|
// TODO: Consider to verify on ground somehow.
|
||||||
|
if (booleans.get(FFData.indexhasPos)) {
|
||||||
|
final List<Double> doubles = packet.getDoubles().getValues();
|
||||||
|
if (doubles.size() != freq.doubles.length) {
|
||||||
|
cancelRedundant = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < freq.doubles.length; i++) {
|
||||||
|
final double val = doubles.get(i).doubleValue();
|
||||||
|
if (val != freq.doubles[i]) {
|
||||||
|
redundant = false;
|
||||||
|
freq.doubles[i] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (booleans.get(FFData.indexhasLook)) {
|
||||||
|
final List<Float> floats = packet.getFloat().getValues();
|
||||||
|
if (floats.size() != freq.floats.length) {
|
||||||
|
cancelRedundant = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < freq.floats.length; i++) {
|
||||||
|
final float val = floats.get(i).floatValue();
|
||||||
|
if (val != freq.floats[i]) {
|
||||||
|
redundant = false;
|
||||||
|
freq.floats[i] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (redundant) {
|
||||||
|
// TODO: Could check first bucket or even just 50 ms to last packet.
|
||||||
|
if (allScore / cc.flyingFrequencySeconds > 20f) {
|
||||||
|
counters.add(idRedundant, 1);
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onViolation(final Player player) {
|
|
||||||
// TODO: Get from a NetConfig (optimized).
|
|
||||||
if (ConfigManager.getConfigFile(player.getWorld().getName()).getBoolean(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE)) {
|
|
||||||
counters.add(idSilent, 1); // Until it is sure if we can get these async.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean onNullPlayer(final PacketEvent event) {
|
|
||||||
// TODO: Config (global?) ?
|
|
||||||
counters.add(idNullPlayer, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||||
|
import fr.neatmonster.nocheatplus.net.NetConfigCache;
|
||||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,8 +26,9 @@ import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||||
* @author dev1mc
|
* @author dev1mc
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class ProtocolLibComponent implements DisableListener, INotifyReload{
|
public class ProtocolLibComponent implements DisableListener, INotifyReload {
|
||||||
|
|
||||||
|
private final NetConfigCache configs = new NetConfigCache();
|
||||||
private final List<PacketAdapter> registeredPacketAdapters = new LinkedList<PacketAdapter>();
|
private final List<PacketAdapter> registeredPacketAdapters = new LinkedList<PacketAdapter>();
|
||||||
|
|
||||||
public ProtocolLibComponent(Plugin plugin) {
|
public ProtocolLibComponent(Plugin plugin) {
|
||||||
|
@ -34,7 +36,7 @@ public class ProtocolLibComponent implements DisableListener, INotifyReload{
|
||||||
register(plugin);
|
register(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void register(Plugin plugin) {
|
private void register(Plugin plugin) {
|
||||||
// Register Classes having a constructor with Plugin as argument.
|
// Register Classes having a constructor with Plugin as argument.
|
||||||
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE)) {
|
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE)) {
|
||||||
register(FlyingFrequency.class, plugin);
|
register(FlyingFrequency.class, plugin);
|
||||||
|
@ -55,7 +57,7 @@ public class ProtocolLibComponent implements DisableListener, INotifyReload{
|
||||||
private void register(Class<? extends PacketAdapter> clazz, Plugin plugin) {
|
private void register(Class<? extends PacketAdapter> clazz, Plugin plugin) {
|
||||||
try {
|
try {
|
||||||
// Construct a new instance using reflection.
|
// Construct a new instance using reflection.
|
||||||
PacketAdapter adapter = clazz.getDeclaredConstructor(Plugin.class).newInstance(plugin);
|
PacketAdapter adapter = clazz.getDeclaredConstructor(Plugin.class).newInstance(configs, plugin);
|
||||||
ProtocolLibrary.getProtocolManager().addPacketListener(adapter);
|
ProtocolLibrary.getProtocolManager().addPacketListener(adapter);
|
||||||
registeredPacketAdapters.add(adapter);
|
registeredPacketAdapters.add(adapter);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -87,6 +89,7 @@ public class ProtocolLibComponent implements DisableListener, INotifyReload{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registeredPacketAdapters.clear();
|
registeredPacketAdapters.clear();
|
||||||
|
configs.clearAllConfigs();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,8 @@ import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
|
|
||||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
import fr.neatmonster.nocheatplus.net.NetConfig;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
import fr.neatmonster.nocheatplus.net.NetConfigCache;
|
||||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
|
||||||
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
import fr.neatmonster.nocheatplus.utilities.TrigUtil;
|
||||||
|
|
||||||
public class SoundDistance extends PacketAdapter {
|
public class SoundDistance extends PacketAdapter {
|
||||||
|
@ -36,14 +35,12 @@ public class SoundDistance extends PacketAdapter {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Maximum distance for thunder effects (squared). */
|
private final NetConfigCache configs;
|
||||||
private final double distSq;
|
private final Location useLoc = new Location(null, 0, 0, 0);
|
||||||
|
|
||||||
public SoundDistance(Plugin plugin) {
|
public SoundDistance(NetConfigCache configs, Plugin plugin) {
|
||||||
super(plugin, PacketType.Play.Server.NAMED_SOUND_EFFECT);
|
super(plugin, PacketType.Play.Server.NAMED_SOUND_EFFECT);
|
||||||
ConfigFile config = ConfigManager.getConfigFile();
|
this.configs = configs;
|
||||||
double dist = config.getDouble(ConfPaths.NET_SOUNDDISTANCE_MAXDISTANCE);
|
|
||||||
distSq = dist * dist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,16 +53,18 @@ public class SoundDistance extends PacketAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
final Location loc = player.getLocation(); // TODO: Use getLocation(useLoc) [synced if async].
|
final NetConfig cc = configs.getConfig(player.getWorld());
|
||||||
|
if (!cc.soundDistanceActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Location loc = player.getLocation(useLoc);
|
||||||
// Compare distance of player to the weather location.
|
// Compare distance of player to the weather location.
|
||||||
final StructureModifier<Integer> ints = packetContainer.getIntegers();
|
final StructureModifier<Integer> ints = packetContainer.getIntegers();
|
||||||
if (TrigUtil.distanceSquared(ints.read(0) / 8, ints.read(2) / 8, loc.getX(), loc.getZ()) > distSq) {
|
if (TrigUtil.distanceSquared(ints.read(0) / 8, ints.read(2) / 8, loc.getX(), loc.getZ()) > cc.soundDistanceSq) {
|
||||||
// TODO: Get from a NetConfig (optimized).
|
event.setCancelled(true);
|
||||||
if (ConfigManager.getConfigFile(player.getWorld().getName()).getBoolean(ConfPaths.NET_SOUNDDISTANCE_ACTIVE)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
useLoc.setWorld(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -598,7 +598,6 @@ public abstract class ConfPaths {
|
||||||
|
|
||||||
private static final String NET_SOUNDDISTANCE = NET + "sounddistance.";
|
private static final String NET_SOUNDDISTANCE = NET + "sounddistance.";
|
||||||
public static final String NET_SOUNDDISTANCE_ACTIVE = NET_SOUNDDISTANCE + "active";
|
public static final String NET_SOUNDDISTANCE_ACTIVE = NET_SOUNDDISTANCE + "active";
|
||||||
@GlobalConfig
|
|
||||||
public static final String NET_SOUNDDISTANCE_MAXDISTANCE = NET_SOUNDDISTANCE + "maxdistance";
|
public static final String NET_SOUNDDISTANCE_MAXDISTANCE = NET_SOUNDDISTANCE + "maxdistance";
|
||||||
|
|
||||||
private static final String NET_FLYINGFREQUENCY = NET + "flyingfrequency.";
|
private static final String NET_FLYINGFREQUENCY = NET + "flyingfrequency.";
|
||||||
|
@ -607,6 +606,7 @@ public abstract class ConfPaths {
|
||||||
public static final String NET_FLYINGFREQUENCY_SECONDS = NET_FLYINGFREQUENCY + "seconds";
|
public static final String NET_FLYINGFREQUENCY_SECONDS = NET_FLYINGFREQUENCY + "seconds";
|
||||||
@GlobalConfig
|
@GlobalConfig
|
||||||
public static final String NET_FLYINGFREQUENCY_MAXPACKETS = NET_FLYINGFREQUENCY + "maxpackets";
|
public static final String NET_FLYINGFREQUENCY_MAXPACKETS = NET_FLYINGFREQUENCY + "maxpackets";
|
||||||
|
public static final String NET_FLYINGFREQUENCY_CANCELREDUNDANT = NET_FLYINGFREQUENCY + "cancelredundant";
|
||||||
|
|
||||||
|
|
||||||
public static final String STRINGS = "strings";
|
public static final String STRINGS = "strings";
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package fr.neatmonster.nocheatplus.config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.utilities.ds.corw.LinkedHashMapCOW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple cache for configurations, adding some convenience functionality.
|
||||||
|
* @author web4web1
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class ConfigCache <K, C> {
|
||||||
|
|
||||||
|
private final Map<K, C> configs;
|
||||||
|
private final boolean cow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param cow Set to true, to use copy-on-write and synchronize writing.
|
||||||
|
* @param initialCapacity
|
||||||
|
*/
|
||||||
|
public ConfigCache(boolean cow, int initialCapacity) {
|
||||||
|
this.cow = cow;
|
||||||
|
// Linked or not linked ?
|
||||||
|
if (cow) {
|
||||||
|
configs = new LinkedHashMapCOW<K, C>(initialCapacity);
|
||||||
|
} else {
|
||||||
|
configs = new HashMap<K, C>(initialCapacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasConfig(final K key) {
|
||||||
|
return configs.containsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public C getConfig(final K key) {
|
||||||
|
final C config = configs.get(key);
|
||||||
|
if (config == null) {
|
||||||
|
return createConfig(key);
|
||||||
|
} else {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private C createConfig(final K key) {
|
||||||
|
final C config = newConfig(key);
|
||||||
|
if (!cow) {
|
||||||
|
configs.put(key, config);
|
||||||
|
return config;
|
||||||
|
} else {
|
||||||
|
return addConfigCOW(key, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private C addConfigCOW(final K key, final C config) {
|
||||||
|
// Re-check to ensure FCFS.
|
||||||
|
synchronized (configs) {
|
||||||
|
if (configs.containsKey(key)) {
|
||||||
|
return configs.get(key);
|
||||||
|
} else {
|
||||||
|
configs.put(key, config);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAllConfigs() {
|
||||||
|
configs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method. In case of cow, not all returned instances might be used.
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected abstract C newConfig(final K key);
|
||||||
|
|
||||||
|
}
|
|
@ -435,6 +435,7 @@ public class DefaultConfig extends ConfigFile {
|
||||||
set(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE, true);
|
set(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE, true);
|
||||||
set(ConfPaths.NET_FLYINGFREQUENCY_SECONDS, 5);
|
set(ConfPaths.NET_FLYINGFREQUENCY_SECONDS, 5);
|
||||||
set(ConfPaths.NET_FLYINGFREQUENCY_MAXPACKETS, 300);
|
set(ConfPaths.NET_FLYINGFREQUENCY_MAXPACKETS, 300);
|
||||||
|
set(ConfPaths.NET_FLYINGFREQUENCY_CANCELREDUNDANT, true);
|
||||||
|
|
||||||
// SoundDistance
|
// SoundDistance
|
||||||
set(ConfPaths.NET_SOUNDDISTANCE_ACTIVE, true);
|
set(ConfPaths.NET_SOUNDDISTANCE_ACTIVE, true);
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package fr.neatmonster.nocheatplus.config;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* World-specific cache for configurations. World names are used as keys, convenience methods are added.
|
||||||
|
* @author web4web1
|
||||||
|
*
|
||||||
|
* @param <C>
|
||||||
|
*/
|
||||||
|
public abstract class WorldConfigCache<C> extends ConfigCache<String, C> {
|
||||||
|
|
||||||
|
public WorldConfigCache(boolean cow) {
|
||||||
|
this(cow, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldConfigCache(boolean cow, int initialCapacity) {
|
||||||
|
super(cow, initialCapacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public C getConfig(final World world) {
|
||||||
|
return getConfig(world.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected C newConfig(final String key) {
|
||||||
|
return newConfig(key, ConfigManager.getConfigFile(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract C newConfig(String key, ConfigFile configFile);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package fr.neatmonster.nocheatplus.net;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||||
|
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||||
|
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for the net checks (fast version, sparse).
|
||||||
|
* @author web4web1
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class NetConfig {
|
||||||
|
|
||||||
|
public final boolean flyingFrequencyActive;
|
||||||
|
public final int flyingFrequencySeconds;
|
||||||
|
public final int flyingFrequencyMaxPackets;
|
||||||
|
public final boolean flyingFrequencyCancelRedundant;
|
||||||
|
|
||||||
|
public final boolean soundDistanceActive;
|
||||||
|
/** Maximum distance for lightning effects (squared). */
|
||||||
|
public final double soundDistanceSq;
|
||||||
|
|
||||||
|
public NetConfig(final ConfigFile config) {
|
||||||
|
|
||||||
|
final ConfigFile globalConfig = ConfigManager.getConfigFile();
|
||||||
|
flyingFrequencyActive = config.getBoolean(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE);
|
||||||
|
flyingFrequencySeconds = Math.max(1, globalConfig.getInt(ConfPaths.NET_FLYINGFREQUENCY_SECONDS));
|
||||||
|
flyingFrequencyMaxPackets = Math.max(1, globalConfig.getInt(ConfPaths.NET_FLYINGFREQUENCY_MAXPACKETS));
|
||||||
|
flyingFrequencyCancelRedundant = config.getBoolean(ConfPaths.NET_FLYINGFREQUENCY_CANCELREDUNDANT);
|
||||||
|
|
||||||
|
soundDistanceActive = config.getBoolean(ConfPaths.NET_SOUNDDISTANCE_ACTIVE);
|
||||||
|
double dist = config.getDouble(ConfPaths.NET_SOUNDDISTANCE_MAXDISTANCE);
|
||||||
|
soundDistanceSq = dist * dist;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package fr.neatmonster.nocheatplus.net;
|
||||||
|
|
||||||
|
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||||
|
import fr.neatmonster.nocheatplus.config.WorldConfigCache;
|
||||||
|
|
||||||
|
public class NetConfigCache extends WorldConfigCache<NetConfig> {
|
||||||
|
|
||||||
|
public NetConfigCache() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected NetConfig newConfig(String key, ConfigFile configFile) {
|
||||||
|
return new NetConfig(configFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user