[BROKEN] Data storage overhaul (basics). (+)

(SAFETY COMMIT)

Largely breaking change.
* Interfaces in front of data types (and 'managers'), some interfaces
removed.
* Data and configuration fetching.
* Check activation checking (config flags, isEnabled, hasBypass).
* CheckType (activation checks, factories removed).
* Lots of collateral signature changes, including IPlayerData.

The (I)WorldDataManager stores per-world data (+ per world per check
type).
* Raw configurations.
* Typical flags: check activation, debug, lag adaption.
* Generic data, such as check configurations or per world check data.

The (I)PlayerDataManager stores per player data.
* Check Data.
* Typical flags: debug
* Exemption
* Check data (and config cache).
* Further mappings and later OfflinePlayerData.
* The registration interface will allow defining, how instances are
handled for registered types (factory, proxy, what on world change, what
on logout, global removal handler, per player removal handler).

(I)PlayerData is intended to be/become the central access point.
* External interface is IPlayerData now.
* Per player debug flags, exemptions.
* Fetching configuration and data: local cache, relaying fetching to
registered factories and proxy-registries/storage (e.g. fetching
configuration from per world storage).

Other fixes/changes:
(+) Extend the debug player command (set true/false, reset to world
default, arbitrary check types).
(+) PlayerData maintains a currentWorldIdentifier (to be used instead of
ChatData in future).
(+) The WorldConfigProvider getAll implementation returns a
LinkedHashSet now, avoiding duplicates.
(+) Move DefaultGenericInstanceRegistry to NCPCore.
(+) Thread-safety considerations for DefaultGenericInstanceRegistry.
(+) Don't log errors on hasBypass checking. TBD: Instead intercept
during listener methods (or even as a feature within the listener node:
e.g. @ThreadContext(primaryThread=true, skipOffContext=true,
cancelOffContext=true).
(+) Add fight.wrongturn permissions to plugin.yml.
(+) Missing GPLv3 headers.

Broken/Missing:
* WorldData inheritance from default: propagate all changes done
directly to the default config to children (all worlds that don't have
an explicit world_config.yml set) - possibly add an OverrideState or
similar, (NONE, FROM_DEFAULT, EXPLICIT) and don't override EXPLICIT if
coming from the default. Calling override on the default WorldData is
not to be confused with calling override for WorldDataManager (override
for all worlds as EXPLICIT).
* Organize overriding for special circumstances (version dependent
activation  and the like). Might want to add registered override
handlers to be called on reload automatically.
* Store generic per check type per world data in the WorldDataManager,
such as configurations and per-world check data. TBD: Factories, cleanup
(!).
* Most efficient referencing (IWorldCheckTypeNode, IHandle<something>?).
* All the registry stuff (see PlayerData).
* Use interfaces for auto registry (and a flag within
RegistrationContext?) - world unload, world change, player join / leave.
* (Data expiration handling including transition to IOfflinePlayerData,
because now data is a little heavier.)
* Further details.
This commit is contained in:
asofold 2018-02-13 15:15:23 +01:00
commit 30902ec352
167 changed files with 6752 additions and 4479 deletions

View File

@ -276,6 +276,38 @@ public class ActionFrequency {
return buffer.toString(); return buffer.toString();
} }
/**
* Update and then reduce all given ActionFrequency instances by the given
* amount, capped at a maximum of 0 for the resulting first bucket score.
*
* @param amount
* The amount to subtract.
* @param freqs
*/
public static void reduce(final long time, final float amount, final ActionFrequency... freqs) {
for (int i = 0; i < freqs.length; i++) {
final ActionFrequency freq = freqs[i];
freq.update(time);
freq.setBucket(0, Math.max(0f, freq.bucketScore(0) - amount));
}
}
/**
* Update and then reduce all given ActionFrequency instances by the given
* amount, without capping the result.
*
* @param amount
* The amount to subtract.
* @param freqs
*/
public static void subtract(final long time, final float amount, final ActionFrequency... freqs) {
for (int i = 0; i < freqs.length; i++) {
final ActionFrequency freq = freqs[i];
freq.update(time);
freq.setBucket(0, freq.bucketScore(0) - amount);
}
}
/** /**
* Deserialize from a string. * Deserialize from a string.
* @param line * @param line

View File

@ -321,7 +321,7 @@ public class HashMapLOW <K, V> {
private LHMEntry<K, V> currentEntry = null; private LHMEntry<K, V> currentEntry = null;
private K lastReturnedKey = null; private K lastReturnedKey = null;
public LHMIterator(HashMapLOW<K, V> map, LHMBucket<K, V>[] buckets) { LHMIterator(HashMapLOW<K, V> map, LHMBucket<K, V>[] buckets) {
this.map = map; this.map = map;
this.buckets = buckets; this.buckets = buckets;
// (Lazily advance.) // (Lazily advance.)
@ -412,6 +412,21 @@ public class HashMapLOW <K, V> {
} }
static class LHMIterable<K, V> implements Iterable<Entry<K,V>> {
private final Iterator<Entry<K, V>> iterator;
LHMIterable(Iterator<Entry<K, V>> iterator) {
this.iterator = iterator;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return iterator;
}
}
/////////////////////// ///////////////////////
// Instance members // Instance members
@ -697,6 +712,16 @@ public class HashMapLOW <K, V> {
return size == 0 ? new LHMIterator<K, V>(null, null) : new LHMIterator<K, V>(this, buckets); return size == 0 ? new LHMIterator<K, V>(null, null) : new LHMIterator<K, V>(this, buckets);
} }
/**
* Get an Iterable containing the same iterator, as is returned by
* iterator(). See: {@link #iterator()}
*
* @return
*/
public Iterable<Entry<K, V>> iterable() {
return new LHMIterable<K, V>(iterator());
}
/** /**
* Get all keys as a LinkedHashSet fit for iteration. The returned set is a * Get all keys as a LinkedHashSet fit for iteration. The returned set is a
* new instance, so changes don't affect the original HashMapLOW instance. * new instance, so changes don't affect the original HashMapLOW instance.

View File

@ -27,12 +27,13 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
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.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.BridgeHealth; import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.components.config.value.OverrideType;
import fr.neatmonster.nocheatplus.components.registry.feature.INotifyReload; import fr.neatmonster.nocheatplus.components.registry.feature.INotifyReload;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil; import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -62,7 +63,9 @@ public class FastConsume extends Check implements Listener, INotifyReload {
private void disableInstantEat() { private void disableInstantEat() {
// TODO: Do this kind of thing via registries later on. // TODO: Do this kind of thing via registries later on.
ConfigManager.setForAllConfigs(ConfPaths.INVENTORY_INSTANTEAT_CHECK, false); //ConfigManager.setForAllConfigs(ConfPaths.INVENTORY_INSTANTEAT_CHECK, false);
NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager().overrideCheckActivation(
this.type, AlmostBoolean.NO, OverrideType.PERMANENT, true);
StaticLog.logInfo("Inventory checks: FastConsume is available, disabled InstantEat."); StaticLog.logInfo("Inventory checks: FastConsume is available, disabled InstantEat.");
} }
@ -75,18 +78,20 @@ public class FastConsume extends Check implements Listener, INotifyReload {
counters.addPrimaryThread(idCancelDead, 1); counters.addPrimaryThread(idCancelDead, 1);
return; return;
} }
if (!isEnabled(player)) { final IPlayerData pData = DataManager.getPlayerData(player);
if (!pData.isCheckActive(type, player)) {
return; return;
} }
final InventoryData data = InventoryData.getData(player); final InventoryData data = pData.getGenericInstance(InventoryData.class);
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
if (check(player, event.getItem(), time, data)){ if (check(player, event.getItem(), time, data, pData)){
event.setCancelled(true); event.setCancelled(true);
DataManager.getPlayerData(player).requestUpdateInventory(); DataManager.getPlayerData(player).requestUpdateInventory();
} }
} }
private boolean check(final Player player, final ItemStack stack, final long time, final InventoryData data){ private boolean check(final Player player, final ItemStack stack,
final long time, final InventoryData data, final IPlayerData pData){
// Uses the instant-eat data for convenience. // Uses the instant-eat data for convenience.
// Consistency checks... // Consistency checks...
if (stack == null){ // || stack.getType() != data.instantEatFood){ if (stack == null){ // || stack.getType() != data.instantEatFood){
@ -100,7 +105,7 @@ public class FastConsume extends Check implements Listener, INotifyReload {
return false; return false;
} }
// Check exceptions. // Check exceptions.
final InventoryConfig cc = InventoryConfig.getConfig(player); final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
final Material mat = stack == null ? null : stack.getType(); final Material mat = stack == null ? null : stack.getType();
if (mat != null){ if (mat != null){
if (cc.fastConsumeWhitelist){ if (cc.fastConsumeWhitelist){
@ -144,8 +149,9 @@ public class FastConsume extends Check implements Listener, INotifyReload {
final ItemStack actualStack = InventoryUtil.getFirstConsumableItemInHand(player); final ItemStack actualStack = InventoryUtil.getFirstConsumableItemInHand(player);
data.instantEatFood = actualStack == null ? null : actualStack.getType(); data.instantEatFood = actualStack == null ? null : actualStack.getType();
// TODO: Allows some abuse: 1. try instantly eat (cancelled) 2. consume item directly when needed. // TODO: Allows some abuse: 1. try instantly eat (cancelled) 2. consume item directly when needed.
} else { }
if (data.debug) { else {
if (pData.isDebugActive(type)) {
debug(player, "PlayerItemConsumeEvent, reset fastconsume: " + data.instantEatFood); debug(player, "PlayerItemConsumeEvent, reset fastconsume: " + data.instantEatFood);
} }
data.instantEatFood = null; data.instantEatFood = null;

View File

@ -23,6 +23,8 @@ import org.bukkit.inventory.meta.BookMeta;
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.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
public class Gutenberg extends Check implements Listener { public class Gutenberg extends Check implements Listener {
@ -42,7 +44,8 @@ public class Gutenberg extends Check implements Listener {
if (!isEnabled(player)) { if (!isEnabled(player)) {
return; return;
} }
final InventoryConfig cc = InventoryConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
final BookMeta newMeta = event.getNewBookMeta(); final BookMeta newMeta = event.getNewBookMeta();
final int pages = newMeta.getPageCount(); final int pages = newMeta.getPageCount();
if (pages <= 50) { if (pages <= 50) {

View File

@ -33,6 +33,7 @@ import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache; import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache; import fr.neatmonster.nocheatplus.utilities.map.WrapBlockCache;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Hot fix for 1.9 and 1.10 (possibly later?): falling block duplication via end * Hot fix for 1.9 and 1.10 (possibly later?): falling block duplication via end
@ -87,7 +88,8 @@ public class HotFixFallingBlockPortalEnter implements Listener {
if (mat != null) { if (mat != null) {
final Location loc = entity.getLocation(useLoc); final Location loc = entity.getLocation(useLoc);
final World world = loc.getWorld(); final World world = loc.getWorld();
if (InventoryConfig.getConfig(world).hotFixFallingBlockEndPortalActive) { final IWorldData worldData = NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager().getWorldData(world);
if (worldData.getGenericInstance(InventoryConfig.class).hotFixFallingBlockEndPortalActive) {
final BlockCache blockCache = wrapBlockCache.getBlockCache(); final BlockCache blockCache = wrapBlockCache.getBlockCache();
blockCache.setAccess(world); blockCache.setAccess(world);
final boolean nearbyPortal = BlockProperties.collidesId(blockCache, loc.getX() - 2.0, loc.getY() - 2.0, loc.getZ() - 2.0, loc.getX() + 3.0, loc.getY() + 3.0, loc.getZ() + 3.0, Material.ENDER_PORTAL); final boolean nearbyPortal = BlockProperties.collidesId(blockCache, loc.getX() - 2.0, loc.getY() - 2.0, loc.getZ() - 2.0, loc.getX() + 3.0, loc.getY() + 3.0, loc.getZ() + 3.0, Material.ENDER_PORTAL);

View File

@ -24,8 +24,6 @@ import com.comphenix.protocol.events.PacketAdapter;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.NetConfigCache;
import fr.neatmonster.nocheatplus.checks.net.NetDataFactory;
import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer; import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
@ -38,8 +36,6 @@ import fr.neatmonster.nocheatplus.utilities.CheckUtils;
public abstract class BaseAdapter extends PacketAdapter implements IDebugPlayer { public abstract class BaseAdapter extends PacketAdapter implements IDebugPlayer {
protected final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class); protected final Counters counters = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(Counters.class);
protected final NetConfigCache configFactory = (NetConfigCache) CheckType.NET.getConfigFactory();
protected final NetDataFactory dataFactory = (NetDataFactory) CheckType.NET.getDataFactory();
/** Override for specific output on the debug method. */ /** Override for specific output on the debug method. */
protected CheckType checkType = CheckType.NET; protected CheckType checkType = CheckType.NET;

View File

@ -27,10 +27,9 @@ import com.comphenix.protocol.events.PacketEvent;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.net.NetConfig; import fr.neatmonster.nocheatplus.checks.net.NetConfig;
import fr.neatmonster.nocheatplus.checks.net.NetData; import fr.neatmonster.nocheatplus.checks.net.NetData;
import fr.neatmonster.nocheatplus.checks.net.NetStatic;
import fr.neatmonster.nocheatplus.checks.net.PacketFrequency; import fr.neatmonster.nocheatplus.checks.net.PacketFrequency;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* Pre-1.9. * Pre-1.9.
@ -74,22 +73,12 @@ public class CatchAllAdapter extends BaseAdapter {
// TODO: Is this a problem, as the server has the player so it could break a block)? // TODO: Is this a problem, as the server has the player so it could break a block)?
return; return;
} }
final NetConfig cc; final IPlayerData pData = DataManager.getPlayerData(player);
try { if (packetFrequency.isEnabled(player, pData)) {
cc = NetStatic.getWorldConfig(player, configFactory, dataFactory); final NetConfig cc = pData.getGenericInstance(NetConfig.class);
} final NetData data = pData.getGenericInstance(NetData.class);
catch (UnsupportedOperationException e) { if (packetFrequency.check(player, data, cc)) {
// Legacy +-. event.setCancelled(true);
// TODO: Get from PlayerData, once HashMapLOW is used.
return;
}
if (cc.packetFrequencyActive) {
final PlayerData pData = DataManager.getPlayerData(player);
if (packetFrequency.isEnabled(player, cc, pData)) {
final NetData data = dataFactory.getData(player);
if (packetFrequency.check(player, data, cc)) {
event.setCancelled(true);
}
} }
} }
} }

View File

@ -21,6 +21,9 @@ import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority; import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.events.PacketEvent;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.players.DataManager;
public class DebugAdapter extends BaseAdapter { public class DebugAdapter extends BaseAdapter {
public DebugAdapter(Plugin plugin) { public DebugAdapter(Plugin plugin) {
@ -33,7 +36,7 @@ public class DebugAdapter extends BaseAdapter {
@Override @Override
public void onPacketReceiving(PacketEvent event) { public void onPacketReceiving(PacketEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
if (dataFactory.getData(player).debug) { if (DataManager.getPlayerData(player).isDebugActive(CheckType.NET)) {
debug(player, "packet: " + event.getPacketType()); debug(player, "packet: " + event.getPacketType());
} }
} }

View File

@ -24,13 +24,12 @@ import com.comphenix.protocol.events.ListenerPriority;
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.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.KeepAliveFrequency; import fr.neatmonster.nocheatplus.checks.net.KeepAliveFrequency;
import fr.neatmonster.nocheatplus.checks.net.NetConfig; import fr.neatmonster.nocheatplus.checks.net.NetConfig;
import fr.neatmonster.nocheatplus.checks.net.NetData; import fr.neatmonster.nocheatplus.checks.net.NetData;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* Limit keep alive packet frequency, set lastKeepAliveTime (even if disabled, * Limit keep alive packet frequency, set lastKeepAliveTime (even if disabled,
@ -46,10 +45,12 @@ public class KeepAliveAdapter extends BaseAdapter {
public KeepAliveAdapter(Plugin plugin) { public KeepAliveAdapter(Plugin plugin) {
super(plugin, ListenerPriority.LOW, PacketType.Play.Client.KEEP_ALIVE); super(plugin, ListenerPriority.LOW, PacketType.Play.Client.KEEP_ALIVE);
this.checkType = CheckType.NET_KEEPALIVEFREQUENCY;
// Add feature tags for checks. // Add feature tags for checks.
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_KEEPALIVEFREQUENCY_ACTIVE)) { if (NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager().isActiveAnywhere(
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(KeepAliveFrequency.class.getSimpleName())); CheckType.NET_KEEPALIVEFREQUENCY)) {
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags(
"checks", Arrays.asList(KeepAliveFrequency.class.getSimpleName()));
} }
NCPAPIProvider.getNoCheatPlusAPI().addComponent(frequencyCheck); NCPAPIProvider.getNoCheatPlusAPI().addComponent(frequencyCheck);
} }
@ -64,16 +65,17 @@ public class KeepAliveAdapter extends BaseAdapter {
return; return;
} }
// Always update last received time. // Always update last received time.
final PlayerData pData = DataManager.getPlayerData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final NetData data = dataFactory.getData(player); final NetData data = pData.getGenericInstance(NetData.class);
data.lastKeepAliveTime = time; data.lastKeepAliveTime = time;
final NetConfig cc = configFactory.getConfig(player); final NetConfig cc = pData.getGenericInstance(NetConfig.class);
// Run check(s). // Run check(s).
// TODO: Match vs. outgoing keep alive requests. // TODO: Match vs. outgoing keep alive requests.
// TODO: Better modeling of actual packet sequences (flying vs. keep alive vs. request/ping). // TODO: Better modeling of actual packet sequences (flying vs. keep alive vs. request/ping).
// TODO: Better integration with god-mode check / trigger reset ndt. // TODO: Better integration with god-mode check / trigger reset ndt.
if (cc.keepAliveFrequencyActive && frequencyCheck.check(player, time, data, cc, pData)) { if (frequencyCheck.isEnabled(player, pData)
&& frequencyCheck.check(player, time, data, cc, pData)) {
event.setCancelled(true); event.setCancelled(true);
} }
} }

View File

@ -33,6 +33,7 @@ import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.reflect.StructureModifier;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.FlyingFrequency; import fr.neatmonster.nocheatplus.checks.net.FlyingFrequency;
import fr.neatmonster.nocheatplus.checks.net.NetConfig; import fr.neatmonster.nocheatplus.checks.net.NetConfig;
import fr.neatmonster.nocheatplus.checks.net.NetData; import fr.neatmonster.nocheatplus.checks.net.NetData;
@ -40,16 +41,16 @@ import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying.PACKET_CONTENT; import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying.PACKET_CONTENT;
import fr.neatmonster.nocheatplus.checks.net.model.TeleportQueue.AckReference; import fr.neatmonster.nocheatplus.checks.net.model.TeleportQueue.AckReference;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean; import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.logging.Streams; import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.time.monotonic.Monotonic; import fr.neatmonster.nocheatplus.time.monotonic.Monotonic;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil; import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Run checks related to moving (pos/look/flying). Skip packets that shouldn't * Run checks related to moving (pos/look/flying). Skip packets that shouldn't
@ -110,10 +111,12 @@ public class MovingFlying extends BaseAdapter {
public MovingFlying(Plugin plugin) { public MovingFlying(Plugin plugin) {
// PacketPlayInFlying[3, legacy: 10] // PacketPlayInFlying[3, legacy: 10]
super(plugin, ListenerPriority.LOW, initPacketTypes()); super(plugin, ListenerPriority.LOW, initPacketTypes());
// Keep the CheckType NET for now.
// Add feature tags for checks. // Add feature tags for checks.
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE)) { if (NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager().isActiveAnywhere(
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(FlyingFrequency.class.getSimpleName())); CheckType.NET_FLYINGFREQUENCY)) {
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags(
"checks", Arrays.asList(FlyingFrequency.class.getSimpleName()));
} }
NCPAPIProvider.getNoCheatPlusAPI().addComponent(flyingFrequency); NCPAPIProvider.getNoCheatPlusAPI().addComponent(flyingFrequency);
} }
@ -155,12 +158,13 @@ public class MovingFlying extends BaseAdapter {
return; return;
} }
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final NetData data = dataFactory.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final NetData data = pData.getGenericInstance(NetData.class);
final AlmostBoolean matched = data.teleportQueue.processAck(teleportId); final AlmostBoolean matched = data.teleportQueue.processAck(teleportId);
if (matched.decideOptimistically()) { if (matched.decideOptimistically()) {
CheckUtils.subtract(System.currentTimeMillis(), 1, data.flyingFrequencyAll); ActionFrequency.subtract(System.currentTimeMillis(), 1, data.flyingFrequencyAll);
} }
if (data.debug) { if (pData.isDebugActive(this.checkType)) { // TODO: FlyingFrequency / NET_MOVING? + check others who depend
debug(player, "Confirm teleport packet" + (matched.decideOptimistically() ? (" (matched=" + matched + ")") : "") + ": " + teleportId); debug(player, "Confirm teleport packet" + (matched.decideOptimistically() ? (" (matched=" + matched + ")") : "") + ": " + teleportId);
} }
} }
@ -191,14 +195,17 @@ public class MovingFlying extends BaseAdapter {
return; return;
} }
final NetConfig cc = configFactory.getConfig(player.getWorld()); final IPlayerData pData = DataManager.getPlayerData(player);
// Always update last received time. // Always update last received time.
final NetData data = dataFactory.getData(player); final NetData data = pData.getGenericInstance(NetData.class);
data.lastKeepAliveTime = time; // Update without much of a contract. data.lastKeepAliveTime = time; // Update without much of a contract.
// TODO: Leniency options too (packet order inversion). -> current: flyingQueue is fetched. // TODO: Leniency options too (packet order inversion). -> current: flyingQueue is fetched.
if (!cc.flyingFrequencyActive) { final IWorldData worldData = pData.getCurrentWorldDataSafe();
if (!worldData.isCheckActive(CheckType.NET_FLYINGFREQUENCY)) {
return; return;
} }
final NetConfig cc = pData.getGenericInstance(NetConfig.class);
boolean cancel = false; boolean cancel = false;
// Interpret the packet content. // Interpret the packet content.
@ -211,14 +218,14 @@ public class MovingFlying extends BaseAdapter {
if (isInvalidContent(packetData)) { if (isInvalidContent(packetData)) {
// TODO: extra actions: log and kick (cancel state is not evaluated) // TODO: extra actions: log and kick (cancel state is not evaluated)
event.setCancelled(true); event.setCancelled(true);
if (data.debug) { if (pData.isDebugActive(this.checkType)) {
debug(player, "Incoming packet, cancel due to malicious content: " + packetData.toString()); debug(player, "Incoming packet, cancel due to malicious content: " + packetData.toString());
} }
return; return;
} }
switch(data.teleportQueue.processAck(packetData)) { switch(data.teleportQueue.processAck(packetData)) {
case WAITING: { case WAITING: {
if (data.debug) { if (pData.isDebugActive(this.checkType)) {
debug(player, "Incoming packet, still waiting for ACK on outgoing position."); debug(player, "Incoming packet, still waiting for ACK on outgoing position.");
} }
if (confirmTeleportType != null && cc.supersededFlyingCancelWaiting) { if (confirmTeleportType != null && cc.supersededFlyingCancelWaiting) {
@ -250,7 +257,7 @@ public class MovingFlying extends BaseAdapter {
case ACK: { case ACK: {
// Skip processing ACK packets, no cancel. // Skip processing ACK packets, no cancel.
skipFlyingFrequency = true; skipFlyingFrequency = true;
if (data.debug) { if (pData.isDebugActive(this.checkType)) {
debug(player, "Incoming packet, interpret as ACK for outgoing position."); debug(player, "Incoming packet, interpret as ACK for outgoing position.");
} }
} }
@ -267,8 +274,8 @@ public class MovingFlying extends BaseAdapter {
// Actual packet frequency check. // Actual packet frequency check.
// TODO: Consider using the NetStatic check. // TODO: Consider using the NetStatic check.
final PlayerData pData = DataManager.getPlayerData(player);
if (!cancel && !skipFlyingFrequency if (!cancel && !skipFlyingFrequency
&& !pData.hasBypass(CheckType.NET_FLYINGFREQUENCY, player)
&& flyingFrequency.check(player, packetData, time, data, cc, pData)) { && flyingFrequency.check(player, packetData, time, data, cc, pData)) {
cancel = true; cancel = true;
} }
@ -285,7 +292,7 @@ public class MovingFlying extends BaseAdapter {
if (cancel) { if (cancel) {
event.setCancelled(true); event.setCancelled(true);
} }
if (data.debug) { if (pData.isDebugActive(this.checkType)) {
debug(player, (packetData == null ? "(Incompatible data)" : packetData.toString()) + (event.isCancelled() ? " CANCEL" : "")); debug(player, (packetData == null ? "(Incompatible data)" : packetData.toString()) + (event.isCancelled() ? " CANCEL" : ""));
} }
} }

View File

@ -24,9 +24,12 @@ import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.reflect.StructureModifier;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.NetData; import fr.neatmonster.nocheatplus.checks.net.NetData;
import fr.neatmonster.nocheatplus.checks.net.model.CountableLocation; import fr.neatmonster.nocheatplus.checks.net.model.CountableLocation;
import fr.neatmonster.nocheatplus.logging.Streams; import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
public class OutgoingPosition extends BaseAdapter { public class OutgoingPosition extends BaseAdapter {
@ -37,7 +40,7 @@ public class OutgoingPosition extends BaseAdapter {
public static final int indexPitch = 1; public static final int indexPitch = 1;
private final Integer ID_OUTGOING_POSITION_UNTRACKED = counters.registerKey("packet.outgoing_position.untracked"); private final Integer ID_OUTGOING_POSITION_UNTRACKED = counters.registerKey("packet.outgoing_position.untracked");
private boolean hasTeleportId = true; private boolean hasTeleportId = true;
public OutgoingPosition(Plugin plugin) { public OutgoingPosition(Plugin plugin) {
@ -55,12 +58,17 @@ public class OutgoingPosition extends BaseAdapter {
} }
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
final Player player = event.getPlayer(); final Player player = event.getPlayer();
if (configFactory.getConfig(player).flyingFrequencyActive) { final IPlayerData pData = DataManager.getPlayerData(player);
interpretPacket(player, event.getPacket(), time, dataFactory.getData(player)); // TODO: In future multiple checks might use this (!)
if (pData.isCheckActive(CheckType.NET_FLYINGFREQUENCY, player)) {
interpretPacket(player, event.getPacket(), time,
pData.getGenericInstance(NetData.class),
pData.isDebugActive(CheckType.NET_FLYINGFREQUENCY));
} }
} }
private void interpretPacket(final Player player, final PacketContainer packet, final long time, final NetData data) { private void interpretPacket(final Player player, final PacketContainer packet,
final long time, final NetData data, final boolean debug) {
final StructureModifier<Double> doubles = packet.getDoubles(); final StructureModifier<Double> doubles = packet.getDoubles();
final StructureModifier<Float> floats = packet.getFloat(); final StructureModifier<Float> floats = packet.getFloat();
@ -78,7 +86,7 @@ public class OutgoingPosition extends BaseAdapter {
final float yaw = floats.read(indexYaw); final float yaw = floats.read(indexYaw);
final float pitch = floats.read(indexPitch); final float pitch = floats.read(indexPitch);
Integer teleportId = Integer.MIN_VALUE; Integer teleportId = Integer.MIN_VALUE;
if (hasTeleportId) { if (hasTeleportId) {
try { try {
final StructureModifier<Integer> integers = packet.getIntegers(); final StructureModifier<Integer> integers = packet.getIntegers();
@ -88,7 +96,7 @@ public class OutgoingPosition extends BaseAdapter {
if (teleportId == null) { if (teleportId == null) {
teleportId = Integer.MIN_VALUE; teleportId = Integer.MIN_VALUE;
} }
if (teleportId != Integer.MIN_VALUE && data.debug) { if (teleportId != Integer.MIN_VALUE && debug) {
debug(player, "Outgoing confirm teleport id: " + teleportId); debug(player, "Outgoing confirm teleport id: " + teleportId);
} }
} }
@ -108,12 +116,12 @@ public class OutgoingPosition extends BaseAdapter {
// Add counter for untracked (by Bukkit API) outgoing teleport. // Add counter for untracked (by Bukkit API) outgoing teleport.
// TODO: There may be other cases which are indicated by Bukkit API events. // TODO: There may be other cases which are indicated by Bukkit API events.
counters.add(ID_OUTGOING_POSITION_UNTRACKED, 1); counters.add(ID_OUTGOING_POSITION_UNTRACKED, 1);
if (data.debug) { if (debug) {
debug(player, "Untracked outgoing position: " + x + ", " + y + ", " + z + " (yaw=" + yaw + ", pitch=" + pitch + ")."); debug(player, "Untracked outgoing position: " + x + ", " + y + ", " + z + " (yaw=" + yaw + ", pitch=" + pitch + ").");
} }
} }
else { else {
if (data.debug) { if (debug) {
debug(player, "Expect ACK on outgoing position: " + packetData); debug(player, "Expect ACK on outgoing position: " + packetData);
} }
} }

View File

@ -37,10 +37,7 @@ import com.comphenix.protocol.events.PacketAdapter;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.NetConfig;
import fr.neatmonster.nocheatplus.checks.net.NetConfigCache;
import fr.neatmonster.nocheatplus.checks.net.NetData; import fr.neatmonster.nocheatplus.checks.net.NetData;
import fr.neatmonster.nocheatplus.checks.net.NetDataFactory;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion; import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI; import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI;
import fr.neatmonster.nocheatplus.components.registry.feature.IDisableListener; import fr.neatmonster.nocheatplus.components.registry.feature.IDisableListener;
@ -50,8 +47,11 @@ 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.logging.Streams; import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.worlds.IWorldDataManager;
/** /**
* Quick and dirty ProtocolLib setup. * Quick and dirty ProtocolLib setup.
@ -89,15 +89,17 @@ public class ProtocolLibComponent implements IDisableListener, INotifyReload, Jo
private final List<PacketAdapter> registeredPacketAdapters = new LinkedList<PacketAdapter>(); private final List<PacketAdapter> registeredPacketAdapters = new LinkedList<PacketAdapter>();
protected final NetConfigCache configFactory = (NetConfigCache) CheckType.NET.getConfigFactory();
protected final NetDataFactory dataFactory = (NetDataFactory) CheckType.NET.getDataFactory();
public ProtocolLibComponent(Plugin plugin) { public ProtocolLibComponent(Plugin plugin) {
register(plugin); register(plugin);
/*
* TODO: Register listeners iff any check is enabled - unregister from
* EventRegistry with unregister.
*/
} }
private void register(Plugin plugin) { private void register(Plugin plugin) {
StaticLog.logInfo("Adding packet level hooks for ProtocolLib (MC " + ProtocolLibrary.getProtocolManager().getMinecraftVersion().getVersion() + ")..."); StaticLog.logInfo("Adding packet level hooks for ProtocolLib (MC " + ProtocolLibrary.getProtocolManager().getMinecraftVersion().getVersion() + ")...");
final IWorldDataManager worldMan = NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager();
//Special purpose. //Special purpose.
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET + ConfPaths.SUB_DEBUG) || ConfigManager.isTrueForAnyConfig(ConfPaths.CHECKS_DEBUG) ) { if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET + ConfPaths.SUB_DEBUG) || ConfigManager.isTrueForAnyConfig(ConfPaths.CHECKS_DEBUG) ) {
// (Debug logging. Only activates if debug is set for checks or checks.net, not on the fly.) // (Debug logging. Only activates if debug is set for checks or checks.net, not on the fly.)
@ -108,25 +110,29 @@ public class ProtocolLibComponent implements IDisableListener, INotifyReload, Jo
// Don't use this listener. // Don't use this listener.
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "Disable EntityUseAdapter due to incompatibilities. Use fight.speed instead of net.attackfrequency."); NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "Disable EntityUseAdapter due to incompatibilities. Use fight.speed instead of net.attackfrequency.");
} }
else if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE)) { else if (worldMan.isActiveAnywhere(CheckType.NET_ATTACKFREQUENCY)) {
// (Also sets lastKeepAliveTime, if enabled.) // (Also sets lastKeepAliveTime, if enabled.)
register("fr.neatmonster.nocheatplus.checks.net.protocollib.UseEntityAdapter", plugin); register("fr.neatmonster.nocheatplus.checks.net.protocollib.UseEntityAdapter", plugin);
} }
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_FLYINGFREQUENCY_ACTIVE)) { if (worldMan.isActiveAnywhere(CheckType.NET_FLYINGFREQUENCY)) {
// (Also sets lastKeepAliveTime, if enabled.) // (Also sets lastKeepAliveTime, if enabled.)
register("fr.neatmonster.nocheatplus.checks.net.protocollib.MovingFlying", plugin); register("fr.neatmonster.nocheatplus.checks.net.protocollib.MovingFlying", plugin);
register("fr.neatmonster.nocheatplus.checks.net.protocollib.OutgoingPosition", plugin); register("fr.neatmonster.nocheatplus.checks.net.protocollib.OutgoingPosition", plugin);
} }
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_KEEPALIVEFREQUENCY_ACTIVE) || ConfigManager.isTrueForAnyConfig(ConfPaths.FIGHT_GODMODE_CHECK)) { if (worldMan.isActiveAnywhere(CheckType.NET_KEEPALIVEFREQUENCY)
|| worldMan.isActiveAnywhere(CheckType.FIGHT_GODMODE)) {
// (Set lastKeepAlive if this or fight.godmode is enabled.) // (Set lastKeepAlive if this or fight.godmode is enabled.)
register("fr.neatmonster.nocheatplus.checks.net.protocollib.KeepAliveAdapter", plugin); register("fr.neatmonster.nocheatplus.checks.net.protocollib.KeepAliveAdapter", plugin);
} }
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_SOUNDDISTANCE_ACTIVE)) { if (worldMan.isActiveAnywhere(CheckType.NET_SOUNDDISTANCE)) {
register("fr.neatmonster.nocheatplus.checks.net.protocollib.SoundDistance", plugin); register("fr.neatmonster.nocheatplus.checks.net.protocollib.SoundDistance", plugin);
} }
if (ConfigManager.isAlmostTrueForAnyConfig(ConfPaths.NET_PACKETFREQUENCY_ACTIVE, ServerVersion.compareMinecraftVersion("1.9") < 0, false)) { if (ServerVersion.compareMinecraftVersion("1.9") < 0) {
register("fr.neatmonster.nocheatplus.checks.net.protocollib.CatchAllAdapter", plugin); if (worldMan.isActiveAnywhere(CheckType.NET_PACKETFREQUENCY)) {
register("fr.neatmonster.nocheatplus.checks.net.protocollib.CatchAllAdapter", plugin);
}
} }
if (!registeredPacketAdapters.isEmpty()) { if (!registeredPacketAdapters.isEmpty()) {
List<String> names = new ArrayList<String>(registeredPacketAdapters.size()); List<String> names = new ArrayList<String>(registeredPacketAdapters.size());
for (PacketAdapter adapter : registeredPacketAdapters) { for (PacketAdapter adapter : registeredPacketAdapters) {
@ -178,8 +184,8 @@ public class ProtocolLibComponent implements IDisableListener, INotifyReload, Jo
@Override @Override
public void onReload() { public void onReload() {
unregister(); unregister();
CheckType.NET.getDataFactory().removeAllData(); // Currently needed for FlyingFrequency. NCPAPIProvider.getNoCheatPlusAPI().getPlayerDataManager().removeGenericInstance(NetData.class); // Currently needed for FlyingFrequency.
register(Bukkit.getPluginManager().getPlugin("NoCheatPlus")); // Store instead ? register(Bukkit.getPluginManager().getPlugin("NoCheatPlus")); // TODO: static plugin getter?
} }
private void unregister() { private void unregister() {
@ -200,14 +206,14 @@ public class ProtocolLibComponent implements IDisableListener, INotifyReload, Jo
@Override @Override
public void playerJoins(final Player player) { public void playerJoins(final Player player) {
if (!registeredPacketAdapters.isEmpty()) { if (!registeredPacketAdapters.isEmpty()) {
dataFactory.getData(player).onJoin(player); DataManager.getGenericInstance(player, NetData.class).onJoin(player);
} }
} }
@Override @Override
public void playerLeaves(final Player player) { public void playerLeaves(final Player player) {
if (!registeredPacketAdapters.isEmpty()) { if (!registeredPacketAdapters.isEmpty()) {
dataFactory.getData(player).onLeave(player); DataManager.getGenericInstance(player, NetData.class).onLeave(player);
} }
} }
@ -215,7 +221,7 @@ public class ProtocolLibComponent implements IDisableListener, INotifyReload, Jo
public void onPlayerRespawn(final PlayerRespawnEvent event) { public void onPlayerRespawn(final PlayerRespawnEvent event) {
if (!registeredPacketAdapters.isEmpty()) { if (!registeredPacketAdapters.isEmpty()) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final NetData data = dataFactory.getData(player); final NetData data = DataManager.getGenericInstance(player, NetData.class);
data.onJoin(player); data.onJoin(player);
final Location loc = event.getRespawnLocation(); final Location loc = event.getRespawnLocation();
data.teleportQueue.onTeleportEvent(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch()); data.teleportQueue.onTeleportEvent(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
@ -232,9 +238,9 @@ public class ProtocolLibComponent implements IDisableListener, INotifyReload, Jo
return; return;
} }
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final NetConfig cc = configFactory.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final NetData data = dataFactory.getData(player); final NetData data = pData.getGenericInstance(NetData.class);
if (cc.flyingFrequencyActive) { if (pData.isCheckActive(CheckType.NET_FLYINGFREQUENCY, player)) {
// Register expected location for comparison with outgoing packets. // Register expected location for comparison with outgoing packets.
data.teleportQueue.onTeleportEvent(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch()); data.teleportQueue.onTeleportEvent(to.getX(), to.getY(), to.getZ(), to.getYaw(), to.getPitch());
} }

View File

@ -33,8 +33,9 @@ import com.comphenix.protocol.reflect.StructureModifier;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.NetConfig; import fr.neatmonster.nocheatplus.checks.net.NetConfig;
import fr.neatmonster.nocheatplus.checks.net.NetConfigCache;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion; import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil; import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
public class SoundDistance extends BaseAdapter { public class SoundDistance extends BaseAdapter {
@ -92,14 +93,12 @@ public class SoundDistance extends BaseAdapter {
)); ));
private final Integer idSoundEffectCancel = counters.registerKey("packet.sound.cancel"); private final Integer idSoundEffectCancel = counters.registerKey("packet.sound.cancel");
private final NetConfigCache configs;
private final Location useLoc = new Location(null, 0, 0, 0); private final Location useLoc = new Location(null, 0, 0, 0);
/** Legacy check behavior. */ /** Legacy check behavior. */
private final boolean pre1_9; private final boolean pre1_9;
public SoundDistance(Plugin plugin) { public SoundDistance(Plugin plugin) {
super(plugin, ListenerPriority.LOW, PacketType.Play.Server.NAMED_SOUND_EFFECT); super(plugin, ListenerPriority.LOW, PacketType.Play.Server.NAMED_SOUND_EFFECT);
this.configs = (NetConfigCache) CheckType.NET.getConfigFactory(); // TODO: DataManager.getConfig(NetConfigCache.class);
this.checkType = CheckType.NET_SOUNDDISTANCE; this.checkType = CheckType.NET_SOUNDDISTANCE;
pre1_9 = ServerVersion.compareMinecraftVersion("1.9") < 0; pre1_9 = ServerVersion.compareMinecraftVersion("1.9") < 0;
inflateEffectNames(); inflateEffectNames();
@ -151,8 +150,8 @@ public class SoundDistance extends BaseAdapter {
} }
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final NetConfig cc = configs.getConfig(player.getWorld()); final IPlayerData pData = DataManager.getPlayerData(player);
if (!cc.soundDistanceActive) { if (!pData.isCheckActive(CheckType.NET_SOUNDDISTANCE, player)) {
return; return;
} }
@ -163,6 +162,7 @@ public class SoundDistance extends BaseAdapter {
// if (data.debug) { // if (data.debug) {
// debug(player, "SoundDistance(" + soundName + "): " + StringUtil.fdec1.format(Math.sqrt(dSq))); // debug(player, "SoundDistance(" + soundName + "): " + StringUtil.fdec1.format(Math.sqrt(dSq)));
// } // }
final NetConfig cc = pData.getGenericInstance(NetConfig.class);
if (dSq > cc.soundDistanceSq) { if (dSq > cc.soundDistanceSq) {
event.setCancelled(true); event.setCancelled(true);
counters.add(idSoundEffectCancel, 1); counters.add(idSoundEffectCancel, 1);

View File

@ -27,13 +27,12 @@ import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.wrappers.EnumWrappers.EntityUseAction; import com.comphenix.protocol.wrappers.EnumWrappers.EntityUseAction;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.AttackFrequency; import fr.neatmonster.nocheatplus.checks.net.AttackFrequency;
import fr.neatmonster.nocheatplus.checks.net.NetConfig; import fr.neatmonster.nocheatplus.checks.net.NetConfig;
import fr.neatmonster.nocheatplus.checks.net.NetData; import fr.neatmonster.nocheatplus.checks.net.NetData;
import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil; import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
public class UseEntityAdapter extends BaseAdapter { public class UseEntityAdapter extends BaseAdapter {
@ -100,10 +99,12 @@ public class UseEntityAdapter extends BaseAdapter {
public UseEntityAdapter(Plugin plugin) { public UseEntityAdapter(Plugin plugin) {
super(plugin, PacketType.Play.Client.USE_ENTITY); super(plugin, PacketType.Play.Client.USE_ENTITY);
this.checkType = CheckType.NET_ATTACKFREQUENCY;
// Add feature tags for checks. // Add feature tags for checks.
if (ConfigManager.isTrueForAnyConfig(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE)) { if (NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager().isActiveAnywhere(
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags("checks", Arrays.asList(AttackFrequency.class.getSimpleName())); CheckType.NET_ATTACKFREQUENCY)) {
NCPAPIProvider.getNoCheatPlusAPI().addFeatureTags(
"checks", Arrays.asList(AttackFrequency.class.getSimpleName()));
} }
attackFrequency = new AttackFrequency(); attackFrequency = new AttackFrequency();
@ -129,14 +130,14 @@ public class UseEntityAdapter extends BaseAdapter {
// TODO: Warn once? // TODO: Warn once?
return; return;
} }
final NetConfig cc = configFactory.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final NetData data = dataFactory.getData(player);
final NetData data = pData.getGenericInstance(NetData.class);
// Always set last received time. // Always set last received time.
data.lastKeepAliveTime = time; data.lastKeepAliveTime = time;
// Quick return, if no checks are active. // Quick return, if no checks are active.
if (!cc.attackFrequencyActive) { if (!pData.isCheckActive(CheckType.NET_ATTACKFREQUENCY, player)) {
return; return;
} }
@ -174,8 +175,9 @@ public class UseEntityAdapter extends BaseAdapter {
// AttackFrequency // AttackFrequency
if (isAttack) { if (isAttack) {
final PlayerData pData = DataManager.getPlayerData(player); final NetConfig cc = pData.getGenericInstance(NetConfig.class);
if (attackFrequency.isEnabled(player, cc, pData) && attackFrequency.check(player, time, data, cc)) { if (attackFrequency.isEnabled(player, pData)
&& attackFrequency.check(player, time, data, cc, pData)) {
cancel = true; cancel = true;
} }
} }

View File

@ -23,16 +23,16 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.actions.types.penalty.IPenaltyList; import fr.neatmonster.nocheatplus.actions.types.penalty.IPenaltyList;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.compat.MCAccess; import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer; import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer;
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle; import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
import fr.neatmonster.nocheatplus.hooks.NCPHookManager; import fr.neatmonster.nocheatplus.hooks.NCPHookManager;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.ExecutionHistory; import fr.neatmonster.nocheatplus.players.ExecutionHistory;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* The parent class of all checks. Don't let this implement Listener without * The parent class of all checks. Don't let this implement Listener without
@ -71,6 +71,7 @@ import fr.neatmonster.nocheatplus.utilities.TickTask;
* actual check.</li> * actual check.</li>
* *
*/ */
// TODO: javadocs redo (above)
public abstract class Check implements IDebugPlayer { public abstract class Check implements IDebugPlayer {
// TODO: Do these get cleaned up ? // TODO: Do these get cleaned up ?
@ -102,6 +103,7 @@ public abstract class Check implements IDebugPlayer {
* @param type * @param type
* the type * the type
*/ */
@SuppressWarnings("deprecation")
public Check(final CheckType type) { public Check(final CheckType type) {
this.type = type; this.type = type;
mcAccess = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstanceHandle(MCAccess.class); mcAccess = NCPAPIProvider.getNoCheatPlusAPI().getGenericInstanceHandle(MCAccess.class);
@ -185,51 +187,38 @@ public abstract class Check implements IDebugPlayer {
} }
/** /**
* Checks both configuration flags and if the player is exempted from this * Full activation check (configuration, exemption, permission).
* check (hasBypass). Intended for higher efficiency with multiple calls.
* *
* @param player * @param player
* @param data * @param data
* @param cc * @param worldData
* @return * @return
*/ */
public boolean isEnabled(final Player player, final ICheckConfig cc, final PlayerData pData) { public boolean isEnabled(final Player player, final IPlayerData pData,
return cc.isEnabled(type) && !CheckUtils.hasBypass(type, player, pData); final IWorldData worldData) {
return pData.isCheckActive(type, player, worldData);
} }
/** /**
* Checks both configuration flags and if the player is exempted from this * Full activation check (configuration, exemption, permission).
* check (hasBypass). Intended for higher efficiency with multiple calls.
* *
* @param player * @param player
* @param cc * @param data
* @return * @return
*/ */
public boolean isEnabled(final Player player, final ICheckConfig cc) { public boolean isEnabled(final Player player, final IPlayerData pData) {
return cc.isEnabled(type) && !CheckUtils.hasBypass(type, player, DataManager.getPlayerData(player)); return pData.isCheckActive(type, player);
} }
/** /**
* Checks both configuration flags and if the player is exempted from this * Full activation check (configuration, exemption, permission).
* check (hasBypass).
* *
* @param player * @param player
* the player * the player
* @return true, if the check is enabled * @return true, if the check is enabled
*/ */
public boolean isEnabled(final Player player) { public boolean isEnabled(final Player player) {
return type.isEnabled(player) && !CheckUtils.hasBypass(type, player, DataManager.getPlayerData(player)); return isEnabled(player, DataManager.getPlayerData(player));
}
/**
* Check if the player is exempted by permissions or otherwise.<br>
*
*
* @param player
* @return
*/
public boolean hasBypass(final Player player) {
return CheckUtils.hasBypass(type, player, DataManager.getPlayerData(player));
} }
@Override @Override

View File

@ -14,28 +14,7 @@
*/ */
package fr.neatmonster.nocheatplus.checks; package fr.neatmonster.nocheatplus.checks;
import org.bukkit.entity.Player; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakConfig;
import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakData;
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractConfig;
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractData;
import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceConfig;
import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceData;
import fr.neatmonster.nocheatplus.checks.chat.ChatConfig;
import fr.neatmonster.nocheatplus.checks.chat.ChatData;
import fr.neatmonster.nocheatplus.checks.combined.CombinedConfig;
import fr.neatmonster.nocheatplus.checks.combined.CombinedData;
import fr.neatmonster.nocheatplus.checks.fight.FightConfig;
import fr.neatmonster.nocheatplus.checks.fight.FightData;
import fr.neatmonster.nocheatplus.checks.inventory.InventoryConfig;
import fr.neatmonster.nocheatplus.checks.inventory.InventoryData;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.net.NetConfigCache;
import fr.neatmonster.nocheatplus.checks.net.NetDataFactory;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.permissions.RegisteredPermission; import fr.neatmonster.nocheatplus.permissions.RegisteredPermission;
@ -46,86 +25,88 @@ import fr.neatmonster.nocheatplus.permissions.RegisteredPermission;
public enum CheckType { public enum CheckType {
ALL(Permissions.CHECKS), ALL(Permissions.CHECKS),
BLOCKBREAK(CheckType.ALL, BlockBreakConfig.factory, BlockBreakData.factory, Permissions.BLOCKBREAK), BLOCKBREAK(CheckTypeType.GROUP, CheckType.ALL, Permissions.BLOCKBREAK),
/** This will allow breaking all special blocks, currently only liquid. Later there might be more sub-types. */ /**
BLOCKBREAK_BREAK(BLOCKBREAK, Permissions.BLOCKBREAK_BREAK), * This will allow breaking all special blocks, currently only liquid. Later
BLOCKBREAK_DIRECTION(BLOCKBREAK, Permissions.BLOCKBREAK_DIRECTION), * there might be more sub-types.
BLOCKBREAK_FASTBREAK(BLOCKBREAK, Permissions.BLOCKBREAK_FASTBREAK), */
BLOCKBREAK_FREQUENCY(BLOCKBREAK, Permissions.BLOCKBREAK_FREQUENCY), BLOCKBREAK_BREAK(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_BREAK),
BLOCKBREAK_NOSWING(BLOCKBREAK, Permissions.BLOCKBREAK_NOSWING), BLOCKBREAK_DIRECTION(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_DIRECTION),
BLOCKBREAK_REACH(BLOCKBREAK, Permissions.BLOCKBREAK_REACH), BLOCKBREAK_FASTBREAK(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_FASTBREAK),
BLOCKBREAK_WRONGBLOCK(BLOCKBREAK, Permissions.BLOCKBREAK_WRONGBLOCK), BLOCKBREAK_FREQUENCY(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_FREQUENCY),
BLOCKBREAK_NOSWING(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_NOSWING),
BLOCKBREAK_REACH(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_REACH),
BLOCKBREAK_WRONGBLOCK(CheckTypeType.CHECK, BLOCKBREAK, Permissions.BLOCKBREAK_WRONGBLOCK),
BLOCKINTERACT(CheckType.ALL, BlockInteractConfig.factory, BlockInteractData.factory, Permissions.BLOCKINTERACT), BLOCKINTERACT(CheckTypeType.GROUP, CheckType.ALL, Permissions.BLOCKINTERACT),
BLOCKINTERACT_DIRECTION(BLOCKINTERACT, Permissions.BLOCKINTERACT_DIRECTION), BLOCKINTERACT_DIRECTION(CheckTypeType.CHECK, BLOCKINTERACT, Permissions.BLOCKINTERACT_DIRECTION),
BLOCKINTERACT_REACH(BLOCKINTERACT, Permissions.BLOCKINTERACT_REACH), BLOCKINTERACT_REACH(CheckTypeType.CHECK, BLOCKINTERACT, Permissions.BLOCKINTERACT_REACH),
BLOCKINTERACT_SPEED(BLOCKINTERACT, Permissions.BLOCKINTERACT_SPEED), BLOCKINTERACT_SPEED(CheckTypeType.CHECK, BLOCKINTERACT, Permissions.BLOCKINTERACT_SPEED),
BLOCKINTERACT_VISIBLE(BLOCKINTERACT, Permissions.BLOCKINTERACT_VISIBLE), BLOCKINTERACT_VISIBLE(CheckTypeType.CHECK, BLOCKINTERACT, Permissions.BLOCKINTERACT_VISIBLE),
BLOCKPLACE(CheckType.ALL, BlockPlaceConfig.factory, BlockPlaceData.factory, Permissions.BLOCKPLACE), BLOCKPLACE(CheckTypeType.GROUP, CheckType.ALL, Permissions.BLOCKPLACE),
BLOCKPLACE_AGAINST(BLOCKPLACE, Permissions.BLOCKPLACE_AGAINST), BLOCKPLACE_AGAINST(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKPLACE_AGAINST),
BLOCKPLACE_AUTOSIGN(BLOCKPLACE, Permissions.BLOCKPLACE_AUTOSIGN), BLOCKPLACE_AUTOSIGN(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKPLACE_AUTOSIGN),
BLOCKPLACE_DIRECTION(BLOCKPLACE, Permissions.BLOCKPLACE_DIRECTION), BLOCKPLACE_DIRECTION(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKPLACE_DIRECTION),
BLOCKPLACE_FASTPLACE(BLOCKPLACE, Permissions.BLOCKPLACE_FASTPLACE), BLOCKPLACE_FASTPLACE(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKPLACE_FASTPLACE),
BLOCKPLACE_NOSWING(BLOCKPLACE, Permissions.BLOCKPLACE_NOSWING), BLOCKPLACE_NOSWING(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKPLACE_NOSWING),
BLOCKPLACE_REACH(BLOCKPLACE, Permissions.BLOCKBREAK_REACH), BLOCKPLACE_REACH(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKBREAK_REACH),
BLOCKPLACE_SPEED(BLOCKPLACE, Permissions.BLOCKPLACE_SPEED), BLOCKPLACE_SPEED(CheckTypeType.CHECK, BLOCKPLACE, Permissions.BLOCKPLACE_SPEED),
CHAT(CheckType.ALL, ChatConfig.factory, ChatData.factory, Permissions.CHAT), CHAT(CheckTypeType.GROUP, CheckType.ALL, Permissions.CHAT),
CHAT_CAPTCHA(CHAT, Permissions.CHAT_CAPTCHA), CHAT_CAPTCHA(CheckTypeType.CHECK, CHAT, Permissions.CHAT_CAPTCHA),
CHAT_COLOR(CHAT, Permissions.CHAT_COLOR), CHAT_COLOR(CheckTypeType.CHECK, CHAT, Permissions.CHAT_COLOR),
CHAT_COMMANDS(CHAT, Permissions.CHAT_COMMANDS), CHAT_COMMANDS(CheckTypeType.CHECK, CHAT, Permissions.CHAT_COMMANDS),
CHAT_TEXT(CHAT, Permissions.CHAT_TEXT), CHAT_TEXT(CheckTypeType.CHECK, CHAT, Permissions.CHAT_TEXT),
CHAT_LOGINS(CHAT, Permissions.CHAT_LOGINS), CHAT_LOGINS(CheckTypeType.CHECK, CHAT, Permissions.CHAT_LOGINS),
CHAT_RELOG(CHAT, Permissions.CHAT_RELOG), CHAT_RELOG(CheckTypeType.CHECK, CHAT, Permissions.CHAT_RELOG),
COMBINED(CheckType.ALL, CombinedConfig.factory, CombinedData.factory, Permissions.COMBINED), COMBINED(CheckTypeType.GROUP, CheckType.ALL, Permissions.COMBINED),
COMBINED_BEDLEAVE(COMBINED, Permissions.COMBINED_BEDLEAVE), COMBINED_BEDLEAVE(CheckTypeType.CHECK, COMBINED, Permissions.COMBINED_BEDLEAVE),
COMBINED_IMPROBABLE(COMBINED, Permissions.COMBINED_IMPROBABLE), COMBINED_IMPROBABLE(CheckTypeType.CHECK, COMBINED, Permissions.COMBINED_IMPROBABLE),
COMBINED_MUNCHHAUSEN(COMBINED, Permissions.COMBINED_MUNCHHAUSEN), COMBINED_MUNCHHAUSEN(CheckTypeType.CHECK, COMBINED, Permissions.COMBINED_MUNCHHAUSEN),
/** Rather for data removal and exemption. */ /** Rather for data removal and exemption. */
COMBINED_YAWRATE(COMBINED), COMBINED_YAWRATE(CheckTypeType.CHECK, COMBINED),
FIGHT(CheckType.ALL, FightConfig.factory, FightData.factory, Permissions.FIGHT), FIGHT(CheckTypeType.CHECK, CheckType.ALL, Permissions.FIGHT),
FIGHT_ANGLE(FIGHT, Permissions.FIGHT_ANGLE), FIGHT_ANGLE(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_ANGLE),
FIGHT_CRITICAL(FIGHT, Permissions.FIGHT_CRITICAL), FIGHT_CRITICAL(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_CRITICAL),
FIGHT_DIRECTION(FIGHT, Permissions.FIGHT_DIRECTION), FIGHT_DIRECTION(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_DIRECTION),
FIGHT_FASTHEAL(FIGHT, Permissions.FIGHT_FASTHEAL), FIGHT_FASTHEAL(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_FASTHEAL),
FIGHT_GODMODE(FIGHT, Permissions.FIGHT_GODMODE), FIGHT_GODMODE(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_GODMODE),
FIGHT_NOSWING(FIGHT, Permissions.FIGHT_NOSWING), FIGHT_NOSWING(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_NOSWING),
FIGHT_REACH(FIGHT, Permissions.FIGHT_REACH), FIGHT_REACH(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_REACH),
FIGHT_SELFHIT(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SELFHIT, FIGHT_SELFHIT(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SELFHIT),
FightConfig.factory, FightData.selfHitDataFactory), FIGHT_SPEED(CheckTypeType.CHECK, FIGHT, Permissions.FIGHT_SPEED),
FIGHT_SPEED(FIGHT, Permissions.FIGHT_SPEED), FIGHT_WRONGTURN(CheckTypeType.CHECK, FIGHT, null),
FIGHT_WRONGTURN(FIGHT, null),
INVENTORY(CheckType.ALL, InventoryConfig.factory, InventoryData.factory, Permissions.INVENTORY), INVENTORY(CheckTypeType.GROUP, CheckType.ALL, Permissions.INVENTORY),
INVENTORY_DROP(INVENTORY, Permissions.INVENTORY_DROP), INVENTORY_DROP(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_DROP),
INVENTORY_FASTCLICK(INVENTORY, Permissions.INVENTORY_FASTCLICK), INVENTORY_FASTCLICK(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_FASTCLICK),
INVENTORY_FASTCONSUME(INVENTORY, Permissions.INVENTORY_FASTCONSUME), INVENTORY_FASTCONSUME(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_FASTCONSUME),
INVENTORY_GUTENBERG(INVENTORY, Permissions.INVENTORY_GUTENBERG), INVENTORY_GUTENBERG(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_GUTENBERG),
INVENTORY_INSTANTBOW(INVENTORY, Permissions.INVENTORY_INSTANTBOW), INVENTORY_INSTANTBOW(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_INSTANTBOW),
INVENTORY_INSTANTEAT(INVENTORY, Permissions.INVENTORY_INSTANTEAT), INVENTORY_INSTANTEAT(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_INSTANTEAT),
INVENTORY_ITEMS(INVENTORY, Permissions.INVENTORY_ITEMS), INVENTORY_ITEMS(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_ITEMS),
INVENTORY_OPEN(INVENTORY, Permissions.INVENTORY_OPEN), INVENTORY_OPEN(CheckTypeType.CHECK, INVENTORY, Permissions.INVENTORY_OPEN),
MOVING(CheckType.ALL, MovingConfig.factory, MovingData.factory, Permissions.MOVING), MOVING(CheckTypeType.GROUP, CheckType.ALL, Permissions.MOVING),
MOVING_CREATIVEFLY(MOVING, Permissions.MOVING_CREATIVEFLY), MOVING_CREATIVEFLY(CheckTypeType.CHECK, MOVING, Permissions.MOVING_CREATIVEFLY),
MOVING_MOREPACKETS(MOVING, Permissions.MOVING_MOREPACKETS), MOVING_MOREPACKETS(CheckTypeType.CHECK, MOVING, Permissions.MOVING_MOREPACKETS),
MOVING_NOFALL(MOVING, Permissions.MOVING_NOFALL), MOVING_NOFALL(CheckTypeType.CHECK, MOVING, Permissions.MOVING_NOFALL),
MOVING_PASSABLE(MOVING, Permissions.MOVING_PASSABLE), MOVING_PASSABLE(CheckTypeType.CHECK, MOVING, Permissions.MOVING_PASSABLE),
MOVING_SURVIVALFLY(MOVING, Permissions.MOVING_SURVIVALFLY), MOVING_SURVIVALFLY(CheckTypeType.CHECK, MOVING, Permissions.MOVING_SURVIVALFLY),
MOVING_VEHICLE(MOVING, Permissions.MOVING_VEHICLE), MOVING_VEHICLE(CheckTypeType.GROUP, MOVING, Permissions.MOVING_VEHICLE),
MOVING_VEHICLE_MOREPACKETS(MOVING_VEHICLE, Permissions.MOVING_VEHICLE_MOREPACKETS), MOVING_VEHICLE_MOREPACKETS(CheckTypeType.CHECK, MOVING_VEHICLE, Permissions.MOVING_VEHICLE_MOREPACKETS),
MOVING_VEHICLE_ENVELOPE(MOVING_VEHICLE, Permissions.MOVING_VEHICLE_ENVELOPE), MOVING_VEHICLE_ENVELOPE(CheckTypeType.CHECK, MOVING_VEHICLE, Permissions.MOVING_VEHICLE_ENVELOPE),
NET(CheckType.ALL, new NetConfigCache(), new NetDataFactory(), Permissions.NET), NET(CheckTypeType.GROUP, CheckType.ALL, Permissions.NET),
NET_ATTACKFREQUENCY(NET, Permissions.NET_ATTACKFREQUENCY), NET_ATTACKFREQUENCY(CheckTypeType.CHECK, NET, Permissions.NET_ATTACKFREQUENCY),
NET_FLYINGFREQUENCY(NET, Permissions.NET_FLYINGFREQUENCY), NET_FLYINGFREQUENCY(CheckTypeType.CHECK, NET, Permissions.NET_FLYINGFREQUENCY),
NET_KEEPALIVEFREQUENCY(NET, Permissions.NET_KEEPALIVEFREQUENCY), NET_KEEPALIVEFREQUENCY(CheckTypeType.CHECK, NET, Permissions.NET_KEEPALIVEFREQUENCY),
NET_PACKETFREQUENCY(NET, Permissions.NET_PACKETFREQUENCY), NET_PACKETFREQUENCY(CheckTypeType.CHECK, NET, Permissions.NET_PACKETFREQUENCY),
NET_SOUNDDISTANCE(NET), // Can not exempt players from this one. NET_SOUNDDISTANCE(CheckTypeType.CHECK, NET), // Can not exempt players from this one.
; ;
@ -144,56 +125,36 @@ public enum CheckType {
/** If not null, this is the check group usually. */ /** If not null, this is the check group usually. */
private final CheckType parent; private final CheckType parent;
/** The check config factory (access CheckConfig instances by CheckType). */
private final CheckConfigFactory configFactory;
/** The check data factory (access CheckData instances by CheckType). */
private final CheckDataFactory dataFactory;
/** The bypass permission. */ /** The bypass permission. */
private final RegisteredPermission permission; private final RegisteredPermission permission;
/** Configuration path for the active flag. */
private final String configPathActive;
/** Configuration path for the debug flag. */
private final String configPathDebug;
/** Configuration path for the lag flag. */
private final String configPathLag;
/** /**
* Special purpose for grouping (ALL). * Special purpose for grouping (ALL).
* *
* @param permission * @param permission
*/ */
private CheckType(final RegisteredPermission permission){ private CheckType(final RegisteredPermission permission){
this(CheckTypeType.SPECIAL, null, permission, null, null); // TODO: Might as well interpret as GROUP.
this(CheckTypeType.SPECIAL, null, permission);
} }
/** /**
* Constructor for root checks or check groups, that are not grouped under * Constructor for checks or groups grouped under another check type,
* another check type. * without having a permission set, with default activation flag path.
*
* @param configFactory
* @param dataFactory
* @param permission
*/
private CheckType(final CheckType parent,
final CheckConfigFactory configFactory, final CheckDataFactory dataFactory,
final RegisteredPermission permission) {
this(CheckTypeType.GROUP, parent, permission, configFactory, dataFactory);
}
/**
* Constructor for sub-checks grouped under another check type, without
* having a permission set.
* *
* @param parent * @param parent
*/ */
private CheckType(final CheckType parent) { private CheckType(final CheckTypeType type, final CheckType parent) {
this(parent, null); this(type, parent, null);
}
/**
* Constructor for sub-checks grouped under another check type.
*
* @param parent
* @param permission
*/
private CheckType(final CheckType parent, final RegisteredPermission permission) {
this(CheckTypeType.CHECK, parent, permission, parent.getConfigFactory(), parent.getDataFactory());
} }
/** /**
@ -205,43 +166,48 @@ public enum CheckType {
* Super check type (usually the group). * Super check type (usually the group).
* @param permission * @param permission
* Bypass permission. * Bypass permission.
* @param configFactory */
* Check config factory. private CheckType(final CheckTypeType type, final CheckType parent,
* @param dataFactory final RegisteredPermission permission) {
* Check data factory. this(type, parent, permission, null);
}
/**
* General constructor (bottom).
*
* @param type
* @param parent
* @param permission
* @param configPathActive
*/ */
private CheckType(final CheckTypeType type, final CheckType parent, private CheckType(final CheckTypeType type, final CheckType parent,
final RegisteredPermission permission, final RegisteredPermission permission,
final CheckConfigFactory configFactory, final CheckDataFactory dataFactory) { final String configPathActive) {
this.type = type; this.type = type;
this.parent = parent; this.parent = parent;
this.permission = permission; this.permission = permission;
this.configFactory = configFactory; this.configPathActive = configPathActive == null ? guessConfigPathActive() : configPathActive ;
this.dataFactory = dataFactory; this.configPathDebug = guessConfigPath(this.configPathActive, ConfPaths.SUB_DEBUG);
this.configPathLag = guessConfigPath(this.configPathActive, ConfPaths.SUB_LAG);
}
private String guessConfigPathActive() {
return guessConfigPathRoot() + ConfPaths.SUB_ACTIVE;
}
private String guessConfigPath(String configPathActive, String suffix) {
final int index = configPathActive.lastIndexOf(".");
return index == -1 ? suffix: configPathActive.substring(0, index + 1) + suffix;
}
private String guessConfigPathRoot() {
return name().toLowerCase().replace('_', '.') + ".";
} }
public CheckTypeType getType() { public CheckTypeType getType() {
return type; return type;
} }
/**
* Gets the configFactory.
*
* @return the configFactory
*/
public CheckConfigFactory getConfigFactory() {
return configFactory;
}
/**
* Gets the dataFactory.
*
* @return the dataFactory
*/
public CheckDataFactory getDataFactory() {
return dataFactory;
}
/** /**
* Gets the name. * Gets the name.
* *
@ -270,14 +236,20 @@ public enum CheckType {
} }
/** /**
* Check if the check is enabled by configuration (no permission check). * Return the configuration path for the activation flag.
* *
* @param player * @return
* the player
* @return true, if the check is enabled
*/ */
public final boolean isEnabled(final Player player) { public String getConfigPathActive() {
return configFactory.getConfig(player).isEnabled(this); return configPathActive;
}
public String getConfigPathDebug() {
return configPathDebug;
}
public String getConfigPathLag() {
return configPathLag;
} }
} }

View File

@ -14,21 +14,17 @@
*/ */
package fr.neatmonster.nocheatplus.checks.access; package fr.neatmonster.nocheatplus.checks.access;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.worlds.IWorldData;
import fr.neatmonster.nocheatplus.config.ConfigFile;
/** /**
* Minimal implementation, doing nothing. * Minimal implementation, doing nothing.
* @author mc_dev * @author asofold
* *
*/ */
public abstract class ACheckConfig implements ICheckConfig { public abstract class ACheckConfig implements ICheckConfig {
/** For on the fly debug setting. */ /** World data storage for this world. */
public boolean debug = false; // TODO: Might make private. public final IWorldData worldData;
/** If to adapt to server side lag. */
public final boolean lag;
/** /**
* *
@ -36,21 +32,9 @@ public abstract class ACheckConfig implements ICheckConfig {
* @param pathPrefix Path prefix for the check section (example for use: prefix+"debug"). * @param pathPrefix Path prefix for the check section (example for use: prefix+"debug").
* @param cachePermissions cachePermissions Permissions to hold in player data cache. Can be null. * @param cachePermissions cachePermissions Permissions to hold in player data cache. Can be null.
*/ */
public ACheckConfig(final ConfigFile config, final String pathPrefix){ public ACheckConfig(final IWorldData worldData){
// TODO: Path prefix construction is somewhat inconsistent with debug hierarchy ? this.worldData = worldData;
debug = config.getBoolean(pathPrefix + ConfPaths.SUB_DEBUG, config.getBoolean(ConfPaths.CHECKS_DEBUG, false));
// TODO: Use lag flag where appropriate and document it (or get rid of it).
lag = config.getBoolean(pathPrefix + ConfPaths.SUB_LAG, true) && config.getBoolean(ConfPaths.MISCELLANEOUS_LAG, true);
} }
@Override
public boolean getDebug() {
return debug;
}
@Override
public void setDebug(final boolean debug) {
this.debug = debug;
}
} }

View File

@ -16,25 +16,11 @@ package fr.neatmonster.nocheatplus.checks.access;
/** /**
* Abstract implementation to do nothing. * Abstract implementation to do nothing.
* @author mc_dev *
* @author asofold
* @TODO: Keep/remove.
* *
*/ */
public abstract class ACheckData implements ICheckData { public abstract class ACheckData implements ICheckData {
public boolean debug; // TODO: Might make private.
public ACheckData(ICheckConfig config) {
setDebug(config.getDebug());
}
@Override
public void setDebug(boolean debug) {
this.debug = debug;
}
@Override
public boolean getDebug() {
return debug;
}
} }

View File

@ -15,16 +15,11 @@
package fr.neatmonster.nocheatplus.checks.access; package fr.neatmonster.nocheatplus.checks.access;
/** /**
* ChecData for async checks like chat, actually implementing cached permissions. *
* @author mc_dev * @author asofold
* @TODO Keep / remove.
* *
*/ */
public abstract class AsyncCheckData extends ACheckData { public abstract class AsyncCheckData extends ACheckData {
// TODO: Still needed ?
public AsyncCheckData(ICheckConfig config) {
super(config);
}
} }

View File

@ -1,54 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.access;
import java.util.UUID;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.components.registry.feature.IRemoveData;
/**
* A factory for creating and accessing data. This design may be outdated, due
* to PlayerData soon holding the check data instances and factories becoming
* factories again.
*
* @author asofold
*/
public interface CheckDataFactory extends IRemoveData{
/**
* Gets the data of the specified player. Data might get created, if not
* present already.
*
* @param player
* the player
* @return the data
*/
public ICheckData getData(Player player);
/**
* Get data, but don't create if not present.
*
* @param playerId
* @param playerName
* @return The data instance, if present. Null otherwise.
*/
public ICheckData getDataIfPresent(UUID playerId, String playerName);
@Override
public ICheckData removeData(String playerName);
}

View File

@ -14,28 +14,12 @@
*/ */
package fr.neatmonster.nocheatplus.checks.access; package fr.neatmonster.nocheatplus.checks.access;
import fr.neatmonster.nocheatplus.checks.CheckType;
/** /**
* This interface must be implemented by all configuration classes. * TODO: Keep / Remove.
* *
* @author asofold * @author asofold
*/ */
public interface ICheckConfig { public interface ICheckConfig {
/**
* Checks if a check is enabled.
*
* @param checkType
* the check type
* @return true, if the check is enabled
*/
public boolean isEnabled(CheckType checkType);
/** On the fly debug flags, to be set by commands and similar. */
public boolean getDebug();
/** On the fly debug flags, to be set by commands and similar. */
public void setDebug(boolean debug);
} }

View File

@ -18,24 +18,15 @@ import fr.neatmonster.nocheatplus.components.data.IData;
/** /**
* This is for future purposes. Might remove...<br> * This is for future purposes. Might remove...<br>
* Some checks in chat synchronize over data, so using this from exectueActions can deadlock.<br> * Some checks in chat synchronize over data, so using this from exectueActions
* One might think of making this an interface not for the internally used data, but for copy of data for external use * can deadlock.<br>
* only. Then sync could go over other objects for async access. * One might think of making this an interface not for the internally used data,
* but for copy of data for external use only. Then sync could go over other
* objects for async access.
* *
* @author asofold * @author asofold
* @TODO Keep/Remove
*/ */
public interface ICheckData extends IData{ public interface ICheckData extends IData{
/**
* Set if to trace/debug this player for the associated checks.
* @param debug
*/
public void setDebug(boolean debug);
/**
* Test if to trace/debug this player for the associated checks.
* @return
*/
public boolean getDebug();
} }

View File

@ -1,105 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.access;
import java.util.Collection;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType;
/**
* Quick and dirty way to add factories for sub checks for more precise data removal from a more general data object.
* @author mc_dev
*
*/
public abstract class SubCheckDataFactory<D extends ICheckData> implements CheckDataFactory {
protected final CheckDataFactory parentFactory;
protected final CheckType checkType;
public SubCheckDataFactory(CheckType checkType, CheckDataFactory parentFactory) {
this.checkType = checkType;
this.parentFactory = parentFactory;
}
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.components.IRemoveData#removeAllData()
*/
@Override
public void removeAllData() {
for (String playerName : getPresentData()) {
D data = getData(playerName);
if (data != null) {
removeFromData(playerName, data);
}
}
}
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.access.CheckDataFactory#getData(org.bukkit.entity.Player)
*/
@Override
public ICheckData getData(Player player) {
return parentFactory.getData(player);
}
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.access.CheckDataFactory#removeData(java.lang.String)
*/
@Override
public ICheckData removeData(String playerName) {
if (!hasData(playerName)) {
return null;
}
D data = getData(playerName);
if (data != null) {
if (removeFromData(playerName, data)) {
// Return data instance, if changed.
return data;
}
}
return null;
}
/**
*
* @param playerName Exact case lookup.
* @return Can return null.
*/
protected abstract D getData(String playerName);
/**
* Names are expected to be exact case. This collection is demanded to be iterable (eclipse: adorable) in case the check runs asynchronously.<br>
* This method might change "a lot" with time.
* @return
*/
protected abstract Collection<String> getPresentData();
/**
* Fast check, if there is data for the player.
* @param playerName Exact case lookup.
* @return
*/
protected abstract boolean hasData(String playerName);
/**
* Remove the specific data from the given data instance.<br>
* TODO: Might add timestamp as argument (ms).
* @param playerName Exact case. Just for reference.
* @param data The data from which to remove the checkType-specific parts. This will never be null.
* @return If changed.
*/
protected abstract boolean removeFromData(String playerName, D data);
}

View File

@ -14,20 +14,12 @@
*/ */
package fr.neatmonster.nocheatplus.checks.blockbreak; package fr.neatmonster.nocheatplus.checks.blockbreak;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configurations specific for the block break checks. Every world gets one of these assigned to it, or if a world * Configurations specific for the block break checks. Every world gets one of these assigned to it, or if a world
@ -35,47 +27,8 @@ import fr.neatmonster.nocheatplus.permissions.Permissions;
*/ */
public class BlockBreakConfig extends ACheckConfig { public class BlockBreakConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return BlockBreakConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
/** The map containing the configurations per world. */
private static final Map<String, BlockBreakConfig> worldsMap = new HashMap<String, BlockBreakConfig>();
/**
* Clear all the configurations.
*/
public static void clear() {
worldsMap.clear();
}
/**
* Gets the configuration for a specified player.
*
* @param player
* the player
* @return the configuration
*/
public static BlockBreakConfig getConfig(final Player player) {
if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(),
new BlockBreakConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName());
}
public final boolean directionCheck;
public final ActionList directionActions; public final ActionList directionActions;
public final boolean fastBreakCheck;
public final boolean fastBreakStrict; public final boolean fastBreakStrict;
public final int fastBreakBuckets; public final int fastBreakBuckets;
public final long fastBreakBucketDur; public final long fastBreakBucketDur;
@ -86,7 +39,6 @@ public class BlockBreakConfig extends ACheckConfig {
public final ActionList fastBreakActions; public final ActionList fastBreakActions;
public final boolean frequencyCheck;
public final int frequencyBuckets; public final int frequencyBuckets;
public final long frequencyBucketDur; public final long frequencyBucketDur;
public final float frequencyBucketFactor; public final float frequencyBucketFactor;
@ -99,13 +51,10 @@ public class BlockBreakConfig extends ACheckConfig {
public boolean improbableFastBreakCheck; public boolean improbableFastBreakCheck;
public final boolean noSwingCheck;
public final ActionList noSwingActions; public final ActionList noSwingActions;
public final boolean reachCheck;
public final ActionList reachActions; public final ActionList reachActions;
public final boolean wrongBlockCheck;
public final float wrongBLockLevel; public final float wrongBLockLevel;
public final ActionList wrongBlockActions; public final ActionList wrongBlockActions;
@ -115,67 +64,38 @@ public class BlockBreakConfig extends ACheckConfig {
* @param data * @param data
* the data * the data
*/ */
public BlockBreakConfig(final ConfigFile data) { public BlockBreakConfig(final IWorldData worldData) {
super(data, ConfPaths.BLOCKBREAK); super(worldData);
directionCheck = data.getBoolean(ConfPaths.BLOCKBREAK_DIRECTION_CHECK); final ConfigFile config = worldData.getRawConfiguration();
directionActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, Permissions.BLOCKBREAK_DIRECTION); directionActions = config.getOptimizedActionList(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, Permissions.BLOCKBREAK_DIRECTION);
// Fastbreak. // Fastbreak.
fastBreakCheck = data.getBoolean(ConfPaths.BLOCKBREAK_FASTBREAK_CHECK); fastBreakStrict = config.getBoolean(ConfPaths.BLOCKBREAK_FASTBREAK_STRICT);
fastBreakStrict = data.getBoolean(ConfPaths.BLOCKBREAK_FASTBREAK_STRICT); fastBreakDelay = config.getLong(ConfPaths.BLOCKBREAK_FASTBREAK_DELAY);
fastBreakDelay = data.getLong(ConfPaths.BLOCKBREAK_FASTBREAK_DELAY); fastBreakGrace = config.getLong(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_CONTENTION,
fastBreakGrace = data.getLong(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_CONTENTION, config.getLong(ConfPaths.BLOCKBREAK_FASTBREAK_GRACE, 2000));
data.getLong(ConfPaths.BLOCKBREAK_FASTBREAK_GRACE, 2000)); fastBreakBucketDur = config.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_DUR, 4000);
fastBreakBucketDur = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_DUR, 4000); fastBreakBucketFactor = (float) config.getDouble(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_FACTOR, 0.99);
fastBreakBucketFactor = (float) data.getDouble(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_FACTOR, 0.99); fastBreakBuckets = config.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_N, 30);
fastBreakBuckets = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_BUCKETS_N, 30); fastBreakModSurvival = config.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_MOD_SURVIVAL);
fastBreakModSurvival = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_MOD_SURVIVAL);
// Fastbreak actions, shared. // Fastbreak actions, shared.
fastBreakActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, Permissions.BLOCKBREAK_FASTBREAK); fastBreakActions = config.getOptimizedActionList(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, Permissions.BLOCKBREAK_FASTBREAK);
frequencyCheck = data.getBoolean(ConfPaths.BLOCKBREAK_FREQUENCY_CHECK); frequencyBuckets = config.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_BUCKETS_N, 2);
frequencyBuckets = data.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_BUCKETS_N, 2); frequencyBucketDur = config.getLong(ConfPaths.BLOCKBREAK_FREQUENCY_BUCKETS_DUR, 1000);
frequencyBucketDur = data.getLong(ConfPaths.BLOCKBREAK_FREQUENCY_BUCKETS_DUR, 1000); frequencyBucketFactor = (float) config.getDouble(ConfPaths.BLOCKBREAK_FREQUENCY_BUCKETS_FACTOR, 1f);
frequencyBucketFactor = (float) data.getDouble(ConfPaths.BLOCKBREAK_FREQUENCY_BUCKETS_FACTOR, 1f); frequencyIntervalCreative = config.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_MOD_CREATIVE);
frequencyIntervalCreative = data.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_MOD_CREATIVE); frequencyIntervalSurvival = config.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_MOD_SURVIVAL);
frequencyIntervalSurvival = data.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_MOD_SURVIVAL); frequencyShortTermLimit = config.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_SHORTTERM_LIMIT);
frequencyShortTermLimit = data.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_SHORTTERM_LIMIT); frequencyShortTermTicks = config.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_SHORTTERM_TICKS);
frequencyShortTermTicks = data.getInt(ConfPaths.BLOCKBREAK_FREQUENCY_SHORTTERM_TICKS); frequencyActions = config.getOptimizedActionList(ConfPaths.BLOCKBREAK_FREQUENCY_ACTIONS, Permissions.BLOCKBREAK_FREQUENCY);
frequencyActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_FREQUENCY_ACTIONS, Permissions.BLOCKBREAK_FREQUENCY);
noSwingCheck = data.getBoolean(ConfPaths.BLOCKBREAK_NOSWING_CHECK); noSwingActions = config.getOptimizedActionList(ConfPaths.BLOCKBREAK_NOSWING_ACTIONS, Permissions.BLOCKBREAK_NOSWING);
noSwingActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_NOSWING_ACTIONS, Permissions.BLOCKBREAK_NOSWING);
reachCheck = data.getBoolean(ConfPaths.BLOCKBREAK_REACH_CHECK); reachActions = config.getOptimizedActionList(ConfPaths.BLOCKBREAK_REACH_ACTIONS, Permissions.BLOCKBREAK_REACH);
reachActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_REACH_ACTIONS, Permissions.BLOCKBREAK_REACH);
wrongBlockCheck = data.getBoolean(ConfPaths.BLOCKBREAK_WRONGBLOCK_CHECK); wrongBLockLevel = config.getInt(ConfPaths.BLOCKBREAK_WRONGBLOCK_LEVEL);
wrongBLockLevel = data.getInt(ConfPaths.BLOCKBREAK_WRONGBLOCK_LEVEL); wrongBlockActions = config.getOptimizedActionList(ConfPaths.BLOCKBREAK_WRONGBLOCK_ACTIONS, Permissions.BLOCKBREAK_WRONGBLOCK);
wrongBlockActions = data.getOptimizedActionList(ConfPaths.BLOCKBREAK_WRONGBLOCK_ACTIONS, Permissions.BLOCKBREAK_WRONGBLOCK);
} }
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster.nocheatplus.checks.CheckType)
*/
@Override
public final boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case BLOCKBREAK_DIRECTION:
return directionCheck;
case BLOCKBREAK_FASTBREAK:
return fastBreakCheck;
case BLOCKBREAK_FREQUENCY:
return frequencyCheck;
case BLOCKBREAK_NOSWING:
return noSwingCheck;
case BLOCKBREAK_REACH:
return reachCheck;
case BLOCKBREAK_WRONGBLOCK:
return wrongBlockCheck;
case BLOCKBREAK_BREAK:
return true;
default:
return true;
}
}
} }

View File

@ -14,18 +14,11 @@
*/ */
package fr.neatmonster.nocheatplus.checks.blockbreak; package fr.neatmonster.nocheatplus.checks.blockbreak;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
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.ICheckData;
import fr.neatmonster.nocheatplus.stats.Timings; import fr.neatmonster.nocheatplus.stats.Timings;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
@ -35,53 +28,6 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
*/ */
public class BlockBreakData extends ACheckData { public class BlockBreakData extends ACheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
@Override
public final ICheckData getData(final Player player) {
return BlockBreakData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return BlockBreakData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return BlockBreakData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
};
/** The map containing the data per players. */
private static final Map<String, BlockBreakData> playersMap = new HashMap<String, BlockBreakData>();
/**
* Gets the data of a specified player.
*
* @param player
* the player
* @return the data
*/
public static BlockBreakData getData(final Player player) {
if (!playersMap.containsKey(player.getName()))
playersMap.put(player.getName(), new BlockBreakData(BlockBreakConfig.getConfig(player)));
return playersMap.get(player.getName());
}
public static ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static void clear(){
playersMap.clear();
}
// Violation levels. // Violation levels.
public double directionVL; public double directionVL;
public double fastBreakVL; public double fastBreakVL;
@ -121,26 +67,15 @@ public class BlockBreakData extends ACheckData {
public BlockBreakData(final BlockBreakConfig cc) { public BlockBreakData(final BlockBreakConfig cc) {
super(cc);
setStats(); setStats();
fastBreakPenalties = new ActionFrequency(cc.fastBreakBuckets, cc.fastBreakBucketDur); fastBreakPenalties = new ActionFrequency(cc.fastBreakBuckets, cc.fastBreakBucketDur);
frequencyBuckets = new ActionFrequency(cc.frequencyBuckets, cc.frequencyBucketDur); frequencyBuckets = new ActionFrequency(cc.frequencyBuckets, cc.frequencyBucketDur);
wrongBlockVL = new ActionFrequency(6, 20000); wrongBlockVL = new ActionFrequency(6, 20000);
} }
@Override void setStats() {
public void setDebug(boolean debug) { if (stats == null) {
super.setDebug(debug); stats = new Timings("NCP/FASTBREAK");
setStats();
}
private void setStats() {
if (getDebug()) {
if (stats == null) {
stats = new Timings("NCP/FASTBREAK");
}
} else {
stats = null;
} }
} }

View File

@ -44,7 +44,7 @@ import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
@ -96,10 +96,11 @@ public class BlockBreakListener extends CheckListener {
public void onBlockBreak(final BlockBreakEvent event) { public void onBlockBreak(final BlockBreakEvent event) {
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final IPlayerData pData = DataManager.getPlayerData(player);
// Illegal enchantments hotfix check. // Illegal enchantments hotfix check.
// TODO: Legacy / encapsulate fully there. // TODO: Legacy / encapsulate fully there.
if (Items.checkIllegalEnchantmentsAllHands(player)) { if (Items.checkIllegalEnchantmentsAllHands(player, pData)) {
event.setCancelled(true); event.setCancelled(true);
counters.addPrimaryThread(idCancelDIllegalItem, 1); counters.addPrimaryThread(idCancelDIllegalItem, 1);
} }
@ -122,10 +123,9 @@ public class BlockBreakListener extends CheckListener {
// Do the actual checks, if still needed. It's a good idea to make computationally cheap checks first, because // Do the actual checks, if still needed. It's a good idea to make computationally cheap checks first, because
// it may save us from doing the computationally expensive checks. // it may save us from doing the computationally expensive checks.
final PlayerData pData = DataManager.getPlayerData(player); // TODO: Use for data + config getting etc. final BlockBreakConfig cc = pData.getGenericInstance(BlockBreakConfig.class);
final BlockBreakConfig cc = BlockBreakConfig.getConfig(player); final BlockBreakData data = pData.getGenericInstance(BlockBreakData.class);
final BlockBreakData data = BlockBreakData.getData(player); final BlockInteractData bdata = pData.getGenericInstance(BlockInteractData.class);
final BlockInteractData bdata = BlockInteractData.getData(player);
/* /*
* Re-check if this is a block interacted with before. With instantly * Re-check if this is a block interacted with before. With instantly
* broken blocks, this may be off by one orthogonally. * broken blocks, this may be off by one orthogonally.
@ -138,30 +138,35 @@ public class BlockBreakListener extends CheckListener {
final GameMode gameMode = player.getGameMode(); final GameMode gameMode = player.getGameMode();
// Has the player broken a block that was not damaged before? // Has the player broken a block that was not damaged before?
final boolean wrongBlockEnabled = wrongBlock.isEnabled(player); final boolean wrongBlockEnabled = wrongBlock.isEnabled(player, pData);
if (wrongBlockEnabled && wrongBlock.check(player, block, cc, data, pData, isInstaBreak)) { if (wrongBlockEnabled && wrongBlock.check(player, block, cc, data, pData, isInstaBreak)) {
cancelled = true; cancelled = true;
} }
// Has the player broken more blocks per second than allowed? // Has the player broken more blocks per second than allowed?
if (!cancelled && frequency.isEnabled(player) && frequency.check(player, tick, cc, data)) { if (!cancelled && frequency.isEnabled(player, pData)
&& frequency.check(player, tick, cc, data, pData)) {
cancelled = true; cancelled = true;
} }
// Has the player broken blocks faster than possible? // Has the player broken blocks faster than possible?
if (!cancelled && gameMode != GameMode.CREATIVE if (!cancelled && gameMode != GameMode.CREATIVE
&& fastBreak.isEnabled(player) && fastBreak.check(player, block, isInstaBreak, cc, data, pData)) { && fastBreak.isEnabled(player, pData)
&& fastBreak.check(player, block, isInstaBreak, cc, data, pData)) {
cancelled = true; cancelled = true;
} }
// Did the arm of the player move before breaking this block? // Did the arm of the player move before breaking this block?
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player, data)) { if (!cancelled && noSwing.isEnabled(player, pData)
&& noSwing.check(player, data, pData)) {
cancelled = true; cancelled = true;
} }
final FlyingQueueHandle flyingHandle; final FlyingQueueHandle flyingHandle;
if (cc.reachCheck || cc.directionCheck) { final boolean reachEnabled = reach.isEnabled(player, pData);
flyingHandle = new FlyingQueueHandle(player); final boolean directionEnabled = direction.isEnabled(player, pData);
if (reachEnabled || directionEnabled) {
flyingHandle = new FlyingQueueHandle(pData);
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
final double eyeHeight = MovingUtil.getEyeHeight(player); final double eyeHeight = MovingUtil.getEyeHeight(player);
// Is the block really in reach distance? // Is the block really in reach distance?
@ -169,7 +174,7 @@ public class BlockBreakListener extends CheckListener {
if (isInteractBlock && bdata.isPassedCheck(CheckType.BLOCKINTERACT_REACH)) { if (isInteractBlock && bdata.isPassedCheck(CheckType.BLOCKINTERACT_REACH)) {
skippedRedundantChecks ++; skippedRedundantChecks ++;
} }
else if (reach.isEnabled(player) && reach.check(player, eyeHeight, block, data)) { else if (reachEnabled && reach.check(player, eyeHeight, block, data, cc)) {
cancelled = true; cancelled = true;
} }
} }
@ -181,8 +186,8 @@ public class BlockBreakListener extends CheckListener {
|| bdata.isPassedCheck(CheckType.BLOCKINTERACT_VISIBLE))) { || bdata.isPassedCheck(CheckType.BLOCKINTERACT_VISIBLE))) {
skippedRedundantChecks ++; skippedRedundantChecks ++;
} }
else if (direction.isEnabled(player) && direction.check(player, loc, eyeHeight, block, else if (directionEnabled && direction.check(player, loc, eyeHeight, block,
flyingHandle, data, cc)) { flyingHandle, data, cc, pData)) {
cancelled = true; cancelled = true;
} }
} }
@ -212,8 +217,9 @@ public class BlockBreakListener extends CheckListener {
// Invalidate last damage position: // Invalidate last damage position:
// data.clickedX = Integer.MAX_VALUE; // data.clickedX = Integer.MAX_VALUE;
// Debug log (only if not cancelled, to avoid spam). // Debug log (only if not cancelled, to avoid spam).
if (data.debug) { if (pData.isDebugActive(CheckType.BLOCKBREAK)) {
debugBlockBreakResult(player, block, skippedRedundantChecks, flyingHandle); debugBlockBreakResult(player, block, skippedRedundantChecks,
flyingHandle, pData);
} }
} }
@ -231,10 +237,10 @@ public class BlockBreakListener extends CheckListener {
} }
private void debugBlockBreakResult(final Player player, final Block block, final int skippedRedundantChecks, private void debugBlockBreakResult(final Player player, final Block block, final int skippedRedundantChecks,
final FlyingQueueHandle flyingHandle) { final FlyingQueueHandle flyingHandle, final IPlayerData pData) {
debug(player, "Block break(" + block.getType() + "): " + block.getX() + ", " + block.getY() + ", " + block.getZ()); debug(player, "Block break(" + block.getType() + "): " + block.getX() + ", " + block.getY() + ", " + block.getZ());
BlockInteractListener.debugBlockVSBlockInteract(player, checkType, block, "onBlockBreak", BlockInteractListener.debugBlockVSBlockInteract(player, checkType, block, "onBlockBreak",
Action.LEFT_CLICK_BLOCK); Action.LEFT_CLICK_BLOCK, pData);
if (skippedRedundantChecks > 0) { if (skippedRedundantChecks > 0) {
debug(player, "Skipped redundant checks: " + skippedRedundantChecks); debug(player, "Skipped redundant checks: " + skippedRedundantChecks);
} }
@ -260,7 +266,7 @@ public class BlockBreakListener extends CheckListener {
public void onPlayerAnimation(final PlayerAnimationEvent event) { public void onPlayerAnimation(final PlayerAnimationEvent event) {
// Just set a flag to true when the arm was swung. // Just set a flag to true when the arm was swung.
// debug(player, "Animation"); // debug(player, "Animation");
BlockBreakData.getData(event.getPlayer()).noSwingArmSwung = true; DataManager.getPlayerData(event.getPlayer()).getGenericInstance(BlockBreakData.class).noSwingArmSwung = true;
} }
/** /**
@ -317,7 +323,8 @@ public class BlockBreakListener extends CheckListener {
private void checkBlockDamage(final Player player, final Block block, final Cancellable event){ private void checkBlockDamage(final Player player, final Block block, final Cancellable event){
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final BlockBreakData data = BlockBreakData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final BlockBreakData data = pData.getGenericInstance(BlockBreakData.class);
// if (event.isCancelled()){ // if (event.isCancelled()){
// // Reset the time, to avoid certain kinds of cheating. => WHICH ? // // Reset the time, to avoid certain kinds of cheating. => WHICH ?
@ -351,9 +358,9 @@ public class BlockBreakListener extends CheckListener {
// Only record first damage: // Only record first damage:
data.setClickedBlock(block, tick, now, tool); data.setClickedBlock(block, tick, now, tool);
// Compare with BlockInteract data (debug first). // Compare with BlockInteract data (debug first).
if (data.debug) { if (pData.isDebugActive(CheckType.BLOCKBREAK)) {
BlockInteractListener.debugBlockVSBlockInteract(player, this.checkType, block, "checkBlockDamage", BlockInteractListener.debugBlockVSBlockInteract(player, this.checkType,
Action.LEFT_CLICK_BLOCK); block, "checkBlockDamage", Action.LEFT_CLICK_BLOCK, pData);
} }
} }
@ -362,7 +369,7 @@ public class BlockBreakListener extends CheckListener {
// Reset clicked block. // Reset clicked block.
// TODO: Not for 1.5.2 and before? // TODO: Not for 1.5.2 and before?
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final BlockBreakData data = BlockBreakData.getData(player); final BlockBreakData data = DataManager.getPlayerData(player).getGenericInstance(BlockBreakData.class);
if (data.toolChanged(player.getInventory().getItem(event.getNewSlot()))) { if (data.toolChanged(player.getInventory().getItem(event.getNewSlot()))) {
data.resetClickedBlock(); data.resetClickedBlock();
} }

View File

@ -27,7 +27,7 @@ import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean; import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.Bridge1_9; import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.PotionUtil; import fr.neatmonster.nocheatplus.utilities.PotionUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
@ -58,7 +58,7 @@ public class FastBreak extends Check {
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final Block block, final AlmostBoolean isInstaBreak, public boolean check(final Player player, final Block block, final AlmostBoolean isInstaBreak,
final BlockBreakConfig cc, final BlockBreakData data, final PlayerData pData) { final BlockBreakConfig cc, final BlockBreakData data, final IPlayerData pData) {
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
boolean cancel = false; boolean cancel = false;
@ -91,57 +91,71 @@ public class FastBreak extends Check {
// lag or cheat or Minecraft. // lag or cheat or Minecraft.
// Count in server side lag, if desired. // Count in server side lag, if desired.
final float lag = cc.lag ? TickTask.getLag(expectedBreakingTime, true) : 1f; final float lag = pData.getCurrentWorldDataSafe().shouldAdjustToLag(type)
? TickTask.getLag(expectedBreakingTime, true) : 1f;
final long missingTime = expectedBreakingTime - (long) (lag * elapsedTime); final long missingTime = expectedBreakingTime - (long) (lag * elapsedTime);
if (missingTime > 0) { if (missingTime > 0) {
// Add as penalty // Add as penalty
data.fastBreakPenalties.add(now, (float) missingTime); data.fastBreakPenalties.add(now, (float) missingTime);
// Only raise a violation, if the total penalty score exceeds the contention duration (for lag, delay). // Only raise a violation, if the total penalty score exceeds the contention duration (for lag, delay).
if (data.fastBreakPenalties.score(cc.fastBreakBucketFactor) > cc.fastBreakGrace) { if (data.fastBreakPenalties.score(cc.fastBreakBucketFactor) > cc.fastBreakGrace) {
// TODO: maybe add one absolute penalty time for big amounts to stop breaking until then // TODO: maybe add one absolute penalty time for big amounts to stop breaking until then
final double vlAdded = (double) missingTime / 1000.0; final double vlAdded = (double) missingTime / 1000.0;
data.fastBreakVL += vlAdded; data.fastBreakVL += vlAdded;
final ViolationData vd = new ViolationData(this, player, data.fastBreakVL, vlAdded, cc.fastBreakActions); final ViolationData vd = new ViolationData(this, player, data.fastBreakVL, vlAdded, cc.fastBreakActions);
if (vd.needsParameters()) { if (vd.needsParameters()) {
vd.setParameter(ParameterName.BLOCK_TYPE, blockType.toString()); vd.setParameter(ParameterName.BLOCK_TYPE, blockType.toString());
}
cancel = executeActions(vd).willCancel();
}
// else: still within contention limits.
} }
cancel = executeActions(vd).willCancel();
}
// else: still within contention limits.
}
} }
else if (expectedBreakingTime > cc.fastBreakDelay) { else if (expectedBreakingTime > cc.fastBreakDelay) {
// Fast breaking does not decrease violation level. // Fast breaking does not decrease violation level.
data.fastBreakVL *= 0.9D; data.fastBreakVL *= 0.9D;
} }
if ((data.debug) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { // TODO: Rework to use (then hopefully completed) BlockBreakKey.
// General stats: if (pData.isDebugActive(type)) {
// TODO: Replace stats by new system (BlockBreakKey once complete), commands to inspect / auto-config. tailDebugStats(player, isInstaBreak, blockType,
if (data.stats != null) { elapsedTime, expectedBreakingTime, data, pData);
data.stats.addStats(data.stats.getId(blockType+ "/u", true), elapsedTime); }
data.stats.addStats(data.stats.getId(blockType + "/r", true), expectedBreakingTime); else {
player.sendMessage(data.stats.getStatsStr(true)); data.stats = null;
}
// Send info about current break:
final ItemStack stack = Bridge1_9.getItemInMainHand(player);
final boolean isValidTool = BlockProperties.isValidTool(blockType, stack);
final double haste = PotionUtil.getPotionEffectAmplifier(player, PotionEffectType.FAST_DIGGING);
String msg = (isInstaBreak.decideOptimistically() ? ("[Insta=" + isInstaBreak + "]") : "[Normal]") + "[" + blockType + "] "+ elapsedTime + "u / " + expectedBreakingTime +"r (" + (isValidTool?"tool":"no-tool") + ")" + (Double.isInfinite(haste) ? "" : " haste=" + ((int) haste + 1));
player.sendMessage(msg);
// net.minecraft.server.Item mcItem = net.minecraft.server.Item.byId[stack.getTypeId()];
// if (mcItem != null) {
// double x = mcItem.getDestroySpeed(((CraftItemStack) stack).getHandle(), net.minecraft.server.Block.byId[blockId]);
// player.sendMessage("mc speed: " + x);
// }
} }
// (The break time is set in the listener). // (The break time is set in the listener).
return cancel; return cancel;
} }
private void tailDebugStats(final Player player, final AlmostBoolean isInstaBreak,
final Material blockType, final long elapsedTime, final long expectedBreakingTime,
final BlockBreakData data, final IPlayerData pData) {
if (pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) {
// General stats:
// TODO: Replace stats by new system (BlockBreakKey once complete), commands to inspect / auto-config.
data.setStats();
data.stats.addStats(data.stats.getId(blockType+ "/u", true), elapsedTime);
data.stats.addStats(data.stats.getId(blockType + "/r", true), expectedBreakingTime);
player.sendMessage(data.stats.getStatsStr(true));
// Send info about current break:
final ItemStack stack = Bridge1_9.getItemInMainHand(player);
final boolean isValidTool = BlockProperties.isValidTool(blockType, stack);
final double haste = PotionUtil.getPotionEffectAmplifier(player, PotionEffectType.FAST_DIGGING);
String msg = (isInstaBreak.decideOptimistically() ? ("[Insta=" + isInstaBreak + "]") : "[Normal]") + "[" + blockType + "] "+ elapsedTime + "u / " + expectedBreakingTime +"r (" + (isValidTool?"tool":"no-tool") + ")" + (Double.isInfinite(haste) ? "" : " haste=" + ((int) haste + 1));
player.sendMessage(msg);
// net.minecraft.server.Item mcItem = net.minecraft.server.Item.byId[stack.getTypeId()];
// if (mcItem != null) {
// double x = mcItem.getDestroySpeed(((CraftItemStack) stack).getHandle(), net.minecraft.server.Block.byId[blockId]);
// player.sendMessage("mc speed: " + x);
// }
}
}
} }

View File

@ -19,6 +19,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.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/** /**
@ -33,7 +34,8 @@ public class Frequency extends Check {
} }
public boolean check(final Player player, final int tick, public boolean check(final Player player, final int tick,
final BlockBreakConfig cc, final BlockBreakData data){ final BlockBreakConfig cc, final BlockBreakData data,
final IPlayerData pData){
final float interval = (float) ((player.getGameMode() == GameMode.CREATIVE)?(cc.frequencyIntervalCreative):(cc.frequencyIntervalSurvival)); final float interval = (float) ((player.getGameMode() == GameMode.CREATIVE)?(cc.frequencyIntervalCreative):(cc.frequencyIntervalSurvival));
data.frequencyBuckets.add(System.currentTimeMillis(), interval); data.frequencyBuckets.add(System.currentTimeMillis(), interval);
@ -41,6 +43,7 @@ public class Frequency extends Check {
// Full period frequency. // Full period frequency.
final float fullScore = data.frequencyBuckets.score(cc.frequencyBucketFactor); final float fullScore = data.frequencyBuckets.score(cc.frequencyBucketFactor);
final long fullTime = cc.frequencyBucketDur * cc.frequencyBuckets; final long fullTime = cc.frequencyBucketDur * cc.frequencyBuckets;
final boolean lag = pData.getCurrentWorldData().shouldAdjustToLag(type);
// Short term arrivals. // Short term arrivals.
if (tick < data.frequencyShortTermTick){ if (tick < data.frequencyShortTermTick){
@ -50,7 +53,7 @@ public class Frequency extends Check {
} }
else if (tick - data.frequencyShortTermTick < cc.frequencyShortTermTicks){ else if (tick - data.frequencyShortTermTick < cc.frequencyShortTermTicks){
// Account for server side lag. // Account for server side lag.
final float stLag = cc.lag ? TickTask.getLag(50L * (tick - data.frequencyShortTermTick), true) : 1f; final float stLag = lag ? TickTask.getLag(50L * (tick - data.frequencyShortTermTick), true) : 1f;
if (stLag < 1.5){ if (stLag < 1.5){
// Within range, add. // Within range, add.
data.frequencyShortTermCount ++; data.frequencyShortTermCount ++;
@ -67,7 +70,7 @@ public class Frequency extends Check {
} }
// Account for server side lag. // Account for server side lag.
final float fullLag = cc.lag ? TickTask.getLag(fullTime, true) : 1f; final float fullLag = lag ? TickTask.getLag(fullTime, true) : 1f;
// Find if one of both or both are violations: // Find if one of both or both are violations:
final float fullViolation = (fullScore > fullTime * fullLag) ? (fullScore - fullTime * fullLag) : 0; final float fullViolation = (fullScore > fullTime * fullLag) ? (fullScore - fullTime * fullLag) : 0;

View File

@ -18,6 +18,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.players.IPlayerData;
/** /**
* We require that the player moves their arm between block breaks, this is what gets checked here. * We require that the player moves their arm between block breaks, this is what gets checked here.
@ -38,7 +39,8 @@ public class NoSwing extends Check {
* the player * the player
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final BlockBreakData data) { public boolean check(final Player player, final BlockBreakData data,
final IPlayerData pData) {
boolean cancel = false; boolean cancel = false;
@ -54,7 +56,7 @@ public class NoSwing extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should // Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event. // cancel the event.
cancel = executeActions(player, data.noSwingVL, 1D, BlockBreakConfig.getConfig(player).noSwingActions).willCancel(); cancel = executeActions(player, data.noSwingVL, 1D, pData.getGenericInstance(BlockBreakConfig.class).noSwingActions).willCancel();
} }
return cancel; return cancel;

View File

@ -51,11 +51,13 @@ public class Reach extends Check {
* *
* @param player * @param player
* the player * the player
* @param cc
* @param location * @param location
* the location * the location
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final double eyeHeight, final Block block, final BlockBreakData data) { public boolean check(final Player player, final double eyeHeight, final Block block,
final BlockBreakData data, final BlockBreakConfig cc) {
boolean cancel = false; boolean cancel = false;
@ -77,7 +79,7 @@ public class Reach extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should // Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event. // cancel the event.
final ViolationData vd = new ViolationData(this, player, data.reachVL, distance, BlockBreakConfig.getConfig(player).reachActions); final ViolationData vd = new ViolationData(this, player, data.reachVL, distance, cc.reachActions);
vd.setParameter(ParameterName.REACH_DISTANCE, String.valueOf(Math.round(data.reachDistance))); vd.setParameter(ParameterName.REACH_DISTANCE, String.valueOf(Math.round(data.reachDistance)));
cancel = executeActions(vd).willCancel(); cancel = executeActions(vd).willCancel();
} else{ } else{

View File

@ -22,7 +22,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.combined.Improbable; import fr.neatmonster.nocheatplus.checks.combined.Improbable;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean; import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil; import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
public class WrongBlock extends Check { public class WrongBlock extends Check {
@ -43,7 +43,7 @@ public class WrongBlock extends Check {
* @return * @return
*/ */
public boolean check(final Player player, final Block block, public boolean check(final Player player, final Block block,
final BlockBreakConfig cc, final BlockBreakData data, final PlayerData pData, final BlockBreakConfig cc, final BlockBreakData data, final IPlayerData pData,
final AlmostBoolean isInstaBreak) { final AlmostBoolean isInstaBreak) {
boolean cancel = false; boolean cancel = false;
@ -52,6 +52,7 @@ public class WrongBlock extends Check {
final int dist = Math.min(4, data.clickedX == Integer.MAX_VALUE ? 100 : TrigUtil.manhattan(data.clickedX, data.clickedY, data.clickedZ, block)); final int dist = Math.min(4, data.clickedX == Integer.MAX_VALUE ? 100 : TrigUtil.manhattan(data.clickedX, data.clickedY, data.clickedZ, block));
final boolean wrongBlock; final boolean wrongBlock;
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final boolean debug = pData.isDebugActive(type);
// TODO: Remove isInstaBreak argument or use it. // TODO: Remove isInstaBreak argument or use it.
if (dist == 0) { if (dist == 0) {
if (wrongTime) { if (wrongTime) {
@ -65,7 +66,7 @@ public class WrongBlock extends Check {
// One might to a concession in case of instant breaking. // One might to a concession in case of instant breaking.
// TODO: WHY ? // TODO: WHY ?
if (now - data.wasInstaBreak < 60) { if (now - data.wasInstaBreak < 60) {
if (data.debug) { if (debug) {
debug(player, "Skip on Manhattan 1 and wasInstaBreak within 60 ms."); debug(player, "Skip on Manhattan 1 and wasInstaBreak within 60 ms.");
} }
wrongBlock = false; wrongBlock = false;
@ -80,7 +81,7 @@ public class WrongBlock extends Check {
} }
if (wrongBlock) { if (wrongBlock) {
if ((data.debug) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { if ((debug) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) {
player.sendMessage("WrongBlock failure with dist: " + dist); player.sendMessage("WrongBlock failure with dist: " + dist);
} }
data.wrongBlockVL.add(now, (float) (dist + 1) / 2f); data.wrongBlockVL.add(now, (float) (dist + 1) / 2f);
@ -89,7 +90,7 @@ public class WrongBlock extends Check {
if (executeActions(player, score, 1D, cc.wrongBlockActions).willCancel()) { if (executeActions(player, score, 1D, cc.wrongBlockActions).willCancel()) {
cancel = true; cancel = true;
} }
if (Improbable.check(player, 2.0f, now, "blockbreak.wrongblock")) { if (Improbable.check(player, 2.0f, now, "blockbreak.wrongblock", pData)) {
cancel = true; cancel = true;
} }
} }

View File

@ -14,20 +14,12 @@
*/ */
package fr.neatmonster.nocheatplus.checks.blockinteract; package fr.neatmonster.nocheatplus.checks.blockinteract;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configurations specific for the block interact checks. Every world gets one of these assigned to it, or if a world * Configurations specific for the block interact checks. Every world gets one of these assigned to it, or if a world
@ -35,55 +27,14 @@ import fr.neatmonster.nocheatplus.permissions.Permissions;
*/ */
public class BlockInteractConfig extends ACheckConfig { public class BlockInteractConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return BlockInteractConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
/** The map containing the configurations per world. */
private static final Map<String, BlockInteractConfig> worldsMap = new HashMap<String, BlockInteractConfig>();
/**
* Clear all the configurations.
*/
public static void clear() {
worldsMap.clear();
}
/**
* Gets the configuration for a specified player.
*
* @param player
* the player
* @return the configuration
*/
public static BlockInteractConfig getConfig(final Player player) {
if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(),
new BlockInteractConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName());
}
public final boolean directionCheck;
public final ActionList directionActions; public final ActionList directionActions;
public final boolean reachCheck;
public final ActionList reachActions; public final ActionList reachActions;
public final boolean speedCheck;
public final long speedInterval; public final long speedInterval;
public final int speedLimit; public final int speedLimit;
public final ActionList speedActions; public final ActionList speedActions;
public final boolean visibleCheck;
public final ActionList visibleActions; public final ActionList visibleActions;
/** /**
@ -92,40 +43,19 @@ public class BlockInteractConfig extends ACheckConfig {
* @param data * @param data
* the data * the data
*/ */
public BlockInteractConfig(final ConfigFile data) { public BlockInteractConfig(final IWorldData worldData) {
super(data, ConfPaths.BLOCKINTERACT); super(worldData);
directionCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_DIRECTION_CHECK); final ConfigFile data = worldData.getRawConfiguration();
directionActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_DIRECTION_ACTIONS, directionActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_DIRECTION_ACTIONS,
Permissions.BLOCKINTERACT_DIRECTION); Permissions.BLOCKINTERACT_DIRECTION);
reachCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_REACH_CHECK);
reachActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, Permissions.BLOCKINTERACT_REACH); reachActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_REACH_ACTIONS, Permissions.BLOCKINTERACT_REACH);
speedCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_SPEED_CHECK);
speedInterval = data.getLong(ConfPaths.BLOCKINTERACT_SPEED_INTERVAL); speedInterval = data.getLong(ConfPaths.BLOCKINTERACT_SPEED_INTERVAL);
speedLimit = data.getInt(ConfPaths.BLOCKINTERACT_SPEED_LIMIT); speedLimit = data.getInt(ConfPaths.BLOCKINTERACT_SPEED_LIMIT);
speedActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_SPEED_ACTIONS, Permissions.BLOCKINTERACT_SPEED); speedActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_SPEED_ACTIONS, Permissions.BLOCKINTERACT_SPEED);
visibleCheck = data.getBoolean(ConfPaths.BLOCKINTERACT_VISIBLE_CHECK);
visibleActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_VISIBLE_ACTIONS, Permissions.BLOCKINTERACT_VISIBLE); visibleActions = data.getOptimizedActionList(ConfPaths.BLOCKINTERACT_VISIBLE_ACTIONS, Permissions.BLOCKINTERACT_VISIBLE);
} }
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster.nocheatplus.checks.CheckType)
*/
@Override
public final boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case BLOCKINTERACT_SPEED:
return speedCheck;
case BLOCKINTERACT_DIRECTION:
return directionCheck;
case BLOCKINTERACT_REACH:
return reachCheck;
case BLOCKINTERACT_VISIBLE:
return visibleCheck;
default:
return true;
}
}
} }

View File

@ -16,23 +16,17 @@ package fr.neatmonster.nocheatplus.checks.blockinteract;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result; import org.bukkit.event.Event.Result;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
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.ICheckData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil; import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
@ -41,53 +35,6 @@ import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
*/ */
public class BlockInteractData extends ACheckData { public class BlockInteractData extends ACheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
@Override
public final ICheckData getData(final Player player) {
return BlockInteractData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return BlockInteractData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return BlockInteractData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
};
/** The map containing the data per players. */
private static final Map<String, BlockInteractData> playersMap = new HashMap<String, BlockInteractData>();
/**
* Gets the data of a specified player.
*
* @param player
* the player
* @return the data
*/
public static BlockInteractData getData(final Player player) {
if (!playersMap.containsKey(player.getName()))
playersMap.put(player.getName(), new BlockInteractData(BlockInteractConfig.getConfig(player)));
return playersMap.get(player.getName());
}
public static ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static void clear(){
playersMap.clear();
}
// Violation levels. // Violation levels.
public double directionVL = 0; public double directionVL = 0;
public double reachVL = 0; public double reachVL = 0;
@ -136,10 +83,6 @@ public class BlockInteractData extends ACheckData {
*/ */
private final Set<CheckType> consumedChecks = new HashSet<CheckType>(); private final Set<CheckType> consumedChecks = new HashSet<CheckType>();
public BlockInteractData(final BlockInteractConfig config) {
super(config);
}
/** /**
* Set last interacted block (coordinates, type, tick). Also resets the * Set last interacted block (coordinates, type, tick). Also resets the
* passed checks. * passed checks.

View File

@ -37,6 +37,8 @@ import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.compat.Bridge1_9; import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.BridgeHealth; import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.compat.BridgeMisc; import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil; import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
@ -52,8 +54,9 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
public class BlockInteractListener extends CheckListener { public class BlockInteractListener extends CheckListener {
public static void debugBlockVSBlockInteract(final Player player, final CheckType checkType, public static void debugBlockVSBlockInteract(final Player player, final CheckType checkType,
final Block block, final String prefix, final Action expectedAction) { final Block block, final String prefix, final Action expectedAction,
final BlockInteractData bdata = BlockInteractData.getData(player); final IPlayerData pData) {
final BlockInteractData bdata = pData.getGenericInstance(BlockInteractData.class);
final int manhattan = bdata.manhattanLastBlock(block); final int manhattan = bdata.manhattanLastBlock(block);
String msg; String msg;
if (manhattan == Integer.MAX_VALUE) { if (manhattan == Integer.MAX_VALUE) {
@ -109,7 +112,8 @@ public class BlockInteractListener extends CheckListener {
@EventHandler(ignoreCancelled = false, priority = EventPriority.LOWEST) @EventHandler(ignoreCancelled = false, priority = EventPriority.LOWEST)
public void onPlayerInteract(final PlayerInteractEvent event) { public void onPlayerInteract(final PlayerInteractEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final BlockInteractData data = BlockInteractData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final BlockInteractData data = pData.getGenericInstance(BlockInteractData.class);
data.resetLastBlock(); data.resetLastBlock();
// Early cancel for interact events with dead players and other. // Early cancel for interact events with dead players and other.
final int cancelId; final int cancelId;
@ -168,7 +172,7 @@ public class BlockInteractListener extends CheckListener {
case RIGHT_CLICK_BLOCK: case RIGHT_CLICK_BLOCK:
stack = Bridge1_9.getUsedItem(player, event); stack = Bridge1_9.getUsedItem(player, event);
if (stack != null && stack.getType() == Material.ENDER_PEARL) { if (stack != null && stack.getType() == Material.ENDER_PEARL) {
checkEnderPearlRightClickBlock(player, block, face, event, previousLastTick, data); checkEnderPearlRightClickBlock(player, block, face, event, previousLastTick, data, pData);
} }
break; break;
default: default:
@ -189,16 +193,16 @@ public class BlockInteractListener extends CheckListener {
} }
} }
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player); final BlockInteractConfig cc = pData.getGenericInstance(BlockInteractConfig.class);
boolean preventUseItem = false; boolean preventUseItem = false;
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
final FlyingQueueHandle flyingHandle = new FlyingQueueHandle(player); final FlyingQueueHandle flyingHandle = new FlyingQueueHandle(pData);
// TODO: Always run all checks, also for !isBlock ? // TODO: Always run all checks, also for !isBlock ?
// Interaction speed. // Interaction speed.
if (!cancelled && speed.isEnabled(player) if (!cancelled && speed.isEnabled(player, pData)
&& speed.check(player, data, cc)) { && speed.check(player, data, cc)) {
cancelled = true; cancelled = true;
preventUseItem = true; preventUseItem = true;
@ -207,27 +211,30 @@ public class BlockInteractListener extends CheckListener {
if (blockChecks) { if (blockChecks) {
final double eyeHeight = MovingUtil.getEyeHeight(player); final double eyeHeight = MovingUtil.getEyeHeight(player);
// First the reach check. // First the reach check.
if (!cancelled && reach.isEnabled(player) if (!cancelled && reach.isEnabled(player, pData)
&& reach.check(player, loc, eyeHeight, block, data, cc)) { && reach.check(player, loc, eyeHeight, block, data, cc)) {
cancelled = true; cancelled = true;
} }
// Second the direction check // Second the direction check
if (!cancelled && direction.isEnabled(player) if (!cancelled && direction.isEnabled(player, pData)
&& direction.check(player, loc, eyeHeight, block, flyingHandle, data, cc)) { && direction.check(player, loc, eyeHeight, block, flyingHandle,
data, cc, pData)) {
cancelled = true; cancelled = true;
} }
// Ray tracing for freecam use etc. // Ray tracing for freecam use etc.
if (!cancelled && visible.isEnabled(player) if (!cancelled && visible.isEnabled(player, pData)
&& visible.check(player, loc, eyeHeight, block, face, action, flyingHandle, data, cc)) { && visible.check(player, loc, eyeHeight, block, face, action, flyingHandle,
data, cc, pData)) {
cancelled = true; cancelled = true;
} }
} }
// If one of the checks requested to cancel the event, do so. // If one of the checks requested to cancel the event, do so.
if (cancelled) { if (cancelled) {
onCancelInteract(player, block, face, event, previousLastTick, preventUseItem, data, cc); onCancelInteract(player, block, face, event, previousLastTick, preventUseItem,
data, cc, pData);
} }
else { else {
if (flyingHandle.isFlyingQueueFetched()) { if (flyingHandle.isFlyingQueueFetched()) {
@ -241,7 +248,7 @@ public class BlockInteractListener extends CheckListener {
cId = idInteractLookFlyingOther; cId = idInteractLookFlyingOther;
} }
counters.add(cId, 1); counters.add(cId, 1);
if (data.debug) { if (pData.isDebugActive(CheckType.BLOCKINTERACT)) {
// Log which entry was used. // Log which entry was used.
logUsedFlyingPacket(player, flyingHandle, flyingIndex); logUsedFlyingPacket(player, flyingHandle, flyingIndex);
} }
@ -266,11 +273,12 @@ public class BlockInteractListener extends CheckListener {
private void onCancelInteract(final Player player, final Block block, final BlockFace face, private void onCancelInteract(final Player player, final Block block, final BlockFace face,
final PlayerInteractEvent event, final int previousLastTick, final boolean preventUseItem, final PlayerInteractEvent event, final int previousLastTick, final boolean preventUseItem,
final BlockInteractData data, final BlockInteractConfig cc) { final BlockInteractData data, final BlockInteractConfig cc, final IPlayerData pData) {
final boolean debug = pData.isDebugActive(CheckType.BLOCKINTERACT);
if (event.isCancelled()) { if (event.isCancelled()) {
// Just prevent using the block. // Just prevent using the block.
event.setUseInteractedBlock(Result.DENY); event.setUseInteractedBlock(Result.DENY);
if (data.debug) { if (debug) {
genericDebug(player, block, face, event, "already cancelled: deny use block", previousLastTick, data, cc); genericDebug(player, block, face, event, "already cancelled: deny use block", previousLastTick, data, cc);
} }
} }
@ -284,7 +292,7 @@ public class BlockInteractListener extends CheckListener {
|| !InventoryUtil.isConsumable(Bridge1_9.getUsedItem(player, event)) || !InventoryUtil.isConsumable(Bridge1_9.getUsedItem(player, event))
) { ) {
event.setUseItemInHand(Result.DENY); event.setUseItemInHand(Result.DENY);
if (data.debug) { if (debug) {
genericDebug(player, block, face, event, "deny item use", previousLastTick, data, cc); genericDebug(player, block, face, event, "deny item use", previousLastTick, data, cc);
} }
} }
@ -292,7 +300,7 @@ public class BlockInteractListener extends CheckListener {
// Consumable and not prevented otherwise. // Consumable and not prevented otherwise.
// TODO: Ender pearl? // TODO: Ender pearl?
event.setUseItemInHand(Result.ALLOW); event.setUseItemInHand(Result.ALLOW);
if (data.debug) { if (debug) {
genericDebug(player, block, face, event, "allow edible item use", previousLastTick, data, cc); genericDebug(player, block, face, event, "allow edible item use", previousLastTick, data, cc);
} }
} }
@ -303,7 +311,8 @@ public class BlockInteractListener extends CheckListener {
public void onPlayerInteractMonitor(final PlayerInteractEvent event) { public void onPlayerInteractMonitor(final PlayerInteractEvent event) {
// Set event resolution. // Set event resolution.
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final BlockInteractData data = BlockInteractData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final BlockInteractData data = pData.getGenericInstance(BlockInteractData.class);
data.setPlayerInteractEventResolution(event); data.setPlayerInteractEventResolution(event);
/* /*
* TODO: BlockDamageEvent fires before BlockInteract/MONITOR level, * TODO: BlockDamageEvent fires before BlockInteract/MONITOR level,
@ -332,14 +341,14 @@ public class BlockInteractListener extends CheckListener {
final ItemStack stack = Bridge1_9.getUsedItem(player, event); final ItemStack stack = Bridge1_9.getUsedItem(player, event);
if (stack != null && BridgeMisc.maybeElytraBoost(player, stack.getType())) { if (stack != null && BridgeMisc.maybeElytraBoost(player, stack.getType())) {
final int power = BridgeMisc.getFireworksPower(stack); final int power = BridgeMisc.getFireworksPower(stack);
final MovingData mData = MovingData.getData(player); final MovingData mData = pData.getGenericInstance(MovingData.class);
final int ticks = Math.max((1 + power) * 20, 30); final int ticks = Math.max((1 + power) * 20, 30);
mData.fireworksBoostDuration = ticks; mData.fireworksBoostDuration = ticks;
// Expiration tick: not general latency, rather a minimum margin for sudden congestion. // Expiration tick: not general latency, rather a minimum margin for sudden congestion.
mData.fireworksBoostTickExpire = TickTask.getTick() + ticks; mData.fireworksBoostTickExpire = TickTask.getTick() + ticks;
// TODO: Invalidation mechanics: by tick/time well ? // TODO: Invalidation mechanics: by tick/time well ?
// TODO: Implement using it in CreativeFly. // TODO: Implement using it in CreativeFly.
if (data.debug) { if (pData.isDebugActive(CheckType.MOVING)) {
debug(player, "Elytra boost (power " + power + "): " + stack); debug(player, "Elytra boost (power " + power + "): " + stack);
} }
} }
@ -348,13 +357,14 @@ public class BlockInteractListener extends CheckListener {
private void checkEnderPearlRightClickBlock(final Player player, final Block block, private void checkEnderPearlRightClickBlock(final Player player, final Block block,
final BlockFace face, final PlayerInteractEvent event, final BlockFace face, final PlayerInteractEvent event,
final int previousLastTick, final BlockInteractData data) { final int previousLastTick, final BlockInteractData data,
final IPlayerData pData) {
if (block == null || !BlockProperties.isPassable(block.getType())) { if (block == null || !BlockProperties.isPassable(block.getType())) {
final CombinedConfig ccc = CombinedConfig.getConfig(player); final CombinedConfig ccc = pData.getGenericInstance(CombinedConfig.class);
if (ccc.enderPearlCheck && ccc.enderPearlPreventClickBlock) { if (ccc.enderPearlCheck && ccc.enderPearlPreventClickBlock) {
event.setUseItemInHand(Result.DENY); event.setUseItemInHand(Result.DENY);
if (data.debug) { if (pData.isDebugActive(CheckType.BLOCKINTERACT)) {
final BlockInteractConfig cc = BlockInteractConfig.getConfig(player); final BlockInteractConfig cc = pData.getGenericInstance(BlockInteractConfig.class);
genericDebug(player, block, face, event, "click block: deny use ender pearl", previousLastTick, data, cc); genericDebug(player, block, face, event, "click block: deny use ender pearl", previousLastTick, data, cc);
} }
} }

View File

@ -29,6 +29,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData; import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle; import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker; import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.collision.InteractRayTracing; import fr.neatmonster.nocheatplus.utilities.collision.InteractRayTracing;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil; import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
@ -113,7 +114,8 @@ public class Visible extends Check {
public boolean check(final Player player, final Location loc, final double eyeHeight, final Block block, public boolean check(final Player player, final Location loc, final double eyeHeight, final Block block,
final BlockFace face, final Action action, final FlyingQueueHandle flyingHandle, final BlockFace face, final Action action, final FlyingQueueHandle flyingHandle,
final BlockInteractData data, final BlockInteractConfig cc) { final BlockInteractData data, final BlockInteractConfig cc,
final IPlayerData pData) {
// TODO: This check might make parts of interact/blockbreak/... + direction (+?) obsolete. // TODO: This check might make parts of interact/blockbreak/... + direction (+?) obsolete.
// TODO: Might confine what to check for (left/right-click, target blocks depending on item in hand, container blocks). // TODO: Might confine what to check for (left/right-click, target blocks depending on item in hand, container blocks).
boolean collides; boolean collides;
@ -124,6 +126,8 @@ public class Visible extends Check {
final double eyeY = loc.getY() + eyeHeight; final double eyeY = loc.getY() + eyeHeight;
final double eyeZ = loc.getZ(); final double eyeZ = loc.getZ();
final boolean debug = pData.isDebugActive(type);
tags.clear(); tags.clear();
if (TrigUtil.isSameBlock(blockX, blockY, blockZ, eyeX, eyeY, eyeZ)) { if (TrigUtil.isSameBlock(blockX, blockY, blockZ, eyeX, eyeY, eyeZ)) {
// Player is interacting with the block their head is in. // Player is interacting with the block their head is in.
@ -137,7 +141,7 @@ public class Visible extends Check {
blockCache.setAccess(loc.getWorld()); blockCache.setAccess(loc.getWorld());
rayTracing.setBlockCache(blockCache); rayTracing.setBlockCache(blockCache);
collides = !checker.checkFlyingQueue(eyeX, eyeY, eyeZ, loc.getYaw(), loc.getPitch(), collides = !checker.checkFlyingQueue(eyeX, eyeY, eyeZ, loc.getYaw(), loc.getPitch(),
blockX, blockY, blockZ, flyingHandle, face, tags, data.debug, player); blockX, blockY, blockZ, flyingHandle, face, tags, debug, player);
checker.cleanup(); checker.cleanup();
useLoc.setWorld(null); useLoc.setWorld(null);
// Cleanup. // Cleanup.
@ -161,7 +165,7 @@ public class Visible extends Check {
else { else {
data.visibleVL *= 0.99; data.visibleVL *= 0.99;
data.addPassedCheck(this.type); data.addPassedCheck(this.type);
if (data.debug) { if (debug) {
debug(player, "pitch=" + loc.getPitch() + ",yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+")); debug(player, "pitch=" + loc.getPitch() + ",yaw=" + loc.getYaw() + " tags=" + StringUtil.join(tags, "+"));
} }
} }

View File

@ -25,7 +25,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData; import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractData; import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractData;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
/** /**
* Check if the placing is legitimate in terms of surrounding materials. * Check if the placing is legitimate in terms of surrounding materials.
@ -40,16 +40,16 @@ public class Against extends Check {
public boolean check(final Player player, final Block block, final Material placedMat, public boolean check(final Player player, final Block block, final Material placedMat,
final Block blockAgainst, final boolean isInteractBlock, final Block blockAgainst, final boolean isInteractBlock,
final BlockPlaceData data, final BlockPlaceConfig cc, final PlayerData pData) { final BlockPlaceData data, final BlockPlaceConfig cc, final IPlayerData pData) {
boolean violation = false; boolean violation = false;
// TODO: Make more precise (workarounds like WATER_LILY, general points, such as action?). // TODO: Make more precise (workarounds like WATER_LILY, general points, such as action?).
// Workaround for signs on cactus and similar. // Workaround for signs on cactus and similar.
final BlockInteractData bdata = BlockInteractData.getData(player); // TODO: pass as argument. final BlockInteractData bdata = pData.getGenericInstance(BlockInteractData.class); // TODO: pass as argument.
final Material againstType = blockAgainst.getType(); final Material againstType = blockAgainst.getType();
if (bdata.isConsumedCheck(this.type) && !bdata.isPassedCheck(this.type)) { if (bdata.isConsumedCheck(this.type) && !bdata.isPassedCheck(this.type)) {
// TODO: Awareness of repeated violation probably is to be implemented below somewhere. // TODO: Awareness of repeated violation probably is to be implemented below somewhere.
violation = true; violation = true;
if (data.debug) { if (pData.isDebugActive(type)) {
debug(player, "Cancel due to block having been consumed by this check."); debug(player, "Cancel due to block having been consumed by this check.");
} }
} }

View File

@ -27,6 +27,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
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.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -50,19 +51,20 @@ public class AutoSign extends Check {
super(CheckType.BLOCKPLACE_AUTOSIGN); super(CheckType.BLOCKPLACE_AUTOSIGN);
} }
public boolean check(final Player player, final Block block, final String[] lines) { public boolean check(final Player player, final Block block, final String[] lines,
final IPlayerData pData) {
// TODO: Might want to reset time + hash ? // TODO: Might want to reset time + hash ?
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
tags.clear(); tags.clear();
final BlockPlaceData data = BlockPlaceData.getData(player); final BlockPlaceData data = pData.getGenericInstance(BlockPlaceData.class);
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); final BlockPlaceConfig cc = pData.getGenericInstance(BlockPlaceConfig.class);
Material mat = block.getType(); Material mat = block.getType();
if (mat == Material.SIGN_POST || mat == Material.WALL_SIGN) { if (mat == Material.SIGN_POST || mat == Material.WALL_SIGN) {
mat = Material.SIGN; mat = Material.SIGN;
} }
if (data.autoSignPlacedHash != BlockPlaceListener.getBlockPlaceHash(block, mat)){ if (data.autoSignPlacedHash != BlockPlaceListener.getBlockPlaceHash(block, mat)){
tags.add("block_mismatch"); tags.add("block_mismatch");
return handleViolation(player, maxEditTime, data); return handleViolation(player, maxEditTime, data, cc);
} }
if (time < data.autoSignPlacedTime){ if (time < data.autoSignPlacedTime){
data.autoSignPlacedTime = 0; data.autoSignPlacedTime = 0;
@ -80,7 +82,7 @@ public class AutoSign extends Check {
if (expected > editTime){ if (expected > editTime){
tags.add("edit_time"); tags.add("edit_time");
return handleViolation(player, expected - editTime, data); return handleViolation(player, expected - editTime, data, cc);
} }
return false; return false;
} }
@ -117,10 +119,12 @@ public class AutoSign extends Check {
* @param data * @param data
* @return * @return
*/ */
private boolean handleViolation(final Player player, final long violationTime, final BlockPlaceData data) { private boolean handleViolation(final Player player, final long violationTime,
final BlockPlaceData data, final BlockPlaceConfig cc) {
final double addedVL = 10.0 * Math.min(maxEditTime, violationTime) / maxEditTime; final double addedVL = 10.0 * Math.min(maxEditTime, violationTime) / maxEditTime;
data.autoSignVL += addedVL; data.autoSignVL += addedVL;
final ViolationData vd = new ViolationData(this, player, data.autoSignVL, addedVL, BlockPlaceConfig.getConfig(player).autoSignActions); final ViolationData vd = new ViolationData(
this, player, data.autoSignVL, addedVL, cc.autoSignActions);
if (vd.needsParameters()){ if (vd.needsParameters()){
vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+")); vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+"));
} }

View File

@ -14,23 +14,17 @@
*/ */
package fr.neatmonster.nocheatplus.checks.blockplace; package fr.neatmonster.nocheatplus.checks.blockplace;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configurations specific for the block place checks. Every world gets one of these assigned to it, or if a world * Configurations specific for the block place checks. Every world gets one of these assigned to it, or if a world
@ -38,67 +32,23 @@ import fr.neatmonster.nocheatplus.permissions.Permissions;
*/ */
public class BlockPlaceConfig extends ACheckConfig { public class BlockPlaceConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return BlockPlaceConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
/** The map containing the configurations per world. */
private static final Map<String, BlockPlaceConfig> worldsMap = new HashMap<String, BlockPlaceConfig>();
/**
* Clear all the configurations.
*/
public static void clear() {
worldsMap.clear();
}
/**
* Gets the configuration for a specified player.
*
* @param player
* the player
* @return the configuration
*/
public static BlockPlaceConfig getConfig(final Player player) {
if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(),
new BlockPlaceConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName());
}
public final boolean againstCheck;
public final ActionList againstActions; public final ActionList againstActions;
public final boolean autoSignCheck;
public final boolean autoSignSkipEmpty; public final boolean autoSignSkipEmpty;
public final ActionList autoSignActions; public final ActionList autoSignActions;
public final boolean directionCheck;
public final ActionList directionActions; public final ActionList directionActions;
public final boolean fastPlaceCheck;
public final int fastPlaceLimit; public final int fastPlaceLimit;
public final int fastPlaceShortTermTicks; public final int fastPlaceShortTermTicks;
public final int fastPlaceShortTermLimit; public final int fastPlaceShortTermLimit;
public final ActionList fastPlaceActions; public final ActionList fastPlaceActions;
public final boolean noSwingCheck;
public final Set<Material> noSwingExceptions = new HashSet<Material>(); public final Set<Material> noSwingExceptions = new HashSet<Material>();
public final ActionList noSwingActions; public final ActionList noSwingActions;
public final boolean reachCheck;
public final ActionList reachActions; public final ActionList reachActions;
public final boolean speedCheck;
public final long speedInterval; public final long speedInterval;
public final ActionList speedActions; public final ActionList speedActions;
@ -111,34 +61,28 @@ public class BlockPlaceConfig extends ACheckConfig {
* @param config * @param config
* *
*/ */
public BlockPlaceConfig(final ConfigFile config) { public BlockPlaceConfig(final IWorldData worldData) {
super(config, ConfPaths.BLOCKPLACE); super(worldData);
final ConfigFile config = worldData.getRawConfiguration();
againstCheck = config.getBoolean(ConfPaths.BLOCKPLACE_AGAINST_CHECK);
againstActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_AGAINST_ACTIONS, Permissions.BLOCKPLACE_AGAINST); againstActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_AGAINST_ACTIONS, Permissions.BLOCKPLACE_AGAINST);
autoSignCheck = config.getBoolean(ConfPaths.BLOCKPLACE_AUTOSIGN_CHECK);
autoSignSkipEmpty = config.getBoolean(ConfPaths.BLOCKPLACE_AUTOSIGN_SKIPEMPTY); autoSignSkipEmpty = config.getBoolean(ConfPaths.BLOCKPLACE_AUTOSIGN_SKIPEMPTY);
autoSignActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_AUTOSIGN_ACTIONS, Permissions.BLOCKPLACE_AUTOSIGN); autoSignActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_AUTOSIGN_ACTIONS, Permissions.BLOCKPLACE_AUTOSIGN);
directionCheck = config.getBoolean(ConfPaths.BLOCKPLACE_DIRECTION_CHECK);
directionActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, Permissions.BLOCKPLACE_DIRECTION); directionActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, Permissions.BLOCKPLACE_DIRECTION);
fastPlaceCheck = config.getBoolean(ConfPaths.BLOCKPLACE_FASTPLACE_CHECK);
fastPlaceLimit = config.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_LIMIT); fastPlaceLimit = config.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_LIMIT);
fastPlaceShortTermTicks = config.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_SHORTTERM_TICKS); fastPlaceShortTermTicks = config.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_SHORTTERM_TICKS);
fastPlaceShortTermLimit = config.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_SHORTTERM_LIMIT); fastPlaceShortTermLimit = config.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_SHORTTERM_LIMIT);
fastPlaceActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_FASTPLACE_ACTIONS, Permissions.BLOCKPLACE_FASTPLACE); fastPlaceActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_FASTPLACE_ACTIONS, Permissions.BLOCKPLACE_FASTPLACE);
noSwingCheck = config.getBoolean(ConfPaths.BLOCKPLACE_NOSWING_CHECK);
config.readMaterialFromList(ConfPaths.BLOCKPLACE_NOSWING_EXCEPTIONS, noSwingExceptions); config.readMaterialFromList(ConfPaths.BLOCKPLACE_NOSWING_EXCEPTIONS, noSwingExceptions);
noSwingActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_NOSWING_ACTIONS, Permissions.BLOCKPLACE_NOSWING); noSwingActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_NOSWING_ACTIONS, Permissions.BLOCKPLACE_NOSWING);
reachCheck = config.getBoolean(ConfPaths.BLOCKPLACE_REACH_CHECK);
reachActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_REACH_ACTIONS, Permissions.BLOCKPLACE_REACH); reachActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_REACH_ACTIONS, Permissions.BLOCKPLACE_REACH);
speedCheck = config.getBoolean(ConfPaths.BLOCKPLACE_SPEED_CHECK);
speedInterval = config.getLong(ConfPaths.BLOCKPLACE_SPEED_INTERVAL); speedInterval = config.getLong(ConfPaths.BLOCKPLACE_SPEED_INTERVAL);
speedActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_SPEED_ACTIONS, Permissions.BLOCKPLACE_SPEED); speedActions = config.getOptimizedActionList(ConfPaths.BLOCKPLACE_SPEED_ACTIONS, Permissions.BLOCKPLACE_SPEED);
@ -152,28 +96,4 @@ public class BlockPlaceConfig extends ACheckConfig {
*/ */
} }
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster.nocheatplus.checks.CheckType)
*/
@Override
public final boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case BLOCKPLACE_DIRECTION:
return directionCheck;
case BLOCKPLACE_FASTPLACE:
return fastPlaceCheck;
case BLOCKPLACE_NOSWING:
return noSwingCheck;
case BLOCKPLACE_REACH:
return reachCheck;
case BLOCKPLACE_SPEED:
return speedCheck;
case BLOCKPLACE_AGAINST:
return againstCheck;
case BLOCKPLACE_AUTOSIGN:
return autoSignCheck;
default:
return true;
}
}
} }

View File

@ -14,15 +14,7 @@
*/ */
package fr.neatmonster.nocheatplus.checks.blockplace; package fr.neatmonster.nocheatplus.checks.blockplace;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
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.ICheckData;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
/** /**
@ -30,53 +22,6 @@ import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
*/ */
public class BlockPlaceData extends ACheckData { public class BlockPlaceData extends ACheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
@Override
public final ICheckData getData(final Player player) {
return BlockPlaceData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return BlockPlaceData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return BlockPlaceData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
};
/** The map containing the data per players. */
private static final Map<String, BlockPlaceData> playersMap = new HashMap<String, BlockPlaceData>();
/**
* Gets the data of a specified player.
*
* @param player
* the player
* @return the data
*/
public static BlockPlaceData getData(final Player player) {
if (!playersMap.containsKey(player.getName()))
playersMap.put(player.getName(), new BlockPlaceData(BlockPlaceConfig.getConfig(player)));
return playersMap.get(player.getName());
}
public static ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static void clear(){
playersMap.clear();
}
// Violation levels. // Violation levels.
public double againstVL = 0; public double againstVL = 0;
public double autoSignVL = 0; public double autoSignVL = 0;
@ -106,8 +51,4 @@ public class BlockPlaceData extends ACheckData {
public boolean speedLastRefused; public boolean speedLastRefused;
public long speedLastTime; public long speedLastTime;
public BlockPlaceData(final BlockPlaceConfig config) {
super (config);
}
} }

View File

@ -49,7 +49,7 @@ import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.BridgeMisc; import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil; import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil; import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
@ -153,14 +153,15 @@ public class BlockPlaceListener extends CheckListener {
} }
boolean cancelled = false; boolean cancelled = false;
final PlayerData pData = DataManager.getPlayerData(player); // TODO: Use for data + config getting etc. final IPlayerData pData = DataManager.getPlayerData(player); // TODO: Use for data + config getting etc.
final BlockPlaceData data = BlockPlaceData.getData(player); final BlockPlaceData data = pData.getGenericInstance(BlockPlaceData.class);
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); final BlockPlaceConfig cc = pData.getGenericInstance(BlockPlaceConfig.class);
final BlockInteractData bdata = BlockInteractData.getData(player); final BlockInteractData bdata = pData.getGenericInstance(BlockInteractData.class);
final int tick = TickTask.getTick(); final int tick = TickTask.getTick();
// isInteractBlock - the block placed against is the block last interacted with. // isInteractBlock - the block placed against is the block last interacted with.
final boolean isInteractBlock = !bdata.getLastIsCancelled() && bdata.matchesLastBlock(tick, blockAgainst); final boolean isInteractBlock = !bdata.getLastIsCancelled() && bdata.matchesLastBlock(tick, blockAgainst);
int skippedRedundantChecks = 0; int skippedRedundantChecks = 0;
final boolean debug = pData.isDebugActive(CheckType.BLOCKPLACE);
final boolean shouldSkipSome; final boolean shouldSkipSome;
if (blockMultiPlaceEvent != null && event.getClass() == blockMultiPlaceEvent) { if (blockMultiPlaceEvent != null && event.getClass() == blockMultiPlaceEvent) {
@ -169,7 +170,7 @@ public class BlockPlaceListener extends CheckListener {
shouldSkipSome = true; shouldSkipSome = true;
} }
else { else {
if (data.debug) { if (debug) {
debug(player, "Block place " + event.getClass().getName() + " " + placedMat); debug(player, "Block place " + event.getClass().getName() + " " + placedMat);
} }
shouldSkipSome = false; shouldSkipSome = false;
@ -187,31 +188,33 @@ public class BlockPlaceListener extends CheckListener {
} }
// Don't run checks, if a set back is scheduled. // Don't run checks, if a set back is scheduled.
if (!cancelled && MovingUtil.hasScheduledPlayerSetBack(player)) { if (!cancelled && pData.isPlayerSetBackScheduled()) {
cancelled = true; cancelled = true;
} }
// Fast place check. // Fast place check.
if (!cancelled && fastPlace.isEnabled(player)) { if (!cancelled && fastPlace.isEnabled(player, pData)) {
if (fastPlace.check(player, block, tick, data, cc)) { if (fastPlace.check(player, block, tick, data, cc, pData)) {
cancelled = true; cancelled = true;
} }
else { else {
// Feed the improbable. // Feed the improbable.
Improbable.feed(player, 0.5f, System.currentTimeMillis()); Improbable.feed(player, 0.5f, System.currentTimeMillis(), pData);
} }
} }
// No swing check (player doesn't swing their arm when placing a lily pad). // No swing check (player doesn't swing their arm when placing a lily pad).
if (!cancelled && !cc.noSwingExceptions.contains(placedMat) if (!cancelled && !cc.noSwingExceptions.contains(placedMat)
&& noSwing.isEnabled(player) && noSwing.check(player, data, cc)) { && noSwing.isEnabled(player, pData) && noSwing.check(player, data, cc)) {
// Consider skipping all insta placables or using simplified version (true or true within time frame). // Consider skipping all insta placables or using simplified version (true or true within time frame).
cancelled = true; cancelled = true;
} }
final FlyingQueueHandle flyingHandle; final FlyingQueueHandle flyingHandle;
if (cc.reachCheck || cc.directionCheck) { final boolean reachCheck = pData.isCheckActive(CheckType.BLOCKPLACE_REACH, player);
flyingHandle = new FlyingQueueHandle(player); final boolean directionCheck = pData.isCheckActive(CheckType.BLOCKPLACE_DIRECTION, player);
if (reachCheck || directionCheck) {
flyingHandle = new FlyingQueueHandle(pData);
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
final double eyeHeight = MovingUtil.getEyeHeight(player); final double eyeHeight = MovingUtil.getEyeHeight(player);
// Reach check (distance). // Reach check (distance).
@ -219,7 +222,7 @@ public class BlockPlaceListener extends CheckListener {
if (isInteractBlock && bdata.isPassedCheck(CheckType.BLOCKINTERACT_REACH)) { if (isInteractBlock && bdata.isPassedCheck(CheckType.BLOCKINTERACT_REACH)) {
skippedRedundantChecks ++; skippedRedundantChecks ++;
} }
else if (reach.isEnabled(player) && reach.check(player, eyeHeight, block, data, cc)) { else if (reachCheck && reach.check(player, eyeHeight, block, data, cc)) {
cancelled = true; cancelled = true;
} }
} }
@ -229,8 +232,8 @@ public class BlockPlaceListener extends CheckListener {
if (isInteractBlock && bdata.isPassedCheck(CheckType.BLOCKINTERACT_DIRECTION)) { if (isInteractBlock && bdata.isPassedCheck(CheckType.BLOCKINTERACT_DIRECTION)) {
skippedRedundantChecks ++; skippedRedundantChecks ++;
} }
else if (direction.isEnabled(player) && direction.check(player, loc, eyeHeight, block, else if (directionCheck && direction.check(player, loc, eyeHeight, block,
flyingHandle, data, cc)) { flyingHandle, data, cc, pData)) {
cancelled = true; cancelled = true;
} }
} }
@ -241,7 +244,7 @@ public class BlockPlaceListener extends CheckListener {
} }
// Surrounding material. // Surrounding material.
if (!cancelled && against.isEnabled(player) && against.check(player, block, placedMat, blockAgainst, if (!cancelled && against.isEnabled(player, pData) && against.check(player, block, placedMat, blockAgainst,
isInteractBlock, data, cc, pData)) { isInteractBlock, data, cc, pData)) {
cancelled = true; cancelled = true;
} }
@ -252,8 +255,9 @@ public class BlockPlaceListener extends CheckListener {
} }
else { else {
// Debug log (only if not cancelled, to avoid spam). // Debug log (only if not cancelled, to avoid spam).
if (data.debug) { if (debug) {
debugBlockPlace(player, placedMat, block, blockAgainst, skippedRedundantChecks, flyingHandle); debugBlockPlace(player, placedMat, block, blockAgainst,
skippedRedundantChecks, flyingHandle, pData);
} }
} }
// Cleanup // Cleanup
@ -262,10 +266,12 @@ public class BlockPlaceListener extends CheckListener {
private void debugBlockPlace(final Player player, final Material placedMat, private void debugBlockPlace(final Player player, final Material placedMat,
final Block block, final Block blockAgainst, final Block block, final Block blockAgainst,
final int skippedRedundantChecks, final FlyingQueueHandle flyingHandle) { final int skippedRedundantChecks, final FlyingQueueHandle flyingHandle,
final IPlayerData pData) {
debug(player, "Block place(" + placedMat + "): " + block.getX() + ", " + block.getY() + ", " + block.getZ()); debug(player, "Block place(" + placedMat + "): " + block.getX() + ", " + block.getY() + ", " + block.getZ());
BlockInteractListener.debugBlockVSBlockInteract(player, checkType, blockAgainst, "onBlockPlace(blockAgainst)", BlockInteractListener.debugBlockVSBlockInteract(player, checkType,
Action.RIGHT_CLICK_BLOCK); blockAgainst, "onBlockPlace(blockAgainst)", Action.RIGHT_CLICK_BLOCK,
pData);
if (skippedRedundantChecks > 0) { if (skippedRedundantChecks > 0) {
debug(player, "Skipped redundant checks: " + skippedRedundantChecks); debug(player, "Skipped redundant checks: " + skippedRedundantChecks);
} }
@ -293,7 +299,8 @@ public class BlockPlaceListener extends CheckListener {
// Somewhat defensive. // Somewhat defensive.
return; return;
} }
if (autoSign.isEnabled(player) && autoSign.check(player, block, lines)) { final IPlayerData pData = DataManager.getPlayerData(player);
if (autoSign.isEnabled(player, pData) && autoSign.check(player, block, lines, pData)) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@ -309,7 +316,7 @@ public class BlockPlaceListener extends CheckListener {
priority = EventPriority.MONITOR) priority = EventPriority.MONITOR)
public void onPlayerAnimation(final PlayerAnimationEvent event) { public void onPlayerAnimation(final PlayerAnimationEvent event) {
// Just set a flag to true when the arm was swung. // Just set a flag to true when the arm was swung.
BlockPlaceData.getData(event.getPlayer()).noSwingArmSwung = true; DataManager.getPlayerData(event.getPlayer()).getGenericInstance(BlockPlaceData.class).noSwingArmSwung = true;
} }
/** /**
@ -334,11 +341,11 @@ public class BlockPlaceListener extends CheckListener {
return; return;
} }
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final BlockPlaceConfig cc = pData.getGenericInstance(BlockPlaceConfig.class);
final Material type = stack.getType(); final Material type = stack.getType();
if (InventoryUtil.isBoat(type)) { if (InventoryUtil.isBoat(type)) {
if (cc.preventBoatsAnywhere) { if (cc.preventBoatsAnywhere) {
final PlayerData pData = DataManager.getPlayerData(player); // TODO: Use for data + config getting etc.
// TODO: Alter config (activation, allow on top of ground). // TODO: Alter config (activation, allow on top of ground).
// TODO: Version/plugin specific alteration for 'default'. // TODO: Version/plugin specific alteration for 'default'.
checkBoatsAnywhere(player, event, cc, pData); checkBoatsAnywhere(player, event, cc, pData);
@ -346,7 +353,7 @@ public class BlockPlaceListener extends CheckListener {
} }
else if (type == Material.MONSTER_EGG) { else if (type == Material.MONSTER_EGG) {
// Check blockplace.speed. // Check blockplace.speed.
if (speed.isEnabled(player, cc) && speed.check(player, cc)) { if (speed.isEnabled(player, pData) && speed.check(player, cc, pData)) {
// If the check was positive, cancel the event. // If the check was positive, cancel the event.
event.setCancelled(true); event.setCancelled(true);
} }
@ -354,7 +361,7 @@ public class BlockPlaceListener extends CheckListener {
} }
private void checkBoatsAnywhere(final Player player, final PlayerInteractEvent event, private void checkBoatsAnywhere(final Player player, final PlayerInteractEvent event,
final BlockPlaceConfig cc, final PlayerData pData) { final BlockPlaceConfig cc, final IPlayerData pData) {
// Check boats-anywhere. // Check boats-anywhere.
final Block block = event.getClickedBlock(); final Block block = event.getClickedBlock();
final Material mat = block.getType(); final Material mat = block.getType();
@ -426,20 +433,21 @@ public class BlockPlaceListener extends CheckListener {
} }
// Do the actual check... // Do the actual check...
final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final BlockPlaceConfig cc = pData.getGenericInstance(BlockPlaceConfig.class);
boolean cancel = false; boolean cancel = false;
if (speed.isEnabled(player)) { if (speed.isEnabled(player, pData)) {
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName())) { if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName(), pData)) {
// Yawrate (checked extra). // Yawrate (checked extra).
cancel = true; cancel = true;
} }
if (speed.check(player, cc)) { if (speed.check(player, cc, pData)) {
// If the check was positive, cancel the event. // If the check was positive, cancel the event.
cancel = true; cancel = true;
} }
else if (Improbable.check(player, 0.6f, now, "blockplace.speed")) { else if (Improbable.check(player, 0.6f, now, "blockplace.speed", pData)) {
// Combined fighting speed. // Combined fighting speed.
cancel = true; cancel = true;
} }
@ -447,7 +455,7 @@ public class BlockPlaceListener extends CheckListener {
// Ender pearl glitch (ab-) use. // Ender pearl glitch (ab-) use.
if (!cancel && type == EntityType.ENDER_PEARL) { if (!cancel && type == EntityType.ENDER_PEARL) {
if (!CombinedConfig.getConfig(player).enderPearlCheck) { if (!pData.getGenericInstance(CombinedConfig.class).enderPearlCheck) {
// Do nothing ! // Do nothing !
// TODO: Might have further flags? // TODO: Might have further flags?
} }
@ -468,7 +476,9 @@ public class BlockPlaceListener extends CheckListener {
final long flags = BlockProperties.F_CLIMBABLE | BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE; final long flags = BlockProperties.F_CLIMBABLE | BlockProperties.F_LIQUID | BlockProperties.F_IGN_PASSABLE;
if (!BlockProperties.isAir(mat) && (BlockProperties.getBlockFlags(mat) & flags) == 0 && !mcAccess.getHandle().hasGravity(mat)) { if (!BlockProperties.isAir(mat) && (BlockProperties.getBlockFlags(mat) & flags) == 0 && !mcAccess.getHandle().hasGravity(mat)) {
// Still fails on piston traps etc. // Still fails on piston traps etc.
if (!BlockProperties.isPassable(player.getLocation(), projectile.getLocation()) && !BlockProperties.isOnGroundOrResetCond(player, player.getLocation(), MovingConfig.getConfig(player).yOnGround)) { if (!BlockProperties.isPassable(player.getLocation(), projectile.getLocation())
&& !BlockProperties.isOnGroundOrResetCond(player, player.getLocation(),
pData.getGenericInstance(MovingConfig.class).yOnGround)) {
cancel = true; cancel = true;
} }
} }

View File

@ -19,6 +19,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.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/** /**
@ -44,9 +45,11 @@ public class FastPlace extends Check {
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final Block block, final int tick, public boolean check(final Player player, final Block block, final int tick,
final BlockPlaceData data, final BlockPlaceConfig cc) { final BlockPlaceData data, final BlockPlaceConfig cc,
final IPlayerData pData) {
data.fastPlaceBuckets.add(System.currentTimeMillis(), 1f); data.fastPlaceBuckets.add(System.currentTimeMillis(), 1f);
final boolean lag = pData.getCurrentWorldData().shouldAdjustToLag(type);
// Full period frequency. // Full period frequency.
final float fullScore = data.fastPlaceBuckets.score(1f); final float fullScore = data.fastPlaceBuckets.score(1f);
@ -59,7 +62,7 @@ public class FastPlace extends Check {
} }
else if (tick - data.fastPlaceShortTermTick < cc.fastPlaceShortTermTicks){ else if (tick - data.fastPlaceShortTermTick < cc.fastPlaceShortTermTicks){
// Account for server side lag. // Account for server side lag.
if (!cc.lag || TickTask.getLag(50L * (tick - data.fastPlaceShortTermTick), true) < 1.2f){ if (!lag || TickTask.getLag(50L * (tick - data.fastPlaceShortTermTick), true) < 1.2f){
// Within range, add. // Within range, add.
data.fastPlaceShortTermCount ++; data.fastPlaceShortTermCount ++;
} }
@ -78,7 +81,7 @@ public class FastPlace extends Check {
final float fullViolation; final float fullViolation;
if (fullScore > cc.fastPlaceLimit) { if (fullScore > cc.fastPlaceLimit) {
// Account for server side lag. // Account for server side lag.
if (cc.lag) { if (lag) {
fullViolation = fullScore / TickTask.getLag(data.fastPlaceBuckets.bucketDuration() * data.fastPlaceBuckets.numberOfBuckets(), true) - cc.fastPlaceLimit; fullViolation = fullScore / TickTask.getLag(data.fastPlaceBuckets.bucketDuration() * data.fastPlaceBuckets.numberOfBuckets(), true) - cc.fastPlaceLimit;
} }
else{ else{

View File

@ -18,6 +18,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.players.IPlayerData;
/** /**
* This check verifies if the player isn't throwing items too quickly, like eggs or arrows. * This check verifies if the player isn't throwing items too quickly, like eggs or arrows.
@ -39,8 +40,9 @@ public class Speed extends Check {
* @param cc * @param cc
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final BlockPlaceConfig cc) { public boolean check(final Player player,
final BlockPlaceData data = BlockPlaceData.getData(player); final BlockPlaceConfig cc, final IPlayerData pData) {
final BlockPlaceData data = pData.getGenericInstance(BlockPlaceData.class);
boolean cancel = false; boolean cancel = false;

View File

@ -20,9 +20,8 @@ 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.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.ColorUtil; import fr.neatmonster.nocheatplus.utilities.ColorUtil;
@ -91,14 +90,15 @@ public class Captcha extends Check implements ICaptcha{
@Override @Override
public void resetCaptcha(Player player){ public void resetCaptcha(Player player){
ChatData data = ChatData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
ChatData data = pData.getGenericInstance(ChatData.class);
synchronized (data) { synchronized (data) {
resetCaptcha(player, ChatConfig.getConfig(player), data, DataManager.getPlayerData(player)); resetCaptcha(player, pData.getGenericInstance(ChatConfig.class), data, pData);
} }
} }
@Override @Override
public void resetCaptcha(Player player, ChatConfig cc, ChatData data, PlayerData pData){ public void resetCaptcha(Player player, ChatConfig cc, ChatData data, IPlayerData pData){
data.captchTries = 0; data.captchTries = 0;
if (shouldCheckCaptcha(player, cc, data, pData) if (shouldCheckCaptcha(player, cc, data, pData)
|| shouldStartCaptcha(player, cc, data, pData)){ || shouldStartCaptcha(player, cc, data, pData)){
@ -113,12 +113,15 @@ public class Captcha extends Check implements ICaptcha{
} }
@Override @Override
public boolean shouldStartCaptcha(Player player, ChatConfig cc, ChatData data, PlayerData pData) { public boolean shouldStartCaptcha(Player player, ChatConfig cc, ChatData data, IPlayerData pData) {
return cc.captchaCheck && !data.captchaStarted && !pData.hasPermission(Permissions.CHAT_CAPTCHA, player); // TODO: Only call if IWorldData.isCheckActive(CHAT_CAPTCHA) has returned true?
return !data.captchaStarted && pData.isCheckActive(CheckType.CHAT_CAPTCHA, player);
} }
@Override @Override
public boolean shouldCheckCaptcha(Player player, ChatConfig cc, ChatData data, PlayerData pData) { public boolean shouldCheckCaptcha(Player player, ChatConfig cc, ChatData data, IPlayerData pData) {
return cc.captchaCheck && data.captchaStarted && !pData.hasPermission(Permissions.CHAT_CAPTCHA, player); // TODO: Only call if IWorldData.isCheckActive(CHAT_CAPTCHA) has returned true?
return data.captchaStarted && pData.isCheckActive(CheckType.CHAT_CAPTCHA, player);
} }
} }

View File

@ -14,23 +14,15 @@
*/ */
package fr.neatmonster.nocheatplus.checks.chat; package fr.neatmonster.nocheatplus.checks.chat;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.EnginePlayerConfig; import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.EnginePlayerConfig;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.permissions.RegisteredPermission; import fr.neatmonster.nocheatplus.permissions.RegisteredPermission;
import fr.neatmonster.nocheatplus.utilities.ColorUtil; import fr.neatmonster.nocheatplus.utilities.ColorUtil;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configurations specific for the "chat" checks. Every world gets one of these assigned to it, or if a world doesn't * Configurations specific for the "chat" checks. Every world gets one of these assigned to it, or if a world doesn't
@ -38,20 +30,8 @@ import fr.neatmonster.nocheatplus.utilities.ColorUtil;
*/ */
public class ChatConfig extends ACheckConfig { public class ChatConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return ChatConfig.getConfig(player);
}
@Override private static final RegisteredPermission[] preferKeepUpdatedPermissions = new RegisteredPermission[]{
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
private static RegisteredPermission[] preferKeepUpdatedPermissions = new RegisteredPermission[]{
// Only the permissions needed for async. checking. // Only the permissions needed for async. checking.
Permissions.CHAT_COLOR, Permissions.CHAT_COLOR,
Permissions.CHAT_TEXT, Permissions.CHAT_TEXT,
@ -59,39 +39,10 @@ public class ChatConfig extends ACheckConfig {
// TODO: COMMANDS, in case of handleascommand? // TODO: COMMANDS, in case of handleascommand?
}; };
/** The map containing the configurations per world. */
private static final Map<String, ChatConfig> worldsMap = new HashMap<String, ChatConfig>();
public static RegisteredPermission[] getPreferKeepUpdatedPermissions() { public static RegisteredPermission[] getPreferKeepUpdatedPermissions() {
return preferKeepUpdatedPermissions; return preferKeepUpdatedPermissions;
} }
/**
* Clear all the configurations.
*/
public static void clear() {
synchronized (worldsMap) {
worldsMap.clear();
}
}
/**
* Gets the configuration for a specified player.
*
* @param player
* the player
* @return the configuration
*/
public static ChatConfig getConfig(final Player player) {
synchronized (worldsMap) {
if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(),
new ChatConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName());
}
}
public final boolean captchaCheck;
public final boolean captchaSkipCommands; public final boolean captchaSkipCommands;
public final String captchaCharacters; public final String captchaCharacters;
public final int captchaLength; public final int captchaLength;
@ -100,16 +51,14 @@ public class ChatConfig extends ACheckConfig {
public final int captchaTries; public final int captchaTries;
public final ActionList captchaActions; public final ActionList captchaActions;
public final boolean colorCheck;
public final ActionList colorActions; public final ActionList colorActions;
public final boolean commandsCheck;
public final double commandsLevel; public final double commandsLevel;
public final int commandsShortTermTicks; public final int commandsShortTermTicks;
public final double commandsShortTermLevel; public final double commandsShortTermLevel;
public final ActionList commandsActions; public final ActionList commandsActions;
public final boolean textCheck; // TODO: Sub check types ?
public final boolean textGlobalCheck; public final boolean textGlobalCheck;
public final boolean textPlayerCheck; public final boolean textPlayerCheck;
public final EnginePlayerConfig textEnginePlayerConfig; public final EnginePlayerConfig textEnginePlayerConfig;
@ -147,7 +96,6 @@ public class ChatConfig extends ACheckConfig {
public final String chatWarningMessage; public final String chatWarningMessage;
public final long chatWarningTimeout; public final long chatWarningTimeout;
public final boolean loginsCheck;
public final boolean loginsPerWorldCount; public final boolean loginsPerWorldCount;
public final int loginsSeconds; public final int loginsSeconds;
public final int loginsLimit; public final int loginsLimit;
@ -157,8 +105,6 @@ public class ChatConfig extends ACheckConfig {
public final boolean consoleOnlyCheck; public final boolean consoleOnlyCheck;
public final String consoleOnlyMessage; public final String consoleOnlyMessage;
public final boolean relogCheck;
public final String relogKickMessage; public final String relogKickMessage;
public final long relogTimeout; public final long relogTimeout;
public final String relogWarningMessage; public final String relogWarningMessage;
@ -172,10 +118,10 @@ public class ChatConfig extends ACheckConfig {
* @param config * @param config
* the data * the data
*/ */
public ChatConfig(final ConfigFile config) { public ChatConfig(final IWorldData worldData) {
super(config, ConfPaths.CHAT); super(worldData);
final ConfigFile config = worldData.getRawConfiguration();
captchaCheck = config.getBoolean(ConfPaths.CHAT_CAPTCHA_CHECK);
captchaSkipCommands = config.getBoolean(ConfPaths.CHAT_CAPTCHA_SKIP_COMMANDS); captchaSkipCommands = config.getBoolean(ConfPaths.CHAT_CAPTCHA_SKIP_COMMANDS);
captchaCharacters = config.getString(ConfPaths.CHAT_CAPTCHA_CHARACTERS); captchaCharacters = config.getString(ConfPaths.CHAT_CAPTCHA_CHARACTERS);
captchaLength = config.getInt(ConfPaths.CHAT_CAPTCHA_LENGTH); captchaLength = config.getInt(ConfPaths.CHAT_CAPTCHA_LENGTH);
@ -184,17 +130,13 @@ public class ChatConfig extends ACheckConfig {
captchaTries = config.getInt(ConfPaths.CHAT_CAPTCHA_TRIES); captchaTries = config.getInt(ConfPaths.CHAT_CAPTCHA_TRIES);
captchaActions = config.getOptimizedActionList(ConfPaths.CHAT_CAPTCHA_ACTIONS, Permissions.CHAT_CAPTCHA); captchaActions = config.getOptimizedActionList(ConfPaths.CHAT_CAPTCHA_ACTIONS, Permissions.CHAT_CAPTCHA);
colorCheck = config.getBoolean(ConfPaths.CHAT_COLOR_CHECK);
colorActions = config.getOptimizedActionList(ConfPaths.CHAT_COLOR_ACTIONS, Permissions.CHAT_COLOR); colorActions = config.getOptimizedActionList(ConfPaths.CHAT_COLOR_ACTIONS, Permissions.CHAT_COLOR);
commandsCheck = config.getBoolean(ConfPaths.CHAT_COMMANDS_CHECK);
commandsLevel = config.getDouble(ConfPaths.CHAT_COMMANDS_LEVEL); commandsLevel = config.getDouble(ConfPaths.CHAT_COMMANDS_LEVEL);
commandsShortTermTicks = config.getInt(ConfPaths.CHAT_COMMANDS_SHORTTERM_TICKS); commandsShortTermTicks = config.getInt(ConfPaths.CHAT_COMMANDS_SHORTTERM_TICKS);
commandsShortTermLevel = config.getDouble(ConfPaths.CHAT_COMMANDS_SHORTTERM_LEVEL);; commandsShortTermLevel = config.getDouble(ConfPaths.CHAT_COMMANDS_SHORTTERM_LEVEL);;
commandsActions = config.getOptimizedActionList(ConfPaths.CHAT_COMMANDS_ACTIONS, Permissions.CHAT_COMMANDS); commandsActions = config.getOptimizedActionList(ConfPaths.CHAT_COMMANDS_ACTIONS, Permissions.CHAT_COMMANDS);
textCheck = config.getBoolean(ConfPaths.CHAT_TEXT_CHECK);
textGlobalCheck = config.getBoolean(ConfPaths.CHAT_TEXT_GL_CHECK, true); textGlobalCheck = config.getBoolean(ConfPaths.CHAT_TEXT_GL_CHECK, true);
textPlayerCheck = config.getBoolean(ConfPaths.CHAT_TEXT_PP_CHECK, true); textPlayerCheck = config.getBoolean(ConfPaths.CHAT_TEXT_PP_CHECK, true);
textEnginePlayerConfig = new EnginePlayerConfig(config); textEnginePlayerConfig = new EnginePlayerConfig(config);
@ -231,14 +173,12 @@ public class ChatConfig extends ACheckConfig {
chatWarningMessage = config.getString(ConfPaths.CHAT_WARNING_MESSAGE); chatWarningMessage = config.getString(ConfPaths.CHAT_WARNING_MESSAGE);
chatWarningTimeout = config.getLong(ConfPaths.CHAT_WARNING_TIMEOUT) * 1000; chatWarningTimeout = config.getLong(ConfPaths.CHAT_WARNING_TIMEOUT) * 1000;
loginsCheck = config.getBoolean(ConfPaths.CHAT_LOGINS_CHECK);
loginsPerWorldCount = config.getBoolean(ConfPaths.CHAT_LOGINS_PERWORLDCOUNT); loginsPerWorldCount = config.getBoolean(ConfPaths.CHAT_LOGINS_PERWORLDCOUNT);
loginsSeconds = config.getInt(ConfPaths.CHAT_LOGINS_SECONDS); loginsSeconds = config.getInt(ConfPaths.CHAT_LOGINS_SECONDS);
loginsLimit = config.getInt(ConfPaths.CHAT_LOGINS_LIMIT); loginsLimit = config.getInt(ConfPaths.CHAT_LOGINS_LIMIT);
loginsKickMessage = config.getString(ConfPaths.CHAT_LOGINS_KICKMESSAGE); loginsKickMessage = config.getString(ConfPaths.CHAT_LOGINS_KICKMESSAGE);
loginsStartupDelay = config.getInt(ConfPaths.CHAT_LOGINS_STARTUPDELAY) * 1000; loginsStartupDelay = config.getInt(ConfPaths.CHAT_LOGINS_STARTUPDELAY) * 1000;
relogCheck = config.getBoolean(ConfPaths.CHAT_RELOG_CHECK);
relogKickMessage = config.getString(ConfPaths.CHAT_RELOG_KICKMESSAGE); relogKickMessage = config.getString(ConfPaths.CHAT_RELOG_KICKMESSAGE);
relogTimeout = config.getLong(ConfPaths.CHAT_RELOG_TIMEOUT); relogTimeout = config.getLong(ConfPaths.CHAT_RELOG_TIMEOUT);
relogWarningMessage = config.getString(ConfPaths.CHAT_RELOG_WARNING_MESSAGE); relogWarningMessage = config.getString(ConfPaths.CHAT_RELOG_WARNING_MESSAGE);
@ -251,26 +191,4 @@ public class ChatConfig extends ACheckConfig {
} }
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster.nocheatplus.checks.CheckType)
*/
@Override
public boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case CHAT_COLOR:
return colorCheck;
case CHAT_TEXT:
return textCheck;
case CHAT_COMMANDS:
return commandsCheck;
case CHAT_CAPTCHA:
return captchaCheck;
case CHAT_RELOG:
return relogCheck;
case CHAT_LOGINS:
return loginsCheck;
default:
return true;
}
}
} }

View File

@ -14,68 +14,13 @@
*/ */
package fr.neatmonster.nocheatplus.checks.chat; package fr.neatmonster.nocheatplus.checks.chat;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.access.AsyncCheckData; import fr.neatmonster.nocheatplus.checks.access.AsyncCheckData;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
/** /**
* Player specific data for the chat checks. * Player specific data for the chat checks.
*/ */
public class ChatData extends AsyncCheckData { public class ChatData extends AsyncCheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
@Override
public final ICheckData getData(final Player player) {
return ChatData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return ChatData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return ChatData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
};
/** The map containing the data per players. */
private static final Map<String, ChatData> playersMap = new HashMap<String, ChatData>();
/**
* Gets the data of a specified player.
*
* @param player
* the player
* @return the data
*/
public static synchronized ChatData getData(final Player player) {
if (!playersMap.containsKey(player.getName()))
playersMap.put(player.getName(), new ChatData(ChatConfig.getConfig(player)));
return playersMap.get(player.getName());
}
public static synchronized ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static synchronized void clear(){
playersMap.clear();
}
// Violation levels. // Violation levels.
public double captchaVL; public double captchaVL;
@ -109,15 +54,6 @@ public class ChatData extends AsyncCheckData {
public int relogWarnings; public int relogWarnings;
public long relogWarningTime; public long relogWarningTime;
/**
* Keep track of current world name, to be used for asynchronous world
* config getting. Set on join and world change, reset on leave.
*/
public String currentWorldName = null;
public ChatData(final ChatConfig config) {
super(config);
}
/** /**
* Clear the data of the no pwnage check. * Clear the data of the no pwnage check.

View File

@ -23,7 +23,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result; import org.bukkit.event.player.PlayerLoginEvent.Result;
@ -42,7 +41,7 @@ import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager; import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.logging.Streams; import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree; import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree;
@ -100,13 +99,6 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
CommandUtil.feedCommands(commandExclusions, config, ConfPaths.CHAT_COMMANDS_EXCLUSIONS, true); CommandUtil.feedCommands(commandExclusions, config, ConfPaths.CHAT_COMMANDS_EXCLUSIONS, true);
} }
@EventHandler(priority=EventPriority.MONITOR)
public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) {
final Player player = event.getPlayer();
ChatData.getData(player).currentWorldName = player.getWorld().getName();
}
/** /**
* We listen to PlayerChat events for obvious reasons. * We listen to PlayerChat events for obvious reasons.
* *
@ -121,11 +113,11 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
// Tell TickTask to update cached permissions. // Tell TickTask to update cached permissions.
// (Might omit this if already cancelled.) // (Might omit this if already cancelled.)
final PlayerData pData = DataManager.getPlayerData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final ChatConfig cc = ChatConfig.getConfig(player); final ChatConfig cc = pData.getGenericInstance(ChatConfig.class);
// First the color check. // First the color check.
if (!alreadyCancelled && color.isEnabled(player)) { if (!alreadyCancelled && color.isEnabled(player, pData)) {
event.setMessage(color.check(player, event.getMessage(), false)); event.setMessage(color.check(player, event.getMessage(), false));
} }
@ -148,11 +140,11 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
final Player player = event.getPlayer(); final Player player = event.getPlayer();
// Tell TickTask to update cached permissions. // Tell TickTask to update cached permissions.
final PlayerData pData = DataManager.getPlayerData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final ChatConfig cc = ChatConfig.getConfig(player); final ChatConfig cc = pData.getGenericInstance(ChatConfig.class);
// Checks that replace parts of the message (color). // Checks that replace parts of the message (color).
if (color.isEnabled(player)) { if (color.isEnabled(player, pData)) {
event.setMessage(color.check(player, event.getMessage(), true)); event.setMessage(color.check(player, event.getMessage(), true));
} }
@ -198,15 +190,15 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
} }
else if (!commandExclusions.hasAnyPrefixWords(messageVars)) { else if (!commandExclusions.hasAnyPrefixWords(messageVars)) {
// Treat as command. // Treat as command.
if (commands.isEnabled(player) && commands.check(player, checkMessage, cc, pData, captcha)) { if (commands.isEnabled(player, pData) && commands.check(player, checkMessage, cc, pData, captcha)) {
event.setCancelled(true); event.setCancelled(true);
} }
else { else {
// TODO: Consider always checking these? // TODO: Consider always checking these?
// Note that this checks for prefixes, not prefix words. // Note that this checks for prefixes, not prefix words.
final MovingConfig mcc = MovingConfig.getConfig(player); final MovingConfig mcc = pData.getGenericInstance(MovingConfig.class);
if (mcc.passableUntrackedCommandCheck && mcc.passableUntrackedCommandPrefixes.hasAnyPrefix(messageVars)) { if (mcc.passableUntrackedCommandCheck && mcc.passableUntrackedCommandPrefixes.hasAnyPrefix(messageVars)) {
if (checkUntrackedLocation(player, message, mcc)) { if (checkUntrackedLocation(player, message, mcc, pData)) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@ -215,10 +207,11 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
} }
private boolean checkUntrackedLocation(final Player player, final String message, final MovingConfig mcc) { private boolean checkUntrackedLocation(final Player player, final String message,
final MovingConfig mcc, final IPlayerData pData) {
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
boolean cancel = false; boolean cancel = false;
if (MovingUtil.shouldCheckUntrackedLocation(player, loc)) { if (MovingUtil.shouldCheckUntrackedLocation(player, loc, pData)) {
final Location newTo = MovingUtil.checkUntrackedLocation(loc); final Location newTo = MovingUtil.checkUntrackedLocation(loc);
if (newTo != null) { if (newTo != null) {
if (mcc.passableUntrackedCommandTryTeleport if (mcc.passableUntrackedCommandTryTeleport
@ -237,9 +230,9 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
} }
private boolean textChecks(final Player player, final String message, private boolean textChecks(final Player player, final String message,
final ChatConfig cc, final PlayerData pData, final ChatConfig cc, final IPlayerData pData,
final boolean isMainThread, final boolean alreadyCancelled) { final boolean isMainThread, final boolean alreadyCancelled) {
return text.isEnabled(player) && text.check(player, message, cc, pData, return text.isEnabled(player, pData) && text.check(player, message, cc, pData,
captcha, isMainThread, alreadyCancelled); captcha, isMainThread, alreadyCancelled);
} }
@ -254,9 +247,9 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
public void onPlayerLogin(final PlayerLoginEvent event) { public void onPlayerLogin(final PlayerLoginEvent event) {
if (event.getResult() != Result.ALLOWED) return; if (event.getResult() != Result.ALLOWED) return;
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final PlayerData pData = DataManager.getPlayerData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final ChatConfig cc = ChatConfig.getConfig(player); final ChatConfig cc = pData.getGenericInstance(ChatConfig.class);
final ChatData data = ChatData.getData(player); final ChatData data = pData.getGenericInstance(ChatData.class);
// (No forced permission update, because the associated permissions are treated as hints rather.) // (No forced permission update, because the associated permissions are treated as hints rather.)
@ -265,10 +258,10 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
captcha.resetCaptcha(player, cc, data, pData); captcha.resetCaptcha(player, cc, data, pData);
} }
// Fast relog check. // Fast relog check.
if (relog.isEnabled(player) && relog.unsafeLoginCheck(player, cc, data)) { if (relog.isEnabled(player, pData) && relog.unsafeLoginCheck(player, cc, data,pData)) {
event.disallow(Result.KICK_OTHER, cc.relogKickMessage); event.disallow(Result.KICK_OTHER, cc.relogKickMessage);
} }
else if (logins.isEnabled(player) && logins.check(player, cc, data)) { else if (logins.isEnabled(player, pData) && logins.check(player, cc, data)) {
event.disallow(Result.KICK_OTHER, cc.loginsKickMessage); event.disallow(Result.KICK_OTHER, cc.loginsKickMessage);
} }
} }
@ -284,13 +277,17 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
@Override @Override
public void playerJoins(final Player player) { public void playerJoins(final Player player) {
final PlayerData pData = DataManager.getPlayerData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final ChatConfig cc = ChatConfig.getConfig(player); final ChatConfig cc = pData.getGenericInstance(ChatConfig.class);
final ChatData data = ChatData.getData(player); final ChatData data = pData.getGenericInstance(ChatData.class);
// Cross-check hack: ChatData holds the current world name (TBD: PlayerData.getWorldInfo() rather). /*
data.currentWorldName = player.getWorld().getName(); * TODO: The isEnabled check must be done with IWorldData (no locking).
* Specifically because enabling/disabling checks should be done in the
* primary thread, regardless of the capabilities of WorldDataManager
* implementation.
*/
synchronized (data) { synchronized (data) {
if (captcha.isEnabled(player, cc, pData)) { if (captcha.isEnabled(player, pData)) {
if (captcha.shouldCheckCaptcha(player, cc, data, pData)) { if (captcha.shouldCheckCaptcha(player, cc, data, pData)) {
// shouldCheckCaptcha: only if really enabled. // shouldCheckCaptcha: only if really enabled.
// TODO: Later: add check for cc.captchaOnLogin or so (before shouldCheckCaptcha). // TODO: Later: add check for cc.captchaOnLogin or so (before shouldCheckCaptcha).
@ -303,7 +300,6 @@ public class ChatListener extends CheckListener implements INotifyReload, JoinLe
@Override @Override
public void playerLeaves(final Player player) { public void playerLeaves(final Player player) {
ChatData.getData(player).currentWorldName = null;
} }
} }

View File

@ -18,6 +18,8 @@ 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.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* The Color check verifies that no color codes are sent in players' messages. * The Color check verifies that no color codes are sent in players' messages.
@ -44,9 +46,10 @@ public class Color extends Check {
*/ */
public String check(final Player player, final String message, final boolean isMainThread) { public String check(final Player player, final String message, final boolean isMainThread) {
final ChatConfig cc = ChatConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final ChatConfig cc = pData.getGenericInstance(ChatConfig.class);
final ChatData data = pData.getGenericInstance(ChatData.class);
final ChatData data = ChatData.getData(player);
// Keep related to ChatData used lock. // Keep related to ChatData used lock.
synchronized (data) { synchronized (data) {
// If the message contains colors... // If the message contains colors...

View File

@ -18,8 +18,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.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.ColorUtil; import fr.neatmonster.nocheatplus.utilities.ColorUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -34,16 +33,16 @@ public class Commands extends Check {
} }
public boolean check(final Player player, final String message, public boolean check(final Player player, final String message,
final ChatConfig cc, final PlayerData pData, final ChatConfig cc, final IPlayerData pData,
final ICaptcha captcha) { final ICaptcha captcha) {
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final int tick = TickTask.getTick(); final int tick = TickTask.getTick();
final ChatData data = ChatData.getData(player); final ChatData data = pData.getGenericInstance(ChatData.class);
final boolean captchaEnabled = !cc.captchaSkipCommands final boolean captchaEnabled = !cc.captchaSkipCommands
&& CheckUtils.isEnabled(CheckType.CHAT_CAPTCHA, player, cc, pData); && pData.isCheckActive(CheckType.CHAT_CAPTCHA, player);
if (captchaEnabled){ if (captchaEnabled){
synchronized (data) { synchronized (data) {
if (captcha.shouldCheckCaptcha(player, cc, data, pData)){ if (captcha.shouldCheckCaptcha(player, cc, data, pData)){
@ -65,7 +64,8 @@ public class Commands extends Check {
data.commandsShortTermWeight = 1.0; data.commandsShortTermWeight = 1.0;
} }
else if (tick - data.commandsShortTermTick < cc.commandsShortTermTicks){ else if (tick - data.commandsShortTermTick < cc.commandsShortTermTicks){
if (!cc.lag || TickTask.getLag(50L * (tick - data.commandsShortTermTick), true) < 1.3f){ if (!pData.getCurrentWorldData().shouldAdjustToLag(type)
|| TickTask.getLag(50L * (tick - data.commandsShortTermTick), true) < 1.3f){
// Add up. // Add up.
data.commandsShortTermWeight += weight; data.commandsShortTermWeight += weight;
} }

View File

@ -16,7 +16,7 @@ package fr.neatmonster.nocheatplus.checks.chat;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* Captcha related operations.<br> * Captcha related operations.<br>
@ -62,7 +62,7 @@ public interface ICaptcha {
* @param pData * @param pData
* @return * @return
*/ */
public boolean shouldCheckCaptcha(Player player, ChatConfig cc, ChatData data, PlayerData pData); public boolean shouldCheckCaptcha(Player player, ChatConfig cc, ChatData data, IPlayerData pData);
/** /**
* Check if captcha should be generated and send to the player. * Check if captcha should be generated and send to the player.
@ -73,7 +73,7 @@ public interface ICaptcha {
* @param pData * @param pData
* @return * @return
*/ */
public boolean shouldStartCaptcha(Player player, ChatConfig cc, ChatData data, PlayerData pData); public boolean shouldStartCaptcha(Player player, ChatConfig cc, ChatData data, IPlayerData pData);
/** /**
* Just resets tries, generate new captcha if necessary. * Just resets tries, generate new captcha if necessary.
@ -83,7 +83,7 @@ public interface ICaptcha {
* @param data * @param data
* @param pData * @param pData
*/ */
public void resetCaptcha(Player player, ChatConfig cc, ChatData data, PlayerData pData); public void resetCaptcha(Player player, ChatConfig cc, ChatData data, IPlayerData pData);
/** /**
* Convenience method. Should synchronize over data of player (!). * Convenience method. Should synchronize over data of player (!).

View File

@ -19,6 +19,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.combined.CombinedData; import fr.neatmonster.nocheatplus.checks.combined.CombinedData;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ColorUtil; import fr.neatmonster.nocheatplus.utilities.ColorUtil;
public class Relog extends Check { public class Relog extends Check {
@ -38,12 +39,13 @@ public class Relog extends Check {
* the data * the data
* @return true, if successful * @return true, if successful
*/ */
public boolean unsafeLoginCheck(final Player player, final ChatConfig cc, final ChatData data) { public boolean unsafeLoginCheck(final Player player,
final ChatConfig cc, final ChatData data, final IPlayerData pData) {
boolean cancel = false; boolean cancel = false;
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final CombinedData cData = CombinedData.getData(player); final CombinedData cData = pData.getGenericInstance(CombinedData.class);
// Enforce the player does not relog too fast. // Enforce the player does not relog too fast.
if (now - cData.lastLogoutTime < cc.relogTimeout) { if (now - cData.lastLogoutTime < cc.relogTimeout) {

View File

@ -32,7 +32,7 @@ import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI;
import fr.neatmonster.nocheatplus.components.registry.feature.INotifyReload; import fr.neatmonster.nocheatplus.components.registry.feature.INotifyReload;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager; import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ColorUtil; import fr.neatmonster.nocheatplus.utilities.ColorUtil;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
@ -69,9 +69,9 @@ public class Text extends Check implements INotifyReload {
* @return * @return
*/ */
public boolean check(final Player player, final String message, public boolean check(final Player player, final String message,
final ChatConfig cc, final PlayerData pData, final ChatConfig cc, final IPlayerData pData,
final ICaptcha captcha, boolean isMainThread, final boolean alreadyCancelled) { final ICaptcha captcha, boolean isMainThread, final boolean alreadyCancelled) {
final ChatData data = ChatData.getData(player); final ChatData data = pData.getGenericInstance(ChatData.class);
synchronized (data) { synchronized (data) {
return unsafeCheck(player, message, captcha, cc, data, pData, isMainThread, alreadyCancelled); return unsafeCheck(player, message, captcha, cc, data, pData, isMainThread, alreadyCancelled);
@ -110,7 +110,7 @@ public class Text extends Check implements INotifyReload {
* @return * @return
*/ */
private boolean unsafeCheck(final Player player, final String message, final ICaptcha captcha, private boolean unsafeCheck(final Player player, final String message, final ICaptcha captcha,
final ChatConfig cc, final ChatData data, final PlayerData pData, final ChatConfig cc, final ChatData data, final IPlayerData pData,
boolean isMainThread, final boolean alreadyCancelled) { boolean isMainThread, final boolean alreadyCancelled) {
// Test captcha. // Test captcha.
@ -130,7 +130,7 @@ public class Text extends Check implements INotifyReload {
boolean cancel = false; boolean cancel = false;
boolean debug = data.debug; final boolean debug = pData.isDebugActive(type);
final List<String> debugParts; final List<String> debugParts;
if (debug) { if (debug) {
@ -180,7 +180,7 @@ public class Text extends Check implements INotifyReload {
} }
} }
final CombinedData cData = CombinedData.getData(player); final CombinedData cData = pData.getGenericInstance(CombinedData.class);
final long timeout = 8000; // TODO: maybe set dynamically in data. final long timeout = 8000; // TODO: maybe set dynamically in data.
// Repetition of last message. // Repetition of last message.
if (cc.textMsgRepeatSelf != 0f && time - data.chatLastTime < timeout) { if (cc.textMsgRepeatSelf != 0f && time - data.chatLastTime < timeout) {

View File

@ -18,6 +18,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.players.IPlayerData;
public class BedLeave extends Check { public class BedLeave extends Check {
@ -32,8 +33,8 @@ public class BedLeave extends Check {
* the player * the player
* @return If to prevent action (use the set back location of survivalfly). * @return If to prevent action (use the set back location of survivalfly).
*/ */
public boolean checkBed(final Player player) { public boolean checkBed(final Player player, final IPlayerData pData) {
final CombinedData data = CombinedData.getData(player); final CombinedData data = pData.getGenericInstance(CombinedData.class);
boolean cancel = false; boolean cancel = false;
// Check if the player had been in bed at all. // Check if the player had been in bed at all.
@ -44,7 +45,8 @@ public class BedLeave extends Check {
// TODO: add tag // TODO: add tag
// And return if we need to do something or not. // And return if we need to do something or not.
if (executeActions(player, data.bedLeaveVL, 1D, CombinedConfig.getConfig(player).bedLeaveActions).willCancel()){ if (executeActions(player, data.bedLeaveVL, 1D,
pData.getGenericInstance(CombinedConfig.class).bedLeaveActions).willCancel()){
cancel = true; cancel = true;
} }
} else{ } else{

View File

@ -18,6 +18,7 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -40,8 +41,9 @@ public class Combined {
* @return * @return
*/ */
public static final boolean checkYawRate(final Player player, final float yaw, final long now, public static final boolean checkYawRate(final Player player, final float yaw, final long now,
final String worldName) { final String worldName, final IPlayerData pData) {
return checkYawRate(player, yaw, now, worldName, CombinedData.getData(player)); return checkYawRate(player, yaw, now, worldName,
pData.getGenericInstance(CombinedData.class), pData);
} }
/** /**
@ -52,8 +54,9 @@ public class Combined {
* @param worldName * @param worldName
*/ */
public static final void feedYawRate(final Player player, final float yaw, final long now, public static final void feedYawRate(final Player player, final float yaw, final long now,
final String worldName) { final String worldName, final IPlayerData pData) {
feedYawRate(player, yaw, now, worldName, CombinedData.getData(player)); feedYawRate(player, yaw, now, worldName,
pData.getGenericInstance(CombinedData.class), pData);
} }
/** /**
@ -68,10 +71,10 @@ public class Combined {
* @return True, if the player was exempted from yawrate. False otherwise. * @return True, if the player was exempted from yawrate. False otherwise.
*/ */
public static final boolean feedYawRate(final Player player, float yaw, final long now, public static final boolean feedYawRate(final Player player, float yaw, final long now,
final String worldName, final CombinedData data) { final String worldName, final CombinedData data, final IPlayerData pData) {
// Check for exemption (hack, sort of). // Check for exemption (hack, sort of).
if (NCPExemptionManager.isExempted(player, CheckType.COMBINED_YAWRATE)) { if (NCPExemptionManager.isExempted(player, CheckType.COMBINED_YAWRATE)) {
resetYawRate(player, yaw, now, true); resetYawRate(player, yaw, now, true, pData);
return true; return true;
} }
@ -145,13 +148,14 @@ public class Combined {
* otherwise. * otherwise.
*/ */
public static final boolean checkYawRate(final Player player, final float yaw, final long now, public static final boolean checkYawRate(final Player player, final float yaw, final long now,
final String worldName, final CombinedData data) { final String worldName, final CombinedData data, final IPlayerData pData) {
if (feedYawRate(player, yaw, now, worldName, data)) { if (feedYawRate(player, yaw, now, worldName, data, pData)) {
return false; return false;
} }
final CombinedConfig cc = CombinedConfig.getConfig(player); final CombinedConfig cc = pData.getGenericInstance(CombinedConfig.class);
final boolean lag = pData.getCurrentWorldData().shouldAdjustToLag(CheckType.COMBINED_IMPROBABLE);
final float threshold = cc.yawRate; final float threshold = cc.yawRate;
@ -160,7 +164,7 @@ public class Combined {
final float stViol; final float stViol;
if (stScore > threshold) { if (stScore > threshold) {
// Account for server side lag. // Account for server side lag.
if (!cc.lag || TickTask.getLag(data.yawFreq.bucketDuration(), true) < 1.2) { if (!lag || TickTask.getLag(data.yawFreq.bucketDuration(), true) < 1.2) {
stViol = stScore; stViol = stScore;
} }
else { else {
@ -174,7 +178,7 @@ public class Combined {
final float fullViol; final float fullViol;
if (fullScore > threshold) { if (fullScore > threshold) {
// Account for server side lag. // Account for server side lag.
if (cc.lag) { if (lag) {
fullViol = fullScore / TickTask.getLag(data.yawFreq.bucketDuration() * data.yawFreq.numberOfBuckets(), true); fullViol = fullScore / TickTask.getLag(data.yawFreq.bucketDuration() * data.yawFreq.numberOfBuckets(), true);
} }
else { else {
@ -194,7 +198,8 @@ public class Combined {
Math.max(cc.yawRatePenaltyFactor * amount , cc.yawRatePenaltyMin), Math.max(cc.yawRatePenaltyFactor * amount , cc.yawRatePenaltyMin),
cc.yawRatePenaltyMax)); cc.yawRatePenaltyMax));
// TODO: balance (100 ... 200 ) ? // TODO: balance (100 ... 200 ) ?
if (cc.yawRateImprobable && Improbable.check(player, amount / 100f, now, "combined.yawrate")) if (cc.yawRateImprobable && Improbable.check(player, amount / 100f, now, "combined.yawrate",
pData))
cancel = true; cancel = true;
} }
if (data.timeFreeze.isPenalty()) { if (data.timeFreeze.isPenalty()) {
@ -210,14 +215,15 @@ public class Combined {
* @param time * @param time
* @param clear If to clear yaws. * @param clear If to clear yaws.
*/ */
public static final void resetYawRate(final Player player, float yaw, final long time, final boolean clear) { public static final void resetYawRate(final Player player, float yaw,
final long time, final boolean clear, final IPlayerData pData) {
if (yaw <= -360f) { if (yaw <= -360f) {
yaw = -((-yaw) % 360f); yaw = -((-yaw) % 360f);
} }
else if (yaw >= 360f) { else if (yaw >= 360f) {
yaw = yaw % 360f; yaw = yaw % 360f;
} }
final CombinedData data = CombinedData.getData(player); final CombinedData data = pData.getGenericInstance(CombinedData.class);
data.lastYaw = yaw; data.lastYaw = yaw;
data.lastYawTime = time; // TODO: One might set to some past-time to allow any move at first. data.lastYawTime = time; // TODO: One might set to some past-time to allow any move at first.
data.sumYaw = 0; data.sumYaw = 0;
@ -235,12 +241,13 @@ public class Combined {
* @param yawRateCheck If to actually check the yaw rate, or just feed. * @param yawRateCheck If to actually check the yaw rate, or just feed.
* @return * @return
*/ */
public static final boolean checkYawRate(final Player player, final float yaw, final long now, final String worldName, final boolean yawRateCheck) { public static final boolean checkYawRate(final Player player, final float yaw, final long now,
final String worldName, final boolean yawRateCheck, final IPlayerData pData) {
if (yawRateCheck) { if (yawRateCheck) {
return checkYawRate(player, yaw, now, worldName); return checkYawRate(player, yaw, now, worldName, pData);
} }
else { else {
feedYawRate(player, yaw, now, worldName); feedYawRate(player, yaw, now, worldName, pData);
return false; return false;
} }
} }

View File

@ -21,51 +21,20 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
public class CombinedConfig extends ACheckConfig { public class CombinedConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return CombinedConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
private static final Map<String, CombinedConfig> worldsMap = new HashMap<String, CombinedConfig>();
public static CombinedConfig getConfig(final Player player) {
final String worldName = player.getWorld().getName();
CombinedConfig cc = worldsMap.get(worldName);
if (cc == null){
cc = new CombinedConfig(ConfigManager.getConfigFile(worldName));
worldsMap.put(worldName, cc);
}
return cc;
}
// Bedleave check. // Bedleave check.
public final boolean bedLeaveCheck;
public final ActionList bedLeaveActions; public final ActionList bedLeaveActions;
// Ender pearl // Ender pearl
@ -74,7 +43,6 @@ public class CombinedConfig extends ACheckConfig {
// Improbable check // Improbable check
/** Do mind that this flag is not used by all components. */ /** Do mind that this flag is not used by all components. */
public final boolean improbableCheck;
public final float improbableLevel; public final float improbableLevel;
public final ActionList improbableActions; public final ActionList improbableActions;
@ -87,7 +55,6 @@ public class CombinedConfig extends ACheckConfig {
public final boolean invulnerableTriggerAlways; public final boolean invulnerableTriggerAlways;
public final boolean invulnerableTriggerFallDistance; public final boolean invulnerableTriggerFallDistance;
public final boolean munchHausenCheck;
public final ActionList munchHausenActions; public final ActionList munchHausenActions;
// Last yaw tracking // Last yaw tracking
@ -97,16 +64,15 @@ public class CombinedConfig extends ACheckConfig {
public final int yawRatePenaltyMin; public final int yawRatePenaltyMin;
public final int yawRatePenaltyMax; public final int yawRatePenaltyMax;
public CombinedConfig(final ConfigFile config) { public CombinedConfig(final IWorldData worldData) {
super(config, ConfPaths.COMBINED); super(worldData);
final ConfigFile config = worldData.getRawConfiguration();
bedLeaveCheck = config.getBoolean(ConfPaths.COMBINED_BEDLEAVE_CHECK);
bedLeaveActions = config.getOptimizedActionList(ConfPaths.COMBINED_BEDLEAVE_ACTIONS, Permissions.COMBINED_BEDLEAVE); bedLeaveActions = config.getOptimizedActionList(ConfPaths.COMBINED_BEDLEAVE_ACTIONS, Permissions.COMBINED_BEDLEAVE);
enderPearlCheck = config.getBoolean(ConfPaths.COMBINED_ENDERPEARL_CHECK); enderPearlCheck = config.getBoolean(ConfPaths.COMBINED_ENDERPEARL_CHECK);
enderPearlPreventClickBlock = config.getBoolean(ConfPaths.COMBINED_ENDERPEARL_PREVENTCLICKBLOCK); enderPearlPreventClickBlock = config.getBoolean(ConfPaths.COMBINED_ENDERPEARL_PREVENTCLICKBLOCK);
improbableCheck = config.getBoolean(ConfPaths.COMBINED_IMPROBABLE_CHECK);
improbableLevel = (float) config.getDouble(ConfPaths.COMBINED_IMPROBABLE_LEVEL); improbableLevel = (float) config.getDouble(ConfPaths.COMBINED_IMPROBABLE_LEVEL);
improbableActions = config.getOptimizedActionList(ConfPaths.COMBINED_IMPROBABLE_ACTIONS, Permissions.COMBINED_IMPROBABLE); improbableActions = config.getOptimizedActionList(ConfPaths.COMBINED_IMPROBABLE_ACTIONS, Permissions.COMBINED_IMPROBABLE);
@ -147,7 +113,6 @@ public class CombinedConfig extends ACheckConfig {
invulnerableTriggerAlways = config.getBoolean(ConfPaths.COMBINED_INVULNERABLE_TRIGGERS_ALWAYS); invulnerableTriggerAlways = config.getBoolean(ConfPaths.COMBINED_INVULNERABLE_TRIGGERS_ALWAYS);
invulnerableTriggerFallDistance = config.getBoolean(ConfPaths.COMBINED_INVULNERABLE_TRIGGERS_FALLDISTANCE); invulnerableTriggerFallDistance = config.getBoolean(ConfPaths.COMBINED_INVULNERABLE_TRIGGERS_FALLDISTANCE);
munchHausenCheck = config.getBoolean(ConfPaths.COMBINED_MUNCHHAUSEN_CHECK);
munchHausenActions = config.getOptimizedActionList(ConfPaths.COMBINED_MUNCHHAUSEN_ACTIONS, Permissions.COMBINED_MUNCHHAUSEN); munchHausenActions = config.getOptimizedActionList(ConfPaths.COMBINED_MUNCHHAUSEN_ACTIONS, Permissions.COMBINED_MUNCHHAUSEN);
yawRate = config.getInt(ConfPaths.COMBINED_YAWRATE_RATE); yawRate = config.getInt(ConfPaths.COMBINED_YAWRATE_RATE);
@ -157,25 +122,4 @@ public class CombinedConfig extends ACheckConfig {
yawRatePenaltyMax = config.getInt(ConfPaths.COMBINED_YAWRATE_PENALTY_MAX); yawRatePenaltyMax = config.getInt(ConfPaths.COMBINED_YAWRATE_PENALTY_MAX);
} }
@Override
public boolean isEnabled(final CheckType checkType) {
switch(checkType){
case COMBINED_IMPROBABLE:
return improbableCheck;
case COMBINED_BEDLEAVE:
return bedLeaveCheck;
case COMBINED_MUNCHHAUSEN:
return munchHausenCheck;
case COMBINED_YAWRATE:
// Always on, depends on other checks.
return true;
default:
return false;
}
}
public static void clear() {
worldsMap.clear();
}
} }

View File

@ -14,65 +14,14 @@
*/ */
package fr.neatmonster.nocheatplus.checks.combined; package fr.neatmonster.nocheatplus.checks.combined;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
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.ICheckData;
import fr.neatmonster.nocheatplus.checks.access.IRemoveSubCheckData; import fr.neatmonster.nocheatplus.checks.access.IRemoveSubCheckData;
import fr.neatmonster.nocheatplus.utilities.PenaltyTime; import fr.neatmonster.nocheatplus.utilities.PenaltyTime;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
public class CombinedData extends ACheckData implements IRemoveSubCheckData { public class CombinedData extends ACheckData implements IRemoveSubCheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
@Override
public final ICheckData getData(final Player player) {
return CombinedData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return CombinedData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return CombinedData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
};
private static final Map<String, CombinedData> playersMap = new HashMap<String, CombinedData>();
public static CombinedData getData(final Player player) {
final String playerName = player.getName();
CombinedData data = playersMap.get(playerName);
if (data == null){
data = new CombinedData(CombinedConfig.getConfig(player));
playersMap.put(playerName, data);
}
return data;
}
public static ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static void clear(){
playersMap.clear();
}
// VLs // VLs
public double bedLeaveVL = 0; public double bedLeaveVL = 0;
public double improbableVL = 0; public double improbableVL = 0;
@ -98,15 +47,12 @@ public class CombinedData extends ACheckData implements IRemoveSubCheckData {
public final ActionFrequency improbableCount = new ActionFrequency(20, 3000); public final ActionFrequency improbableCount = new ActionFrequency(20, 3000);
// General data // General data
// TODO: -> PlayerData (-> OfflinePlayerData)
public String lastWorld = ""; public String lastWorld = "";
public long lastJoinTime; public long lastJoinTime;
public long lastLogoutTime; public long lastLogoutTime;
public long lastMoveTime; public long lastMoveTime;
public CombinedData(final CombinedConfig config){
super(config);
}
@Override @Override
public boolean removeSubCheckData(final CheckType checkType) { public boolean removeSubCheckData(final CheckType checkType) {
switch(checkType) { switch(checkType) {

View File

@ -28,6 +28,8 @@ import org.bukkit.event.player.PlayerToggleSprintEvent;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckListener; import fr.neatmonster.nocheatplus.checks.CheckListener;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -65,10 +67,13 @@ public class CombinedListener extends CheckListener {
// TODO: EventPriority // TODO: EventPriority
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final CombinedData data = CombinedData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final CombinedConfig cc = CombinedConfig.getConfig(player); final CombinedData data = pData.getGenericInstance(CombinedData.class);
final CombinedConfig cc = pData.getGenericInstance(CombinedConfig.class);
if (cc.invulnerableCheck && (cc.invulnerableTriggerAlways || cc.invulnerableTriggerFallDistance && player.getFallDistance() > 0)){ if (cc.invulnerableCheck
&& (cc.invulnerableTriggerAlways || cc.invulnerableTriggerFallDistance
&& player.getFallDistance() > 0)){
// TODO: maybe make a heuristic for small fall distances with ground under feet (prevents future abuse with jumping) ? // TODO: maybe make a heuristic for small fall distances with ground under feet (prevents future abuse with jumping) ?
final int invulnerableTicks = mcAccess.getHandle().getInvulnerableTicks(player); final int invulnerableTicks = mcAccess.getHandle().getInvulnerableTicks(player);
if (invulnerableTicks == Integer.MAX_VALUE) { if (invulnerableTicks == Integer.MAX_VALUE) {
@ -86,7 +91,8 @@ public class CombinedListener extends CheckListener {
final Entity entity = event.getEntity(); final Entity entity = event.getEntity();
if (!(entity instanceof Player)) return; if (!(entity instanceof Player)) return;
final Player player = (Player) entity; final Player player = (Player) entity;
final CombinedConfig cc = CombinedConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final CombinedConfig cc = pData.getGenericInstance(CombinedConfig.class);
if (!cc.invulnerableCheck) return; if (!cc.invulnerableCheck) return;
final DamageCause cause = event.getCause(); final DamageCause cause = event.getCause();
// Ignored causes. // Ignored causes.
@ -94,7 +100,7 @@ public class CombinedListener extends CheckListener {
// Modified invulnerable ticks. // Modified invulnerable ticks.
Integer modifier = cc.invulnerableModifiers.get(cause); Integer modifier = cc.invulnerableModifiers.get(cause);
if (modifier == null) modifier = cc.invulnerableModifierDefault; if (modifier == null) modifier = cc.invulnerableModifierDefault;
final CombinedData data = CombinedData.getData(player); final CombinedData data = pData.getGenericInstance(CombinedData.class);
// TODO: account for tick task reset ? [it should not though, due to data resetting too, but API would allow it] // TODO: account for tick task reset ? [it should not though, due to data resetting too, but API would allow it]
if (TickTask.getTick() >= data.invulnerableTick + modifier.intValue()) return; if (TickTask.getTick() >= data.invulnerableTick + modifier.intValue()) return;
// Still invulnerable. // Still invulnerable.

View File

@ -21,6 +21,8 @@ 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.components.registry.feature.IDisableListener; import fr.neatmonster.nocheatplus.components.registry.feature.IDisableListener;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/** /**
@ -41,8 +43,21 @@ public class Improbable extends Check implements IDisableListener{
* @param now * @param now
* @return * @return
*/ */
public static final boolean check(final Player player, final float weight, final long now, final String tags){ public static final boolean check(final Player player, final float weight, final long now,
return instance.checkImprobable(player, weight, now, tags); final String tags, final IPlayerData pData){
return instance.checkImprobable(player, weight, now, tags, pData);
}
/**
* Feed the check but no violations processing (convenience method).
* @param player
* @param weight
* @param now
* @param pData
*/
public static final void feed(final Player player, final float weight, final long now,
final IPlayerData pData){
pData.getGenericInstance(CombinedData.class).improbableCount.add(now, weight);
} }
/** /**
@ -51,8 +66,8 @@ public class Improbable extends Check implements IDisableListener{
* @param weight * @param weight
* @param now * @param now
*/ */
public static final void feed(final Player player, final float weight, final long now){ public static void feed(final Player player, final float weight, long now) {
CombinedData.getData(player).improbableCount.add(now, weight); feed(player, weight, now, DataManager.getPlayerData(player));
} }
//////////////////////////////////// ////////////////////////////////////
@ -64,16 +79,19 @@ public class Improbable extends Check implements IDisableListener{
instance = this; instance = this;
} }
private boolean checkImprobable(final Player player, final float weight, final long now, final String tags) { private boolean checkImprobable(final Player player, final float weight, final long now,
if (!isEnabled(player)) return false; final String tags, final IPlayerData pData) {
final CombinedData data = CombinedData.getData(player); if (!pData.isCheckActive(type, player)) {
final CombinedConfig cc = CombinedConfig.getConfig(player); return false;
}
final CombinedData data = pData.getGenericInstance(CombinedData.class);
final CombinedConfig cc = pData.getGenericInstance(CombinedConfig.class);
data.improbableCount.add(now, weight); data.improbableCount.add(now, weight);
final float shortTerm = data.improbableCount.bucketScore(0); final float shortTerm = data.improbableCount.bucketScore(0);
double violation = 0; double violation = 0;
boolean violated = false; boolean violated = false;
if (shortTerm * 0.8f > cc.improbableLevel / 20.0){ if (shortTerm * 0.8f > cc.improbableLevel / 20.0){
final float lag = cc.lag ? TickTask.getLag(data.improbableCount.bucketDuration(), true) : 1f; final float lag = pData.getCurrentWorldData().shouldAdjustToLag(type) ? TickTask.getLag(data.improbableCount.bucketDuration(), true) : 1f;
if (shortTerm / lag > cc.improbableLevel / 20.0){ if (shortTerm / lag > cc.improbableLevel / 20.0){
violation += shortTerm * 2d / lag; violation += shortTerm * 2d / lag;
violated = true; violated = true;
@ -81,7 +99,7 @@ public class Improbable extends Check implements IDisableListener{
} }
final double full = data.improbableCount.score(1.0f); final double full = data.improbableCount.score(1.0f);
if (full > cc.improbableLevel){ if (full > cc.improbableLevel){
final float lag = cc.lag ? TickTask.getLag(data.improbableCount.bucketDuration() * data.improbableCount.numberOfBuckets(), true) : 1f; final float lag = pData.getCurrentWorldData().shouldAdjustToLag(type) ? TickTask.getLag(data.improbableCount.bucketDuration() * data.improbableCount.numberOfBuckets(), true) : 1f;
if (full / lag > cc.improbableLevel){ if (full / lag > cc.improbableLevel){
violation += full / lag; violation += full / lag;
violated = true; violated = true;

View File

@ -20,6 +20,8 @@ import org.bukkit.event.player.PlayerFishEvent.State;
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.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* Very, very important check. * Very, very important check.
@ -34,10 +36,12 @@ public class MunchHausen extends Check {
public boolean checkFish(final Player player, final Entity caught, final State state) { public boolean checkFish(final Player player, final Entity caught, final State state) {
if (caught == null || !(caught instanceof Player)) return false; if (caught == null || !(caught instanceof Player)) return false;
final Player caughtPlayer = (Player) caught; final Player caughtPlayer = (Player) caught;
final CombinedData data = CombinedData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final CombinedData data = pData.getGenericInstance(CombinedData.class);
if (player.equals(caughtPlayer)){ if (player.equals(caughtPlayer)){
data.munchHausenVL += 1.0; data.munchHausenVL += 1.0;
if (executeActions(player, data.munchHausenVL, 1.0, CombinedConfig.getConfig(player).munchHausenActions).willCancel()){ if (executeActions(player, data.munchHausenVL, 1.0,
pData.getGenericInstance(CombinedConfig.class).munchHausenActions).willCancel()){
return true; return true;
} }
} }

View File

@ -32,7 +32,7 @@ import fr.neatmonster.nocheatplus.checks.moving.model.LiftOffEnvelope;
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveInfo; import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveInfo;
import fr.neatmonster.nocheatplus.checks.moving.util.AuxMoving; import fr.neatmonster.nocheatplus.checks.moving.util.AuxMoving;
import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil; import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
@ -58,13 +58,14 @@ public class Critical extends Check {
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final Location loc, public boolean check(final Player player, final Location loc,
final FightData data, final FightConfig cc, final PlayerData pData) { final FightData data, final FightConfig cc,
final IPlayerData pData) {
boolean cancel = false; boolean cancel = false;
final double mcFallDistance = (double) player.getFallDistance(); final double mcFallDistance = (double) player.getFallDistance();
final MovingConfig mCc = MovingConfig.getConfig(player); final MovingConfig mCc = pData.getGenericInstance(MovingConfig.class);
if (data.debug) { if (pData.isDebugActive(type)) {
debug(player, "y=" + loc.getY() + " mcfalldist=" + mcFallDistance); debug(player, "y=" + loc.getY() + " mcfalldist=" + mcFallDistance);
} }
@ -72,13 +73,17 @@ public class Critical extends Check {
// not in liquid, not in vehicle, and without blindness effect). // not in liquid, not in vehicle, and without blindness effect).
if (mcFallDistance > 0.0 && !player.isInsideVehicle() && !player.hasPotionEffect(PotionEffectType.BLINDNESS)) { if (mcFallDistance > 0.0 && !player.isInsideVehicle() && !player.hasPotionEffect(PotionEffectType.BLINDNESS)) {
// Might be a violation. // Might be a violation.
final MovingData dataM = MovingData.getData(player); final MovingData dataM = pData.getGenericInstance(MovingData.class);
/*
* TODO: NoFall data max y. (past moves too perhaps - low jump,
* number split moves without reason)
*/
// TODO: Skip near the highest jump height (needs check if head collided with something solid, which also detects low jump). // TODO: Skip near the highest jump height (needs check if head collided with something solid, which also detects low jump).
if (!dataM.isVelocityJumpPhase() && if (!dataM.isVelocityJumpPhase() &&
(dataM.sfLowJump && !dataM.sfNoLowJump && dataM.liftOffEnvelope == LiftOffEnvelope.NORMAL (dataM.sfLowJump && !dataM.sfNoLowJump && dataM.liftOffEnvelope == LiftOffEnvelope.NORMAL
|| mcFallDistance < cc.criticalFallDistance && !BlockProperties.isResetCond(player, loc, mCc.yOnGround))) { || mcFallDistance < cc.criticalFallDistance && !BlockProperties.isResetCond(player, loc, mCc.yOnGround))) {
final MovingConfig ccM = MovingConfig.getConfig(player); final MovingConfig ccM = pData.getGenericInstance(MovingConfig.class);
// TODO: Use past move tracking to check for SurvivalFly and the like? // TODO: Use past move tracking to check for SurvivalFly and the like?
final PlayerMoveInfo moveInfo = auxMoving.usePlayerMoveInfo(); final PlayerMoveInfo moveInfo = auxMoving.usePlayerMoveInfo();
moveInfo.set(player, loc, null, ccM.yOnGround); moveInfo.set(player, loc, null, ccM.yOnGround);

View File

@ -19,25 +19,27 @@ 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.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.players.PlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/** /**
* Legacy check (client side health regeneration).
* *
* @author mc_dev * @author asofold
* *
*/ */
public class FastHeal extends Check { public class FastHeal extends Check {
public FastHeal(){ public FastHeal(){
super(CheckType.FIGHT_FASTHEAL); super(CheckType.FIGHT_FASTHEAL);
} }
public boolean check(final Player player){ public boolean check(final Player player, final IPlayerData pData){
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
final PlayerData pData = DataManager.getPlayerData(player);
final FightConfig cc = FightConfig.getConfig(player); final FightConfig cc = pData.getGenericInstance(FightConfig.class);
final FightData data = FightData.getData(player); final FightData data = pData.getGenericInstance(FightData.class);
boolean cancel = false; boolean cancel = false;
if (time < data.fastHealRefTime || time - data.fastHealRefTime >= cc.fastHealInterval){ if (time < data.fastHealRefTime || time - data.fastHealRefTime >= cc.fastHealInterval){
// Reset. // Reset.
@ -63,7 +65,7 @@ public class FastHeal extends Check {
} }
} }
if (data.debug && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){ if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){
player.sendMessage("Regain health(SATIATED): " + (time - data.fastHealRefTime) + " ms "+ "(buffer=" + data.fastHealBuffer + ")" +" , cancel=" + cancel); player.sendMessage("Regain health(SATIATED): " + (time - data.fastHealRefTime) + " ms "+ "(buffer=" + data.fastHealBuffer + ")" +" , cancel=" + cancel);
} }

View File

@ -14,23 +14,17 @@
*/ */
package fr.neatmonster.nocheatplus.checks.fight; package fr.neatmonster.nocheatplus.checks.fight;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean; import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.versions.Bugs; import fr.neatmonster.nocheatplus.compat.versions.Bugs;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion; import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.config.value.OverrideType;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configurations specific for the "fight" checks. Every world gets one of these assigned to it, or if a world doesn't * Configurations specific for the "fight" checks. Every world gets one of these assigned to it, or if a world doesn't
@ -38,72 +32,28 @@ import fr.neatmonster.nocheatplus.permissions.Permissions;
*/ */
public class FightConfig extends ACheckConfig { public class FightConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return FightConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
/** The map containing the configurations per world. */
private static final Map<String, FightConfig> worldsMap = new HashMap<String, FightConfig>();
/**
* Clear all the configurations.
*/
public static void clear() {
worldsMap.clear();
}
/**
* Gets the configuration for a specified player.
*
* @param player
* the player
* @return the configuration
*/
public static FightConfig getConfig(final Player player) {
if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(),
new FightConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName());
}
public final boolean angleCheck;
public final double angleThreshold; public final double angleThreshold;
public final ActionList angleActions; public final ActionList angleActions;
public final long toolChangeAttackPenalty; public final long toolChangeAttackPenalty;
public final boolean criticalCheck;
public final double criticalFallDistance; public final double criticalFallDistance;
public final ActionList criticalActions; public final ActionList criticalActions;
public final boolean directionCheck;
public final boolean directionStrict; public final boolean directionStrict;
public final long directionPenalty; public final long directionPenalty;
public final ActionList directionActions; public final ActionList directionActions;
public final boolean fastHealCheck;
public final long fastHealInterval; public final long fastHealInterval;
public final long fastHealBuffer; public final long fastHealBuffer;
public final ActionList fastHealActions; public final ActionList fastHealActions;
public final boolean godModeCheck;
public final long godModeLagMinAge; public final long godModeLagMinAge;
public final long godModeLagMaxAge; public final long godModeLagMaxAge;
public final ActionList godModeActions; public final ActionList godModeActions;
public final boolean noSwingCheck;
public final ActionList noSwingActions; public final ActionList noSwingActions;
public final boolean reachCheck;
public final long reachPenalty; public final long reachPenalty;
public final boolean reachPrecision; public final boolean reachPrecision;
public final boolean reachReduce; public final boolean reachReduce;
@ -113,10 +63,8 @@ public class FightConfig extends ACheckConfig {
public final ActionList reachActions; public final ActionList reachActions;
public final boolean selfHitCheck;
public final ActionList selfHitActions; public final ActionList selfHitActions;
public final boolean speedCheck;
public final int speedLimit; public final int speedLimit;
public final int speedBuckets; public final int speedBuckets;
public final long speedBucketDur; public final long speedBucketDur;
@ -126,11 +74,9 @@ public class FightConfig extends ACheckConfig {
public final int speedShortTermTicks; public final int speedShortTermTicks;
public final ActionList speedActions; public final ActionList speedActions;
public final boolean wrongTurnEnabled;
public final ActionList wrongTurnActions; public final ActionList wrongTurnActions;
// Special flags: // Special flags:
public final boolean yawRateCheck;
public final boolean cancelDead; public final boolean cancelDead;
public final boolean knockBackVelocityPvP; public final boolean knockBackVelocityPvP;
@ -143,94 +89,61 @@ public class FightConfig extends ACheckConfig {
* @param data * @param data
* the data * the data
*/ */
public FightConfig(final ConfigFile data) { public FightConfig(final IWorldData worldData) {
super(data, ConfPaths.FIGHT); super(worldData);
angleCheck = data.getBoolean(ConfPaths.FIGHT_ANGLE_CHECK); final ConfigFile config = worldData.getRawConfiguration();
angleThreshold = data.getDouble(ConfPaths.FIGHT_ANGLE_THRESHOLD); angleThreshold = config.getDouble(ConfPaths.FIGHT_ANGLE_THRESHOLD);
angleActions = data.getOptimizedActionList(ConfPaths.FIGHT_ANGLE_ACTIONS, Permissions.FIGHT_ANGLE); angleActions = config.getOptimizedActionList(ConfPaths.FIGHT_ANGLE_ACTIONS, Permissions.FIGHT_ANGLE);
toolChangeAttackPenalty = data.getLong(ConfPaths.FIGHT_TOOLCHANGEPENALTY); toolChangeAttackPenalty = config.getLong(ConfPaths.FIGHT_TOOLCHANGEPENALTY);
criticalCheck = data.getBoolean(ConfPaths.FIGHT_CRITICAL_CHECK); criticalFallDistance = config.getDouble(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE);
criticalFallDistance = data.getDouble(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE); criticalActions = config.getOptimizedActionList(ConfPaths.FIGHT_CRITICAL_ACTIONS, Permissions.FIGHT_CRITICAL);
criticalActions = data.getOptimizedActionList(ConfPaths.FIGHT_CRITICAL_ACTIONS, Permissions.FIGHT_CRITICAL);
directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK); directionStrict = config.getBoolean(ConfPaths.FIGHT_DIRECTION_STRICT);
directionStrict = data.getBoolean(ConfPaths.FIGHT_DIRECTION_STRICT); directionPenalty = config.getLong(ConfPaths.FIGHT_DIRECTION_PENALTY);
directionPenalty = data.getLong(ConfPaths.FIGHT_DIRECTION_PENALTY); directionActions = config.getOptimizedActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION);
directionActions = data.getOptimizedActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION);
fastHealCheck = ServerVersion.compareMinecraftVersion("1.9") < 0 ? data.getBoolean(ConfPaths.FIGHT_FASTHEAL_CHECK) : false; if (ServerVersion.compareMinecraftVersion("1.9") >= 0) {
fastHealInterval = data.getLong(ConfPaths.FIGHT_FASTHEAL_INTERVAL); worldData.overrideCheckActivation(CheckType.FIGHT_FASTHEAL,
fastHealBuffer = data.getLong(ConfPaths.FIGHT_FASTHEAL_BUFFER); AlmostBoolean.NO, OverrideType.PERMANENT,
fastHealActions = data.getOptimizedActionList(ConfPaths.FIGHT_FASTHEAL_ACTIONS, Permissions.FIGHT_FASTHEAL); true);
}
fastHealInterval = config.getLong(ConfPaths.FIGHT_FASTHEAL_INTERVAL);
fastHealBuffer = config.getLong(ConfPaths.FIGHT_FASTHEAL_BUFFER);
fastHealActions = config.getOptimizedActionList(ConfPaths.FIGHT_FASTHEAL_ACTIONS, Permissions.FIGHT_FASTHEAL);
godModeCheck = data.getBoolean(ConfPaths.FIGHT_GODMODE_CHECK); godModeLagMinAge = config.getLong(ConfPaths.FIGHT_GODMODE_LAGMINAGE);
godModeLagMinAge = data.getLong(ConfPaths.FIGHT_GODMODE_LAGMINAGE); godModeLagMaxAge = config.getLong(ConfPaths.FIGHT_GODMODE_LAGMAXAGE);
godModeLagMaxAge = data.getLong(ConfPaths.FIGHT_GODMODE_LAGMAXAGE); godModeActions = config.getOptimizedActionList(ConfPaths.FIGHT_GODMODE_ACTIONS, Permissions.FIGHT_GODMODE);
godModeActions = data.getOptimizedActionList(ConfPaths.FIGHT_GODMODE_ACTIONS, Permissions.FIGHT_GODMODE);
noSwingCheck = data.getBoolean(ConfPaths.FIGHT_NOSWING_CHECK); noSwingActions = config.getOptimizedActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING);
noSwingActions = data.getOptimizedActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING);
reachCheck = data.getBoolean(ConfPaths.FIGHT_REACH_CHECK); reachSurvivalDistance = config.getDouble(ConfPaths.FIGHT_REACH_SURVIVALDISTANCE, 3.5, 6.0, 4.4);
reachSurvivalDistance = data.getDouble(ConfPaths.FIGHT_REACH_SURVIVALDISTANCE, 3.5, 6.0, 4.4); reachPenalty = config.getLong(ConfPaths.FIGHT_REACH_PENALTY);
reachPenalty = data.getLong(ConfPaths.FIGHT_REACH_PENALTY); reachPrecision = config.getBoolean(ConfPaths.FIGHT_REACH_PRECISION);
reachPrecision = data.getBoolean(ConfPaths.FIGHT_REACH_PRECISION); reachReduce = config.getBoolean(ConfPaths.FIGHT_REACH_REDUCE);
reachReduce = data.getBoolean(ConfPaths.FIGHT_REACH_REDUCE); reachReduceDistance = config.getDouble(ConfPaths.FIGHT_REACH_REDUCEDISTANCE, 0, reachSurvivalDistance, 0.9);
reachReduceDistance = data.getDouble(ConfPaths.FIGHT_REACH_REDUCEDISTANCE, 0, reachSurvivalDistance, 0.9); reachReduceStep = config.getDouble(ConfPaths.FIGHT_REACH_REDUCESTEP, 0, reachReduceDistance, 0.15);
reachReduceStep = data.getDouble(ConfPaths.FIGHT_REACH_REDUCESTEP, 0, reachReduceDistance, 0.15); reachActions = config.getOptimizedActionList(ConfPaths.FIGHT_REACH_ACTIONS, Permissions.FIGHT_REACH);
reachActions = data.getOptimizedActionList(ConfPaths.FIGHT_REACH_ACTIONS, Permissions.FIGHT_REACH);
selfHitCheck = data.getBoolean(ConfPaths.FIGHT_SELFHIT_CHECK); selfHitActions = config.getOptimizedActionList(ConfPaths.FIGHT_SELFHIT_ACTIONS, Permissions.FIGHT_SELFHIT);
selfHitActions = data.getOptimizedActionList(ConfPaths.FIGHT_SELFHIT_ACTIONS, Permissions.FIGHT_SELFHIT);
speedCheck = data.getBoolean(ConfPaths.FIGHT_SPEED_CHECK); speedLimit = config.getInt(ConfPaths.FIGHT_SPEED_LIMIT);
speedLimit = data.getInt(ConfPaths.FIGHT_SPEED_LIMIT); speedBuckets = config.getInt(ConfPaths.FIGHT_SPEED_BUCKETS_N, 6);
speedBuckets = data.getInt(ConfPaths.FIGHT_SPEED_BUCKETS_N, 6); speedBucketDur = config.getLong(ConfPaths.FIGHT_SPEED_BUCKETS_DUR, 333);
speedBucketDur = data.getLong(ConfPaths.FIGHT_SPEED_BUCKETS_DUR, 333); speedBucketFactor = (float) config.getDouble(ConfPaths.FIGHT_SPEED_BUCKETS_FACTOR, 1f);
speedBucketFactor = (float) data.getDouble(ConfPaths.FIGHT_SPEED_BUCKETS_FACTOR, 1f); speedShortTermLimit = config.getInt(ConfPaths.FIGHT_SPEED_SHORTTERM_LIMIT);
speedShortTermLimit = data.getInt(ConfPaths.FIGHT_SPEED_SHORTTERM_LIMIT); speedShortTermTicks = config.getInt(ConfPaths.FIGHT_SPEED_SHORTTERM_TICKS);
speedShortTermTicks = data.getInt(ConfPaths.FIGHT_SPEED_SHORTTERM_TICKS); speedActions = config.getOptimizedActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED);
speedActions = data.getOptimizedActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED);
wrongTurnEnabled = data.getBoolean(ConfPaths.FIGHT_WRONGTURN_CHECK); wrongTurnActions = config.getOptimizedActionList(ConfPaths.FIGHT_WRONGTURN_ACTIONS,
wrongTurnActions = data.getOptimizedActionList(ConfPaths.FIGHT_WRONGTURN_ACTIONS,
CheckType.FIGHT_WRONGTURN.getPermission()); CheckType.FIGHT_WRONGTURN.getPermission());
yawRateCheck = data.getBoolean(ConfPaths.FIGHT_YAWRATE_CHECK, true); cancelDead = config.getBoolean(ConfPaths.FIGHT_CANCELDEAD);
cancelDead = data.getBoolean(ConfPaths.FIGHT_CANCELDEAD); AlmostBoolean ref = config.getAlmostBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, AlmostBoolean.MAYBE);
AlmostBoolean ref = data.getAlmostBoolean(ConfPaths.FIGHT_PVP_KNOCKBACKVELOCITY, AlmostBoolean.MAYBE);
knockBackVelocityPvP = ref == AlmostBoolean.MAYBE ? Bugs.shouldPvpKnockBackVelocity() : ref.decide(); knockBackVelocityPvP = ref == AlmostBoolean.MAYBE ? Bugs.shouldPvpKnockBackVelocity() : ref.decide();
} }
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster.nocheatplus.checks.CheckType)
*/
@Override
public final boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case FIGHT_ANGLE:
return angleCheck;
case FIGHT_CRITICAL:
return criticalCheck;
case FIGHT_DIRECTION:
return directionCheck;
case FIGHT_GODMODE:
return godModeCheck;
case FIGHT_NOSWING:
return noSwingCheck;
case FIGHT_REACH:
return reachCheck;
case FIGHT_SPEED:
return speedCheck;
case FIGHT_SELFHIT:
return selfHitCheck;
case FIGHT_FASTHEAL:
return fastHealCheck;
default:
return true;
}
}
} }

View File

@ -14,21 +14,11 @@
*/ */
package fr.neatmonster.nocheatplus.checks.fight; package fr.neatmonster.nocheatplus.checks.fight;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Map;
import java.util.UUID;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
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.ICheckData;
import fr.neatmonster.nocheatplus.checks.access.IRemoveSubCheckData; import fr.neatmonster.nocheatplus.checks.access.IRemoveSubCheckData;
import fr.neatmonster.nocheatplus.checks.access.SubCheckDataFactory;
import fr.neatmonster.nocheatplus.utilities.CheckTypeUtil;
import fr.neatmonster.nocheatplus.utilities.PenaltyTime; import fr.neatmonster.nocheatplus.utilities.PenaltyTime;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
@ -37,112 +27,6 @@ import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
*/ */
public class FightData extends ACheckData implements IRemoveSubCheckData { public class FightData extends ACheckData implements IRemoveSubCheckData {
public static class FightDataFactory implements CheckDataFactory {
protected FightDataFactory() {
// Discourage creation here.
};
@Override
public final ICheckData getData(final Player player) {
return FightData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return FightData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return FightData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
}
/** The factory for general fight data. */
public static final CheckDataFactory factory = new FightDataFactory();
/** SelfHit factory */
public static final CheckDataFactory selfHitDataFactory = new SubCheckDataFactory<FightData>(CheckType.FIGHT, factory) {
@Override
protected FightData getData(String playerName) {
return playersMap.get(playerName);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return playersMap.get(playerName);
}
@Override
protected Collection<String> getPresentData() {
return playersMap.keySet();
}
@Override
protected boolean hasData(String playerName) {
return playersMap.containsKey(playerName);
}
@Override
protected boolean removeFromData(String playerName, FightData data) {
if (data.selfHitVL.score(1f) > 0f) {
data.selfHitVL.clear(System.currentTimeMillis());
return true;
}
else {
return false;
}
}
};
public static CheckDataFactory getCheckDataFactory(CheckType checkType) {
if (checkType != CheckType.FIGHT && !CheckTypeUtil.isAncestor(CheckType.FIGHT, checkType)) {
throw new IllegalArgumentException("Can only return a CheckDataFactory for the check group FIGHT.");
}
switch(checkType) {
// Note that CheckType does need adaption for new entries (!).
case FIGHT_SELFHIT:
return selfHitDataFactory;
default:
return factory;
}
}
/** The map containing the data per players. */
protected static final Map<String, FightData> playersMap = new HashMap<String, FightData>(); // Not sure about visibility (selfhit).
/**
* Gets the data of a specified player.
*
* @param player
* the player
* @return the data
*/
public static FightData getData(final Player player) {
if (!playersMap.containsKey(player.getName()))
playersMap.put(player.getName(), new FightData(FightConfig.getConfig(player)));
return playersMap.get(player.getName());
}
public static ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static void clear(){
playersMap.clear();
}
// Violation levels. // Violation levels.
public double angleVL; public double angleVL;
public double criticalVL; public double criticalVL;
@ -225,7 +109,6 @@ public class FightData extends ACheckData implements IRemoveSubCheckData {
public FightData(final FightConfig config){ public FightData(final FightConfig config){
super(config);
speedBuckets = new ActionFrequency(config.speedBuckets, config.speedBucketDur); speedBuckets = new ActionFrequency(config.speedBuckets, config.speedBucketDur);
// Start with full fast-heal buffer. // Start with full fast-heal buffer.
fastHealBuffer = config.fastHealBuffer; fastHealBuffer = config.fastHealBuffer;

View File

@ -59,7 +59,7 @@ import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHand
import fr.neatmonster.nocheatplus.components.registry.feature.JoinLeaveListener; import fr.neatmonster.nocheatplus.components.registry.feature.JoinLeaveListener;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters; import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
@ -139,18 +139,19 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
*/ */
private boolean handleNormalDamage(final Player player, final boolean attackerIsFake, private boolean handleNormalDamage(final Player player, final boolean attackerIsFake,
final Entity damaged, final boolean damagedIsFake, final Entity damaged, final boolean damagedIsFake,
final double originalDamage, final double finalDamage, final int tick, final FightData data) { final double originalDamage, final double finalDamage,
final int tick, final FightData data, final IPlayerData pData) {
final PlayerData pData = DataManager.getPlayerData(player); final FightConfig cc = pData.getGenericInstance(FightConfig.class);
final FightConfig cc = FightConfig.getConfig(player);
// Hotfix attempt for enchanted books. // Hotfix attempt for enchanted books.
// TODO: maybe a generalized version for the future... // TODO: maybe a generalized version for the future...
// Illegal enchantments hotfix check. // Illegal enchantments hotfix check.
if (Items.checkIllegalEnchantmentsAllHands(player)) { if (Items.checkIllegalEnchantmentsAllHands(player, pData)) {
return true; return true;
} }
final boolean debug = pData.isDebugActive(checkType);
boolean cancelled = false; boolean cancelled = false;
final String worldName = player.getWorld().getName(); final String worldName = player.getWorld().getName();
@ -181,9 +182,11 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
else { else {
tickAge = tick - data.lastAttackTick; tickAge = tick - data.lastAttackTick;
// TODO: Maybe use 3d distance if dy(normalized) is too big. // TODO: Maybe use 3d distance if dy(normalized) is too big.
targetMove = TrigUtil.distance(data.lastAttackedX, data.lastAttackedZ, damagedLoc.getX(), damagedLoc.getZ()); targetMove = TrigUtil.distance(data.lastAttackedX, data.lastAttackedZ,
damagedLoc.getX(), damagedLoc.getZ());
msAge = (long) (50f * TickTask.getLag(50L * tickAge, true) * (float) tickAge); msAge = (long) (50f * TickTask.getLag(50L * tickAge, true) * (float) tickAge);
normalizedMove = msAge == 0 ? targetMove : targetMove * Math.min(20.0, 1000.0 / (double) msAge); normalizedMove = msAge == 0 ? targetMove
: targetMove * Math.min(20.0, 1000.0 / (double) msAge);
} }
// TODO: calculate factor for dists: ticks * 50 * lag // TODO: calculate factor for dists: ticks * 50 * lag
@ -199,18 +202,23 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// damagedPlayer.getLocation(useLoc2); // damagedPlayer.getLocation(useLoc2);
// } // }
// Log. // Log.
if (data.debug && DataManager.getPlayerData(damagedPlayer).hasPermission( if (debug && DataManager.getPlayerData(damagedPlayer).hasPermission(
Permissions.ADMINISTRATION_DEBUG, damagedPlayer)) { Permissions.ADMINISTRATION_DEBUG, damagedPlayer)) {
damagedPlayer.sendMessage("Attacked by " + player.getName() + ": inv=" + mcAccess.getHandle().getInvulnerableTicks(damagedPlayer) + " ndt=" + damagedPlayer.getNoDamageTicks()); damagedPlayer.sendMessage("Attacked by " + player.getName() + ": inv=" + mcAccess.getHandle().getInvulnerableTicks(damagedPlayer) + " ndt=" + damagedPlayer.getNoDamageTicks());
} }
// Check for self hit exploits (mind that projectiles are excluded from this.) // Check for self hit exploits (mind that projectiles are excluded from this.)
if (selfHit.isEnabled(player) && selfHit.check(player, damagedPlayer, data, cc)) { if (selfHit.isEnabled(player, pData) && selfHit.check(player, damagedPlayer, data, cc)) {
cancelled = true; cancelled = true;
} }
// Get+update the damaged players. // Get+update the damaged players.
// TODO: Problem with NPCs: data stays (not a big problem). // TODO: Problem with NPCs: data stays (not a big problem).
// (This is done even if the event has already been cancelled, to keep track, if the player is on a horse.) // (This is done even if the event has already been cancelled, to keep track, if the player is on a horse.)
damagedTrace = MovingData.getData(damagedPlayer).updateTrace(damagedPlayer, damagedLoc, tick, damagedIsFake ? null : mcAccess.getHandle()); damagedTrace = DataManager.getPlayerData(damagedPlayer).getGenericInstance(
MovingData.class
).updateTrace(
damagedPlayer, damagedLoc, tick,
damagedIsFake ? null : mcAccess.getHandle()
);
} }
else { else {
damagedPlayer = null; // TODO: This is a temporary workaround. damagedPlayer = null; // TODO: This is a temporary workaround.
@ -222,7 +230,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
} }
// Log generic properties of this attack. // Log generic properties of this attack.
if (data.debug) { if (debug) {
debug(player, "Attacks " + (damagedPlayer == null ? ("entity " + damaged.getType()) : ("player" + damagedPlayer.getName())) + " damage=" + (finalDamage == originalDamage ? finalDamage : (originalDamage + "/" + finalDamage))); debug(player, "Attacks " + (damagedPlayer == null ? ("entity " + damaged.getType()) : ("player" + damagedPlayer.getName())) + " damage=" + (finalDamage == originalDamage ? finalDamage : (originalDamage + "/" + finalDamage)));
} }
@ -246,7 +254,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
if (tick == data.sweepTick && locHashCode == data.sweepLocationHashCode) { if (tick == data.sweepTick && locHashCode == data.sweepLocationHashCode) {
// TODO: Might limit the amount of 'too far off' sweep hits, possibly silent cancel for low frequency. // TODO: Might limit the amount of 'too far off' sweep hits, possibly silent cancel for low frequency.
// Could further guard by checking equality of loc to last location. // Could further guard by checking equality of loc to last location.
if (data.debug) { if (debug) {
debug(player, "(Assume sweep attack follow up damage.)"); debug(player, "(Assume sweep attack follow up damage.)");
} }
return cancelled; return cancelled;
@ -273,23 +281,25 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// TODO: Add as real check. // TODO: Add as real check.
// TODO: Add something on packet level already. // TODO: Add something on packet level already.
if (wrongTurn.isEnabled(player, cc, pData) && wrongTurn.check(damagedPlayer, loc, data, cc)) { if (pData.isCheckActive(CheckType.FIGHT_WRONGTURN, damagedPlayer)
&& wrongTurn.check(damagedPlayer, loc, data, cc)) {
cancelled = true; cancelled = true;
} }
// Run through the main checks. // Run through the main checks.
if (!cancelled && speed.isEnabled(player)) { if (!cancelled && speed.isEnabled(player, pData)) {
if (speed.check(player, now)) { if (speed.check(player, now, data, cc, pData)) {
cancelled = true; cancelled = true;
// Still feed the improbable. // Still feed the improbable.
if (data.speedVL > 50) { if (data.speedVL > 50) {
Improbable.check(player, 2f, now, "fight.speed"); Improbable.check(player, 2f, now, "fight.speed", pData);
} }
else { else {
Improbable.feed(player, 2f, now); Improbable.feed(player, 2f, now);
} }
} }
else if (normalizedMove > 2.0 && Improbable.check(player, 1f, now, "fight.speed")) { else if (normalizedMove > 2.0 && Improbable.check(player, 1f, now,
"fight.speed", pData)) {
// Feed improbable in case of ok-moves too. // Feed improbable in case of ok-moves too.
// TODO: consider only feeding if attacking with higher average speed (!) // TODO: consider only feeding if attacking with higher average speed (!)
cancelled = true; cancelled = true;
@ -297,12 +307,12 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
} }
// TODO: Consider to always check improbable (first?). At least if config.always or speed or net.attackfrequency are enabled. // 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, pData)) { if (!cancelled && critical.isEnabled(player, pData) && critical.check(player, loc, data, cc, pData)) {
// TODO: Check config for settings. // TODO: Check config for settings.
cancelled = true; cancelled = true;
} }
if (!cancelled && noSwing.isEnabled(player) && noSwing.check(player, data, cc)) { if (!cancelled && noSwing.isEnabled(player, pData) && noSwing.check(player, data, cc)) {
cancelled = true; cancelled = true;
} }
@ -313,13 +323,14 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
} }
if (!cancelled) { if (!cancelled) {
final boolean reachEnabled = reach.isEnabled(player); final boolean reachEnabled = reach.isEnabled(player, pData);
final boolean directionEnabled = direction.isEnabled(player); final boolean directionEnabled = direction.isEnabled(player, pData);
if (reachEnabled || directionEnabled) { if (reachEnabled || directionEnabled) {
if (damagedTrace != null) { if (damagedTrace != null) {
// Checks that use the LocationTrace instance of the attacked entity/player. // Checks that use the LocationTrace instance of the attacked entity/player.
cancelled = locationTraceChecks(player, loc, data, cc, pData, cancelled = locationTraceChecks(player, loc, data, cc, pData,
damaged, damagedIsFake, damagedLoc, damagedTrace, tick, now, reachEnabled, directionEnabled); damaged, damagedIsFake, damagedLoc, damagedTrace, tick, now, debug,
reachEnabled, directionEnabled);
} }
else { else {
// Still use the classic methods for non-players. maybe[] // Still use the classic methods for non-players. maybe[]
@ -337,18 +348,19 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// Check angle with allowed window. // Check angle with allowed window.
// TODO: Actual angle needs to be related to the best matching trace element(s) (loop checks). // TODO: Actual angle needs to be related to the best matching trace element(s) (loop checks).
if (angle.isEnabled(player)) { if (angle.isEnabled(player, pData)) {
// TODO: Revise, use own trace. // TODO: Revise, use own trace.
// The "fast turning" checks are checked in any case because they accumulate data. // The "fast turning" checks are checked in any case because they accumulate data.
// Improbable yaw changing: Moving events might be missing up to a ten degrees change. // Improbable yaw changing: Moving events might be missing up to a ten degrees change.
if (Combined.checkYawRate(player, loc.getYaw(), now, worldName, cc.yawRateCheck)) { if (Combined.checkYawRate(player, loc.getYaw(), now, worldName,
pData.isCheckActive(CheckType.COMBINED_YAWRATE, player), pData)) {
// (Check or just feed). // (Check or just feed).
// TODO: Work into this somehow attacking the same aim and/or similar aim position (not cancel then). // TODO: Work into this somehow attacking the same aim and/or similar aim position (not cancel then).
cancelled = true; cancelled = true;
} }
// Angle check. // Angle check.
if (angle.check(player, loc, damaged, worldChanged, data, cc)) { if (angle.check(player, loc, damaged, worldChanged, data, cc)) {
if (!cancelled && data.debug) { if (!cancelled && debug) {
debug(player, "FIGHT_ANGLE cancel without yawrate cancel."); debug(player, "FIGHT_ANGLE cancel without yawrate cancel.");
} }
cancelled = true; cancelled = true;
@ -370,14 +382,14 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// TODO: Confine further with simple pre-conditions. // TODO: Confine further with simple pre-conditions.
// TODO: Evaluate if moving traces can help here. // TODO: Evaluate if moving traces can help here.
if (!cancelled && TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) < 4.5) { if (!cancelled && TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) < 4.5) {
final MovingData mData = MovingData.getData(player); final MovingData mData = pData.getGenericInstance(MovingData.class);
// Check if fly checks is an issue at all, re-check "real sprinting". // Check if fly checks is an issue at all, re-check "real sprinting".
final PlayerMoveData lastMove = mData.playerMoves.getFirstPastMove(); final PlayerMoveData lastMove = mData.playerMoves.getFirstPastMove();
if (lastMove.valid && mData.liftOffEnvelope == LiftOffEnvelope.NORMAL) { if (lastMove.valid && mData.liftOffEnvelope == LiftOffEnvelope.NORMAL) {
final double hDist = TrigUtil.xzDistance(loc, lastMove.from); final double hDist = TrigUtil.xzDistance(loc, lastMove.from);
if (hDist >= 0.23) { if (hDist >= 0.23) {
// TODO: Might need to check hDist relative to speed / modifiers. // TODO: Might need to check hDist relative to speed / modifiers.
final MovingConfig mCc = MovingConfig.getConfig(player); final MovingConfig mCc = pData.getGenericInstance(MovingConfig.class);
final PlayerMoveInfo moveInfo = auxMoving.usePlayerMoveInfo(); final PlayerMoveInfo moveInfo = auxMoving.usePlayerMoveInfo();
moveInfo.set(player, loc, null, mCc.yOnGround); moveInfo.set(player, loc, null, mCc.yOnGround);
if (now <= mData.timeSprinting + mCc.sprintingGrace if (now <= mData.timeSprinting + mCc.sprintingGrace
@ -385,7 +397,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// Judge as "lost sprint" problem. // Judge as "lost sprint" problem.
// TODO: What would mData.lostSprintCount > 0 mean here? // TODO: What would mData.lostSprintCount > 0 mean here?
mData.lostSprintCount = 7; mData.lostSprintCount = 7;
if ((data.debug || mCc.debug) && BuildParameters.debugLevel > 0) { if ((debug || pData.isDebugActive(CheckType.MOVING))
&& BuildParameters.debugLevel > 0) {
debug(player, "lostsprint: hDist to last from: " + hDist + " | targetdist=" + TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) + " | sprinting=" + player.isSprinting() + " | food=" + player.getFoodLevel() +" | hbuf=" + mData.sfHorizontalBuffer); debug(player, "lostsprint: hDist to last from: " + hDist + " | targetdist=" + TrigUtil.distance(loc.getX(), loc.getZ(), damagedLoc.getX(), damagedLoc.getZ()) + " | sprinting=" + player.isSprinting() + " | food=" + player.getFoodLevel() +" | hbuf=" + mData.sfHorizontalBuffer);
} }
} }
@ -398,7 +411,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
// (Cancel after sprinting hacks, because of potential fp). // (Cancel after sprinting hacks, because of potential fp).
if (!cancelled && data.attackPenalty.isPenalty(now)) { if (!cancelled && data.attackPenalty.isPenalty(now)) {
cancelled = true; cancelled = true;
if (data.debug) { if (debug) {
debug(player, "~ attack penalty."); debug(player, "~ attack penalty.");
} }
} }
@ -426,10 +439,11 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
* @return If to cancel (true) or not (false). * @return If to cancel (true) or not (false).
*/ */
private boolean locationTraceChecks(final Player player, final Location loc, private boolean locationTraceChecks(final Player player, final Location loc,
final FightData data, final FightConfig cc, final PlayerData pData, final FightData data, final FightConfig cc, final IPlayerData pData,
final Entity damaged, final boolean damagedIsFake, final Entity damaged, final boolean damagedIsFake,
final Location damagedLoc, LocationTrace damagedTrace, final Location damagedLoc, LocationTrace damagedTrace,
final long tick, final long now, final boolean reachEnabled, final boolean directionEnabled) { final long tick, final long now, final boolean debug,
final boolean reachEnabled, final boolean directionEnabled) {
// TODO: Order / splitting off generic stuff. // TODO: Order / splitting off generic stuff.
/* /*
* TODO: Abstract: interface with common setup/loop/post routine, only * TODO: Abstract: interface with common setup/loop/post routine, only
@ -501,7 +515,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
} }
} }
// TODO: Log exact state, probably record min/max latency (individually). // TODO: Log exact state, probably record min/max latency (individually).
if (data.debug && latencyEstimate >= 0) { if (debug && latencyEstimate >= 0) {
debug(player, "Latency estimate: " + latencyEstimate + " ms."); // FCFS rather, at present. debug(player, "Latency estimate: " + latencyEstimate + " ms."); // FCFS rather, at present.
} }
return cancelled; return cancelled;
@ -518,33 +532,44 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
final Entity damaged = event.getEntity(); final Entity damaged = event.getEntity();
final Player damagedPlayer = damaged instanceof Player ? (Player) damaged : null; final Player damagedPlayer = damaged instanceof Player ? (Player) damaged : null;
final FightData damagedData = damagedPlayer == null ? null : FightData.getData(damagedPlayer); final FightData damagedData;
final boolean damagedIsDead = damaged.isDead(); final boolean damagedIsDead = damaged.isDead();
final boolean damagedIsFake = !crossPlugin.getHandle().isNativeEntity(damaged); final boolean damagedIsFake = !crossPlugin.getHandle().isNativeEntity(damaged);
if (damagedPlayer != null && !damagedIsDead) { if (damagedPlayer != null) {
// God mode check. final IPlayerData damagedPData = DataManager.getPlayerData(damagedPlayer);
// (Do not test the savage.) damagedData = damagedPData.getGenericInstance(FightData.class);
if (godMode.isEnabled(damagedPlayer) if (!damagedIsDead) {
&& godMode.check(damagedPlayer, damagedIsFake, BridgeHealth.getDamage(event), damagedData)) { // God mode check.
// It requested to "cancel" the players invulnerability, so set their noDamageTicks to 0. // (Do not test the savage.)
damagedPlayer.setNoDamageTicks(0); if (damagedPData.isCheckActive(CheckType.FIGHT_GODMODE, damagedPlayer)
} && godMode.check(damagedPlayer, damagedIsFake,
// Adjust buffer for fast heal checks. BridgeHealth.getDamage(event), damagedData, damagedPData)) {
if (BridgeHealth.getHealth(damagedPlayer) >= BridgeHealth.getMaxHealth(damagedPlayer)) { // It requested to "cancel" the players invulnerability, so set their noDamageTicks to 0.
// TODO: Might use the same FightData instance for GodMode. damagedPlayer.setNoDamageTicks(0);
if (damagedData.fastHealBuffer < 0) {
// Reduce negative buffer with each full health.
damagedData.fastHealBuffer /= 2;
} }
// Set reference time. // Adjust buffer for fast heal checks.
damagedData.fastHealRefTime = System.currentTimeMillis(); if (BridgeHealth.getHealth(damagedPlayer) >= BridgeHealth.getMaxHealth(damagedPlayer)) {
// TODO: Might use the same FightData instance for GodMode.
if (damagedData.fastHealBuffer < 0) {
// Reduce negative buffer with each full health.
damagedData.fastHealBuffer /= 2;
}
// Set reference time.
damagedData.fastHealRefTime = System.currentTimeMillis();
}
// TODO: TEST: Check unused velocity for the damaged player. (Needs more efficient pre condition checks.)
} }
// TODO: TEST: Check unused velocity for the damaged player. (Needs more efficient pre condition checks.) if (damagedPData.isDebugActive(checkType)) {
if (damagedData.debug) {
// TODO: Pass result to further checks for reference? // TODO: Pass result to further checks for reference?
UnusedVelocity.checkUnusedVelocity(damagedPlayer, CheckType.FIGHT); UnusedVelocity.checkUnusedVelocity(damagedPlayer, CheckType.FIGHT, damagedPData);
} }
} }
else {
damagedData = null;
}
// Attacking entities. // Attacking entities.
if (event instanceof EntityDamageByEntityEvent) { if (event instanceof EntityDamageByEntityEvent) {
onEntityDamageByEntity(damaged, damagedPlayer, damagedIsDead, damagedIsFake, onEntityDamageByEntity(damaged, damagedPlayer, damagedIsDead, damagedIsFake,
@ -591,14 +616,16 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
} }
} }
final FightData attackerData; final FightData attackerData;
final IPlayerData attackerPData = attacker == null ? null : DataManager.getPlayerData(attacker);
if (attacker != null) { if (attacker != null) {
attackerData = FightData.getData(attacker);
attackerData = attackerPData.getGenericInstance(FightData.class);
// TODO: TEST: Check unused velocity for the attacker. (Needs more efficient pre condition checks.) // TODO: TEST: Check unused velocity for the attacker. (Needs more efficient pre condition checks.)
if (attackerData.debug) { if (attackerPData.isDebugActive(checkType)) {
// TODO: Pass result to further checks for reference? // TODO: Pass result to further checks for reference?
// TODO: attackerData.debug flag. // TODO: attackerData.debug flag.
// TODO: Fake players likely have unused velocity, just clear unused? // TODO: Fake players likely have unused velocity, just clear unused?
UnusedVelocity.checkUnusedVelocity(attacker, CheckType.FIGHT); UnusedVelocity.checkUnusedVelocity(attacker, CheckType.FIGHT, attackerPData);
} }
// Workaround for subsequent melee damage eventsfor explosions. TODO: Legacy or not, need a KB. // Workaround for subsequent melee damage eventsfor explosions. TODO: Legacy or not, need a KB.
if (damageCause == DamageCause.BLOCK_EXPLOSION || damageCause == DamageCause.ENTITY_EXPLOSION) { if (damageCause == DamageCause.BLOCK_EXPLOSION || damageCause == DamageCause.ENTITY_EXPLOSION) {
@ -621,7 +648,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
} }
// Prevent attacking if a set back is scheduled. // Prevent attacking if a set back is scheduled.
else if (MovingUtil.hasScheduledPlayerSetBack(player)) { else if (MovingUtil.hasScheduledPlayerSetBack(player)) {
if (attackerData.debug) { if (attackerPData.isDebugActive(checkType)) {
// Use fight data flag for efficiency. // Use fight data flag for efficiency.
debug(attacker, "Prevent melee attack, due to a scheduled set back."); debug(attacker, "Prevent melee attack, due to a scheduled set back.");
} }
@ -631,7 +658,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
else if (handleNormalDamage(player, !crossPlugin.getHandle().isNativePlayer(player), else if (handleNormalDamage(player, !crossPlugin.getHandle().isNativePlayer(player),
damaged, damagedIsFake, damaged, damagedIsFake,
BridgeHealth.getOriginalDamage(event), BridgeHealth.getFinalDamage(event), BridgeHealth.getOriginalDamage(event), BridgeHealth.getFinalDamage(event),
tick, attackerData)) { tick, attackerData, attackerPData)) {
event.setCancelled(true); event.setCancelled(true);
} }
} }
@ -643,7 +670,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
final Entity damaged = event.getEntity(); final Entity damaged = event.getEntity();
if (damaged instanceof Player) { if (damaged instanceof Player) {
final Player damagedPlayer = (Player) damaged; final Player damagedPlayer = (Player) damaged;
final FightData damagedData = FightData.getData(damagedPlayer); final IPlayerData damagedPData = DataManager.getPlayerData(damagedPlayer);
final FightData damagedData = damagedPData.getGenericInstance(FightData.class);
final int ndt = damagedPlayer.getNoDamageTicks(); final int ndt = damagedPlayer.getNoDamageTicks();
if (damagedData.lastDamageTick == TickTask.getTick() && damagedData.lastNoDamageTicks != ndt) { if (damagedData.lastDamageTick == TickTask.getTick() && damagedData.lastNoDamageTicks != ndt) {
// Plugin compatibility thing. // Plugin compatibility thing.
@ -654,9 +682,11 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
case ENTITY_ATTACK: case ENTITY_ATTACK:
if (event instanceof EntityDamageByEntityEvent) { if (event instanceof EntityDamageByEntityEvent) {
final Entity entity = ((EntityDamageByEntityEvent) event).getDamager(); final Entity entity = ((EntityDamageByEntityEvent) event).getDamager();
if ((entity instanceof Player) && !damagedPlayer.isInsideVehicle() && FightConfig.getConfig(damagedPlayer).knockBackVelocityPvP) { if ((entity instanceof Player) && !damagedPlayer.isInsideVehicle()
&& damagedPData.getGenericInstance(FightConfig.class).knockBackVelocityPvP) {
// TODO: Use the velocity event that is sent anyway and replace x/z if 0 (queue max. values). // TODO: Use the velocity event that is sent anyway and replace x/z if 0 (queue max. values).
applyKnockBack((Player) entity, damagedPlayer, damagedData); applyKnockBack((Player) entity, damagedPlayer,
damagedData, damagedPData);
} }
} }
default: default:
@ -671,17 +701,18 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
* @param damagedPlayer * @param damagedPlayer
* @param damagedData * @param damagedData
*/ */
private void applyKnockBack(final Player attacker, final Player damagedPlayer, final FightData damagedData) { private void applyKnockBack(final Player attacker, final Player damagedPlayer,
final FightData damagedData, final IPlayerData pData) {
final double level = getKnockBackLevel(attacker); final double level = getKnockBackLevel(attacker);
final MovingData mdata = MovingData.getData(damagedPlayer); final MovingData mdata = pData.getGenericInstance(MovingData.class);
final MovingConfig mcc = MovingConfig.getConfig(damagedPlayer); final MovingConfig mcc = pData.getGenericInstance(MovingConfig.class);
// TODO: How is the direction really calculated? // TODO: How is the direction really calculated?
// Aim at sqrt(vx * vx + vz * vz, 2), not the exact direction. // Aim at sqrt(vx * vx + vz * vz, 2), not the exact direction.
final double vx = level / Math.sqrt(8.0); final double vx = level / Math.sqrt(8.0);
final double vz = vx; final double vz = vx;
final double vy = 0.462; // TODO: (0.365) Needs other workarounds, to allow more when moving off ground (vel + GRAVITY_MAX or max jump gain + little?). final double vy = 0.462; // TODO: (0.365) Needs other workarounds, to allow more when moving off ground (vel + GRAVITY_MAX or max jump gain + little?).
useLoc1.setWorld(null); // Cleanup. useLoc1.setWorld(null); // Cleanup.
if (damagedData.debug || mdata.debug) { if (pData.isDebugActive(checkType) || pData.isDebugActive(CheckType.MOVING)) {
debug(damagedPlayer, "Received knockback level: " + level); debug(damagedPlayer, "Received knockback level: " + level);
} }
mdata.addVelocity(damagedPlayer, mcc, vx, vy, vz, VelocityFlags.ORIGIN_PVP); mdata.addVelocity(damagedPlayer, mcc, vx, vy, vz, VelocityFlags.ORIGIN_PVP);
@ -742,7 +773,8 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
* TODO: First one always fails: Packet inversion on 1.12.2? This could * TODO: First one always fails: Packet inversion on 1.12.2? This could
* be moved to packet level (register either). * be moved to packet level (register either).
*/ */
FightData.getData(event.getPlayer()).noSwingArmSwung = true; DataManager.getGenericInstance(event.getPlayer(),
FightData.class).noSwingArmSwung = true;
} }
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
@ -763,7 +795,9 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
return; return;
} }
// TODO: EATING reason / peaceful difficulty / regen potion - byCaptain SpigotMC // TODO: EATING reason / peaceful difficulty / regen potion - byCaptain SpigotMC
if (fastHeal.isEnabled(player) && fastHeal.check(player)) { final IPlayerData pData = DataManager.getPlayerData(player);
if (pData.isCheckActive(CheckType.FIGHT_FASTHEAL, player)
&& fastHeal.check(player, pData)) {
// TODO: Can clients force events with 0-re-gain ? // TODO: Can clients force events with 0-re-gain ?
event.setCancelled(true); event.setCancelled(true);
} }
@ -776,7 +810,7 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
return; return;
} }
final Player player = (Player) entity; final Player player = (Player) entity;
final FightData data = FightData.getData(player); final FightData data = DataManager.getGenericInstance(player, FightData.class);
// Adjust god mode data: // Adjust god mode data:
// Remember the time. // Remember the time.
data.regainHealthTime = System.currentTimeMillis(); data.regainHealthTime = System.currentTimeMillis();
@ -792,21 +826,23 @@ public class FightListener extends CheckListener implements JoinLeaveListener{
@Override @Override
public void playerLeaves(final Player player) { public void playerLeaves(final Player player) {
final FightData data = FightData.getData(player); final FightData data = DataManager.getGenericInstance(player, FightData.class);
data.angleHits.clear(); data.angleHits.clear();
} }
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) { public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) {
FightData.getData(event.getPlayer()).onWorldChange(); DataManager.getGenericInstance(event.getPlayer(),
FightData.class).onWorldChange();
} }
@EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR) @EventHandler(ignoreCancelled = false, priority = EventPriority.MONITOR)
public void onItemHeld(final PlayerItemHeldEvent event) { public void onItemHeld(final PlayerItemHeldEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final long penalty = FightConfig.getConfig(player).toolChangeAttackPenalty; final IPlayerData pData = DataManager.getPlayerData(player);
final long penalty = pData.getGenericInstance(FightConfig.class).toolChangeAttackPenalty;
if (penalty > 0 ) { if (penalty > 0 ) {
FightData.getData(player).attackPenalty.applyPenalty(penalty); pData.getGenericInstance(FightData.class).attackPenalty.applyPenalty(penalty);
} }
} }

View File

@ -24,6 +24,7 @@ import fr.neatmonster.nocheatplus.checks.net.NetData;
import fr.neatmonster.nocheatplus.compat.BridgeHealth; import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.compat.IBridgeCrossPlugin; import fr.neatmonster.nocheatplus.compat.IBridgeCrossPlugin;
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle; import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -47,7 +48,8 @@ public class GodMode extends Check {
* @param damage * @param damage
* @return * @return
*/ */
public boolean check(final Player player, final boolean playerIsFake, final double damage, final FightData data){ public boolean check(final Player player, final boolean playerIsFake,
final double damage, final FightData data, final IPlayerData pData){
final int tick = TickTask.getTick(); final int tick = TickTask.getTick();
final int noDamageTicks = Math.max(0, player.getNoDamageTicks()); final int noDamageTicks = Math.max(0, player.getNoDamageTicks());
@ -145,16 +147,16 @@ public class GodMode extends Check {
} }
} }
final FightConfig cc = FightConfig.getConfig(player); final FightConfig cc = pData.getGenericInstance(FightConfig.class);
// Check for client side lag. // Check for client side lag.
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final long maxAge = cc.godModeLagMaxAge; final long maxAge = cc.godModeLagMaxAge;
long keepAlive = Long.MIN_VALUE; long keepAlive = Long.MIN_VALUE;
if (NCPAPIProvider.getNoCheatPlusAPI().hasFeatureTag("checks", "KeepAliveFrequency")) { if (NCPAPIProvider.getNoCheatPlusAPI().hasFeatureTag("checks", "KeepAliveFrequency")) {
keepAlive = ((NetData) (CheckType.NET_KEEPALIVEFREQUENCY.getDataFactory().getData(player))).lastKeepAliveTime; keepAlive = pData.getGenericInstance(NetData.class).lastKeepAliveTime;
} }
keepAlive = Math.max(keepAlive, CheckUtils.guessKeepAliveTime(player, now, maxAge)); keepAlive = Math.max(keepAlive, CheckUtils.guessKeepAliveTime(player, now, maxAge, pData));
if (keepAlive != Double.MIN_VALUE && now - keepAlive > cc.godModeLagMinAge && now - keepAlive < maxAge){ if (keepAlive != Double.MIN_VALUE && now - keepAlive > cc.godModeLagMinAge && now - keepAlive < maxAge){
// Assume lag. // Assume lag.
@ -169,7 +171,8 @@ public class GodMode extends Check {
if (data.godModeAcc > 2){ if (data.godModeAcc > 2){
// TODO: To match with old checks vls / actions, either change actions or apply a factor. // TODO: To match with old checks vls / actions, either change actions or apply a factor.
data.godModeVL += delta; data.godModeVL += delta;
if (executeActions(player, data.godModeVL, delta, FightConfig.getConfig(player).godModeActions).willCancel()){ if (executeActions(player, data.godModeVL, delta,
pData.getGenericInstance(FightConfig.class).godModeActions).willCancel()){
cancel = true; cancel = true;
} }
else { else {

View File

@ -29,7 +29,7 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.combined.Improbable; import fr.neatmonster.nocheatplus.checks.combined.Improbable;
import fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace.ITraceEntry; import fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace.ITraceEntry;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil; import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
@ -71,7 +71,7 @@ public class Reach extends Check {
*/ */
public boolean check(final Player player, final Location pLoc, public boolean check(final Player player, final Location pLoc,
final Entity damaged, final boolean damagedIsFake, final Location dRef, final Entity damaged, final boolean damagedIsFake, final Location dRef,
final FightData data, final FightConfig cc, final PlayerData pData) { final FightData data, final FightConfig cc, final IPlayerData pData) {
boolean cancel = false; boolean cancel = false;
// The maximum distance allowed to interact with an entity in survival mode. // The maximum distance allowed to interact with an entity in survival mode.
@ -114,7 +114,8 @@ public class Reach extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should // Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event. // cancel the event.
cancel = executeActions(player, data.reachVL, violation, cc.reachActions).willCancel(); cancel = executeActions(player, data.reachVL, violation, cc.reachActions).willCancel();
if (Improbable.check(player, (float) violation / 2f, System.currentTimeMillis(), "fight.reach")){ if (Improbable.check(player, (float) violation / 2f, System.currentTimeMillis(),
"fight.reach", pData)){
cancel = true; cancel = true;
} }
if (cancel && cc.reachPenalty > 0){ if (cancel && cc.reachPenalty > 0){
@ -146,7 +147,7 @@ public class Reach extends Check {
data.reachMod = Math.min(1.0, data.reachMod + DYNAMIC_STEP); data.reachMod = Math.min(1.0, data.reachMod + DYNAMIC_STEP);
} }
if (data.debug && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){ if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){
player.sendMessage("NC+: Attack/reach " + damaged.getType()+ " height="+ StringUtil.fdec3.format(height) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(reachMod)); player.sendMessage("NC+: Attack/reach " + damaged.getType()+ " height="+ StringUtil.fdec3.format(height) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(reachMod));
} }
@ -163,7 +164,9 @@ public class Reach extends Check {
* @param cc * @param cc
* @return * @return
*/ */
public ReachContext getContext(final Player player, final Location pLoc, final Entity damaged, final Location damagedLoc, final FightData data, final FightConfig cc) { public ReachContext getContext(final Player player, final Location pLoc,
final Entity damaged, final Location damagedLoc,
final FightData data, final FightConfig cc) {
final ReachContext context = new ReachContext(); final ReachContext context = new ReachContext();
context.distanceLimit = player.getGameMode() == GameMode.CREATIVE ? CREATIVE_DISTANCE : cc.reachSurvivalDistance + getDistMod(damaged); context.distanceLimit = player.getGameMode() == GameMode.CREATIVE ? CREATIVE_DISTANCE : cc.reachSurvivalDistance + getDistMod(damaged);
context.distanceMin = (context.distanceLimit - cc.reachReduceDistance) / context.distanceLimit; context.distanceMin = (context.distanceLimit - cc.reachReduceDistance) / context.distanceLimit;
@ -234,7 +237,7 @@ public class Reach extends Check {
*/ */
public boolean loopFinish(final Player player, final Location pLoc, final Entity damaged, public boolean loopFinish(final Player player, final Location pLoc, final Entity damaged,
final ReachContext context, final ITraceEntry traceEntry, final boolean forceViolation, final ReachContext context, final ITraceEntry traceEntry, final boolean forceViolation,
final FightData data, final FightConfig cc, final PlayerData pData) { final FightData data, final FightConfig cc, final IPlayerData pData) {
final double lenpRel = forceViolation && context.minViolation != Double.MAX_VALUE ? context.minViolation : context.minResult; final double lenpRel = forceViolation && context.minViolation != Double.MAX_VALUE ? context.minViolation : context.minResult;
if (lenpRel == Double.MAX_VALUE) { if (lenpRel == Double.MAX_VALUE) {
return false; return false;
@ -251,7 +254,8 @@ public class Reach extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should // Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event. // cancel the event.
cancel = executeActions(player, data.reachVL, violation, cc.reachActions).willCancel(); cancel = executeActions(player, data.reachVL, violation, cc.reachActions).willCancel();
if (Improbable.check(player, (float) violation / 2f, System.currentTimeMillis(), "fight.reach")){ if (Improbable.check(player, (float) violation / 2f, System.currentTimeMillis(),
"fight.reach", pData)){
cancel = true; cancel = true;
} }
if (cancel && cc.reachPenalty > 0){ if (cancel && cc.reachPenalty > 0){
@ -284,7 +288,7 @@ public class Reach extends Check {
data.reachMod = Math.min(1.0, data.reachMod + DYNAMIC_STEP); data.reachMod = Math.min(1.0, data.reachMod + DYNAMIC_STEP);
} }
if (data.debug && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){ if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){
// TODO: Height: remember successful ITraceEntry // TODO: Height: remember successful ITraceEntry
player.sendMessage("NC+: Attack/reach " + damaged.getType()+ (traceEntry == null ? "" : (" height=" + traceEntry.getBoxMarginVertical())) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(data.reachMod)); player.sendMessage("NC+: Attack/reach " + damaged.getType()+ (traceEntry == null ? "" : (" height=" + traceEntry.getBoxMarginVertical())) + " dist=" + StringUtil.fdec3.format(lenpRel) +" @" + StringUtil.fdec3.format(data.reachMod));
} }

View File

@ -20,6 +20,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
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.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/** /**
@ -42,10 +43,11 @@ public class Speed extends Check {
* @param now * @param now
* @return true, if successful * @return true, if successful
*/ */
public boolean check(final Player player, final long now) { public boolean check(final Player player, final long now,
final FightConfig cc = FightConfig.getConfig(player); final FightData data, final FightConfig cc,
final FightData data = FightData.getData(player); final IPlayerData pData) {
final boolean lag = pData.getCurrentWorldData().shouldAdjustToLag(type);
boolean cancel = false; boolean cancel = false;
// Add to frequency. // Add to frequency.
@ -53,7 +55,7 @@ public class Speed extends Check {
// Medium term (normalized to one second), account for server side lag. // Medium term (normalized to one second), account for server side lag.
final long fullTime = cc.speedBucketDur * cc.speedBuckets; final long fullTime = cc.speedBucketDur * cc.speedBuckets;
final float fullLag = cc.lag ? TickTask.getLag(fullTime, true) : 1f; final float fullLag = lag ? TickTask.getLag(fullTime, true) : 1f;
final float total = data.speedBuckets.score(cc.speedBucketFactor) * 1000f / (fullLag * fullTime); final float total = data.speedBuckets.score(cc.speedBucketFactor) * 1000f / (fullLag * fullTime);
// Short term. // Short term.
@ -65,7 +67,7 @@ public class Speed extends Check {
} }
else if (tick - data.speedShortTermTick < cc.speedShortTermTicks){ else if (tick - data.speedShortTermTick < cc.speedShortTermTicks){
// Account for server side lag. // Account for server side lag.
if (!cc.lag || TickTask.getLag(50L * (tick - data.speedShortTermTick), true) < 1.5f){ if (!lag || TickTask.getLag(50L * (tick - data.speedShortTermTick), true) < 1.5f){
// Within range, add. // Within range, add.
data.speedShortTermCount ++; data.speedShortTermCount ++;
} }

View File

@ -1,3 +1,17 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.fight; package fr.neatmonster.nocheatplus.checks.fight;
import org.bukkit.Location; import org.bukkit.Location;
@ -18,7 +32,8 @@ public class WrongTurn extends Check {
super(CheckType.FIGHT_WRONGTURN); super(CheckType.FIGHT_WRONGTURN);
} }
public boolean check (final Player player, final Location loc, final FightData data, final FightConfig cc) { public boolean check (final Player player, final Location loc,
final FightData data, final FightConfig cc) {
final float pitch = loc.getPitch(); final float pitch = loc.getPitch();

View File

@ -26,6 +26,7 @@ import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.checks.access.ICheckData; import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle; import fr.neatmonster.nocheatplus.checks.net.FlyingQueueHandle;
import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker; import fr.neatmonster.nocheatplus.checks.net.FlyingQueueLookBlockChecker;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.collision.CollideRayVsAABB; import fr.neatmonster.nocheatplus.utilities.collision.CollideRayVsAABB;
import fr.neatmonster.nocheatplus.utilities.collision.ICollideRayVsAABB; import fr.neatmonster.nocheatplus.utilities.collision.ICollideRayVsAABB;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil; import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
@ -128,7 +129,8 @@ public abstract class AbstractBlockDirectionCheck<D extends ICheckData, C extend
* @return True, if the check has been failed. * @return True, if the check has been failed.
*/ */
public boolean check(final Player player, final Location loc, final double eyeHeight, public boolean check(final Player player, final Location loc, final double eyeHeight,
final Block block, final FlyingQueueHandle flyingHandle, final D data, final C cc) { final Block block, final FlyingQueueHandle flyingHandle,
final D data, final C cc, final IPlayerData pData) {
boolean cancel = false; boolean cancel = false;
// How far "off" is the player with their aim. // How far "off" is the player with their aim.
@ -151,7 +153,7 @@ public abstract class AbstractBlockDirectionCheck<D extends ICheckData, C extend
// TODO: Consider a protected field with a tolerance value. // TODO: Consider a protected field with a tolerance value.
if (distance != Double.MAX_VALUE) { if (distance != Double.MAX_VALUE) {
distance = Math.sqrt(distance); distance = Math.sqrt(distance);
if (data.getDebug()) { if (pData.isDebugActive(type)) {
outputDebugFail(player, boulder, distance); outputDebugFail(player, boulder, distance);
} }

View File

@ -18,6 +18,8 @@ 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.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* The Drop check will find out if a player drops too many items within a short amount of time. * The Drop check will find out if a player drops too many items within a short amount of time.
@ -42,8 +44,9 @@ public class Drop extends Check {
// Take time once. // Take time once.
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
final InventoryConfig cc = InventoryConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryData data = InventoryData.getData(player); final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
final InventoryData data = pData.getGenericInstance(InventoryData.class);
boolean cancel = false; boolean cancel = false;

View File

@ -23,7 +23,7 @@ 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.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil; import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -92,7 +92,8 @@ public class FastClick extends Check {
public boolean check(final Player player, final long now, public boolean check(final Player player, final long now,
final InventoryView view, final int slot, final ItemStack cursor, final InventoryView view, final int slot, final ItemStack cursor,
final ItemStack clicked, final boolean isShiftClick, final ItemStack clicked, final boolean isShiftClick,
final InventoryData data, final InventoryConfig cc, final PlayerData pData) { final InventoryData data, final InventoryConfig cc,
final IPlayerData pData) {
// Take time once. // Take time once.
final float amount; final float amount;
@ -149,7 +150,7 @@ public class FastClick extends Check {
cancel = executeActions(vd).willCancel(); cancel = executeActions(vd).willCancel();
} }
if (data.debug && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){ if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)){
player.sendMessage("FastClick: " + data.fastClickFreq.bucketScore(0) + " | " + data.fastClickFreq.score(1f) + " | cursor=" + cursor + " | clicked=" + clicked); player.sendMessage("FastClick: " + data.fastClickFreq.bucketScore(0) + " | " + data.fastClickFreq.score(1f) + " | cursor=" + cursor + " | clicked=" + clicked);
} }

View File

@ -21,7 +21,7 @@ import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
/** /**
@ -49,9 +49,9 @@ public class InstantBow extends Check {
*/ */
public boolean check(final Player player, final float force, final long now) { public boolean check(final Player player, final float force, final long now) {
final PlayerData pData = DataManager.getPlayerData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryData data = InventoryData.getData(player); final InventoryData data = pData.getGenericInstance(InventoryData.class);
final InventoryConfig cc = InventoryConfig.getConfig(player); final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
boolean cancel = false; boolean cancel = false;
@ -81,7 +81,10 @@ public class InstantBow extends Check {
else { else {
// Account for server side lag. // Account for server side lag.
// (Do not apply correction to invalid pulling.) // (Do not apply correction to invalid pulling.)
final long correctedPullduration = valid ? (cc.lag ? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration) : pullDuration) : 0; final long correctedPullduration = valid ?
(pData.getCurrentWorldData().shouldAdjustToLag(type)
? (long) (TickTask.getLag(expectedPullDuration, true) * pullDuration)
: pullDuration) : 0;
if (correctedPullduration < expectedPullDuration) { if (correctedPullduration < expectedPullDuration) {
// TODO: Consider: Allow one time but set yawrate penalty time ? // TODO: Consider: Allow one time but set yawrate penalty time ?
final double difference = (expectedPullDuration - pullDuration) / 100D; final double difference = (expectedPullDuration - pullDuration) / 100D;
@ -95,7 +98,7 @@ public class InstantBow extends Check {
} }
} }
if (data.debug && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) { if (pData.isDebugActive(type) && pData.hasPermission(Permissions.ADMINISTRATION_DEBUG, player)) {
player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")"); player.sendMessage(ChatColor.YELLOW + "NCP: " + ChatColor.GRAY + "Bow shot - force: " + force +", " + (cc.instantBowStrict || pullDuration < 2 * expectedPullDuration ? ("pull time: " + pullDuration) : "") + "(" + expectedPullDuration +")");
} }

View File

@ -20,6 +20,8 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
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.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* The InstantEat check will find out if a player eats their food too fast. * The InstantEat check will find out if a player eats their food too fast.
@ -46,7 +48,8 @@ public class InstantEat extends Check {
// Take time once. // Take time once.
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
final InventoryData data = InventoryData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryData data = pData.getGenericInstance(InventoryData.class);
boolean cancel = false; boolean cancel = false;
@ -72,7 +75,8 @@ public class InstantEat extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should // Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event. // cancel the event.
final ViolationData vd = new ViolationData(this, player, data.instantEatVL, difference, InventoryConfig.getConfig(player).instantEatActions); final ViolationData vd = new ViolationData(this, player, data.instantEatVL,
difference, pData.getGenericInstance(InventoryConfig.class).instantEatActions);
if (data.instantEatFood != null) { if (data.instantEatFood != null) {
vd.setParameter(ParameterName.FOOD, data.instantEatFood.toString()); vd.setParameter(ParameterName.FOOD, data.instantEatFood.toString());
} }

View File

@ -14,24 +14,17 @@
*/ */
package fr.neatmonster.nocheatplus.checks.inventory; package fr.neatmonster.nocheatplus.checks.inventory;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.worlds.WorldData;
/** /**
* Configurations specific for the "inventory" checks. Every world gets one of * Configurations specific for the "inventory" checks. Every world gets one of
@ -40,87 +33,31 @@ import fr.neatmonster.nocheatplus.permissions.Permissions;
*/ */
public class InventoryConfig extends ACheckConfig { public class InventoryConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return InventoryConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
/** The map containing the configurations per world. */
private static final Map<String, InventoryConfig> worldsMap = new HashMap<String, InventoryConfig>();
/**
* Clear all the configurations.
*/
public static void clear() {
worldsMap.clear();
}
/**
* Gets the configuration for a specified player.
*
* @param player
* the player
* @return the configuration
*/
public static InventoryConfig getConfig(final Player player) {
return getConfig(player.getWorld());
}
public static InventoryConfig getConfig(final World world) {
return getWorldConfig(world.getName());
}
public static final InventoryConfig getWorldConfig(final String worldName) {
InventoryConfig cc = worldsMap.get(worldName);
if (cc == null) {
cc = new InventoryConfig(ConfigManager.getConfigFile(worldName));
worldsMap.put(worldName, cc);
}
return cc;
}
public final boolean dropCheck;
public final int dropLimit; public final int dropLimit;
public final long dropTimeFrame; public final long dropTimeFrame;
public final ActionList dropActions; public final ActionList dropActions;
public final boolean fastClickCheck;
public final boolean fastClickSpareCreative; public final boolean fastClickSpareCreative;
public final boolean fastClickTweaks1_5; public final boolean fastClickTweaks1_5;
public final float fastClickShortTermLimit; public final float fastClickShortTermLimit;
public final float fastClickNormalLimit; public final float fastClickNormalLimit;
public final ActionList fastClickActions; public final ActionList fastClickActions;
public final boolean fastConsumeCheck;
public final long fastConsumeDuration; public final long fastConsumeDuration;
public final boolean fastConsumeWhitelist; public final boolean fastConsumeWhitelist;
public final Set<Material> fastConsumeItems = new HashSet<Material>(); public final Set<Material> fastConsumeItems = new HashSet<Material>();
public final ActionList fastConsumeActions; public final ActionList fastConsumeActions;
public final boolean gutenbergCheck;
public final ActionList gutenbergActions; public final ActionList gutenbergActions;
public final boolean instantBowCheck;
public final boolean instantBowStrict; public final boolean instantBowStrict;
public final long instantBowDelay; public final long instantBowDelay;
public final boolean instantBowImprobableFeedOnly; public final boolean instantBowImprobableFeedOnly;
public final float instantBowImprobableWeight; public final float instantBowImprobableWeight;
public final ActionList instantBowActions; public final ActionList instantBowActions;
public final boolean instantEatCheck;
public final ActionList instantEatActions; public final ActionList instantEatActions;
public final boolean itemsCheck;
public final boolean openCheck;
public final boolean openClose; public final boolean openClose;
public final boolean openCancelOther; public final boolean openCancelOther;
@ -133,77 +70,38 @@ public class InventoryConfig extends ACheckConfig {
* @param data * @param data
* the data * the data
*/ */
public InventoryConfig(final ConfigFile data) { public InventoryConfig(final WorldData worldData) {
super(data, ConfPaths.INVENTORY); super(worldData);
dropCheck = data.getBoolean(ConfPaths.INVENTORY_DROP_CHECK); final ConfigFile data = worldData.getRawConfiguration();
dropLimit = data.getInt(ConfPaths.INVENTORY_DROP_LIMIT); dropLimit = data.getInt(ConfPaths.INVENTORY_DROP_LIMIT);
dropTimeFrame = data.getLong(ConfPaths.INVENTORY_DROP_TIMEFRAME); dropTimeFrame = data.getLong(ConfPaths.INVENTORY_DROP_TIMEFRAME);
dropActions = data.getOptimizedActionList(ConfPaths.INVENTORY_DROP_ACTIONS, Permissions.INVENTORY_DROP); dropActions = data.getOptimizedActionList(ConfPaths.INVENTORY_DROP_ACTIONS, Permissions.INVENTORY_DROP);
fastClickCheck = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_CHECK);
fastClickSpareCreative = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_SPARECREATIVE); fastClickSpareCreative = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_SPARECREATIVE);
fastClickTweaks1_5 = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_TWEAKS1_5); fastClickTweaks1_5 = data.getBoolean(ConfPaths.INVENTORY_FASTCLICK_TWEAKS1_5);
fastClickShortTermLimit = (float) data.getDouble(ConfPaths.INVENTORY_FASTCLICK_LIMIT_SHORTTERM); fastClickShortTermLimit = (float) data.getDouble(ConfPaths.INVENTORY_FASTCLICK_LIMIT_SHORTTERM);
fastClickNormalLimit = (float) data.getDouble(ConfPaths.INVENTORY_FASTCLICK_LIMIT_NORMAL); fastClickNormalLimit = (float) data.getDouble(ConfPaths.INVENTORY_FASTCLICK_LIMIT_NORMAL);
fastClickActions = data.getOptimizedActionList(ConfPaths.INVENTORY_FASTCLICK_ACTIONS, Permissions.INVENTORY_FASTCLICK); fastClickActions = data.getOptimizedActionList(ConfPaths.INVENTORY_FASTCLICK_ACTIONS, Permissions.INVENTORY_FASTCLICK);
fastConsumeCheck = data.getBoolean(ConfPaths.INVENTORY_FASTCONSUME_CHECK);
fastConsumeDuration = (long) (1000.0 * data.getDouble(ConfPaths.INVENTORY_FASTCONSUME_DURATION)); fastConsumeDuration = (long) (1000.0 * data.getDouble(ConfPaths.INVENTORY_FASTCONSUME_DURATION));
fastConsumeWhitelist = data.getBoolean(ConfPaths.INVENTORY_FASTCONSUME_WHITELIST); fastConsumeWhitelist = data.getBoolean(ConfPaths.INVENTORY_FASTCONSUME_WHITELIST);
data.readMaterialFromList(ConfPaths.INVENTORY_FASTCONSUME_ITEMS, fastConsumeItems); data.readMaterialFromList(ConfPaths.INVENTORY_FASTCONSUME_ITEMS, fastConsumeItems);
fastConsumeActions = data.getOptimizedActionList(ConfPaths.INVENTORY_FASTCONSUME_ACTIONS, Permissions.INVENTORY_FASTCONSUME); fastConsumeActions = data.getOptimizedActionList(ConfPaths.INVENTORY_FASTCONSUME_ACTIONS, Permissions.INVENTORY_FASTCONSUME);
gutenbergCheck = data.getBoolean(ConfPaths.INVENTORY_GUTENBERG_CHECK);
gutenbergActions = data.getOptimizedActionList(ConfPaths.INVENTORY_GUTENBERG_ACTIONS, Permissions.INVENTORY_GUTENBERG); gutenbergActions = data.getOptimizedActionList(ConfPaths.INVENTORY_GUTENBERG_ACTIONS, Permissions.INVENTORY_GUTENBERG);
instantBowCheck = data.getBoolean(ConfPaths.INVENTORY_INSTANTBOW_CHECK);
instantBowStrict = data.getBoolean(ConfPaths.INVENTORY_INSTANTBOW_STRICT); instantBowStrict = data.getBoolean(ConfPaths.INVENTORY_INSTANTBOW_STRICT);
instantBowDelay = data.getInt(ConfPaths.INVENTORY_INSTANTBOW_DELAY); instantBowDelay = data.getInt(ConfPaths.INVENTORY_INSTANTBOW_DELAY);
instantBowImprobableFeedOnly = data.getBoolean(ConfPaths.INVENTORY_INSTANTBOW_IMPROBABLE_FEEDONLY); instantBowImprobableFeedOnly = data.getBoolean(ConfPaths.INVENTORY_INSTANTBOW_IMPROBABLE_FEEDONLY);
instantBowImprobableWeight = (float) data.getDouble(ConfPaths.INVENTORY_INSTANTBOW_IMPROBABLE_WEIGHT); instantBowImprobableWeight = (float) data.getDouble(ConfPaths.INVENTORY_INSTANTBOW_IMPROBABLE_WEIGHT);
instantBowActions = data.getOptimizedActionList(ConfPaths.INVENTORY_INSTANTBOW_ACTIONS, Permissions.INVENTORY_INSTANTBOW); instantBowActions = data.getOptimizedActionList(ConfPaths.INVENTORY_INSTANTBOW_ACTIONS, Permissions.INVENTORY_INSTANTBOW);
instantEatCheck = data.getBoolean(ConfPaths.INVENTORY_INSTANTEAT_CHECK);
instantEatActions = data.getOptimizedActionList(ConfPaths.INVENTORY_INSTANTEAT_ACTIONS, Permissions.INVENTORY_INSTANTEAT); instantEatActions = data.getOptimizedActionList(ConfPaths.INVENTORY_INSTANTEAT_ACTIONS, Permissions.INVENTORY_INSTANTEAT);
itemsCheck = data.getBoolean(ConfPaths.INVENTORY_ITEMS_CHECK);
openCheck = data.getBoolean(ConfPaths.INVENTORY_OPEN_CHECK);
openClose = data.getBoolean(ConfPaths.INVENTORY_OPEN_CLOSE); openClose = data.getBoolean(ConfPaths.INVENTORY_OPEN_CLOSE);
openCancelOther = data.getBoolean(ConfPaths.INVENTORY_OPEN_CANCELOTHER); openCancelOther = data.getBoolean(ConfPaths.INVENTORY_OPEN_CANCELOTHER);
hotFixFallingBlockEndPortalActive = data.getBoolean(ConfPaths.INVENTORY_HOTFIX_DUPE_FALLINGBLOCKENDPORTAL); hotFixFallingBlockEndPortalActive = data.getBoolean(ConfPaths.INVENTORY_HOTFIX_DUPE_FALLINGBLOCKENDPORTAL);
} }
/*
* (non-Javadoc)
*
* @see
* fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster
* .nocheatplus.checks.CheckType)
*/
@Override
public final boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case INVENTORY_FASTCLICK:
return fastClickCheck;
case INVENTORY_ITEMS:
return itemsCheck;
case INVENTORY_OPEN:
return openCheck;
case INVENTORY_DROP:
return dropCheck;
case INVENTORY_INSTANTBOW:
return instantBowCheck;
case INVENTORY_INSTANTEAT:
return instantEatCheck;
case INVENTORY_FASTCONSUME:
return fastConsumeCheck;
case INVENTORY_GUTENBERG:
return gutenbergCheck;
default:
return true;
}
}
} }

View File

@ -14,16 +14,9 @@
*/ */
package fr.neatmonster.nocheatplus.checks.inventory; package fr.neatmonster.nocheatplus.checks.inventory;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Material; import org.bukkit.Material;
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.ICheckData;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
/** /**
@ -31,53 +24,6 @@ import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
*/ */
public class InventoryData extends ACheckData { public class InventoryData extends ACheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
@Override
public final ICheckData getData(final Player player) {
return InventoryData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return InventoryData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return InventoryData.removeData(playerName);
}
@Override
public void removeAllData() {
clear();
}
};
/** The map containing the data per players. */
private static final Map<String, InventoryData> playersMap = new HashMap<String, InventoryData>();
/**
* Gets the data of a specified player.
*
* @param player
* the player
* @return the data
*/
public static InventoryData getData(final Player player) {
if (!playersMap.containsKey(player.getName()))
playersMap.put(player.getName(), new InventoryData(InventoryConfig.getConfig(player)));
return playersMap.get(player.getName());
}
public static ICheckData removeData(final String playerName) {
return playersMap.remove(playerName);
}
public static void clear(){
playersMap.clear();
}
// Violation levels. // Violation levels.
public double dropVL; public double dropVL;
public double fastClickVL; public double fastClickVL;
@ -107,8 +53,4 @@ public class InventoryData extends ACheckData {
public Material instantEatFood; public Material instantEatFood;
public long instantEatInteract; public long instantEatInteract;
public InventoryData(final InventoryConfig config) {
super(config);
}
} }

View File

@ -56,7 +56,7 @@ import fr.neatmonster.nocheatplus.components.entity.IEntityAccessVehicle;
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle; import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
import fr.neatmonster.nocheatplus.components.registry.feature.JoinLeaveListener; import fr.neatmonster.nocheatplus.components.registry.feature.JoinLeaveListener;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.stats.Counters; import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil; import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
@ -110,14 +110,16 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
// Only if a player shot the arrow. // Only if a player shot the arrow.
if (event.getEntity() instanceof Player) { if (event.getEntity() instanceof Player) {
final Player player = (Player) event.getEntity(); final Player player = (Player) event.getEntity();
if (instantBow.isEnabled(player)) { final IPlayerData pData = DataManager.getPlayerData(player);
if (instantBow.isEnabled(player, pData)) {
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
if (Combined.checkYawRate(player, loc.getYaw(), now, loc.getWorld().getName())) { if (Combined.checkYawRate(player, loc.getYaw(), now,
loc.getWorld().getName(), pData)) {
// No else if with this, could be cancelled due to other checks feeding, does not have actions. // No else if with this, could be cancelled due to other checks feeding, does not have actions.
event.setCancelled(true); event.setCancelled(true);
} }
final InventoryConfig cc = InventoryConfig.getConfig(player); final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
// Still check instantBow, whatever yawrate says. // Still check instantBow, whatever yawrate says.
if (instantBow.check(player, event.getForce(), now)) { if (instantBow.check(player, event.getForce(), now)) {
// The check requested the event to be cancelled. // The check requested the event to be cancelled.
@ -127,7 +129,8 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
if (cc.instantBowImprobableFeedOnly) { if (cc.instantBowImprobableFeedOnly) {
Improbable.feed(player, cc.instantBowImprobableWeight, now); Improbable.feed(player, cc.instantBowImprobableWeight, now);
} }
else if (Improbable.check(player, cc.instantBowImprobableWeight, now, "inventory.instantbow")) { else if (Improbable.check(player, cc.instantBowImprobableWeight,
now, "inventory.instantbow", pData)) {
// Combined fighting speed (Else if: Matter of taste, preventing extreme cascading and actions spam). // Combined fighting speed (Else if: Matter of taste, preventing extreme cascading and actions spam).
event.setCancelled(true); event.setCancelled(true);
} }
@ -150,7 +153,9 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
// Only if a player ate food. // Only if a player ate food.
if (event.getEntity() instanceof Player) { if (event.getEntity() instanceof Player) {
final Player player = (Player) event.getEntity(); final Player player = (Player) event.getEntity();
if (instantEat.isEnabled(player) && instantEat.check(player, event.getFoodLevel())) { final IPlayerData pData = DataManager.getPlayerData(player);
if (instantEat.isEnabled(player, pData)
&& instantEat.check(player, event.getFoodLevel())) {
event.setCancelled(true); event.setCancelled(true);
} }
else if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) { else if (player.isDead() && BridgeHealth.getHealth(player) <= 0.0) {
@ -179,9 +184,10 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
return; return;
} }
final Player player = (Player) entity; final Player player = (Player) entity;
final InventoryData data = InventoryData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryData data = pData.getGenericInstance(InventoryData.class);
final int slot = event.getSlot(); final int slot = event.getSlot();
if (data.debug) { if (pData.isDebugActive(checkType)) {
outputDebugInventoryClick(player, slot, event, data); outputDebugInventoryClick(player, slot, event, data);
} }
if (slot == InventoryView.OUTSIDE || slot < 0) { if (slot == InventoryView.OUTSIDE || slot < 0) {
@ -194,14 +200,14 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
boolean cancel = false; boolean cancel = false;
// Illegal enchantment checks. // Illegal enchantment checks.
try{ try{
if (!cancel && Items.checkIllegalEnchantments(player, clicked)) { if (!cancel && Items.checkIllegalEnchantments(player, clicked, pData)) {
cancel = true; cancel = true;
counters.addPrimaryThread(idIllegalItem, 1); counters.addPrimaryThread(idIllegalItem, 1);
} }
} }
catch(final ArrayIndexOutOfBoundsException e) {} // Hotfix (CB) catch(final ArrayIndexOutOfBoundsException e) {} // Hotfix (CB)
try{ try{
if (!cancel && Items.checkIllegalEnchantments(player, cursor)) { if (!cancel && Items.checkIllegalEnchantments(player, cursor, pData)) {
cancel = true; cancel = true;
counters.addPrimaryThread(idIllegalItem, 1); counters.addPrimaryThread(idIllegalItem, 1);
} }
@ -209,10 +215,9 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
catch(final ArrayIndexOutOfBoundsException e) {} // Hotfix (CB) catch(final ArrayIndexOutOfBoundsException e) {} // Hotfix (CB)
// Fast inventory manipulation check. // Fast inventory manipulation check.
if (fastClick.isEnabled(player)) { if (fastClick.isEnabled(player, pData)) {
final InventoryConfig cc = InventoryConfig.getConfig(player); final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
if (player.getGameMode() != GameMode.CREATIVE || !cc.fastClickSpareCreative) { if (player.getGameMode() != GameMode.CREATIVE || !cc.fastClickSpareCreative) {
final PlayerData pData = DataManager.getPlayerData(player);
if (fastClick.check(player, now, if (fastClick.check(player, now,
event.getView(), slot, cursor, clicked, event.isShiftClick(), event.getView(), slot, cursor, clicked, event.isShiftClick(),
data, cc, pData)) { data, cc, pData)) {
@ -301,20 +306,21 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
public void onPlayerDropItem(final PlayerDropItemEvent event) { public void onPlayerDropItem(final PlayerDropItemEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final IPlayerData pData = DataManager.getPlayerData(player);
// Illegal enchantments hotfix check. // Illegal enchantments hotfix check.
final Item item = event.getItemDrop(); final Item item = event.getItemDrop();
if (item != null) { if (item != null) {
// No cancel here. // No cancel here.
Items.checkIllegalEnchantments(player, item.getItemStack()); Items.checkIllegalEnchantments(player, item.getItemStack(), pData);
} }
// If the player died, all their items are dropped so ignore them. // If the player died, all their items are dropped so ignore them.
if (event.getPlayer().isDead()) if (event.getPlayer().isDead())
return; return;
if (drop.isEnabled(event.getPlayer())) { if (pData.isCheckActive(CheckType.INVENTORY_DROP, player)) {
if (drop.check(event.getPlayer())) { if (drop.check(player)) {
// TODO: Is the following command still correct? If so, adapt actions. // TODO: Is the following command still correct? If so, adapt actions.
/* /*
* Cancelling drop events is not save (in certain circumstances * Cancelling drop events is not save (in certain circumstances
@ -341,7 +347,8 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
return; return;
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final InventoryData data = InventoryData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryData data = pData.getGenericInstance(InventoryData.class);
boolean resetAll = false; boolean resetAll = false;
@ -366,7 +373,7 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
} else resetAll = true; } else resetAll = true;
// Illegal enchantments hotfix check. // Illegal enchantments hotfix check.
if (Items.checkIllegalEnchantments(player, item)) { if (Items.checkIllegalEnchantments(player, item, pData)) {
event.setCancelled(true); event.setCancelled(true);
counters.addPrimaryThread(idIllegalItem, 1); counters.addPrimaryThread(idIllegalItem, 1);
} }
@ -377,7 +384,8 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
if (resetAll) { if (resetAll) {
// Nothing that we are interested in, reset data. // Nothing that we are interested in, reset data.
if (data.debug && data.instantEatFood != null) { if (pData.isDebugActive(CheckType.INVENTORY_INSTANTEAT)
&& data.instantEatFood != null) {
debug(player, "PlayerInteractEvent, reset fastconsume (legacy: instanteat)."); debug(player, "PlayerInteractEvent, reset fastconsume (legacy: instanteat).");
} }
data.instantBowInteract = 0; data.instantBowInteract = 0;
@ -407,7 +415,7 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
Entity entity = event.getRightClicked(); Entity entity = event.getRightClicked();
if (stack != null && stack.getType() == Material.MONSTER_EGG if (stack != null && stack.getType() == Material.MONSTER_EGG
&& (entity == null || entity instanceof LivingEntity || entity instanceof ComplexEntityPart) && (entity == null || entity instanceof LivingEntity || entity instanceof ComplexEntityPart)
&& items.isEnabled(player)) { && items.isEnabled(player, DataManager.getPlayerData(player))) {
event.setCancelled(true); event.setCancelled(true);
counters.addPrimaryThread(idEggOnEntity, 1); counters.addPrimaryThread(idEggOnEntity, 1);
return; return;
@ -428,8 +436,9 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onItemHeldChange(final PlayerItemHeldEvent event) { public void onItemHeldChange(final PlayerItemHeldEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final InventoryData data = InventoryData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
if (data.debug && data.instantEatFood != null) { final InventoryData data = pData.getGenericInstance(InventoryData.class);
if (pData.isDebugActive(checkType) && data.instantEatFood != null) {
debug(player, "PlayerItemHeldEvent, reset fastconsume (legacy: instanteat)."); debug(player, "PlayerItemHeldEvent, reset fastconsume (legacy: instanteat).");
} }
data.instantBowInteract = 0; data.instantBowInteract = 0;
@ -438,8 +447,8 @@ public class InventoryListener extends CheckListener implements JoinLeaveListen
// Illegal enchantments hotfix check. // Illegal enchantments hotfix check.
final PlayerInventory inv = player.getInventory(); final PlayerInventory inv = player.getInventory();
Items.checkIllegalEnchantments(player, inv.getItem(event.getNewSlot())); Items.checkIllegalEnchantments(player, inv.getItem(event.getNewSlot()), pData);
Items.checkIllegalEnchantments(player, inv.getItem(event.getPreviousSlot())); Items.checkIllegalEnchantments(player, inv.getItem(event.getPreviousSlot()), pData);
} }
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)

View File

@ -25,6 +25,7 @@ import org.bukkit.inventory.ItemStack;
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.compat.Bridge1_9; import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.players.IPlayerData;
public class Items extends Check{ public class Items extends Check{
@ -42,12 +43,14 @@ public class Items extends Check{
* @param player * @param player
* @return True if the check is failed. * @return True if the check is failed.
*/ */
public static final boolean checkIllegalEnchantmentsAllHands(final Player player) { public static final boolean checkIllegalEnchantmentsAllHands(final Player player,
final IPlayerData pData) {
boolean result = false; boolean result = false;
if (checkIllegalEnchantments(player, Bridge1_9.getItemInMainHand(player))) { if (checkIllegalEnchantments(player, Bridge1_9.getItemInMainHand(player), pData)) {
result = true; result = true;
} }
if (Bridge1_9.hasGetItemInOffHand() && checkIllegalEnchantments(player, Bridge1_9.getItemInOffHand(player))) { if (Bridge1_9.hasGetItemInOffHand()
&& checkIllegalEnchantments(player, Bridge1_9.getItemInOffHand(player), pData)) {
result = true; result = true;
} }
return result; return result;
@ -61,7 +64,8 @@ public class Items extends Check{
* @param stack * @param stack
* @return True if the check is failed. * @return True if the check is failed.
*/ */
public static final boolean checkIllegalEnchantments(final Player player, final ItemStack stack){ public static final boolean checkIllegalEnchantments(final Player player,
final ItemStack stack, final IPlayerData pData){
if (stack == null) { if (stack == null) {
return false; return false;
} }
@ -70,7 +74,7 @@ public class Items extends Check{
// TODO: Make stuff configurable. // TODO: Make stuff configurable.
if (type == Material.WRITTEN_BOOK){ if (type == Material.WRITTEN_BOOK){
final Map<Enchantment, Integer> enchantments = stack.getEnchantments(); final Map<Enchantment, Integer> enchantments = stack.getEnchantments();
if (enchantments != null && !enchantments.isEmpty() && instance.isEnabled(player)){ if (enchantments != null && !enchantments.isEmpty() && pData.isCheckActive(instance.type, player)){
// TODO: differentiate sub checks maybe or add extra permissions, later. // TODO: differentiate sub checks maybe or add extra permissions, later.
for (final Enchantment ench : new HashSet<Enchantment>(enchantments.keySet())){ for (final Enchantment ench : new HashSet<Enchantment>(enchantments.keySet())){
stack.removeEnchantment(ench); stack.removeEnchantment(ench);

View File

@ -24,6 +24,8 @@ import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.components.registry.event.IHandle; import fr.neatmonster.nocheatplus.components.registry.event.IHandle;
import fr.neatmonster.nocheatplus.components.registry.feature.IDisableListener; import fr.neatmonster.nocheatplus.components.registry.feature.IDisableListener;
import fr.neatmonster.nocheatplus.hooks.ExemptionSettings; import fr.neatmonster.nocheatplus.hooks.ExemptionSettings;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil; import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
/** /**
@ -74,7 +76,8 @@ public class Open extends Check implements IDisableListener{
|| !InventoryUtil.hasInventoryOpen(player)) { || !InventoryUtil.hasInventoryOpen(player)) {
return false; return false;
} }
final InventoryConfig cc = InventoryConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final InventoryConfig cc = pData.getGenericInstance(InventoryConfig.class);
if (cc.openClose) { if (cc.openClose) {
final UUID id = player.getUniqueId(); final UUID id = player.getUniqueId();
if (this.nestedPlayer == null || !id.equals(this.nestedPlayer)) { if (this.nestedPlayer == null || !id.equals(this.nestedPlayer)) {

View File

@ -29,8 +29,6 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckConfig;
import fr.neatmonster.nocheatplus.checks.moving.magic.Magic; import fr.neatmonster.nocheatplus.checks.moving.magic.Magic;
import fr.neatmonster.nocheatplus.checks.moving.model.ModelFlying; import fr.neatmonster.nocheatplus.checks.moving.model.ModelFlying;
import fr.neatmonster.nocheatplus.checks.moving.player.PlayerSetBackMethod; import fr.neatmonster.nocheatplus.checks.moving.player.PlayerSetBackMethod;
@ -40,13 +38,14 @@ import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.Bridge1_9; import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.versions.Bugs; import fr.neatmonster.nocheatplus.compat.versions.Bugs;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion; import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.config.value.OverrideType;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.utilities.ColorUtil; import fr.neatmonster.nocheatplus.utilities.ColorUtil;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree; import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree;
import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configurations specific for the moving checks. Every world gets one of these * Configurations specific for the moving checks. Every world gets one of these
@ -54,59 +53,6 @@ import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation;
*/ */
public class MovingConfig extends ACheckConfig { public class MovingConfig extends ACheckConfig {
/** The factory creating configurations. */
public static final CheckConfigFactory factory = new CheckConfigFactory() {
@Override
public final ICheckConfig getConfig(final Player player) {
return MovingConfig.getConfig(player);
}
@Override
public void removeAllConfigs() {
clear(); // Band-aid.
}
};
/** The map containing the configurations per world. */
private static final Map<String, MovingConfig> worldsMap = new HashMap<String, MovingConfig>();
/**
* Clear all the configurations.
*/
public static void clear() {
worldsMap.clear();
}
/**
* Gets the configuration for a specified player . <br>
* NOTE: Currently only per-world configs are implemented. This method might
* or might not get removed some day.
*
* @param player
* the player
* @return the configuration
*/
public static MovingConfig getConfig(final Player player) {
return getConfig(player.getWorld().getName());
}
/**
* Get a per-world config.
*
* @param worldName
* Exact case world name.
* @return
*/
public static MovingConfig getConfig(final String worldName) {
final MovingConfig cc = worldsMap.get(worldName);
if (cc != null){
return cc;
}
final MovingConfig ccNew = new MovingConfig(ConfigManager.getConfigFile(worldName));
worldsMap.put(worldName, ccNew);
return ccNew;
}
// Model flying ids. // Model flying ids.
public static final String ID_JETPACK_ELYTRA = "jetpack.elytra"; public static final String ID_JETPACK_ELYTRA = "jetpack.elytra";
public static final String ID_POTION_LEVITATION = "potion.levitation"; public static final String ID_POTION_LEVITATION = "potion.levitation";
@ -116,13 +62,11 @@ public class MovingConfig extends ACheckConfig {
public final boolean ignoreCreative; public final boolean ignoreCreative;
public final boolean ignoreAllowFlight; public final boolean ignoreAllowFlight;
public final boolean creativeFlyCheck;
private final Map<GameMode, ModelFlying> flyingModelGameMode = new HashMap<GameMode, ModelFlying>(); private final Map<GameMode, ModelFlying> flyingModelGameMode = new HashMap<GameMode, ModelFlying>();
private final ModelFlying flyingModelElytra; private final ModelFlying flyingModelElytra;
private final ModelFlying flyingModelLevitation; private final ModelFlying flyingModelLevitation;
public final ActionList creativeFlyActions; public final ActionList creativeFlyActions;
public final boolean morePacketsCheck;
/** Assumed number of packets per second under ideal conditions. */ /** Assumed number of packets per second under ideal conditions. */
public final float morePacketsEPSIdeal; public final float morePacketsEPSIdeal;
/** The maximum number of packets per second that we accept. */ /** The maximum number of packets per second that we accept. */
@ -134,7 +78,6 @@ public class MovingConfig extends ACheckConfig {
public final int morePacketsSetBackAge; public final int morePacketsSetBackAge;
public final ActionList morePacketsActions; public final ActionList morePacketsActions;
public final boolean noFallCheck;
/** /**
* Deal damage instead of Minecraft, whenever a player is judged to be on * Deal damage instead of Minecraft, whenever a player is judged to be on
* ground. * ground.
@ -154,7 +97,6 @@ public class MovingConfig extends ACheckConfig {
public final boolean noFallAntiCriticals; public final boolean noFallAntiCriticals;
public final ActionList noFallActions; public final ActionList noFallActions;
public final boolean passableCheck;
// TODO: passableAccuracy: also use if not using ray-tracing // TODO: passableAccuracy: also use if not using ray-tracing
public final ActionList passableActions; public final ActionList passableActions;
public final boolean passableUntrackedTeleportCheck; public final boolean passableUntrackedTeleportCheck;
@ -162,7 +104,6 @@ public class MovingConfig extends ACheckConfig {
public final boolean passableUntrackedCommandTryTeleport; public final boolean passableUntrackedCommandTryTeleport;
public final SimpleCharPrefixTree passableUntrackedCommandPrefixes = new SimpleCharPrefixTree(); public final SimpleCharPrefixTree passableUntrackedCommandPrefixes = new SimpleCharPrefixTree();
public final boolean survivalFlyCheck;
public final int survivalFlyBlockingSpeed; public final int survivalFlyBlockingSpeed;
public final int survivalFlySneakingSpeed; public final int survivalFlySneakingSpeed;
public final int survivalFlySpeedingSpeed; public final int survivalFlySpeedingSpeed;
@ -184,7 +125,7 @@ public class MovingConfig extends ACheckConfig {
public final long survivalFlyVLFreeze; public final long survivalFlyVLFreeze;
public final ActionList survivalFlyActions; public final ActionList survivalFlyActions;
public final boolean sfHoverCheck; public final boolean sfHoverCheck; // TODO: Sub check ?
public final int sfHoverTicks; public final int sfHoverTicks;
public final int sfHoverLoginTicks; public final int sfHoverLoginTicks;
public final boolean sfHoverFallDamage; public final boolean sfHoverFallDamage;
@ -230,10 +171,8 @@ public class MovingConfig extends ACheckConfig {
public final Set<EntityType> ignoredVehicles = new HashSet<EntityType>(); public final Set<EntityType> ignoredVehicles = new HashSet<EntityType>();
public final boolean vehicleMorePacketsCheck;
public final ActionList vehicleMorePacketsActions; public final ActionList vehicleMorePacketsActions;
public final boolean vehicleEnvelopeActive;
public final HashMap<EntityType, Double> vehicleEnvelopeHorizontalSpeedCap = new HashMap<EntityType, Double>(); public final HashMap<EntityType, Double> vehicleEnvelopeHorizontalSpeedCap = new HashMap<EntityType, Double>();
public final ActionList vehicleEnvelopeActions; public final ActionList vehicleEnvelopeActions;
@ -251,13 +190,13 @@ public class MovingConfig extends ACheckConfig {
* @param config * @param config
* the data * the data
*/ */
public MovingConfig(final ConfigFile config) { public MovingConfig(final IWorldData worldData) {
super(config, ConfPaths.MOVING); super(worldData);
final ConfigFile config = worldData.getRawConfiguration();
ignoreCreative = config.getBoolean(ConfPaths.MOVING_CREATIVEFLY_IGNORECREATIVE); ignoreCreative = config.getBoolean(ConfPaths.MOVING_CREATIVEFLY_IGNORECREATIVE);
ignoreAllowFlight = config.getBoolean(ConfPaths.MOVING_CREATIVEFLY_IGNOREALLOWFLIGHT); ignoreAllowFlight = config.getBoolean(ConfPaths.MOVING_CREATIVEFLY_IGNOREALLOWFLIGHT);
creativeFlyCheck = config.getBoolean(ConfPaths.MOVING_CREATIVEFLY_CHECK);
final ModelFlying defaultModel = new ModelFlying("gamemode.creative", config, final ModelFlying defaultModel = new ModelFlying("gamemode.creative", config,
ConfPaths.MOVING_CREATIVEFLY_MODEL + "creative.", new ModelFlying().lock()); ConfPaths.MOVING_CREATIVEFLY_MODEL + "creative.", new ModelFlying().lock());
for (final GameMode gameMode : GameMode.values()) { for (final GameMode gameMode : GameMode.values()) {
@ -273,7 +212,6 @@ public class MovingConfig extends ACheckConfig {
creativeFlyActions = config.getOptimizedActionList(ConfPaths.MOVING_CREATIVEFLY_ACTIONS, creativeFlyActions = config.getOptimizedActionList(ConfPaths.MOVING_CREATIVEFLY_ACTIONS,
Permissions.MOVING_CREATIVEFLY); Permissions.MOVING_CREATIVEFLY);
morePacketsCheck = config.getBoolean(ConfPaths.MOVING_MOREPACKETS_CHECK);
morePacketsEPSIdeal = config.getInt(ConfPaths.MOVING_MOREPACKETS_EPSIDEAL); morePacketsEPSIdeal = config.getInt(ConfPaths.MOVING_MOREPACKETS_EPSIDEAL);
morePacketsEPSMax = Math.max(morePacketsEPSIdeal, config.getInt(ConfPaths.MOVING_MOREPACKETS_EPSMAX)); morePacketsEPSMax = Math.max(morePacketsEPSIdeal, config.getInt(ConfPaths.MOVING_MOREPACKETS_EPSMAX));
morePacketsEPSBuckets = 2 * Math.max(1, Math.min(60, config.getInt(ConfPaths.MOVING_MOREPACKETS_SECONDS))); morePacketsEPSBuckets = 2 * Math.max(1, Math.min(60, config.getInt(ConfPaths.MOVING_MOREPACKETS_SECONDS)));
@ -283,7 +221,6 @@ public class MovingConfig extends ACheckConfig {
morePacketsSetBackAge = config.getInt(ConfPaths.MOVING_MOREPACKETS_SETBACKAGE); morePacketsSetBackAge = config.getInt(ConfPaths.MOVING_MOREPACKETS_SETBACKAGE);
morePacketsActions = config.getOptimizedActionList(ConfPaths.MOVING_MOREPACKETS_ACTIONS, Permissions.MOVING_MOREPACKETS); morePacketsActions = config.getOptimizedActionList(ConfPaths.MOVING_MOREPACKETS_ACTIONS, Permissions.MOVING_MOREPACKETS);
noFallCheck = config.getBoolean(ConfPaths.MOVING_NOFALL_CHECK);
noFallDealDamage = config.getBoolean(ConfPaths.MOVING_NOFALL_DEALDAMAGE); noFallDealDamage = config.getBoolean(ConfPaths.MOVING_NOFALL_DEALDAMAGE);
noFallSkipAllowFlight = config.getBoolean(ConfPaths.MOVING_NOFALL_SKIPALLOWFLIGHT); noFallSkipAllowFlight = config.getBoolean(ConfPaths.MOVING_NOFALL_SKIPALLOWFLIGHT);
noFallViolationReset = config.getBoolean(ConfPaths.MOVING_NOFALL_RESETONVL); noFallViolationReset = config.getBoolean(ConfPaths.MOVING_NOFALL_RESETONVL);
@ -292,14 +229,12 @@ public class MovingConfig extends ACheckConfig {
noFallAntiCriticals = config.getBoolean(ConfPaths.MOVING_NOFALL_ANTICRITICALS); noFallAntiCriticals = config.getBoolean(ConfPaths.MOVING_NOFALL_ANTICRITICALS);
noFallActions = config.getOptimizedActionList(ConfPaths.MOVING_NOFALL_ACTIONS, Permissions.MOVING_NOFALL); noFallActions = config.getOptimizedActionList(ConfPaths.MOVING_NOFALL_ACTIONS, Permissions.MOVING_NOFALL);
passableCheck = config.getBoolean(ConfPaths.MOVING_PASSABLE_CHECK);
passableActions = config.getOptimizedActionList(ConfPaths.MOVING_PASSABLE_ACTIONS, Permissions.MOVING_PASSABLE); passableActions = config.getOptimizedActionList(ConfPaths.MOVING_PASSABLE_ACTIONS, Permissions.MOVING_PASSABLE);
passableUntrackedTeleportCheck = config.getBoolean(ConfPaths.MOVING_PASSABLE_UNTRACKED_TELEPORT_ACTIVE); passableUntrackedTeleportCheck = config.getBoolean(ConfPaths.MOVING_PASSABLE_UNTRACKED_TELEPORT_ACTIVE);
passableUntrackedCommandCheck = config.getBoolean(ConfPaths.MOVING_PASSABLE_UNTRACKED_CMD_ACTIVE); passableUntrackedCommandCheck = config.getBoolean(ConfPaths.MOVING_PASSABLE_UNTRACKED_CMD_ACTIVE);
passableUntrackedCommandTryTeleport = config.getBoolean(ConfPaths.MOVING_PASSABLE_UNTRACKED_CMD_TRYTELEPORT); passableUntrackedCommandTryTeleport = config.getBoolean(ConfPaths.MOVING_PASSABLE_UNTRACKED_CMD_TRYTELEPORT);
CommandUtil.feedCommands(passableUntrackedCommandPrefixes, config, ConfPaths.MOVING_PASSABLE_UNTRACKED_CMD_PREFIXES, true); CommandUtil.feedCommands(passableUntrackedCommandPrefixes, config, ConfPaths.MOVING_PASSABLE_UNTRACKED_CMD_PREFIXES, true);
survivalFlyCheck = config.getBoolean(ConfPaths.MOVING_SURVIVALFLY_CHECK);
// Default values are specified here because this settings aren't showed by default into the configuration file. // Default values are specified here because this settings aren't showed by default into the configuration file.
survivalFlyBlockingSpeed = config.getInt(ConfPaths.MOVING_SURVIVALFLY_BLOCKINGSPEED, 100); survivalFlyBlockingSpeed = config.getInt(ConfPaths.MOVING_SURVIVALFLY_BLOCKINGSPEED, 100);
survivalFlySneakingSpeed = config.getInt(ConfPaths.MOVING_SURVIVALFLY_SNEAKINGSPEED, 100); survivalFlySneakingSpeed = config.getInt(ConfPaths.MOVING_SURVIVALFLY_SNEAKINGSPEED, 100);
@ -389,10 +324,12 @@ public class MovingConfig extends ACheckConfig {
vehicleEnforceLocation = ref.decideOptimistically(); // Currently rather enabled. vehicleEnforceLocation = ref.decideOptimistically(); // Currently rather enabled.
vehiclePreventDestroyOwn = config.getBoolean(ConfPaths.MOVING_VEHICLE_PREVENTDESTROYOWN); vehiclePreventDestroyOwn = config.getBoolean(ConfPaths.MOVING_VEHICLE_PREVENTDESTROYOWN);
scheduleVehicleSetBacks = config.getAlmostBoolean(ConfPaths.MOVING_VEHICLE_SCHEDULESETBACKS, AlmostBoolean.MAYBE).decide(); scheduleVehicleSetBacks = config.getAlmostBoolean(ConfPaths.MOVING_VEHICLE_SCHEDULESETBACKS, AlmostBoolean.MAYBE).decide();
vehicleMorePacketsCheck = config.getBoolean(ConfPaths.MOVING_VEHICLE_MOREPACKETS_CHECK);
vehicleMorePacketsActions = config.getOptimizedActionList(ConfPaths.MOVING_VEHICLE_MOREPACKETS_ACTIONS, Permissions.MOVING_MOREPACKETS); vehicleMorePacketsActions = config.getOptimizedActionList(ConfPaths.MOVING_VEHICLE_MOREPACKETS_ACTIONS, Permissions.MOVING_MOREPACKETS);
ref = config.getAlmostBoolean(ConfPaths.MOVING_VEHICLE_ENVELOPE_ACTIVE, AlmostBoolean.MAYBE); ref = config.getAlmostBoolean(ConfPaths.MOVING_VEHICLE_ENVELOPE_ACTIVE, AlmostBoolean.MAYBE);
vehicleEnvelopeActive = ref == AlmostBoolean.MAYBE ? ServerVersion.compareMinecraftVersion("1.9") >= 0 : ref.decide(); if (ServerVersion.compareMinecraftVersion("1.9") < 0) {
worldData.overrideCheckActivation(CheckType.MOVING_VEHICLE_ENVELOPE,
AlmostBoolean.NO, OverrideType.PERMANENT, true);
}
config.readDoubleValuesForEntityTypes(ConfPaths.MOVING_VEHICLE_ENVELOPE_HSPEEDCAP, vehicleEnvelopeHorizontalSpeedCap, 4.0, true); config.readDoubleValuesForEntityTypes(ConfPaths.MOVING_VEHICLE_ENVELOPE_HSPEEDCAP, vehicleEnvelopeHorizontalSpeedCap, 4.0, true);
vehicleEnvelopeActions = config.getOptimizedActionList(ConfPaths.MOVING_VEHICLE_ENVELOPE_ACTIONS, Permissions.MOVING_VEHICLE_ENVELOPE); vehicleEnvelopeActions = config.getOptimizedActionList(ConfPaths.MOVING_VEHICLE_ENVELOPE_ACTIONS, Permissions.MOVING_VEHICLE_ENVELOPE);
// Ignored vehicle types (ignore mostly, no checks run). // Ignored vehicle types (ignore mostly, no checks run).
@ -420,44 +357,6 @@ public class MovingConfig extends ACheckConfig {
msgKickIllegalVehicleMove = ColorUtil.replaceColors(config.getString(ConfPaths.MOVING_MESSAGE_ILLEGALVEHICLEMOVE)); msgKickIllegalVehicleMove = ColorUtil.replaceColors(config.getString(ConfPaths.MOVING_MESSAGE_ILLEGALVEHICLEMOVE));
} }
/* (non-Javadoc)
* @see fr.neatmonster.nocheatplus.checks.ICheckConfig#isEnabled(fr.neatmonster.nocheatplus.checks.CheckType)
*/
@Override
public final boolean isEnabled(final CheckType checkType) {
switch (checkType) {
case MOVING_NOFALL:
return noFallCheck;
case MOVING_SURVIVALFLY:
return survivalFlyCheck;
case MOVING_PASSABLE:
return passableCheck;
case MOVING_MOREPACKETS:
return morePacketsCheck;
case MOVING_VEHICLE_MOREPACKETS:
return vehicleMorePacketsCheck;
case MOVING_VEHICLE_ENVELOPE:
return vehicleEnvelopeActive;
case MOVING_CREATIVEFLY:
return creativeFlyCheck;
default:
return true;
}
}
/**
* Fetches data and config for sub checks (potentially redundant fetching).
*
* @param player
* @param fromLocation
* @return
* @deprecated Having a from location but no config/data ...
*/
@Deprecated
public ModelFlying getModelFlying(final Player player, final PlayerLocation fromLocation) {
return getModelFlying(player, fromLocation, MovingData.getData(player), MovingConfig.getConfig(player));
}
public ModelFlying getModelFlying(final Player player, final PlayerLocation fromLocation, public ModelFlying getModelFlying(final Player player, final PlayerLocation fromLocation,
final MovingData data, final MovingConfig cc) { final MovingData data, final MovingConfig cc) {
final GameMode gameMode = player.getGameMode(); final GameMode gameMode = player.getGameMode();

View File

@ -15,21 +15,15 @@
package fr.neatmonster.nocheatplus.checks.moving; package fr.neatmonster.nocheatplus.checks.moving;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
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.ICheckData;
import fr.neatmonster.nocheatplus.checks.access.IRemoveSubCheckData; import fr.neatmonster.nocheatplus.checks.access.IRemoveSubCheckData;
import fr.neatmonster.nocheatplus.checks.moving.location.setback.DefaultSetBackStorage; import fr.neatmonster.nocheatplus.checks.moving.location.setback.DefaultSetBackStorage;
import fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace; import fr.neatmonster.nocheatplus.checks.moving.location.tracking.LocationTrace;
@ -47,10 +41,10 @@ import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry;
import fr.neatmonster.nocheatplus.checks.moving.velocity.VelocityFlags; import fr.neatmonster.nocheatplus.checks.moving.velocity.VelocityFlags;
import fr.neatmonster.nocheatplus.checks.workaround.WRPT; import fr.neatmonster.nocheatplus.checks.workaround.WRPT;
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeReference; import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeReference;
import fr.neatmonster.nocheatplus.components.data.ICanHandleTimeRunningBackwards;
import fr.neatmonster.nocheatplus.components.entity.IEntityAccessDimensions; import fr.neatmonster.nocheatplus.components.entity.IEntityAccessDimensions;
import fr.neatmonster.nocheatplus.components.location.IGetPosition; import fr.neatmonster.nocheatplus.components.location.IGetPosition;
import fr.neatmonster.nocheatplus.components.location.IPositionWithLook; import fr.neatmonster.nocheatplus.components.location.IPositionWithLook;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionAccumulator; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionAccumulator;
@ -66,84 +60,31 @@ import fr.neatmonster.nocheatplus.workaround.IWorkaroundRegistry.WorkaroundSet;
*/ */
public class MovingData extends ACheckData implements IRemoveSubCheckData { public class MovingData extends ACheckData implements IRemoveSubCheckData {
public static final class MovingDataFactory implements CheckDataFactory, ICanHandleTimeRunningBackwards { /*
@Override * TODO: Handle world unload and other by registration (PlayerDataManager) -
public final ICheckData getData(final Player player) { * might just implement the interfaces and auto-handle at registration.
return MovingData.getData(player);
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return MovingData.playersMap.get(playerName);
}
@Override
public ICheckData removeData(final String playerName) {
return MovingData.removeData(playerName);
}
@Override
public void removeAllData() {
MovingData.clear();
}
@Override
public void handleTimeRanBackwards() {
for (final MovingData data : playersMap.values()) {
data.handleTimeRanBackwards();
}
}
}
/** The factory creating data. */
public static final CheckDataFactory factory = new MovingDataFactory();
private static Map<String, MovingData> playersMap = new HashMap<String, MovingData>();
/** The map containing the data per players. */
/**
* Gets the data of a specified player.
* final CheckDataFactory factory = new CheckDataFactory(
* @param player
* the player
* @return the data
*/ */
public static MovingData getData(final Player player) {
// Note that the trace might be null after just calling this.
MovingData data = playersMap.get(player.getName());
if (data == null) {
data = new MovingData(MovingConfig.getConfig(player));
playersMap.put(player.getName(), data);
}
return data;
}
public static ICheckData removeData(final String playerName) { // /**
return playersMap.remove(playerName); // * Clear data related to the given world.
} // * @param world The world that gets unloaded.
// */
public static void clear() { // public static void onWorldUnload(final World world) {
playersMap.clear(); // // TODO: Register with check (interfaces or just an event listener).
} // final String worldName = world.getName();
// for (final MovingData data : playersMap.values()) {
/** // data.onWorldUnload(worldName);
* Clear data related to the given world. // }
* @param world The world that gets unloaded. // }
*/ //
public static void onWorldUnload(final World world) { // public static void onReload() {
final String worldName = world.getName(); // // TODO: Register with check (interfaces or just an event listener).
for (final MovingData data : playersMap.values()) { // final MovingConfig globalCc = MovingConfig.getConfig((String) null);
data.onWorldUnload(worldName); // final int tick = TickTask.getTick();
} // for (final MovingData data : playersMap.values()) {
} // data.adjustOnReload(globalCc, tick);
// }
public static void onReload() { // }
final MovingConfig globalCc = MovingConfig.getConfig((String) null);
final int tick = TickTask.getTick();
for (final MovingData data : playersMap.values()) {
data.adjustOnReload(globalCc, tick);
}
}
// Check specific. // Check specific.
@ -365,8 +306,10 @@ public class MovingData extends ACheckData implements IRemoveSubCheckData {
/** Task id of the vehicle set back task. */ /** Task id of the vehicle set back task. */
public int vehicleSetBackTaskId = -1; public int vehicleSetBackTaskId = -1;
public MovingData(final MovingConfig config) { private final IPlayerData pData;
super(config);
public MovingData(final MovingConfig config, final IPlayerData pData) {
this.pData = pData;
morePacketsFreq = new ActionFrequency(config.morePacketsEPSBuckets, 500); morePacketsFreq = new ActionFrequency(config.morePacketsEPSBuckets, 500);
morePacketsBurstFreq = new ActionFrequency(12, 5000); morePacketsBurstFreq = new ActionFrequency(12, 5000);
@ -675,7 +618,7 @@ public class MovingData extends ACheckData implements IRemoveSubCheckData {
* @param amount * @param amount
*/ */
public void reducePlayerMorePacketsData(final float amount) { public void reducePlayerMorePacketsData(final float amount) {
CheckUtils.reduce(System.currentTimeMillis(), amount, morePacketsFreq, morePacketsBurstFreq); ActionFrequency.reduce(System.currentTimeMillis(), amount, morePacketsFreq, morePacketsBurstFreq);
} }
public void clearVehicleMorePacketsData() { public void clearVehicleMorePacketsData() {
@ -916,12 +859,11 @@ public class MovingData extends ACheckData implements IRemoveSubCheckData {
*/ */
public void addVelocity(final Player player, final MovingConfig cc, public void addVelocity(final Player player, final MovingConfig cc,
final double vx, final double vy, final double vz, final long flags) { final double vx, final double vy, final double vz, final long flags) {
final int tick = TickTask.getTick(); final int tick = TickTask.getTick();
// TODO: Slightly odd to call this each time, might switch to a counter-strategy (move - remove). // TODO: Slightly odd to call this each time, might switch to a counter-strategy (move - remove).
removeInvalidVelocity(tick - cc.velocityActivationTicks); removeInvalidVelocity(tick - cc.velocityActivationTicks);
if (debug) { if (pData.isDebugActive(CheckType.MOVING)) {
CheckUtils.debug(player, CheckType.MOVING, "New velocity: " + vx + ", " + vy + ", " + vz); CheckUtils.debug(player, CheckType.MOVING, "New velocity: " + vx + ", " + vy + ", " + vz);
} }

View File

@ -39,6 +39,7 @@ import fr.neatmonster.nocheatplus.checks.moving.util.MovingUtil;
import fr.neatmonster.nocheatplus.compat.Bridge1_9; import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.BridgeMisc; import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker; import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation;
import fr.neatmonster.nocheatplus.utilities.location.TrigUtil; import fr.neatmonster.nocheatplus.utilities.location.TrigUtil;
@ -71,12 +72,15 @@ public class CreativeFly extends Check {
* @return * @return
*/ */
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, public Location check(final Player player, final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc, final long time, final int tick, final MovingData data, final MovingConfig cc, final IPlayerData pData,
final long time, final int tick,
final boolean useBlockChangeTracker) { final boolean useBlockChangeTracker) {
// Reset tags, just in case. // Reset tags, just in case.
tags.clear(); tags.clear();
final boolean debug = pData.isDebugActive(type);
// Some edge data for this move. // Some edge data for this move.
final GameMode gameMode = player.getGameMode(); final GameMode gameMode = player.getGameMode();
final PlayerMoveData thisMove = data.playerMoves.getCurrentMove(); final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
@ -197,7 +201,7 @@ public class CreativeFly extends Check {
final double result = Math.max(0.0, resultH) + Math.max(0.0, resultV); final double result = Math.max(0.0, resultH) + Math.max(0.0, resultV);
if (data.debug) { if (debug) {
outpuDebugMove(player, hDistance, limitH, yDistance, limitV, model, tags, data); outpuDebugMove(player, hDistance, limitH, yDistance, limitV, model, tags, data);
} }
@ -228,7 +232,7 @@ public class CreativeFly extends Check {
// Maximum height check (silent set back). // Maximum height check (silent set back).
if (to.getY() > maximumHeight) { if (to.getY() > maximumHeight) {
setBack = data.getSetBack(to); setBack = data.getSetBack(to);
if (data.debug) { if (debug) {
debug(player, "Maximum height exceeded, silent set-back."); debug(player, "Maximum height exceeded, silent set-back.");
} }
} }
@ -244,7 +248,7 @@ public class CreativeFly extends Check {
if (setBack.getY() > maximumHeight) { if (setBack.getY() > maximumHeight) {
// Correct the y position. // Correct the y position.
setBack.setY(getCorrectedHeight(maximumHeight, setBack.getWorld())); setBack.setY(getCorrectedHeight(maximumHeight, setBack.getWorld()));
if (data.debug) { if (debug) {
debug(player, "Maximum height exceeded by set back, correct to: " + setBack.getY()); debug(player, "Maximum height exceeded by set back, correct to: " + setBack.getY());
} }
} }

View File

@ -27,6 +27,7 @@ import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig; import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData; import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.net.NetStatic; import fr.neatmonster.nocheatplus.checks.net.NetStatic;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation;
@ -62,9 +63,11 @@ public class MorePackets extends Check {
* @return * @return
*/ */
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, public Location check(final Player player, final PlayerLocation from, final PlayerLocation to,
final boolean allowSetSetBack, final MovingData data, final MovingConfig cc) { final boolean allowSetSetBack, final MovingData data, final MovingConfig cc,
final IPlayerData pData) {
// Take time once, first: // Take time once, first:
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
final boolean debug = pData.isDebugActive(type);
// if (from.isSamePos(to)) { // if (from.isSamePos(to)) {
// // Ignore moves with "just look" for now. // // Ignore moves with "just look" for now.
@ -94,7 +97,7 @@ public class MorePackets extends Check {
// Violation handling. // Violation handling.
final ViolationData vd = new ViolationData(this, player, data.morePacketsVL, violation, cc.morePacketsActions); final ViolationData vd = new ViolationData(this, player, data.morePacketsVL, violation, cc.morePacketsActions);
if (data.debug || vd.needsParameters()) { if (debug || vd.needsParameters()) {
vd.setParameter(ParameterName.PACKETS, Integer.toString(new Double(violation).intValue())); vd.setParameter(ParameterName.PACKETS, Integer.toString(new Double(violation).intValue()));
vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+")); vd.setParameter(ParameterName.TAGS, StringUtil.join(tags, "+"));
} }
@ -107,7 +110,7 @@ public class MorePackets extends Check {
// Update the set back location. (CHANGED to only update, if not a violation.) // Update the set back location. (CHANGED to only update, if not a violation.)
// (Might update whenever newTo == null) // (Might update whenever newTo == null)
data.setMorePacketsSetBack(from); data.setMorePacketsSetBack(from);
if (data.debug) { if (debug) {
debug(player, "Update set back (morepackets) to from."); debug(player, "Update set back (morepackets) to from.");
} }
} }

View File

@ -29,9 +29,7 @@ import fr.neatmonster.nocheatplus.checks.moving.magic.Magic;
import fr.neatmonster.nocheatplus.checks.moving.model.LocationData; import fr.neatmonster.nocheatplus.checks.moving.model.LocationData;
import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData; import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
import fr.neatmonster.nocheatplus.compat.BridgeHealth; import fr.neatmonster.nocheatplus.compat.BridgeHealth;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData;
import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation;
/** /**
@ -71,7 +69,8 @@ public class NoFall extends Check {
* Double.NEGATIVE_INFINITY. * Double.NEGATIVE_INFINITY.
*/ */
private void handleOnGround(final Player player, final double y, final double previousSetBackY, private void handleOnGround(final Player player, final double y, final double previousSetBackY,
final boolean reallyOnGround, final MovingData data, final MovingConfig cc) { final boolean reallyOnGround, final MovingData data, final MovingConfig cc,
final IPlayerData pData) {
// Damage to be dealt. // Damage to be dealt.
final float fallDist = (float) getApplicableFallHeight(player, y, previousSetBackY, data); final float fallDist = (float) getApplicableFallHeight(player, y, previousSetBackY, data);
final double maxD = getDamage(fallDist); final double maxD = getDamage(fallDist);
@ -85,7 +84,7 @@ public class NoFall extends Check {
} }
else { else {
// TODO: more effects like sounds, maybe use custom event with violation added. // TODO: more effects like sounds, maybe use custom event with violation added.
if (data.debug) { if (pData.isDebugActive(type)) {
debug(player, "NoFall deal damage" + (reallyOnGround ? "" : "violation") + ": " + maxD); debug(player, "NoFall deal damage" + (reallyOnGround ? "" : "violation") + ": " + maxD);
} }
// TODO: might not be necessary: if (mcPlayer.invulnerableTicks <= 0) [no damage event for resetting] // TODO: might not be necessary: if (mcPlayer.invulnerableTicks <= 0) [no damage event for resetting]
@ -209,8 +208,9 @@ public class NoFall extends Check {
*/ */
public void check(final Player player, final PlayerLocation pFrom, final PlayerLocation pTo, public void check(final Player player, final PlayerLocation pFrom, final PlayerLocation pTo,
final double previousSetBackY, final double previousSetBackY,
final MovingData data, final MovingConfig cc) { final MovingData data, final MovingConfig cc, final IPlayerData pData) {
final boolean debug = pData.isDebugActive(type);
final PlayerMoveData thisMove = data.playerMoves.getCurrentMove(); final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
final LocationData from = thisMove.from; final LocationData from = thisMove.from;
final LocationData to = thisMove.to; final LocationData to = thisMove.to;
@ -260,7 +260,7 @@ public class NoFall extends Check {
} }
else if (fromOnGround || !toOnGround && thisMove.touchedGround) { else if (fromOnGround || !toOnGround && thisMove.touchedGround) {
// Check if to deal damage (fall back damage check). // Check if to deal damage (fall back damage check).
touchDown(player, minY, previousSetBackY, data, cc); // Includes the current y-distance on descend! touchDown(player, minY, previousSetBackY, data, cc, pData); // Includes the current y-distance on descend!
// Ensure very big/strange moves don't yield violations. // Ensure very big/strange moves don't yield violations.
if (toY - fromY <= -Magic.FALL_DAMAGE_DIST) { if (toY - fromY <= -Magic.FALL_DAMAGE_DIST) {
data.noFallSkipAirCheck = true; data.noFallSkipAirCheck = true;
@ -276,7 +276,7 @@ public class NoFall extends Check {
// In this case the player has traveled further: add the difference. // In this case the player has traveled further: add the difference.
data.noFallFallDistance -= yDiff; data.noFallFallDistance -= yDiff;
} }
touchDown(player, minY, previousSetBackY, data, cc); touchDown(player, minY, previousSetBackY, data, cc, pData);
} }
else { else {
// Ensure fall distance is correct, or "anyway"? // Ensure fall distance is correct, or "anyway"?
@ -301,7 +301,7 @@ public class NoFall extends Check {
else if (cc.noFallAntiCriticals && (toReset || toOnGround || (fromReset || fromOnGround || thisMove.touchedGround) && yDiff >= 0)) { else if (cc.noFallAntiCriticals && (toReset || toOnGround || (fromReset || fromOnGround || thisMove.touchedGround) && yDiff >= 0)) {
final double max = Math.max(data.noFallFallDistance, mcFallDistance); final double max = Math.max(data.noFallFallDistance, mcFallDistance);
if (max > 0.0 && max < 0.75) { // (Ensure this does not conflict with deal-damage set to false.) if (max > 0.0 && max < 0.75) { // (Ensure this does not conflict with deal-damage set to false.)
if (data.debug) { if (debug) {
debug(player, "NoFall: Reset fall distance (anticriticals): mc=" + mcFallDistance +" / nf=" + data.noFallFallDistance); debug(player, "NoFall: Reset fall distance (anticriticals): mc=" + mcFallDistance +" / nf=" + data.noFallFallDistance);
} }
if (data.noFallFallDistance > 0) { if (data.noFallFallDistance > 0) {
@ -313,7 +313,7 @@ public class NoFall extends Check {
} }
} }
if (data.debug) { if (debug) {
debug(player, "NoFall: mc=" + mcFallDistance +" / nf=" + data.noFallFallDistance + (oldNFDist < data.noFallFallDistance ? " (+" + (data.noFallFallDistance - oldNFDist) + ")" : "") + " | ymax=" + data.noFallMaxY); debug(player, "NoFall: mc=" + mcFallDistance +" / nf=" + data.noFallFallDistance + (oldNFDist < data.noFallFallDistance ? " (+" + (data.noFallFallDistance - oldNFDist) + ")" : "") + " | ymax=" + data.noFallMaxY);
} }
@ -331,9 +331,9 @@ public class NoFall extends Check {
* @param cc * @param cc
*/ */
private void touchDown(final Player player, final double minY, final double previousSetBackY, private void touchDown(final Player player, final double minY, final double previousSetBackY,
final MovingData data, final MovingConfig cc) { final MovingData data, final MovingConfig cc, IPlayerData pData) {
if (cc.noFallDealDamage) { if (cc.noFallDealDamage) {
handleOnGround(player, minY, previousSetBackY, true, data, cc); handleOnGround(player, minY, previousSetBackY, true, data, cc, pData);
} }
else { else {
adjustFallDistance(player, minY, true, data, cc); adjustFallDistance(player, minY, true, data, cc);
@ -359,15 +359,16 @@ public class NoFall extends Check {
* Quit or kick: adjust fall distance if necessary. * Quit or kick: adjust fall distance if necessary.
* @param player * @param player
*/ */
public void onLeave(final Player player) { public void onLeave(final Player player, final MovingData data,
final MovingData data = MovingData.getData(player); final IPlayerData pData) {
final float fallDistance = player.getFallDistance(); final float fallDistance = player.getFallDistance();
// TODO: Might also detect too high mc fall dist. // TODO: Might also detect too high mc fall dist.
if (data.noFallFallDistance > fallDistance) { if (data.noFallFallDistance > fallDistance) {
final double playerY = player.getLocation(useLoc).getY(); final double playerY = player.getLocation(useLoc).getY();
useLoc.setWorld(null); useLoc.setWorld(null);
if (player.isFlying() || player.getGameMode() == GameMode.CREATIVE if (player.isFlying() || player.getGameMode() == GameMode.CREATIVE
|| player.getAllowFlight() && MovingConfig.getConfig(player).noFallSkipAllowFlight) { || player.getAllowFlight()
&& pData.getGenericInstance(MovingConfig.class).noFallSkipAllowFlight) {
// Forestall potential issues with flying plugins. // Forestall potential issues with flying plugins.
player.setFallDistance(0f); player.setFallDistance(0f);
data.noFallFallDistance = 0f; data.noFallFallDistance = 0f;
@ -387,22 +388,12 @@ public class NoFall extends Check {
* @param player * @param player
* @param data * @param data
*/ */
public void checkDamage(final Player player, final MovingData data, final double y) { public void checkDamage(final Player player, final double y,
final MovingConfig cc = MovingConfig.getConfig(player); final MovingData data, final IPlayerData pData) {
final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
// Deal damage. // Deal damage.
handleOnGround(player, y, data.hasSetBack() ? data.getSetBackY() : Double.NEGATIVE_INFINITY, handleOnGround(player, y, data.hasSetBack() ? data.getSetBackY() : Double.NEGATIVE_INFINITY,
false, data, cc); false, data, cc, pData);
}
/**
* Convenience method bypassing the factories.
* @param player
* @param cc
* @return
*/
public boolean isEnabled(final Player player , final MovingConfig cc, final PlayerData pData) {
return cc.noFallCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_NOFALL)
&& !pData.hasPermission(Permissions.MOVING_NOFALL, player);
} }
} }

View File

@ -28,6 +28,7 @@ import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig; import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData; import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker; import fr.neatmonster.nocheatplus.compat.blocks.changetracker.BlockChangeTracker;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.collision.Axis; import fr.neatmonster.nocheatplus.utilities.collision.Axis;
import fr.neatmonster.nocheatplus.utilities.collision.ICollidePassable; import fr.neatmonster.nocheatplus.utilities.collision.ICollidePassable;
import fr.neatmonster.nocheatplus.utilities.collision.PassableAxisTracing; import fr.neatmonster.nocheatplus.utilities.collision.PassableAxisTracing;
@ -70,13 +71,20 @@ public class Passable extends Check {
blockTracker = NCPAPIProvider.getNoCheatPlusAPI().getBlockChangeTracker(); blockTracker = NCPAPIProvider.getNoCheatPlusAPI().getBlockChangeTracker();
} }
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, public Location check(final Player player,
final MovingData data, final MovingConfig cc, final int tick, final boolean useBlockChangeTracker) { final PlayerLocation from, final PlayerLocation to,
return checkActual(player, from, to, data, cc, tick, useBlockChangeTracker); final MovingData data, final MovingConfig cc, final IPlayerData pData,
final int tick, final boolean useBlockChangeTracker) {
return checkActual(player, from, to, data, cc, pData, tick, useBlockChangeTracker);
} }
private Location checkActual(final Player player, final PlayerLocation from, final PlayerLocation to, private Location checkActual(final Player player,
final MovingData data, final MovingConfig cc, final int tick, final boolean useBlockChangeTracker) { final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc, final IPlayerData pData,
final int tick, final boolean useBlockChangeTracker) {
final boolean debug = pData.isDebugActive(type);
// TODO: Distinguish feet vs. box. // TODO: Distinguish feet vs. box.
// Block distances (sum, max) for from-to (not for loc!). // Block distances (sum, max) for from-to (not for loc!).
@ -84,9 +92,11 @@ public class Passable extends Check {
// Check default order first, then others. // Check default order first, then others.
rayTracing.setAxisOrder(Axis.AXIS_ORDER_YXZ); rayTracing.setAxisOrder(Axis.AXIS_ORDER_YXZ);
String newTag = checkRayTracing(player, from, to, manhattan, data, cc, tick, useBlockChangeTracker); String newTag = checkRayTracing(player, from, to, manhattan,
data, cc, debug, tick, useBlockChangeTracker);
if (newTag != null) { if (newTag != null) {
newTag = checkRayTracingAlernateOrder(player, from, to, manhattan, data, cc, tick, newTag = checkRayTracingAlernateOrder(player, from, to, manhattan,
debug, data, cc, tick,
useBlockChangeTracker, newTag); useBlockChangeTracker, newTag);
} }
// Finally handle violations. // Finally handle violations.
@ -97,13 +107,16 @@ public class Passable extends Check {
} }
else { else {
// Direct return. // Direct return.
return potentialViolation(player, from, to, manhattan, newTag, data, cc); return potentialViolation(player, from, to, manhattan,
debug, newTag, data, cc);
} }
} }
private String checkRayTracingAlernateOrder(final Player player, private String checkRayTracingAlernateOrder(final Player player,
final PlayerLocation from, final PlayerLocation to, final int manhattan, final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc, final int tick, final boolean useBlockChangeTracker, final int manhattan, final boolean debug,
final MovingData data, final MovingConfig cc,
final int tick, final boolean useBlockChangeTracker,
final String previousTag) { final String previousTag) {
/* /*
* General assumption for now: Not all combinations have to be checked. * General assumption for now: Not all combinations have to be checked.
@ -116,16 +129,19 @@ public class Passable extends Check {
if (axis == Axis.X_AXIS || axis == Axis.Z_AXIS) { if (axis == Axis.X_AXIS || axis == Axis.Z_AXIS) {
// Test the horizontal alternative only. // Test the horizontal alternative only.
rayTracing.setAxisOrder(Axis.AXIS_ORDER_YZX); rayTracing.setAxisOrder(Axis.AXIS_ORDER_YZX);
return checkRayTracing(player, from, to, manhattan, data, cc, tick, useBlockChangeTracker); return checkRayTracing(player, from, to, manhattan, data, cc,
debug, tick, useBlockChangeTracker);
} }
else if (axis == Axis.Y_AXIS) { else if (axis == Axis.Y_AXIS) {
// Test both horizontal options, each before vertical. // Test both horizontal options, each before vertical.
rayTracing.setAxisOrder(Axis.AXIS_ORDER_XZY); rayTracing.setAxisOrder(Axis.AXIS_ORDER_XZY);
if (checkRayTracing(player, from, to, manhattan, data, cc, tick, useBlockChangeTracker) == null) { if (checkRayTracing(player, from, to, manhattan, data, cc,
debug, tick, useBlockChangeTracker) == null) {
return null; return null;
} }
rayTracing.setAxisOrder(Axis.AXIS_ORDER_ZXY); rayTracing.setAxisOrder(Axis.AXIS_ORDER_ZXY);
return checkRayTracing(player, from, to, manhattan, data, cc, tick, useBlockChangeTracker); return checkRayTracing(player, from, to, manhattan, data, cc,
debug, tick, useBlockChangeTracker);
} }
else { else {
return previousTag; // In case nothing could be done. return previousTag; // In case nothing could be done.
@ -134,7 +150,8 @@ public class Passable extends Check {
private String checkRayTracing(final Player player, private String checkRayTracing(final Player player,
final PlayerLocation from, final PlayerLocation to, final int manhattan, final PlayerLocation from, final PlayerLocation to, final int manhattan,
final MovingData data, final MovingConfig cc, final int tick, final boolean useBlockChangeTracker) { final MovingData data, final MovingConfig cc, final boolean debug,
final int tick, final boolean useBlockChangeTracker) {
String tags = null; String tags = null;
// NOTE: axis order is set externally. // NOTE: axis order is set externally.
setNormalMargins(rayTracing, from); setNormalMargins(rayTracing, from);
@ -153,7 +170,7 @@ public class Passable extends Check {
else if (rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) { else if (rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
tags = "raytracing_maxsteps_"; tags = "raytracing_maxsteps_";
} }
if (data.debug) { if (debug) {
debugExtraCollisionDetails(player, rayTracing, "std"); debugExtraCollisionDetails(player, rayTracing, "std");
} }
rayTracing.cleanup(); rayTracing.cleanup();
@ -182,22 +199,25 @@ public class Passable extends Check {
* @return * @return
*/ */
private Location potentialViolation(final Player player, private Location potentialViolation(final Player player,
final PlayerLocation from, final PlayerLocation to, final int manhattan, final PlayerLocation from, final PlayerLocation to,
final int manhattan, final boolean debug,
String tags, final MovingData data, final MovingConfig cc) { String tags, final MovingData data, final MovingConfig cc) {
// TODO: Might need the workaround for fences. // TODO: Might need the workaround for fences.
return actualViolation(player, from, to, tags, data, cc); return actualViolation(player, from, to, tags, debug, data, cc);
} }
private Location actualViolation(final Player player, final PlayerLocation from, final PlayerLocation to, private Location actualViolation(final Player player,
final String tags, final MovingData data, final MovingConfig cc) { final PlayerLocation from, final PlayerLocation to,
final String tags, final boolean debug,
final MovingData data, final MovingConfig cc) {
Location setBackLoc = null; // Alternative to from.getLocation(). Location setBackLoc = null; // Alternative to from.getLocation().
// Prefer the set back location from the data. // Prefer the set back location from the data.
if (data.hasSetBack()) { if (data.hasSetBack()) {
setBackLoc = data.getSetBack(to); setBackLoc = data.getSetBack(to);
if (data.debug) { if (debug) {
debug(player, "Using set back location for passable."); debug(player, "Using set back location for passable.");
} }
} }
@ -205,7 +225,7 @@ public class Passable extends Check {
// Return the reset position. // Return the reset position.
data.passableVL += 1d; data.passableVL += 1d;
final ViolationData vd = new ViolationData(this, player, data.passableVL, 1, cc.passableActions); final ViolationData vd = new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
if (data.debug || vd.needsParameters()) { if (debug || vd.needsParameters()) {
vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ())); vd.setParameter(ParameterName.LOCATION_FROM, String.format(Locale.US, "%.2f, %.2f, %.2f", from.getX(), from.getY(), from.getZ()));
vd.setParameter(ParameterName.LOCATION_TO, String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ())); vd.setParameter(ParameterName.LOCATION_TO, String.format(Locale.US, "%.2f, %.2f, %.2f", to.getX(), to.getY(), to.getZ()));
vd.setParameter(ParameterName.DISTANCE, String.format(Locale.US, "%.2f", TrigUtil.distance(from, to))); vd.setParameter(ParameterName.DISTANCE, String.format(Locale.US, "%.2f", TrigUtil.distance(from, to)));
@ -221,7 +241,7 @@ public class Passable extends Check {
newTo = LocUtil.clone(setBackLoc); newTo = LocUtil.clone(setBackLoc);
} else { } else {
newTo = from.getLocation(); newTo = from.getLocation();
if (data.debug) { if (debug) {
debug(player, "Using from location for passable."); debug(player, "Using from location for passable.");
} }
} }

View File

@ -49,7 +49,7 @@ import fr.neatmonster.nocheatplus.components.modifier.IAttributeAccess;
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle; import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
import fr.neatmonster.nocheatplus.logging.Streams; import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionAccumulator; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionAccumulator;
@ -117,12 +117,14 @@ public class SurvivalFly extends Check {
* @param useBlockChangeTracker * @param useBlockChangeTracker
* @return * @return
*/ */
public Location check(final Player player, final PlayerLocation from, final PlayerLocation to, public Location check(final Player player,
final PlayerLocation from, final PlayerLocation to,
final int multiMoveCount, final int multiMoveCount,
final MovingData data, final MovingConfig cc, final PlayerData pData, final MovingData data, final MovingConfig cc, final IPlayerData pData,
final int tick, final long now, final boolean useBlockChangeTracker) { final int tick, final long now, final boolean useBlockChangeTracker) {
tags.clear(); tags.clear();
if (data.debug) { final boolean debug = pData.isDebugActive(type);
if (debug) {
justUsedWorkarounds.clear(); justUsedWorkarounds.clear();
data.ws.setJustUsedIds(justUsedWorkarounds); data.ws.setJustUsedIds(justUsedWorkarounds);
} }
@ -255,7 +257,7 @@ public class SurvivalFly extends Check {
&& TrigUtil.isSamePosAndLook(thisMove.from, lastMove.to)) { && TrigUtil.isSamePosAndLook(thisMove.from, lastMove.to)) {
// Ground somehow appeared out of thin air (block place). // Ground somehow appeared out of thin air (block place).
data.setSetBack(from); data.setSetBack(from);
if (data.debug) { if (debug) {
debug(player, "Adjust set back on move: from is now on ground."); debug(player, "Adjust set back on move: from is now on ground.");
} }
} }
@ -436,7 +438,7 @@ public class SurvivalFly extends Check {
vDistanceAboveLimit = res[1]; vDistanceAboveLimit = res[1];
if (res[0] == Double.MIN_VALUE && res[1] == Double.MIN_VALUE) { if (res[0] == Double.MIN_VALUE && res[1] == Double.MIN_VALUE) {
// Silent set back. // Silent set back.
if (data.debug) { if (debug) {
tags.add("silentsbcobweb"); tags.add("silentsbcobweb");
outputDebug(player, to, data, cc, hDistance, hAllowedDistance, hFreedom, outputDebug(player, to, data, cc, hDistance, hAllowedDistance, hFreedom,
yDistance, vAllowedDistance, fromOnGround, resetFrom, toOnGround, resetTo, thisMove); yDistance, vAllowedDistance, fromOnGround, resetFrom, toOnGround, resetTo, thisMove);
@ -486,7 +488,7 @@ public class SurvivalFly extends Check {
// Debug output. // Debug output.
final int tagsLength; final int tagsLength;
if (data.debug) { if (debug) {
outputDebug(player, to, data, cc, hDistance, hAllowedDistance, hFreedom, outputDebug(player, to, data, cc, hDistance, hAllowedDistance, hFreedom,
yDistance, vAllowedDistance, fromOnGround, resetFrom, toOnGround, resetTo, thisMove); yDistance, vAllowedDistance, fromOnGround, resetFrom, toOnGround, resetTo, thisMove);
tagsLength = tags.size(); tagsLength = tags.size();
@ -660,7 +662,7 @@ public class SurvivalFly extends Check {
// Update unused velocity tracking. // Update unused velocity tracking.
// TODO: Hide and seek with API. // TODO: Hide and seek with API.
// TODO: Pull down tick / timing data (perhaps add an API object for millis + source + tick + sequence count (+ source of sequence count). // TODO: Pull down tick / timing data (perhaps add an API object for millis + source + tick + sequence count (+ source of sequence count).
if (data.debug) { if (debug) {
// TODO: Only update, if velocity is queued at all. // TODO: Only update, if velocity is queued at all.
data.getVerticalVelocityTracker().updateBlockedState(tick, data.getVerticalVelocityTracker().updateBlockedState(tick,
// Assume blocked with being in web/water, despite not entirely correct. // Assume blocked with being in web/water, despite not entirely correct.
@ -676,14 +678,16 @@ public class SurvivalFly extends Check {
data.lastFrictionVertical = data.nextFrictionVertical; data.lastFrictionVertical = data.nextFrictionVertical;
// Log tags added after violation handling. // Log tags added after violation handling.
if (data.debug && tags.size() > tagsLength) { if (debug && tags.size() > tagsLength) {
logPostViolationTags(player); logPostViolationTags(player);
} }
return null; return null;
} }
private boolean toOnGroundPastStates(final PlayerLocation from, final PlayerLocation to, private boolean toOnGroundPastStates(
final PlayerMoveData thisMove, int tick, final MovingData data, final MovingConfig cc) { final PlayerLocation from, final PlayerLocation to,
final PlayerMoveData thisMove, int tick,
final MovingData data, final MovingConfig cc) {
// TODO: Heuristics / more / which? (too short move, typical step up moves, typical levels, ...) // TODO: Heuristics / more / which? (too short move, typical step up moves, typical levels, ...)
if (to.isOnGroundOpportune(cc.yOnGround, 0L, blockChangeTracker, data.blockChangeRef, tick)) { if (to.isOnGroundOpportune(cc.yOnGround, 0L, blockChangeTracker, data.blockChangeRef, tick)) {
tags.add("pastground_to"); tags.add("pastground_to");
@ -782,7 +786,8 @@ public class SurvivalFly extends Check {
* @param data * @param data
* @param cc * @param cc
*/ */
private void setNextFriction(final PlayerMoveData thisMove, final MovingData data, final MovingConfig cc) { private void setNextFriction(final PlayerMoveData thisMove,
final MovingData data, final MovingConfig cc) {
// NOTE: Other methods might still override nextFriction to 1.0 due to burst/lift-off envelope. // NOTE: Other methods might still override nextFriction to 1.0 due to burst/lift-off envelope.
// TODO: Other media / medium transitions / friction by block. // TODO: Other media / medium transitions / friction by block.
final LocationData from = thisMove.from; final LocationData from = thisMove.from;
@ -830,7 +835,7 @@ public class SurvivalFly extends Check {
*/ */
private double setAllowedhDist(final Player player, final boolean sprinting, private double setAllowedhDist(final Player player, final boolean sprinting,
final PlayerMoveData thisMove, final PlayerMoveData thisMove,
final MovingData data, final MovingConfig cc, final PlayerData pData, final MovingData data, final MovingConfig cc, final IPlayerData pData,
final boolean checkPermissions) final boolean checkPermissions)
{ {
// TODO: Optimize for double checking? // TODO: Optimize for double checking?
@ -1003,9 +1008,10 @@ public class SurvivalFly extends Check {
*/ */
private double[] vDistAir(final long now, final Player player, final PlayerLocation from, private double[] vDistAir(final long now, final Player player, final PlayerLocation from,
final boolean fromOnGround, final boolean resetFrom, final PlayerLocation to, final boolean fromOnGround, final boolean resetFrom, final PlayerLocation to,
final boolean toOnGround, final boolean resetTo, final double hDistance, final double yDistance, final boolean toOnGround, final boolean resetTo,
final double hDistance, final double yDistance,
final int multiMoveCount, final PlayerMoveData lastMove, final int multiMoveCount, final PlayerMoveData lastMove,
final MovingData data, final MovingConfig cc, final PlayerData pData) { final MovingData data, final MovingConfig cc, final IPlayerData pData) {
final PlayerMoveData thisMove = data.playerMoves.getCurrentMove(); final PlayerMoveData thisMove = data.playerMoves.getCurrentMove();
// Y-distance for normal jumping, like in air. // Y-distance for normal jumping, like in air.
double vAllowedDistance = 0.0; double vAllowedDistance = 0.0;
@ -1327,7 +1333,8 @@ public class SurvivalFly extends Check {
* @param cc * @param cc
* @return * @return
*/ */
private double vAllowedDistanceNoData(final PlayerMoveData thisMove, final PlayerMoveData lastMove, private double vAllowedDistanceNoData(
final PlayerMoveData thisMove, final PlayerMoveData lastMove,
final double maxJumpGain, final double jumpGainMargin, final double maxJumpGain, final double jumpGainMargin,
final MovingData data, final MovingConfig cc) { final MovingData data, final MovingConfig cc) {
if (lastMove.valid) { if (lastMove.valid) {
@ -1425,7 +1432,8 @@ public class SurvivalFly extends Check {
* @param tag Tag to be added in case of a violation of this sub-check. * @param tag Tag to be added in case of a violation of this sub-check.
* @return A violation value > 0.001, to be interpreted like a moving violation. * @return A violation value > 0.001, to be interpreted like a moving violation.
*/ */
private static final double verticalAccounting(final double yDistance, final ActionAccumulator acc, final ArrayList<String> tags, final String tag) { private static final double verticalAccounting(final double yDistance,
final ActionAccumulator acc, final ArrayList<String> tags, final String tag) {
// TODO: Add air friction and do it per move anyway !? // TODO: Add air friction and do it per move anyway !?
final int count0 = acc.bucketCount(0); final int count0 = acc.bucketCount(0);
if (count0 > 0) { if (count0 > 0) {
@ -1463,7 +1471,9 @@ public class SurvivalFly extends Check {
* @param vDistanceAboveLimit * @param vDistanceAboveLimit
* @return vDistanceAboveLimit * @return vDistanceAboveLimit
*/ */
private double yDirChange(final PlayerLocation from, final PlayerLocation to, final double yDistance, double vDistanceAboveLimit, final PlayerMoveData lastMove, final MovingData data) { private double yDirChange(final PlayerLocation from, final PlayerLocation to,
final double yDistance, double vDistanceAboveLimit,
final PlayerMoveData lastMove, final MovingData data) {
// TODO: Does this account for velocity in a sufficient way? // TODO: Does this account for velocity in a sufficient way?
if (yDistance > 0) { if (yDistance > 0) {
// TODO: Clear active vertical velocity here ? // TODO: Clear active vertical velocity here ?
@ -1538,10 +1548,11 @@ public class SurvivalFly extends Check {
* @param skipPermChecks * @param skipPermChecks
* @return hAllowedDistance, hDistanceAboveLimit, hFreedom * @return hAllowedDistance, hDistanceAboveLimit, hFreedom
*/ */
private double[] hDistAfterFailure(final Player player, final PlayerLocation from, final PlayerLocation to, private double[] hDistAfterFailure(final Player player,
final PlayerLocation from, final PlayerLocation to,
double hAllowedDistance, double hDistanceAboveLimit, final boolean sprinting, double hAllowedDistance, double hDistanceAboveLimit, final boolean sprinting,
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final PlayerMoveData thisMove, final PlayerMoveData lastMove,
final MovingData data, final MovingConfig cc, final PlayerData pData, final MovingData data, final MovingConfig cc, final IPlayerData pData,
final boolean skipPermChecks) { final boolean skipPermChecks) {
// TODO: Still not entirely sure about this checking order. // TODO: Still not entirely sure about this checking order.
@ -1633,7 +1644,10 @@ public class SurvivalFly extends Check {
* @param data * @param data
* @return hDistanceAboveLimit * @return hDistanceAboveLimit
*/ */
private double bunnyHop(final PlayerLocation from, final PlayerLocation to, final double hAllowedDistance, double hDistanceAboveLimit, final boolean sprinting, final PlayerMoveData thisMove, final PlayerMoveData lastMove, final MovingData data, final MovingConfig cc) { private double bunnyHop(final PlayerLocation from, final PlayerLocation to,
final double hAllowedDistance, double hDistanceAboveLimit, final boolean sprinting,
final PlayerMoveData thisMove, final PlayerMoveData lastMove,
final MovingData data, final MovingConfig cc) {
// Check "bunny fly" here, to not fall over sprint resetting on the way. // Check "bunny fly" here, to not fall over sprint resetting on the way.
boolean allowHop = true; boolean allowHop = true;
boolean double_bunny = false; boolean double_bunny = false;
@ -1819,7 +1833,9 @@ public class SurvivalFly extends Check {
* @param data * @param data
* @return vAllowedDistance, vDistanceAboveLimit * @return vAllowedDistance, vDistanceAboveLimit
*/ */
private double[] vDistLiquid(final PlayerLocation from, final PlayerLocation to, final boolean toOnGround, final double yDistance, final PlayerMoveData lastMove, final MovingData data) { private double[] vDistLiquid(final PlayerLocation from, final PlayerLocation to,
final boolean toOnGround, final double yDistance, final PlayerMoveData lastMove,
final MovingData data) {
data.sfNoLowJump = true; data.sfNoLowJump = true;
// Expected envelopes. // Expected envelopes.
@ -1879,7 +1895,8 @@ public class SurvivalFly extends Check {
* @param data * @param data
* @return vDistanceAboveLimit * @return vDistanceAboveLimit
*/ */
private double vDistClimbable(final Player player, final PlayerLocation from, final PlayerLocation to, private double vDistClimbable(final Player player,
final PlayerLocation from, final PlayerLocation to,
final boolean fromOnGround, final boolean toOnGround, final boolean fromOnGround, final boolean toOnGround,
final PlayerMoveData thisMove, final PlayerMoveData lastMove, final PlayerMoveData thisMove, final PlayerMoveData lastMove,
final double yDistance, final MovingData data) { final double yDistance, final MovingData data) {
@ -1951,7 +1968,9 @@ public class SurvivalFly extends Check {
* @param cc * @param cc
* @return vAllowedDistance, vDistanceAboveLimit * @return vAllowedDistance, vDistanceAboveLimit
*/ */
private double[] vDistWeb(final Player player, final PlayerMoveData thisMove, final boolean toOnGround, final double hDistanceAboveLimit, final long now, final MovingData data, final MovingConfig cc) { private double[] vDistWeb(final Player player, final PlayerMoveData thisMove,
final boolean toOnGround, final double hDistanceAboveLimit, final long now,
final MovingData data, final MovingConfig cc) {
final double yDistance = thisMove.yDistance; final double yDistance = thisMove.yDistance;
double vAllowedDistance = 0.0; double vAllowedDistance = 0.0;
double vDistanceAboveLimit = 0.0; double vDistanceAboveLimit = 0.0;
@ -2000,7 +2019,9 @@ public class SurvivalFly extends Check {
* @param cc * @param cc
* @return * @return
*/ */
private Location handleViolation(final long now, final double result, final Player player, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc) private Location handleViolation(final long now, final double result,
final Player player, final PlayerLocation from, final PlayerLocation to,
final MovingData data, final MovingConfig cc)
{ {
// Increment violation level. // Increment violation level.
data.survivalFlyVL += result; data.survivalFlyVL += result;
@ -2032,7 +2053,8 @@ public class SurvivalFly extends Check {
* @param cc * @param cc
* @param data * @param data
*/ */
public final void handleHoverViolation(final Player player, final Location loc, final MovingConfig cc, final MovingData data) { public final void handleHoverViolation(final Player player, final Location loc,
final MovingConfig cc, final MovingData data) {
data.survivalFlyVL += cc.sfHoverViolation; data.survivalFlyVL += cc.sfHoverViolation;
// TODO: Extra options for set back / kick, like vl? // TODO: Extra options for set back / kick, like vl?
@ -2125,7 +2147,8 @@ public class SurvivalFly extends Check {
final MovingData data, final MovingConfig cc, final MovingData data, final MovingConfig cc,
final double hDistance, final double hAllowedDistance, final double hFreedom, final double hDistance, final double hAllowedDistance, final double hFreedom,
final double yDistance, final double vAllowedDistance, final double yDistance, final double vAllowedDistance,
final boolean fromOnGround, final boolean resetFrom, final boolean toOnGround, final boolean resetTo, final boolean fromOnGround, final boolean resetFrom,
final boolean toOnGround, final boolean resetTo,
final PlayerMoveData thisMove) { final PlayerMoveData thisMove) {
// TODO: Show player name once (!) // TODO: Show player name once (!)
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove(); final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();

View File

@ -14,15 +14,15 @@
*/ */
package fr.neatmonster.nocheatplus.checks.moving.player; package fr.neatmonster.nocheatplus.checks.moving.player;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData; import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleAxisVelocity; import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleAxisVelocity;
import fr.neatmonster.nocheatplus.checks.moving.velocity.UnusedTracker; import fr.neatmonster.nocheatplus.checks.moving.velocity.UnusedTracker;
import fr.neatmonster.nocheatplus.logging.debug.DebugUtil; import fr.neatmonster.nocheatplus.logging.debug.DebugUtil;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
public class UnusedVelocity { public class UnusedVelocity {
@ -35,8 +35,13 @@ public class UnusedVelocity {
* @param player * @param player
* @return If the player has failed the check, whatever that means. * @return If the player has failed the check, whatever that means.
*/ */
public static boolean checkUnusedVelocity(final Player player, final CheckType checkType) { public static boolean checkUnusedVelocity(final Player player,
return checkUnusedVelocity(player, checkType, MovingData.getData(player), MovingConfig.getConfig(player)); final CheckType checkType, final IPlayerData pData) {
return checkUnusedVelocity(
player, checkType,
pData.getGenericInstance(MovingData.class),
pData.getGenericInstance(MovingConfig.class)
);
} }
@ -48,7 +53,8 @@ public class UnusedVelocity {
* @param cc * @param cc
* @return If the player has failed the check, whatever that means. * @return If the player has failed the check, whatever that means.
*/ */
public static boolean checkUnusedVelocity(final Player player, final CheckType checkType, final MovingData data, final MovingConfig cc) { public static boolean checkUnusedVelocity(final Player player,
final CheckType checkType, final MovingData data, final MovingConfig cc) {
boolean violation = false; boolean violation = false;
final SimpleAxisVelocity verVel = data.getVerticalVelocityTracker(); final SimpleAxisVelocity verVel = data.getVerticalVelocityTracker();
violation |= quickCheckDirection(player, verVel.unusedTrackerPos, checkType, "vert/pos", data, cc); violation |= quickCheckDirection(player, verVel.unusedTrackerPos, checkType, "vert/pos", data, cc);

View File

@ -39,11 +39,9 @@ import fr.neatmonster.nocheatplus.compat.Bridge1_9;
import fr.neatmonster.nocheatplus.compat.BridgeMisc; import fr.neatmonster.nocheatplus.compat.BridgeMisc;
import fr.neatmonster.nocheatplus.compat.MCAccess; import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer; import fr.neatmonster.nocheatplus.components.debug.IDebugPlayer;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil; import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation; import fr.neatmonster.nocheatplus.utilities.location.PlayerLocation;
@ -77,17 +75,13 @@ public class MovingUtil {
* @return * @return
*/ */
public static final boolean shouldCheckSurvivalFly(final Player player, final PlayerLocation fromLocation, public static final boolean shouldCheckSurvivalFly(final Player player, final PlayerLocation fromLocation,
final MovingData data, final MovingConfig cc, final PlayerData pData) { final MovingData data, final MovingConfig cc, final IPlayerData pData) {
final GameMode gameMode = player.getGameMode(); final GameMode gameMode = player.getGameMode();
/* // (Full activation check - use permission caching for performance rather.)
* TODO: Model rare to check conditions (elytra, ...) on base of one return pData.isCheckActive(CheckType.MOVING_SURVIVALFLY, player)
* pre-check and a method to delegate to. Reuse method(s) with && gameMode != BridgeMisc.GAME_MODE_SPECTATOR
* MovingConfig.
*/
return cc.survivalFlyCheck && gameMode != BridgeMisc.GAME_MODE_SPECTATOR
&& (cc.ignoreCreative || gameMode != GameMode.CREATIVE) && !player.isFlying() && (cc.ignoreCreative || gameMode != GameMode.CREATIVE) && !player.isFlying()
&& (cc.ignoreAllowFlight || !player.getAllowFlight()) && (cc.ignoreAllowFlight || !player.getAllowFlight())
&& !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY)
&& ( && (
!Bridge1_9.isGlidingWithElytra(player) !Bridge1_9.isGlidingWithElytra(player)
|| !isGlidingWithElytraValid(player, fromLocation, data, cc) || !isGlidingWithElytraValid(player, fromLocation, data, cc)
@ -96,7 +90,7 @@ public class MovingUtil {
Double.isInfinite(Bridge1_9.getLevitationAmplifier(player)) Double.isInfinite(Bridge1_9.getLevitationAmplifier(player))
|| fromLocation.isInLiquid() || fromLocation.isInLiquid()
) )
&& !pData.hasPermission(Permissions.MOVING_SURVIVALFLY, player); ;
} }
/** /**
@ -287,10 +281,11 @@ public class MovingUtil {
* @param loc * @param loc
* @return * @return
*/ */
public static boolean shouldCheckUntrackedLocation(final Player player, final Location loc) { public static boolean shouldCheckUntrackedLocation(final Player player,
final Location loc, final IPlayerData pData) {
return !TrigUtil.isSamePos(loc, loc.getWorld().getSpawnLocation()) return !TrigUtil.isSamePos(loc, loc.getWorld().getSpawnLocation())
&& !BlockProperties.isPassable(loc) && !BlockProperties.isPassable(loc)
&& CheckType.MOVING_PASSABLE.isEnabled(player); && pData.isCheckActive(CheckType.MOVING_PASSABLE, player);
} }
/** /**
@ -321,7 +316,8 @@ public class MovingUtil {
// TODO: Exempt other warps -> HASH based exemption (expire by time, keep high count)? // TODO: Exempt other warps -> HASH based exemption (expire by time, keep high count)?
if (TrigUtil.isSamePos(loc, refLoc) && (entity instanceof Player)) { if (TrigUtil.isSamePos(loc, refLoc) && (entity instanceof Player)) {
final Player other = (Player) entity; final Player other = (Player) entity;
final MovingData otherData = MovingData.getData(other); final IPlayerData otherPData = DataManager.getPlayerData(other);
final MovingData otherData = otherPData.getGenericInstance(MovingData.class);
final PlayerMoveData otherLastMove = otherData.playerMoves.getFirstPastMove(); final PlayerMoveData otherLastMove = otherData.playerMoves.getFirstPastMove();
if (!otherLastMove.toIsValid) { if (!otherLastMove.toIsValid) {
// Data might have been removed. // Data might have been removed.
@ -365,8 +361,10 @@ public class MovingUtil {
* @param data * @param data
* @return * @return
*/ */
public static double getRealisticFallDistance(final Player player, final double fromY, final double toY, final MovingData data) { public static double getRealisticFallDistance(final Player player,
if (CheckType.MOVING_NOFALL.isEnabled(player)) { // Not optimal final double fromY, final double toY,
final MovingData data, final IPlayerData pData) {
if (pData.isCheckActive(CheckType.MOVING_NOFALL, player)) {
// (NoFall will not be checked, if this method is called.) // (NoFall will not be checked, if this method is called.)
if (data.noFallMaxY >= fromY ) { if (data.noFallMaxY >= fromY ) {
return Math.max(0.0, data.noFallMaxY - toY); return Math.max(0.0, data.noFallMaxY - toY);
@ -387,7 +385,8 @@ public class MovingUtil {
* @param from * @param from
* @param data * @param data
*/ */
public static void checkSetBack(final Player player, final PlayerLocation from, final MovingData data, final IDebugPlayer idp) { public static void checkSetBack(final Player player, final PlayerLocation from,
final MovingData data, final IPlayerData pData, final IDebugPlayer idp) {
if (!data.hasSetBack()) { if (!data.hasSetBack()) {
data.setSetBack(from); data.setSetBack(from);
} }
@ -396,7 +395,7 @@ public class MovingUtil {
(from.isOnGround() || from.isResetCond())) { (from.isOnGround() || from.isResetCond())) {
// TODO: Move most to a method? // TODO: Move most to a method?
// TODO: Is a margin needed for from.isOnGround()? [bukkitapionly] // TODO: Is a margin needed for from.isOnGround()? [bukkitapionly]
if (data.debug) { if (pData.isDebugActive(CheckType.MOVING)) {
// TODO: Should this be info? // TODO: Should this be info?
idp.debug(player, "Adjust set back after join/respawn: " + from.getLocation()); idp.debug(player, "Adjust set back after join/respawn: " + from.getLocation());
} }
@ -446,8 +445,9 @@ public class MovingUtil {
* @param data * @param data
* @param cc * @param cc
*/ */
public static void ensureChunksLoaded(final Player player, final Location from, final Location to, final PlayerMoveData lastMove, public static void ensureChunksLoaded(final Player player,
final String tag, final MovingData data, final MovingConfig cc) { final Location from, final Location to, final PlayerMoveData lastMove,
final String tag, final MovingConfig cc, final IPlayerData pData) {
// (Worlds must be equal. Ensured in player move handling.) // (Worlds must be equal. Ensured in player move handling.)
final double x0 = from.getX(); final double x0 = from.getX();
final double z0 = from.getZ(); final double z0 = from.getZ();
@ -489,7 +489,7 @@ public class MovingUtil {
if (loadTo) { if (loadTo) {
loaded += MapUtil.ensureChunksLoaded(to.getWorld(), x1, z1, margin); loaded += MapUtil.ensureChunksLoaded(to.getWorld(), x1, z1, margin);
} }
if (loaded > 0 && data.debug) { if (loaded > 0 && pData.isDebugActive(CheckType.MOVING)) {
StaticLog.logInfo("Player " + tag + ": Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + from.getWorld().getName() + " for player: " + player.getName()); StaticLog.logInfo("Player " + tag + ": Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + from.getWorld().getName() + " for player: " + player.getName());
} }
} }
@ -505,8 +505,10 @@ public class MovingUtil {
* @param data * @param data
* @param cc * @param cc
*/ */
public static void ensureChunksLoaded(final Player player, final Location loc, final String tag, public static void ensureChunksLoaded(final Player player,
final MovingData data, final MovingConfig cc) { final Location loc, final String tag,
final MovingData data, final MovingConfig cc,
final IPlayerData pData) {
final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove(); final PlayerMoveData lastMove = data.playerMoves.getFirstPastMove();
final double x0 = loc.getX(); final double x0 = loc.getX();
final double z0 = loc.getZ(); final double z0 = loc.getZ();
@ -524,7 +526,7 @@ public class MovingUtil {
} }
} }
int loaded = MapUtil.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), Magic.CHUNK_LOAD_MARGIN_MIN); int loaded = MapUtil.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), Magic.CHUNK_LOAD_MARGIN_MIN);
if (loaded > 0 && data.debug) { if (loaded > 0 && pData.isDebugActive(CheckType.MOVING)) {
StaticLog.logInfo("Player " + tag + ": Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName()); StaticLog.logInfo("Player " + tag + ": Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
} }
} }
@ -537,7 +539,8 @@ public class MovingUtil {
* @return * @return
*/ */
public static boolean hasScheduledPlayerSetBack(final Player player) { public static boolean hasScheduledPlayerSetBack(final Player player) {
return hasScheduledPlayerSetBack(player.getUniqueId(), MovingData.getData(player)); return hasScheduledPlayerSetBack(player.getUniqueId(),
DataManager.getGenericInstance(player, MovingData.class));
} }
/** /**
@ -548,8 +551,12 @@ public class MovingUtil {
* @return * @return
*/ */
public static boolean hasScheduledPlayerSetBack(final UUID playerId, final MovingData data) { public static boolean hasScheduledPlayerSetBack(final UUID playerId, final MovingData data) {
final PlayerData pd = DataManager.getPlayerData(playerId); return data.hasTeleported() && isPlayersetBackScheduled(playerId);
return pd != null && data.hasTeleported() && pd.isPlayerSetBackScheduled(); }
private static boolean isPlayersetBackScheduled(final UUID playerId) {
final IPlayerData pd = DataManager.getPlayerData(playerId);
return pd != null && pd.isPlayerSetBackScheduled();
} }
/** /**
@ -558,10 +565,12 @@ public class MovingUtil {
* @param debugMessagePrefix * @param debugMessagePrefix
* @return True, if the teleport has been successful. * @return True, if the teleport has been successful.
*/ */
public static boolean processStoredSetBack(final Player player, final String debugMessagePrefix) { public static boolean processStoredSetBack(final Player player,
final MovingData data = MovingData.getData(player); final String debugMessagePrefix, final IPlayerData pData) {
final MovingData data = pData.getGenericInstance(MovingData.class);
final boolean debug = pData.isDebugActive(CheckType.MOVING);
if (!data.hasTeleported()) { if (!data.hasTeleported()) {
if (data.debug) { if (debug) {
CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "No stored location available."); CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "No stored location available.");
} }
return false; return false;
@ -571,7 +580,7 @@ public class MovingUtil {
final Location loc = player.getLocation(useLoc); final Location loc = player.getLocation(useLoc);
if (data.isTeleportedPosition(loc)) { if (data.isTeleportedPosition(loc)) {
// Skip redundant teleport. // Skip redundant teleport.
if (data.debug) { if (debug) {
CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "Skip teleport, player is there, already."); CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "Skip teleport, player is there, already.");
} }
data.resetTeleported(); // Not necessary to keep. data.resetTeleported(); // Not necessary to keep.
@ -582,7 +591,7 @@ public class MovingUtil {
// (player is somewhere else.) // (player is somewhere else.)
// Post-1.9 packet level workaround. // Post-1.9 packet level workaround.
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
// TODO: Consider to skip checking for packet level, if not available (plus optimize access). // TODO: Consider to skip checking for packet level, if not available (plus optimize access).
// TODO: Consider a config flag, so this can be turned off (set back method). // TODO: Consider a config flag, so this can be turned off (set back method).
final PlayerSetBackMethod method = cc.playerSetBackMethod; final PlayerSetBackMethod method = cc.playerSetBackMethod;
@ -605,9 +614,9 @@ public class MovingUtil {
*/ */
// (CANCEL + UPDATE_FROM mean a certain teleport to the set back, still could be repeated tp.) // (CANCEL + UPDATE_FROM mean a certain teleport to the set back, still could be repeated tp.)
// TODO: Better method, full sync reference? // TODO: Better method, full sync reference?
final CountableLocation cl = ((NetData) CheckType.NET.getDataFactory().getData(player)).teleportQueue.getLastAck(); final CountableLocation cl = pData.getGenericInstance(NetData.class).teleportQueue.getLastAck();
if (data.isTeleportedPosition(cl)) { if (data.isTeleportedPosition(cl)) {
if (data.debug) { if (debug) {
CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "Skip teleport, having received an ACK for the teleport on packet level. Player is at: " + LocUtil.simpleFormat(loc)); CheckUtils.debug(player, CheckType.MOVING, debugMessagePrefix + "Skip teleport, having received an ACK for the teleport on packet level. Player is at: " + LocUtil.simpleFormat(loc));
} }
// Keep teleported in data. Subject to debug logs and/or discussion. // Keep teleported in data. Subject to debug logs and/or discussion.
@ -623,7 +632,7 @@ public class MovingUtil {
return true; return true;
} }
else { else {
if (data .debug) { if (debug) {
CheckUtils.debug(player, CheckType.MOVING, "Player set back on tick: Teleport failed."); CheckUtils.debug(player, CheckType.MOVING, "Player set back on tick: Teleport failed.");
} }
return false; return false;

View File

@ -57,13 +57,14 @@ import fr.neatmonster.nocheatplus.components.registry.event.IHandle;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.logging.Streams; import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.players.DataManager; import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils; import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.entity.PassengerUtil; import fr.neatmonster.nocheatplus.utilities.entity.PassengerUtil;
import fr.neatmonster.nocheatplus.utilities.location.LocUtil; import fr.neatmonster.nocheatplus.utilities.location.LocUtil;
import fr.neatmonster.nocheatplus.utilities.location.RichBoundsLocation; import fr.neatmonster.nocheatplus.utilities.location.RichBoundsLocation;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties; import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.worlds.IWorldDataManager;
/** /**
* Aggregate vehicle checks (moving, a player is somewhere above in the * Aggregate vehicle checks (moving, a player is somewhere above in the
@ -85,6 +86,8 @@ public class VehicleChecks extends CheckListener {
/** The instance of NoCheatPlus. */ /** The instance of NoCheatPlus. */
private final Plugin plugin = Bukkit.getPluginManager().getPlugin("NoCheatPlus"); // TODO private final Plugin plugin = Bukkit.getPluginManager().getPlugin("NoCheatPlus"); // TODO
private final IWorldDataManager worldDataManager = NCPAPIProvider.getNoCheatPlusAPI().getWorldDataManager();
private final Set<EntityType> normalVehicles = new HashSet<EntityType>(); private final Set<EntityType> normalVehicles = new HashSet<EntityType>();
/** Temporary use, reset world to null afterwards, avoid nesting. */ /** Temporary use, reset world to null afterwards, avoid nesting. */
@ -146,10 +149,11 @@ public class VehicleChecks extends CheckListener {
return; return;
} }
final EntityType vehicleType = vehicle.getType(); final EntityType vehicleType = vehicle.getType();
final MovingData data = MovingData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final MovingData data = pData.getGenericInstance(MovingData.class);
final Location from = event.getFrom(); final Location from = event.getFrom();
final Location to = event.getTo(); final Location to = event.getTo();
if (data.debug) { if (pData.isDebugActive(checkType)) {
outputDebugVehicleMoveEvent(player, from, to); outputDebugVehicleMoveEvent(player, from, to);
} }
if (from == null) { if (from == null) {
@ -178,11 +182,14 @@ public class VehicleChecks extends CheckListener {
// TODO: Ignore or continue? // TODO: Ignore or continue?
} }
// Process as move. // Process as move.
debug(player, "VehicleMoveEvent: legacy handling, potential issue."); final boolean debug = pData.isDebugActive(checkType);
if (debug) {
debug(player, "VehicleMoveEvent: legacy handling, potential issue.");
}
// TODO: Actually here consistency with past position tracking should be tested. // TODO: Actually here consistency with past position tracking should be tested.
// TODO: Abstraction creation before calling checkVehicleMove, compare/align with onVehicleUpdate. // TODO: Abstraction creation before calling checkVehicleMove, compare/align with onVehicleUpdate.
checkVehicleMove(vehicle, vehicleType, from, to, player, false, data); checkVehicleMove(vehicle, vehicleType, from, to, player, false, data, pData, debug);
} }
private void outputDebugVehicleMoveEvent(final Player player, final Location from, final Location to) { private void outputDebugVehicleMoveEvent(final Player player, final Location from, final Location to) {
@ -201,12 +208,14 @@ public class VehicleChecks extends CheckListener {
* @param to * @param to
* @param data * @param data
*/ */
public Location onPlayerMoveVehicle(final Player player, final Location from, final Location to, final MovingData data) { public Location onPlayerMoveVehicle(final Player player,
final Location from, final Location to,
final MovingData data, final IPlayerData pData) {
// Workaround for pigs and other (1.5.x and before)! // Workaround for pigs and other (1.5.x and before)!
// Note that with 1.6 not even PlayerMove fires for horses and pigs. // Note that with 1.6 not even PlayerMove fires for horses and pigs.
// (isInsideVehicle is the faster check without object creation, do re-check though, if it changes to only check for Vehicle instances.) // (isInsideVehicle is the faster check without object creation, do re-check though, if it changes to only check for Vehicle instances.)
final Entity vehicle = passengerUtil.getLastNonPlayerVehicle(player); final Entity vehicle = passengerUtil.getLastNonPlayerVehicle(player);
if (data.debug) { if (pData.isDebugActive(checkType)) {
debug(player, "onPlayerMoveVehicle: vehicle: " + vehicle); debug(player, "onPlayerMoveVehicle: vehicle: " + vehicle);
} }
data.wasInVehicle = true; data.wasInVehicle = true;
@ -225,14 +234,15 @@ public class VehicleChecks extends CheckListener {
final EntityType vehicleType = vehicle.getType(); final EntityType vehicleType = vehicle.getType();
if (!normalVehicles.contains(vehicleType)) { if (!normalVehicles.contains(vehicleType)) {
// Treat like VehicleUpdateEvent. // Treat like VehicleUpdateEvent.
onVehicleUpdate(vehicle, vehicleType, player, true, data); onVehicleUpdate(vehicle, vehicleType, player, true,
data, pData, pData.isDebugActive(checkType));
return null; return null;
} }
else { else {
final Location vLoc = vehicle.getLocation(); final Location vLoc = vehicle.getLocation();
data.vehicleConsistency = MoveConsistency.getConsistency(from, to, vLoc); data.vehicleConsistency = MoveConsistency.getConsistency(from, to, vLoc);
// TODO: Consider TeleportUtil.forceMount or similar. // TODO: Consider TeleportUtil.forceMount or similar.
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
if (data.vehicleConsistency == MoveConsistency.INCONSISTENT) { if (data.vehicleConsistency == MoveConsistency.INCONSISTENT) {
if (cc.vehicleEnforceLocation) { if (cc.vehicleEnforceLocation) {
// checks.moving.vehicle.enforcelocation // checks.moving.vehicle.enforcelocation
@ -258,7 +268,7 @@ public class VehicleChecks extends CheckListener {
* @param event * @param event
*/ */
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void b(final VehicleUpdateEvent event) { public void onVehicleUpdate(final VehicleUpdateEvent event) {
// TODO: VehicleUpdateEvent. How to track teleporting of the vehicle? // TODO: VehicleUpdateEvent. How to track teleporting of the vehicle?
// TODO: Track just left vehicle/entity positions otherwise (on tick + vehicle update)? // TODO: Track just left vehicle/entity positions otherwise (on tick + vehicle update)?
// TODO: No problem: (?) update 'authorized state' if no player passenger. // TODO: No problem: (?) update 'authorized state' if no player passenger.
@ -267,7 +277,7 @@ public class VehicleChecks extends CheckListener {
if (!normalVehicles.contains(vehicleType)) { if (!normalVehicles.contains(vehicleType)) {
// A little extra sweep to check for debug flags. // A little extra sweep to check for debug flags.
normalVehicles.add(vehicleType); normalVehicles.add(vehicleType);
if (MovingConfig.getConfig(vehicle.getWorld().getName()).debug) { if (worldDataManager.getWorldData(vehicle.getWorld()).isDebugActive(checkType)) {
debug(null, "VehicleUpdateEvent fired for: " + vehicleType); debug(null, "VehicleUpdateEvent fired for: " + vehicleType);
} }
} }
@ -285,14 +295,16 @@ public class VehicleChecks extends CheckListener {
onPlayerVehicleLeave(player, vehicle); onPlayerVehicleLeave(player, vehicle);
return; return;
} }
final MovingData data = MovingData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final MovingData data = pData.getGenericInstance(MovingData.class);
//final MovingConfig cc = MovingConfig.getConfig(player); //final MovingConfig cc = MovingConfig.getConfig(player);
if (data.debug) { final boolean debug = pData.isDebugActive(checkType);
if (debug) {
final Location loc = vehicle.getLocation(useLoc1); final Location loc = vehicle.getLocation(useLoc1);
debug(player, "VehicleUpdateEvent: " + vehicleType + " " + loc); debug(player, "VehicleUpdateEvent: " + vehicleType + " " + loc);
useLoc1.setWorld(null); useLoc1.setWorld(null);
} }
onVehicleUpdate(vehicle, vehicleType, player, false, data); onVehicleUpdate(vehicle, vehicleType, player, false, data, pData, debug);
} }
/** /**
@ -309,19 +321,20 @@ public class VehicleChecks extends CheckListener {
* @param fake * @param fake
* True, if this is the real VehicleUpdateEvent, false if it's * True, if this is the real VehicleUpdateEvent, false if it's
* the PlayerMoveEvent (or other). * the PlayerMoveEvent (or other).
* @param pData
*/ */
private void onVehicleUpdate(final Entity vehicle, final EntityType vehicleType, final Player player, final boolean fake, private void onVehicleUpdate(final Entity vehicle, final EntityType vehicleType, final Player player, final boolean fake,
final MovingData data) { final MovingData data, final IPlayerData pData, final boolean debug) {
// TODO: (private or public?) // TODO: (private or public?)
// TODO: Might pass last position for reference. // TODO: Might pass last position for reference.
if (data.debug) { if (debug) {
if (lastPosLook != null) { if (lastPosLook != null) {
// Retrieve last pos. // Retrieve last pos.
lastPosLook.getHandle().getPositionAndLook(vehicle, usePos1); lastPosLook.getHandle().getPositionAndLook(vehicle, usePos1);
debug(player, "Last position is reported as: " + LocUtil.simpleFormat(usePos1)); debug(player, "Last position is reported as: " + LocUtil.simpleFormat(usePos1));
} }
} }
checkVehicleMove(vehicle, vehicleType, null, null, player, true, data); checkVehicleMove(vehicle, vehicleType, null, null, player, true, data, pData, debug);
} }
/** /**
@ -337,13 +350,14 @@ public class VehicleChecks extends CheckListener {
* @param player * @param player
* @param fake * @param fake
* @param data * @param data
* @param pData2
* @param debug
*/ */
private void checkVehicleMove(final Entity vehicle, final EntityType vehicleType, private void checkVehicleMove(final Entity vehicle, final EntityType vehicleType,
final Location from, final Location to, final Player player, final boolean fake, final Location from, final Location to, final Player player, final boolean fake,
final MovingData data) { final MovingData data, final IPlayerData pData, boolean debug) {
// TODO: Detect teleportation and similar. // TODO: Detect teleportation and similar.
final PlayerData pData = DataManager.getPlayerData(player); final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
final MovingConfig cc = MovingConfig.getConfig(player);
// Exclude certain vehicle types. // Exclude certain vehicle types.
if (cc.ignoredVehicles.contains(vehicleType)) { if (cc.ignoredVehicles.contains(vehicleType)) {
// 100% legit. // 100% legit.
@ -360,9 +374,9 @@ public class VehicleChecks extends CheckListener {
// Determine the best location to use as past move. // Determine the best location to use as past move.
// TODO: Could also check the set backs for plausible entries, however that would lead to a violation by default. Could use an indicator. // TODO: Could also check the set backs for plausible entries, however that would lead to a violation by default. Could use an indicator.
final Location refLoc = from == null ? vehicleLocation : from; final Location refLoc = from == null ? vehicleLocation : from;
MovingUtil.ensureChunksLoaded(player, refLoc, "vehicle move (no past move)", data, cc); MovingUtil.ensureChunksLoaded(player, refLoc, "vehicle move (no past move)", data, cc, pData);
aux.resetVehiclePositions(vehicle, refLoc, data, cc); aux.resetVehiclePositions(vehicle, refLoc, data, cc);
if (data.debug) { if (pData.isDebugActive(checkType)) {
// TODO: Might warn instead. // TODO: Might warn instead.
debug(player, "Missing past move data, set to: " + firstPastMove.from); debug(player, "Missing past move data, set to: " + firstPastMove.from);
} }
@ -391,12 +405,13 @@ public class VehicleChecks extends CheckListener {
recoverVehicleSetBack(player, vehicle, vehicleLocation, moveInfo, data, cc); recoverVehicleSetBack(player, vehicle, vehicleLocation, moveInfo, data, cc);
} }
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.STATUS, CheckUtils.getLogMessagePrefix(player, CheckType.MOVING_VEHICLE) + "Illegal coordinates on checkVehicleMove: from: " + from + " , to: " + to); NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.STATUS, CheckUtils.getLogMessagePrefix(player, CheckType.MOVING_VEHICLE) + "Illegal coordinates on checkVehicleMove: from: " + from + " , to: " + to);
setBack(player, vehicle, newTo, data, cc); setBack(player, vehicle, newTo, data, cc, pData);
aux.returnVehicleMoveInfo(moveInfo); aux.returnVehicleMoveInfo(moveInfo);
return; return;
} }
// Ensure chunks are loaded. // Ensure chunks are loaded.
MovingUtil.ensureChunksLoaded(player, useFrom, useTo, firstPastMove, "vehicle move", data, cc); MovingUtil.ensureChunksLoaded(player, useFrom, useTo, firstPastMove,
"vehicle move", cc, pData);
// Initialize currentMove. // Initialize currentMove.
final VehicleMoveData thisMove = data.vehicleMoves.getCurrentMove(); final VehicleMoveData thisMove = data.vehicleMoves.getCurrentMove();
thisMove.set(moveInfo.from, moveInfo.to); thisMove.set(moveInfo.from, moveInfo.to);
@ -480,8 +495,9 @@ public class VehicleChecks extends CheckListener {
final Location vehicleLocation, final World world, final Location vehicleLocation, final World world,
final VehicleMoveInfo moveInfo, final VehicleMoveData thisMove, final VehicleMoveData firstPastMove, final VehicleMoveInfo moveInfo, final VehicleMoveData thisMove, final VehicleMoveData firstPastMove,
final Player player, final boolean fake, final Player player, final boolean fake,
final MovingData data, final MovingConfig cc, final PlayerData pData) { final MovingData data, final MovingConfig cc, final IPlayerData pData) {
// TODO: (private or public?) // TODO: (private or public?)
final boolean debug = pData.isDebugActive(checkType);
data.joinOrRespawn = false; data.joinOrRespawn = false;
data.vehicleConsistency = MoveConsistency.getConsistency(thisMove, player.getLocation(useLoc1)); data.vehicleConsistency = MoveConsistency.getConsistency(thisMove, player.getLocation(useLoc1));
@ -506,7 +522,7 @@ public class VehicleChecks extends CheckListener {
data.clearNoFallData(); data.clearNoFallData();
} }
if (data.debug) { if (debug) {
// Log move. // Log move.
outputDebugVehicleMove(player, vehicle, thisMove, fake); outputDebugVehicleMove(player, vehicle, thisMove, fake);
} }
@ -515,19 +531,19 @@ public class VehicleChecks extends CheckListener {
// Ensure a common set back for now. // Ensure a common set back for now.
if (!data.vehicleSetBacks.isDefaultEntryValid()) { if (!data.vehicleSetBacks.isDefaultEntryValid()) {
ensureSetBack(player, thisMove, data); ensureSetBack(player, thisMove, data, pData);
} }
// Moving envelope check(s). // Moving envelope check(s).
// TODO: Use set back storage for testing if this is appropriate (use SetBackEntry instead, remove Location retrieval then?). // TODO: Use set back storage for testing if this is appropriate (use SetBackEntry instead, remove Location retrieval then?).
if ((newTo == null || data.vehicleSetBacks.getSafeMediumEntry().isValidAndOlderThan(newTo)) if ((newTo == null || data.vehicleSetBacks.getSafeMediumEntry().isValidAndOlderThan(newTo))
&& vehicleEnvelope.isEnabled(player, cc, pData)) { && pData.isCheckActive(CheckType.MOVING_VEHICLE_ENVELOPE, player)) {
// Skip if this is the first move after set back, with to=set back. // Skip if this is the first move after set back, with to=set back.
if (data.timeSinceSetBack == 0 || thisMove.to.hashCode() == data.lastSetBackHash) { if (data.timeSinceSetBack == 0 || thisMove.to.hashCode() == data.lastSetBackHash) {
// TODO: This is a hot fix, to prevent a set back loop. Depends on having only the morepackets set back for vehicles. // TODO: This is a hot fix, to prevent a set back loop. Depends on having only the morepackets set back for vehicles.
// TODO: Perhaps might want to add || !data.equalsAnyVehicleSetBack(to) // TODO: Perhaps might want to add || !data.equalsAnyVehicleSetBack(to)
thisMove.specialCondition = true; thisMove.specialCondition = true;
if (data.debug) { if (debug) {
debug(player, "Skip envelope check on first move after set back acknowledging the set back with an odd starting point (from)."); debug(player, "Skip envelope check on first move after set back acknowledging the set back with an odd starting point (from).");
} }
} }
@ -535,7 +551,8 @@ public class VehicleChecks extends CheckListener {
// Set up basic details about what/how to check. // Set up basic details about what/how to check.
vehicleEnvelope.prepareCheckDetails(vehicle, moveInfo, thisMove); vehicleEnvelope.prepareCheckDetails(vehicle, moveInfo, thisMove);
// Check. // Check.
final SetBackEntry tempNewTo = vehicleEnvelope.check(player, vehicle, thisMove, fake, data, cc); final SetBackEntry tempNewTo = vehicleEnvelope.check(player, vehicle,
thisMove, fake, data, cc, pData);
if (tempNewTo != null) { if (tempNewTo != null) {
newTo = tempNewTo; newTo = tempNewTo;
} }
@ -545,8 +562,9 @@ public class VehicleChecks extends CheckListener {
// More packets: Sort this in last, to avoid setting the set back early. Always check to adjust set back, for now. // More packets: Sort this in last, to avoid setting the set back early. Always check to adjust set back, for now.
// TODO: Still always update the frequency part? // TODO: Still always update the frequency part?
if ((newTo == null || data.vehicleSetBacks.getMidTermEntry().isValidAndOlderThan(newTo))) { if ((newTo == null || data.vehicleSetBacks.getMidTermEntry().isValidAndOlderThan(newTo))) {
if (vehicleMorePackets.isEnabled(player, cc, pData)) { if (pData.isCheckActive(CheckType.MOVING_VEHICLE_MOREPACKETS, player)) {
final SetBackEntry tempNewTo = vehicleMorePackets.check(player, thisMove, newTo, data, cc); final SetBackEntry tempNewTo = vehicleMorePackets.check(player, thisMove, newTo,
data, cc, pData);
if (tempNewTo != null) { if (tempNewTo != null) {
newTo = tempNewTo; newTo = tempNewTo;
} }
@ -571,7 +589,7 @@ public class VehicleChecks extends CheckListener {
data.vehicleMoves.finishCurrentMove(); data.vehicleMoves.finishCurrentMove();
} }
else { else {
setBack(player, vehicle, newTo, data, cc); setBack(player, vehicle, newTo, data, cc, pData);
} }
useLoc1.setWorld(null); useLoc1.setWorld(null);
} }
@ -581,7 +599,7 @@ public class VehicleChecks extends CheckListener {
for (final Entity passenger : passengers) { for (final Entity passenger : passengers) {
if ((passenger instanceof Player) && !player.equals(passenger)) { if ((passenger instanceof Player) && !player.equals(passenger)) {
final Player otherPlayer = (Player) passenger; final Player otherPlayer = (Player) passenger;
final MovingData otherData = MovingData.getData(otherPlayer); final MovingData otherData = DataManager.getGenericInstance(otherPlayer, MovingData.class);
otherData.resetVehiclePositions(moveInfo.to); otherData.resetVehiclePositions(moveInfo.to);
// TODO: Reset all precisely to what there is or this or what not. // TODO: Reset all precisely to what there is or this or what not.
otherData.vehicleSetBacks.resetAllLazily(data.vehicleSetBacks.getOldestValidEntry()); otherData.vehicleSetBacks.resetAllLazily(data.vehicleSetBacks.getOldestValidEntry());
@ -599,7 +617,8 @@ public class VehicleChecks extends CheckListener {
* @param thisMove * @param thisMove
* @param data * @param data
*/ */
private void ensureSetBack(final Player player, final VehicleMoveData thisMove, final MovingData data) { private void ensureSetBack(final Player player, final VehicleMoveData thisMove,
final MovingData data, final IPlayerData pData) {
final IGetLocationWithLook ensureLoc; final IGetLocationWithLook ensureLoc;
if (!data.vehicleSetBacks.isAnyEntryValid()) { if (!data.vehicleSetBacks.isAnyEntryValid()) {
ensureLoc = thisMove.from; ensureLoc = thisMove.from;
@ -608,20 +627,23 @@ public class VehicleChecks extends CheckListener {
ensureLoc = data.vehicleSetBacks.getOldestValidEntry(); ensureLoc = data.vehicleSetBacks.getOldestValidEntry();
} }
data.vehicleSetBacks.setDefaultEntry(ensureLoc); data.vehicleSetBacks.setDefaultEntry(ensureLoc);
if (data.debug) { if (pData.isDebugActive(checkType)) {
debug(player, "Ensure vehicle set back: " + ensureLoc); debug(player, "Ensure vehicle set back: " + ensureLoc);
} }
// if (data.vehicleSetBackTaskId != -1) { // if (data.vehicleSetBackTaskId != -1) {
// // TODO: This is likely the wrong thing to do! // // TODO: This is likely the wrong thing to do!
// Bukkit.getScheduler().cancelTask(data.vehicleSetBackTaskId); // Bukkit.getScheduler().cancelTask(data.vehicleSetBackTaskId);
// data.vehicleSetBackTaskId = -1; // data.vehicleSetBackTaskId = -1;
// if (data.debug) { // if (debug) {
// debug(player, "Cancel set back task on ensureSetBack."); // debug(player, "Cancel set back task on ensureSetBack.");
// } // }
// } // }
} }
private void setBack(final Player player, final Entity vehicle, final SetBackEntry newTo, final MovingData data, final MovingConfig cc) { private void setBack(final Player player, final Entity vehicle,
final SetBackEntry newTo, final MovingData data,
final MovingConfig cc, final IPlayerData pData) {
final boolean debug = pData.isDebugActive(checkType);
// TODO: Generic set back manager, preventing all sorts of stuff that might be attempted or just happen before the task is running? // TODO: Generic set back manager, preventing all sorts of stuff that might be attempted or just happen before the task is running?
if (data.vehicleSetBackTaskId == -1) { if (data.vehicleSetBackTaskId == -1) {
// Schedule a delayed task to teleport back the vehicle with the player. // Schedule a delayed task to teleport back the vehicle with the player.
@ -632,20 +654,20 @@ public class VehicleChecks extends CheckListener {
// TODO: Prevent vehicle data resetting due to dismount/mount/teleport. // TODO: Prevent vehicle data resetting due to dismount/mount/teleport.
// TODO: Force fall type of set back? // TODO: Force fall type of set back?
// (Future: Dismount penalty does not need extra handling, both are teleported anyway.) // (Future: Dismount penalty does not need extra handling, both are teleported anyway.)
if (data.debug) { if (debug) {
debug(player, "Will set back to: " + newTo); debug(player, "Will set back to: " + newTo);
} }
boolean scheduleSetBack = cc.scheduleVehicleSetBacks; boolean scheduleSetBack = cc.scheduleVehicleSetBacks;
// Schedule as task, if set so. // Schedule as task, if set so.
if (scheduleSetBack) { if (scheduleSetBack) {
aux.resetVehiclePositions(vehicle, LocUtil.set(useLoc2, vehicle.getWorld(), newTo), data, cc); // Heavy-ish, though. aux.resetVehiclePositions(vehicle, LocUtil.set(useLoc2, vehicle.getWorld(), newTo), data, cc); // Heavy-ish, though.
data.vehicleSetBackTaskId = Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new VehicleSetBackTask(vehicle, player, newTo.getLocation(vehicle.getWorld()), data.debug)); data.vehicleSetBackTaskId = Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new VehicleSetBackTask(vehicle, player, newTo.getLocation(vehicle.getWorld()), debug));
if (data.vehicleSetBackTaskId == -1) { if (data.vehicleSetBackTaskId == -1) {
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.STATUS, "Failed to schedule vehicle set back task. Player: " + player.getName() + " , set back: " + newTo); NCPAPIProvider.getNoCheatPlusAPI().getLogManager().warning(Streams.STATUS, "Failed to schedule vehicle set back task. Player: " + player.getName() + " , set back: " + newTo);
scheduleSetBack = false; // Force direct teleport as a fall-back measure. scheduleSetBack = false; // Force direct teleport as a fall-back measure.
} }
else if (data.debug) { else if (debug) {
debug(player, "Vehicle set back task id: " + data.vehicleSetBackTaskId); debug(player, "Vehicle set back task id: " + data.vehicleSetBackTaskId);
} }
} }
@ -658,14 +680,15 @@ public class VehicleChecks extends CheckListener {
* resetting and updating the set back (if needed) is done there * resetting and updating the set back (if needed) is done there
* (hack, subject to current review). * (hack, subject to current review).
*/ */
if (data.debug) { if (debug) {
debug(player, "Attempt to set the player back directly."); debug(player, "Attempt to set the player back directly.");
} }
passengerUtil.teleportWithPassengers(vehicle, player, newTo.getLocation(vehicle.getWorld()), data.debug); passengerUtil.teleportWithPassengers(vehicle, player,
newTo.getLocation(vehicle.getWorld()), debug, pData);
} }
} }
else if (data.debug) { else if (debug) {
// TODO: Reset positions. // TODO: Reset positions.
data.vehicleMoves.invalidate(); data.vehicleMoves.invalidate();
debug(player, "Vehicle set back task already scheduled, skip this time."); debug(player, "Vehicle set back task already scheduled, skip this time.");
@ -692,21 +715,23 @@ public class VehicleChecks extends CheckListener {
* @return True, if an event is to be cancelled. * @return True, if an event is to be cancelled.
*/ */
public boolean onPlayerVehicleEnter(final Player player, final Entity vehicle) { public boolean onPlayerVehicleEnter(final Player player, final Entity vehicle) {
final MovingData data = MovingData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final boolean debug = pData.isDebugActive(checkType);
final MovingData data = pData.getGenericInstance(MovingData.class);
if (!data.isVehicleSetBack && MovingUtil.hasScheduledPlayerSetBack(player.getUniqueId(), data)) { if (!data.isVehicleSetBack && MovingUtil.hasScheduledPlayerSetBack(player.getUniqueId(), data)) {
if (data.debug) { if (debug) {
debug(player, "Vehicle enter: prevent, due to a scheduled set back."); debug(player, "Vehicle enter: prevent, due to a scheduled set back.");
} }
return true; return true;
} }
if (data.debug) { if (debug) {
debug(player, "Vehicle enter: first vehicle: " + vehicle.getClass().getName()); debug(player, "Vehicle enter: first vehicle: " + vehicle.getClass().getName());
} }
// Check for nested vehicles. // Check for nested vehicles.
final Entity lastVehicle = passengerUtil.getLastNonPlayerVehicle(vehicle, true); final Entity lastVehicle = passengerUtil.getLastNonPlayerVehicle(vehicle, true);
if (lastVehicle == null) { if (lastVehicle == null) {
data.clearVehicleData(); data.clearVehicleData();
if (data.debug) { if (debug) {
debugNestedVehicleEnter(player); debugNestedVehicleEnter(player);
} }
return false; return false;
@ -714,14 +739,14 @@ public class VehicleChecks extends CheckListener {
else if (!lastVehicle.equals(vehicle)) { else if (!lastVehicle.equals(vehicle)) {
// Nested vehicles. // Nested vehicles.
// TODO: Should in general skip checking these? Set backs don't yet work with these anyway (either... or ...). // TODO: Should in general skip checking these? Set backs don't yet work with these anyway (either... or ...).
if (data.debug) { if (debug) {
debug(player, "Vehicle enter: last of nested vehicles: " + lastVehicle.getClass().getName()); debug(player, "Vehicle enter: last of nested vehicles: " + lastVehicle.getClass().getName());
} }
dataOnVehicleEnter(player, lastVehicle, data); dataOnVehicleEnter(player, lastVehicle, data, pData);
} }
else { else {
// Proceed normally. // Proceed normally.
dataOnVehicleEnter(player, vehicle, data); dataOnVehicleEnter(player, vehicle, data, pData);
} }
return false; return false;
} }
@ -745,9 +770,10 @@ public class VehicleChecks extends CheckListener {
* @param player * @param player
* @param vehicle * @param vehicle
*/ */
private void dataOnVehicleEnter(final Player player, final Entity vehicle, final MovingData data) { private void dataOnVehicleEnter(final Player player, final Entity vehicle,
final MovingData data, final IPlayerData pData) {
// Adjust data. // Adjust data.
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
data.joinOrRespawn = false; data.joinOrRespawn = false;
data.removeAllVelocity(); data.removeAllVelocity();
// Event should have a vehicle, in case check this last. // Event should have a vehicle, in case check this last.
@ -764,7 +790,7 @@ public class VehicleChecks extends CheckListener {
data.vehicleSetBacks.resetAll(vLoc); data.vehicleSetBacks.resetAll(vLoc);
} }
aux.resetVehiclePositions(vehicle, vLoc, data, cc); aux.resetVehiclePositions(vehicle, vLoc, data, cc);
if (data.debug) { if (pData.isDebugActive(checkType)) {
debug(player, "Vehicle enter: " + vehicle.getType() + " , player: " + useLoc2 + " c=" + data.vehicleConsistency); debug(player, "Vehicle enter: " + vehicle.getType() + " , player: " + useLoc2 + " c=" + data.vehicleConsistency);
} }
useLoc1.setWorld(null); useLoc1.setWorld(null);
@ -778,8 +804,9 @@ public class VehicleChecks extends CheckListener {
* @param data * @param data
* @param cc * @param cc
*/ */
public void onVehicleLeaveMiss(final Player player, final MovingData data, final MovingConfig cc) { public void onVehicleLeaveMiss(final Player player,
if (data.debug) { final MovingData data, final MovingConfig cc, final IPlayerData pData) {
if (pData.isDebugActive(checkType)) {
StaticLog.logWarning("VehicleExitEvent missing for: " + player.getName()); StaticLog.logWarning("VehicleExitEvent missing for: " + player.getName());
} }
onPlayerVehicleLeave(player, null); onPlayerVehicleLeave(player, null);
@ -808,11 +835,11 @@ public class VehicleChecks extends CheckListener {
final Entity attacker = event.getAttacker(); final Entity attacker = event.getAttacker();
if (attacker instanceof Player && passengerUtil.isPassenger(attacker, event.getVehicle())) { if (attacker instanceof Player && passengerUtil.isPassenger(attacker, event.getVehicle())) {
final Player player = (Player) attacker; final Player player = (Player) attacker;
final MovingConfig cc = MovingConfig.getConfig(player); final IPlayerData pData = DataManager.getPlayerData(player);
final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
if (cc.vehiclePreventDestroyOwn) { if (cc.vehiclePreventDestroyOwn) {
final PlayerData pData = DataManager.getPlayerData(player); if (pData.isCheckActive(CheckType.MOVING_SURVIVALFLY, player)
if (CheckUtils.isEnabled(CheckType.MOVING_SURVIVALFLY, player, cc, pData) || pData.isCheckActive(CheckType.MOVING_CREATIVEFLY, player)) {
|| CheckUtils.isEnabled(CheckType.MOVING_CREATIVEFLY, player, cc, pData)) {
} }
event.setCancelled(true); event.setCancelled(true);
// TODO: This message must be configurable. // TODO: This message must be configurable.
@ -836,7 +863,9 @@ public class VehicleChecks extends CheckListener {
* @param vehicle May be null in case of "not possible to determine". * @param vehicle May be null in case of "not possible to determine".
*/ */
private void onPlayerVehicleLeave(final Player player, final Entity vehicle) { private void onPlayerVehicleLeave(final Player player, final Entity vehicle) {
final MovingData data = MovingData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final MovingData data = pData.getGenericInstance(MovingData.class);
final boolean debug = pData.isDebugActive(checkType);
data.wasInVehicle = false; data.wasInVehicle = false;
data.joinOrRespawn = false; data.joinOrRespawn = false;
// if (data.vehicleSetBackTaskId != -1) { // if (data.vehicleSetBackTaskId != -1) {
@ -845,7 +874,7 @@ public class VehicleChecks extends CheckListener {
// return; // return;
// } // }
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = pData.getGenericInstance(MovingConfig.class);
// TODO: Loc can be inconsistent, determine which to use ! // TODO: Loc can be inconsistent, determine which to use !
final Location pLoc = player.getLocation(useLoc1); final Location pLoc = player.getLocation(useLoc1);
Location loc = pLoc; // The location to use as set back. Location loc = pLoc; // The location to use as set back.
@ -875,7 +904,7 @@ public class VehicleChecks extends CheckListener {
} }
} }
} }
if (data.debug) { if (debug) {
debug(player, "Vehicle leave: " + vehicle.getType() + "@" + pLoc.distance(vLoc)); debug(player, "Vehicle leave: " + vehicle.getType() + "@" + pLoc.distance(vLoc));
} }
} }
@ -885,7 +914,7 @@ public class VehicleChecks extends CheckListener {
loc.setY(Location.locToBlock(loc.getY()) + 1.25); loc.setY(Location.locToBlock(loc.getY()) + 1.25);
} }
if (data.debug) { if (debug) {
debug(player, "Vehicle leave: " + pLoc.toString() + (pLoc.equals(loc) ? "" : " / player at: " + pLoc.toString())); debug(player, "Vehicle leave: " + pLoc.toString() + (pLoc.equals(loc) ? "" : " / player at: " + pLoc.toString()));
} }
aux.resetPositionsAndMediumProperties(player, loc, data, cc); aux.resetPositionsAndMediumProperties(player, loc, data, cc);

View File

@ -36,6 +36,7 @@ import fr.neatmonster.nocheatplus.checks.moving.model.PlayerMoveData;
import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveData; import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveData;
import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveInfo; import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveInfo;
import fr.neatmonster.nocheatplus.checks.workaround.WRPT; import fr.neatmonster.nocheatplus.checks.workaround.WRPT;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil; import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.StringUtil;
@ -103,16 +104,21 @@ public class VehicleEnvelope extends Check {
bestHorse = clazz == null ? ReflectionUtil.getClass("org.bukkit.entity.Horse") : clazz; bestHorse = clazz == null ? ReflectionUtil.getClass("org.bukkit.entity.Horse") : clazz;
} }
public SetBackEntry check(final Player player, final Entity vehicle, final VehicleMoveData thisMove, final boolean isFake, final MovingData data, final MovingConfig cc) { public SetBackEntry check(final Player player, final Entity vehicle,
final VehicleMoveData thisMove, final boolean isFake,
final MovingData data, final MovingConfig cc,
final IPlayerData pData) {
final boolean debug = pData.isDebugActive(type);
// Delegate to a sub-check. // Delegate to a sub-check.
tags.clear(); tags.clear();
tags.add("entity." + vehicle.getType()); tags.add("entity." + vehicle.getType());
if (data.debug) { if (debug) {
debugDetails.clear(); debugDetails.clear();
data.ws.setJustUsedIds(debugDetails); // Add just used workaround ids to this list directly, for now. data.ws.setJustUsedIds(debugDetails); // Add just used workaround ids to this list directly, for now.
} }
final boolean violation = checkEntity(player, vehicle, thisMove, isFake, data, cc); final boolean violation = checkEntity(player, vehicle, thisMove, isFake,
if (data.debug && !debugDetails.isEmpty()) { data, cc, debug);
if (debug && !debugDetails.isEmpty()) {
debugDetails(player); debugDetails(player);
debugDetails.clear(); debugDetails.clear();
} }
@ -157,9 +163,12 @@ public class VehicleEnvelope extends Check {
} }
} }
private boolean checkEntity(final Player player, final Entity vehicle, final VehicleMoveData thisMove, final boolean isFake, final MovingData data, final MovingConfig cc) { private boolean checkEntity(final Player player, final Entity vehicle,
final VehicleMoveData thisMove, final boolean isFake,
final MovingData data, final MovingConfig cc,
final boolean debug) {
boolean violation = false; boolean violation = false;
if (data.debug) { if (debug) {
debugDetails.add("inair: " + data.sfJumpPhase); debugDetails.add("inair: " + data.sfJumpPhase);
} }
@ -179,7 +188,7 @@ public class VehicleEnvelope extends Check {
// TODO: Get extended liquid specs (allow confine to certain flags, here: water). Contains info if water is only flowing down, surface properties (non liquid blocks?), still water. // TODO: Get extended liquid specs (allow confine to certain flags, here: water). Contains info if water is only flowing down, surface properties (non liquid blocks?), still water.
if (thisMove.from.inWeb) { if (thisMove.from.inWeb) {
// TODO: Check anything? // TODO: Check anything?
if (data.debug) { if (debug) {
debugDetails.add(""); debugDetails.add("");
} }
// if (thisMove.yDistance > 0.0) { // if (thisMove.yDistance > 0.0) {
@ -205,7 +214,7 @@ public class VehicleEnvelope extends Check {
} }
else if (thisMove.from.inWater && thisMove.to.inWater) { else if (thisMove.from.inWater && thisMove.to.inWater) {
// Default in-medium move. // Default in-medium move.
if (data.debug) { if (debug) {
debugDetails.add("water-water"); debugDetails.add("water-water");
} }
// TODO: Should still cover extreme moves here. // TODO: Should still cover extreme moves here.
@ -229,27 +238,27 @@ public class VehicleEnvelope extends Check {
} }
if (thisMove.from.onIce && thisMove.to.onIce) { if (thisMove.from.onIce && thisMove.to.onIce) {
// Default on-ice move. // Default on-ice move.
if (data.debug) { if (debug) {
debugDetails.add("ice-ice"); debugDetails.add("ice-ice");
} }
// TODO: Should still cover extreme moves here. // TODO: Should still cover extreme moves here.
} }
else { else {
// (TODO: actually a default on-ground move.) // (TODO: actually a default on-ground move.)
if (data.debug) { if (debug) {
debugDetails.add("ground-ground"); debugDetails.add("ground-ground");
} }
} }
} }
else if (checkDetails.inAir) { else if (checkDetails.inAir) {
// In-air move. // In-air move.
if (checkInAir(thisMove, data)) { if (checkInAir(thisMove, data, debug)) {
violation = true; violation = true;
} }
} }
else { else {
// Some transition to probably handle. // Some transition to probably handle.
if (data.debug) { if (debug) {
debugDetails.add("?-?"); debugDetails.add("?-?");
} }
// TODO: Lift off speed etc. // TODO: Lift off speed etc.
@ -371,11 +380,12 @@ public class VehicleEnvelope extends Check {
* @param data * @param data
* @return * @return
*/ */
private boolean checkInAir(final VehicleMoveData thisMove, final MovingData data) { private boolean checkInAir(final VehicleMoveData thisMove, final MovingData data,
final boolean debug) {
// TODO: Distinguish sfJumpPhase and inAirDescendCount (after reaching the highest point). // TODO: Distinguish sfJumpPhase and inAirDescendCount (after reaching the highest point).
if (data.debug) { if (debug) {
debugDetails.add("air-air"); debugDetails.add("air-air");
} }
@ -422,7 +432,7 @@ public class VehicleEnvelope extends Check {
violation = false; violation = false;
checkDetails.checkDescendMuch = checkDetails.checkAscendMuch = false; // (Full envelope has been checked.) checkDetails.checkDescendMuch = checkDetails.checkAscendMuch = false; // (Full envelope has been checked.)
} }
if (data.debug) { if (debug) {
debugDetails.add("maxDescend: " + maxDescend); debugDetails.add("maxDescend: " + maxDescend);
} }
} }

View File

@ -24,6 +24,7 @@ import fr.neatmonster.nocheatplus.checks.moving.MovingConfig;
import fr.neatmonster.nocheatplus.checks.moving.MovingData; import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.checks.moving.location.setback.SetBackEntry; import fr.neatmonster.nocheatplus.checks.moving.location.setback.SetBackEntry;
import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveData; import fr.neatmonster.nocheatplus.checks.moving.model.VehicleMoveData;
import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* This check does the exact same thing as the MorePacket check but this one works for players inside vehicles. * This check does the exact same thing as the MorePacket check but this one works for players inside vehicles.
@ -58,7 +59,8 @@ public class VehicleMorePackets extends Check {
* @return the location * @return the location
*/ */
public SetBackEntry check(final Player player, final VehicleMoveData thisMove, public SetBackEntry check(final Player player, final VehicleMoveData thisMove,
final SetBackEntry setBack, final MovingData data, final MovingConfig cc) { final SetBackEntry setBack, final MovingData data, final MovingConfig cc,
final IPlayerData pData) {
// Take time once, first: // Take time once, first:
final long time = System.currentTimeMillis(); final long time = System.currentTimeMillis();
final boolean allowSetSetBack = setBack == null && data.vehicleSetBackTaskId == -1; final boolean allowSetSetBack = setBack == null && data.vehicleSetBackTaskId == -1;
@ -74,6 +76,9 @@ public class VehicleMorePackets extends Check {
return data.vehicleSetBacks.getValidMidTermEntry(); return data.vehicleSetBacks.getValidMidTermEntry();
} }
final boolean debug = pData.isDebugActive(type);
// Player used up buffer, they fail the check. // Player used up buffer, they fail the check.
if (data.vehicleMorePacketsBuffer < 0) { if (data.vehicleMorePacketsBuffer < 0) {
@ -83,7 +88,7 @@ public class VehicleMorePackets extends Check {
// Execute whatever actions are associated with this check and the violation level and find out if we should // Execute whatever actions are associated with this check and the violation level and find out if we should
// cancel the event. // cancel the event.
final ViolationData vd = new ViolationData(this, player, data.vehicleMorePacketsVL, -data.vehicleMorePacketsBuffer, cc.vehicleMorePacketsActions); final ViolationData vd = new ViolationData(this, player, data.vehicleMorePacketsVL, -data.vehicleMorePacketsBuffer, cc.vehicleMorePacketsActions);
if (data.debug || vd.needsParameters()) { if (debug || vd.needsParameters()) {
vd.setParameter(ParameterName.PACKETS, Integer.toString(-data.vehicleMorePacketsBuffer)); vd.setParameter(ParameterName.PACKETS, Integer.toString(-data.vehicleMorePacketsBuffer));
} }
if (executeActions(vd).willCancel()){ if (executeActions(vd).willCancel()){
@ -114,11 +119,12 @@ public class VehicleMorePackets extends Check {
// Set the new set back location. // Set the new set back location.
if (allowSetSetBack && newTo == null) { if (allowSetSetBack && newTo == null) {
data.vehicleSetBacks.setMidTermEntry(thisMove.from); data.vehicleSetBacks.setMidTermEntry(thisMove.from);
if (data.debug) { if (debug) {
debug(player, "Update vehicle morepackets set back: " + thisMove.from); debug(player, "Update vehicle morepackets set back: " + thisMove.from);
} }
} }
} else if (data.vehicleMorePacketsLastTime > time) { }
else if (data.vehicleMorePacketsLastTime > time) {
// Security check, maybe system time changed. // Security check, maybe system time changed.
data.vehicleMorePacketsLastTime = time; data.vehicleMorePacketsLastTime = time;
} }

View File

@ -21,6 +21,8 @@ import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.NCPAPIProvider; import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.checks.moving.MovingData; import fr.neatmonster.nocheatplus.checks.moving.MovingData;
import fr.neatmonster.nocheatplus.logging.StaticLog; import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.players.DataManager;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.entity.PassengerUtil; import fr.neatmonster.nocheatplus.utilities.entity.PassengerUtil;
/** /**
@ -57,11 +59,12 @@ public class VehicleSetBackTask implements Runnable{
@Override @Override
public void run() { public void run() {
final MovingData data = MovingData.getData(player); final IPlayerData pData = DataManager.getPlayerData(player);
final MovingData data = pData.getGenericInstance(MovingData.class);
data.vehicleSetBackTaskId = -1; data.vehicleSetBackTaskId = -1;
try{ try{
NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(PassengerUtil.class).teleportWithPassengers( NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(PassengerUtil.class).teleportWithPassengers(
vehicle, player, location, debug, passengers, true); vehicle, player, location, debug, passengers, true, pData);
} }
catch(Throwable t){ catch(Throwable t){
StaticLog.logSevere(t); StaticLog.logSevere(t);

View File

@ -20,6 +20,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
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.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
public class AttackFrequency extends Check { public class AttackFrequency extends Check {
@ -28,7 +29,8 @@ public class AttackFrequency extends Check {
super(CheckType.NET_ATTACKFREQUENCY); super(CheckType.NET_ATTACKFREQUENCY);
} }
public boolean check(final Player player, final long time, final NetData data, final NetConfig cc) { public boolean check(final Player player, final long time,
final NetData data, final NetConfig cc, final IPlayerData pData) {
// Update frequency. // Update frequency.
data.attackFrequencySeconds.add(time, 1f); data.attackFrequencySeconds.add(time, 1f);
double maxVL = 0.0; double maxVL = 0.0;
@ -84,7 +86,7 @@ public class AttackFrequency extends Check {
if (maxVL > 0.0) { if (maxVL > 0.0) {
// Trigger a violation. // Trigger a violation.
final ViolationData vd = new ViolationData(this, player, maxVL, 1.0, cc.attackFrequencyActions); final ViolationData vd = new ViolationData(this, player, maxVL, 1.0, cc.attackFrequencyActions);
if (data.debug || vd.needsParameters()) { if (pData.isDebugActive(type) || vd.needsParameters()) {
vd.setParameter(ParameterName.PACKETS, Integer.toString((int) sum)); vd.setParameter(ParameterName.PACKETS, Integer.toString((int) sum));
vd.setParameter(ParameterName.LIMIT, Integer.toString((int) maxLimit)); vd.setParameter(ParameterName.LIMIT, Integer.toString((int) maxLimit));
vd.setParameter(ParameterName.TAGS, tags); vd.setParameter(ParameterName.TAGS, tags);

View File

@ -19,8 +19,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.net.model.DataPacketFlying; import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
/** /**
* Check frequency of (pos/look/) flying packets, disregarding packet content. * Check frequency of (pos/look/) flying packets, disregarding packet content.
@ -48,11 +47,10 @@ public class FlyingFrequency extends Check {
* @return * @return
*/ */
public boolean check(final Player player, final DataPacketFlying packetData, final long time, public boolean check(final Player player, final DataPacketFlying packetData, final long time,
final NetData data, final NetConfig cc, final PlayerData pData) { final NetData data, final NetConfig cc, final IPlayerData pData) {
data.flyingFrequencyAll.add(time, 1f); data.flyingFrequencyAll.add(time, 1f);
final float allScore = data.flyingFrequencyAll.score(1f); final float allScore = data.flyingFrequencyAll.score(1f);
if (allScore / cc.flyingFrequencySeconds > cc.flyingFrequencyPPS if (allScore / cc.flyingFrequencySeconds > cc.flyingFrequencyPPS
&& !CheckUtils.hasBypass(CheckType.NET_FLYINGFREQUENCY, player, pData)
&& executeActions(player, allScore / cc.flyingFrequencySeconds - cc.flyingFrequencyPPS, 1.0 / cc.flyingFrequencySeconds, cc.flyingFrequencyActions).willCancel()) { && executeActions(player, allScore / cc.flyingFrequencySeconds - cc.flyingFrequencyPPS, 1.0 / cc.flyingFrequencySeconds, cc.flyingFrequencyActions).willCancel()) {
return true; return true;
} else { } else {

View File

@ -14,11 +14,9 @@
*/ */
package fr.neatmonster.nocheatplus.checks.net; package fr.neatmonster.nocheatplus.checks.net;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying; import fr.neatmonster.nocheatplus.checks.net.model.DataPacketFlying;
import fr.neatmonster.nocheatplus.components.registry.event.IHandle; import fr.neatmonster.nocheatplus.components.registry.event.IHandle;
import fr.neatmonster.nocheatplus.players.IPlayerData;
/** /**
* Convenience for providing several checks with a lazy-init handle for fetching * Convenience for providing several checks with a lazy-init handle for fetching
@ -32,7 +30,7 @@ import fr.neatmonster.nocheatplus.components.registry.event.IHandle;
*/ */
public class FlyingQueueHandle implements IHandle<DataPacketFlying[]> { public class FlyingQueueHandle implements IHandle<DataPacketFlying[]> {
private final Player player; private final IPlayerData pData;
private DataPacketFlying[] queue; private DataPacketFlying[] queue;
/** /**
* Convenience flag for keeping track amongst multiple checks, which all get * Convenience flag for keeping track amongst multiple checks, which all get
@ -40,14 +38,15 @@ public class FlyingQueueHandle implements IHandle<DataPacketFlying[]> {
*/ */
private boolean currentLocationValid = true; private boolean currentLocationValid = true;
public FlyingQueueHandle(Player player) { public FlyingQueueHandle(IPlayerData pData) {
this.player = player; // TODO: PlayerData ?
this.pData = pData;
} }
@Override @Override
public DataPacketFlying[] getHandle() { public DataPacketFlying[] getHandle() {
if (queue == null) { if (queue == null) {
queue = ((NetData) CheckType.NET.getDataFactory().getData(player)).copyFlyingQueue(); queue = pData.getGenericInstance(NetData.class).copyFlyingQueue();
} }
return queue; return queue;
} }

View File

@ -18,8 +18,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.players.PlayerData; import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
public class KeepAliveFrequency extends Check { public class KeepAliveFrequency extends Check {
@ -36,10 +35,10 @@ public class KeepAliveFrequency extends Check {
* @return If to cancel. * @return If to cancel.
*/ */
public boolean check(final Player player, final long time, final NetData data, final NetConfig cc, public boolean check(final Player player, final long time, final NetData data, final NetConfig cc,
final PlayerData pData) { final IPlayerData pData) {
data.keepAliveFreq.add(time, 1f); data.keepAliveFreq.add(time, 1f);
final float first = data.keepAliveFreq.bucketScore(0); final float first = data.keepAliveFreq.bucketScore(0);
if (first > 1f && !CheckUtils.hasBypass(CheckType.NET_KEEPALIVEFREQUENCY, player, pData)) { if (first > 1f) {
// Trigger a violation. // Trigger a violation.
final double vl = Math.max(first - 1f, data.keepAliveFreq.score(1f) - data.keepAliveFreq.numberOfBuckets()); final double vl = Math.max(first - 1f, data.keepAliveFreq.score(1f) - data.keepAliveFreq.numberOfBuckets());
if (executeActions(player, vl, 1.0, cc.keepAliveFrequencyActions).willCancel()) { if (executeActions(player, vl, 1.0, cc.keepAliveFrequencyActions).willCancel()) {

View File

@ -17,12 +17,15 @@ package fr.neatmonster.nocheatplus.checks.net;
import fr.neatmonster.nocheatplus.actions.ActionList; import fr.neatmonster.nocheatplus.actions.ActionList;
import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.ACheckConfig; import fr.neatmonster.nocheatplus.checks.access.ACheckConfig;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion; import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.components.config.value.OverrideType;
import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfPaths;
import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.ConfigManager; import fr.neatmonster.nocheatplus.config.ConfigManager;
import fr.neatmonster.nocheatplus.permissions.Permissions; import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.permissions.RegisteredPermission; import fr.neatmonster.nocheatplus.permissions.RegisteredPermission;
import fr.neatmonster.nocheatplus.worlds.IWorldData;
/** /**
* Configuration for the net checks (fast version, sparse). * Configuration for the net checks (fast version, sparse).
@ -47,7 +50,6 @@ public class NetConfig extends ACheckConfig {
// Instance // Instance
///////////// /////////////
public final boolean attackFrequencyActive;
public final float attackFrequencyLimitSecondsHalf; public final float attackFrequencyLimitSecondsHalf;
public final float attackFrequencyLimitSecondsOne; public final float attackFrequencyLimitSecondsOne;
public final float attackFrequencyLimitSecondsTwo; public final float attackFrequencyLimitSecondsTwo;
@ -55,7 +57,6 @@ public class NetConfig extends ACheckConfig {
public final float attackFrequencyLimitSecondsEight; public final float attackFrequencyLimitSecondsEight;
public final ActionList attackFrequencyActions; public final ActionList attackFrequencyActions;
public final boolean flyingFrequencyActive;
public final int flyingFrequencySeconds; public final int flyingFrequencySeconds;
public final double flyingFrequencyPPS; public final double flyingFrequencyPPS;
public final ActionList flyingFrequencyActions; public final ActionList flyingFrequencyActions;
@ -63,27 +64,24 @@ public class NetConfig extends ACheckConfig {
public final int flyingFrequencyRedundantSeconds; public final int flyingFrequencyRedundantSeconds;
public final ActionList flyingFrequencyRedundantActions; public final ActionList flyingFrequencyRedundantActions;
public final boolean keepAliveFrequencyActive;
public final ActionList keepAliveFrequencyActions; public final ActionList keepAliveFrequencyActions;
public final boolean packetFrequencyActive;
public final float packetFrequencyPacketsPerSecond; public final float packetFrequencyPacketsPerSecond;
public final int packetFrequencySeconds; public final int packetFrequencySeconds;
public final ActionList packetFrequencyActions; public final ActionList packetFrequencyActions;
public final boolean soundDistanceActive;
/** Maximum distance for lightning effects (squared). */ /** Maximum distance for lightning effects (squared). */
public final double soundDistanceSq; public final double soundDistanceSq;
public final boolean supersededFlyingCancelWaiting; public final boolean supersededFlyingCancelWaiting;
public NetConfig(final ConfigFile config) { public NetConfig(final IWorldData worldData) {
// TODO: These permissions should have default policies. // TODO: These permissions should have default policies.
super(config, ConfPaths.NET); super(worldData);
final ConfigFile config = worldData.getRawConfiguration();
final ConfigFile globalConfig = ConfigManager.getConfigFile(); final ConfigFile globalConfig = ConfigManager.getConfigFile();
attackFrequencyActive = config.getBoolean(ConfPaths.NET_ATTACKFREQUENCY_ACTIVE);
attackFrequencyLimitSecondsHalf = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_HALF); attackFrequencyLimitSecondsHalf = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_HALF);
attackFrequencyLimitSecondsOne = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_ONE); attackFrequencyLimitSecondsOne = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_ONE);
attackFrequencyLimitSecondsTwo = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_TWO); attackFrequencyLimitSecondsTwo = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_TWO);
@ -91,7 +89,6 @@ public class NetConfig extends ACheckConfig {
attackFrequencyLimitSecondsEight = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_EIGHT); attackFrequencyLimitSecondsEight = config.getInt(ConfPaths.NET_ATTACKFREQUENCY_SECONDS_EIGHT);
attackFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_ATTACKFREQUENCY_ACTIONS, Permissions.NET_ATTACKFREQUENCY); 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)); flyingFrequencySeconds = Math.max(1, globalConfig.getInt(ConfPaths.NET_FLYINGFREQUENCY_SECONDS));
flyingFrequencyPPS = Math.max(1.0, globalConfig.getDouble(ConfPaths.NET_FLYINGFREQUENCY_PACKETSPERSECOND)); flyingFrequencyPPS = Math.max(1.0, globalConfig.getDouble(ConfPaths.NET_FLYINGFREQUENCY_PACKETSPERSECOND));
flyingFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_FLYINGFREQUENCY_ACTIONS, Permissions.NET_FLYINGFREQUENCY); flyingFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_FLYINGFREQUENCY_ACTIONS, Permissions.NET_FLYINGFREQUENCY);
@ -100,15 +97,17 @@ public class NetConfig extends ACheckConfig {
// Same permission for "silent". // Same permission for "silent".
flyingFrequencyRedundantActions = config.getOptimizedActionList(ConfPaths.NET_FLYINGFREQUENCY_REDUNDANT_ACTIONS, Permissions.NET_FLYINGFREQUENCY); flyingFrequencyRedundantActions = config.getOptimizedActionList(ConfPaths.NET_FLYINGFREQUENCY_REDUNDANT_ACTIONS, Permissions.NET_FLYINGFREQUENCY);
keepAliveFrequencyActive = config.getBoolean(ConfPaths.NET_KEEPALIVEFREQUENCY_ACTIVE);
keepAliveFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_KEEPALIVEFREQUENCY_ACTIONS, Permissions.NET_KEEPALIVEFREQUENCY); keepAliveFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_KEEPALIVEFREQUENCY_ACTIONS, Permissions.NET_KEEPALIVEFREQUENCY);
packetFrequencyActive = config.getAlmostBoolean(ConfPaths.NET_PACKETFREQUENCY_ACTIVE, ServerVersion.compareMinecraftVersion("1.9") < 0, false); if (ServerVersion.compareMinecraftVersion("1.9") >= 0) {
// TODO: Disable packet frequency or activate 'pessimistically'.
worldData.overrideCheckActivation(CheckType.NET_PACKETFREQUENCY,
AlmostBoolean.NO, OverrideType.PERMANENT, true);
}
packetFrequencyPacketsPerSecond = config.getInt(ConfPaths.NET_PACKETFREQUENCY_PPS); packetFrequencyPacketsPerSecond = config.getInt(ConfPaths.NET_PACKETFREQUENCY_PPS);
packetFrequencySeconds = config.getInt(ConfPaths.NET_PACKETFREQUENCY_SECONDS); packetFrequencySeconds = config.getInt(ConfPaths.NET_PACKETFREQUENCY_SECONDS);
packetFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_PACKETFREQUENCY_ACTIONS, Permissions.NET_PACKETFREQUENCY); packetFrequencyActions = config.getOptimizedActionList(ConfPaths.NET_PACKETFREQUENCY_ACTIONS, Permissions.NET_PACKETFREQUENCY);
soundDistanceActive = config.getBoolean(ConfPaths.NET_SOUNDDISTANCE_ACTIVE);
double dist = config.getDouble(ConfPaths.NET_SOUNDDISTANCE_MAXDISTANCE); double dist = config.getDouble(ConfPaths.NET_SOUNDDISTANCE_MAXDISTANCE);
soundDistanceSq = dist * dist; soundDistanceSq = dist * dist;
@ -116,22 +115,4 @@ public class NetConfig extends ACheckConfig {
} }
@Override
public boolean isEnabled(final CheckType checkType) {
switch(checkType) {
case NET_ATTACKFREQUENCY:
return attackFrequencyActive;
case NET_FLYINGFREQUENCY:
return flyingFrequencyActive;
case NET_PACKETFREQUENCY:
return packetFrequencyActive;
case NET_SOUNDDISTANCE:
return soundDistanceActive;
case NET_KEEPALIVEFREQUENCY:
return keepAliveFrequencyActive;
default:
return true;
}
}
} }

View File

@ -1,49 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.net;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.access.CheckConfigFactory;
import fr.neatmonster.nocheatplus.config.ConfigFile;
import fr.neatmonster.nocheatplus.config.WorldConfigCache;
/**
* Copy-on-write per-world configuration cache.
* @author asofold
*
*/
public class NetConfigCache extends WorldConfigCache<NetConfig> implements CheckConfigFactory {
public NetConfigCache() {
super(true);
}
@Override
protected NetConfig newConfig(String key, ConfigFile configFile) {
return new NetConfig(configFile);
}
@Override
public NetConfig getConfig(final Player player) {
return getConfig(player.getWorld());
}
@Override
public void removeAllConfigs() {
clearAllConfigs();
}
}

View File

@ -92,7 +92,6 @@ public class NetData extends ACheckData {
public final ActionFrequency packetFrequency; public final ActionFrequency packetFrequency;
public NetData(final NetConfig config) { public NetData(final NetConfig config) {
super(config);
flyingFrequencyAll = new ActionFrequency(config.flyingFrequencySeconds, 1000L); flyingFrequencyAll = new ActionFrequency(config.flyingFrequencySeconds, 1000L);
flyingFrequencyRedundantFreq = new ActionFrequency(config.flyingFrequencyRedundantSeconds, 1000L); flyingFrequencyRedundantFreq = new ActionFrequency(config.flyingFrequencyRedundantSeconds, 1000L);
if (config.packetFrequencySeconds <= 2) { if (config.packetFrequencySeconds <= 2) {

View File

@ -1,74 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.neatmonster.nocheatplus.checks.net;
import java.util.Iterator;
import java.util.UUID;
import java.util.Map.Entry;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.checks.access.ICheckData;
import fr.neatmonster.nocheatplus.components.data.ICanHandleTimeRunningBackwards;
import fr.neatmonster.nocheatplus.utilities.ds.map.HashMapLOW;
/**
* Factory for NetData.
* @author asofold
*
*/
public class NetDataFactory implements CheckDataFactory, ICanHandleTimeRunningBackwards {
private final HashMapLOW<String, NetData> dataMap = new HashMapLOW<String, NetData>(35);
@Override
public void removeAllData() {
dataMap.clear();
}
@Override
public NetData getData(Player player) {
NetData data = dataMap.get(player.getName());
if (data != null) {
return data;
} else {
data = new NetData((NetConfig) CheckType.NET.getConfigFactory().getConfig(player));
dataMap.put(player.getName(), data);
return data;
}
}
@Override
public ICheckData getDataIfPresent(UUID playerId, String playerName) {
return dataMap.get(playerName);
}
@Override
public NetData removeData(String playerName) {
return dataMap.remove(playerName);
}
@Override
public void handleTimeRanBackwards() {
final Iterator<Entry<String, NetData>> it = dataMap.iterator();
while (it.hasNext()) {
final Entry<String, NetData> entry = it.next();
entry.getValue().handleSystemTimeRanBackwards();
}
}
}

View File

@ -16,10 +16,6 @@ package fr.neatmonster.nocheatplus.checks.net;
import java.util.List; import java.util.List;
import org.bukkit.World;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.chat.ChatData;
import fr.neatmonster.nocheatplus.utilities.TickTask; import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency; import fr.neatmonster.nocheatplus.utilities.ds.count.ActionFrequency;
@ -167,23 +163,4 @@ public class NetStatic {
return Math.max(0.0, violation); return Math.max(0.0, violation);
} }
/**
* Convenience: Check stored world names in case the world is null.
*
* NOTE:
* @param player
* @param configCache
* @param dataFactory
* @return
*/
public static NetConfig getWorldConfig(Player player, NetConfigCache configCache, NetDataFactory dataFactory) {
World world = null;
try {
world = player.getWorld();
}
catch (UnsupportedOperationException e) {}
// TODO: Abusing ChatData for tracking world names. Should be in PlayerData or some generic data.
return configCache.getConfig(world == null ? ChatData.getData(player).currentWorldName : world.getName());
}
} }

Some files were not shown because too many files have changed in this diff Show More