[BLEEDING] Prepare 'data removal light' for time running backwards.

Introduce an interface to indicate if a CheckDataFactory or IRemoveData
instance can do something better than removing all data, in case the
system time ran backwards. An extra method in data manager is used
instead of clearAllData, which will test for implementation of that
interface. Concerns CheckDataFactory instances accessible via CheckType 
and IRemoveData instances registered with DataManager (via
NoCheatPlusAPI or directly).

Implementation details and related changes:
* TickTask: Let ActionFrequency handle time running backwards (spikes).
* NetData/Factory: Use HashMapLOW. Selectively clear/adjust.
* MovingData: Keep past move tracking (and some other).
This commit is contained in:
asofold 2016-02-08 00:09:26 +01:00
parent 40a83839e5
commit f6a004015d
6 changed files with 123 additions and 10 deletions

View File

@ -24,6 +24,7 @@ import fr.neatmonster.nocheatplus.checks.moving.velocity.FrictionAxisVelocity;
import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleAxisVelocity;
import fr.neatmonster.nocheatplus.checks.moving.velocity.SimpleEntry;
import fr.neatmonster.nocheatplus.checks.workaround.WRPT;
import fr.neatmonster.nocheatplus.components.ICanHandleTimeRunningBackwards;
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
import fr.neatmonster.nocheatplus.utilities.PlayerLocation;
import fr.neatmonster.nocheatplus.utilities.TickTask;
@ -36,8 +37,7 @@ import fr.neatmonster.nocheatplus.workaround.IWorkaroundRegistry.WorkaroundSet;
*/
public class MovingData extends ACheckData {
/** The factory creating data. */
public static final CheckDataFactory factory = new CheckDataFactory() {
public static final class MovingDataFactory implements CheckDataFactory, ICanHandleTimeRunningBackwards {
@Override
public final ICheckData getData(final Player player) {
return MovingData.getData(player);
@ -50,9 +50,19 @@ public class MovingData extends ACheckData {
@Override
public void removeAllData() {
clear();
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. */
@ -1020,4 +1030,16 @@ public class MovingData extends ACheckData {
verticalBounce = null;
}
public void handleTimeRanBackwards() {
final long time = System.currentTimeMillis();
timeSprinting = Math.min(timeSprinting, time);
morePacketsVehicleLastTime = Math.min(morePacketsVehicleLastTime, time);
sfCobwebTime = Math.min(sfCobwebTime, time);
sfVLTime = Math.min(sfVLTime, time);
trace.reset(); // Might implement something better some time (trace.handleTimeRanBackwards -> set time values, object pool).
clearAccounting(); // Not sure: adding up might not be nice.
removeAllVelocity(); // TODO: This likely leads to problems.
// (ActionFrequency can handle this.)
}
}

View File

@ -119,4 +119,17 @@ public class NetData extends ACheckData {
return out;
}
/**
* (Not implementing the interface, to avoid confusion.)
*/
public void handleSystemTimeRanBackwards() {
final long now = System.currentTimeMillis();
teleportQueue.clear(); // Can't handle timeouts. TODO: Might still keep.
lastKeepAliveTime = Math.min(lastKeepAliveTime, now);
flyingFrequencyTimeNotOnGround = Math.min(flyingFrequencyTimeNotOnGround, now);
flyingFrequencyTimeOnGround = Math.min(flyingFrequencyTimeOnGround, now);
// (Keep flyingQueue.)
// (ActionFrequency can handle this.)
}
}

View File

@ -1,19 +1,24 @@
package fr.neatmonster.nocheatplus.checks.net;
import java.util.Iterator;
import java.util.Map.Entry;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
import fr.neatmonster.nocheatplus.utilities.ds.corw.LinkedHashMapCOW;
import fr.neatmonster.nocheatplus.components.ICanHandleTimeRunningBackwards;
import fr.neatmonster.nocheatplus.utilities.ds.map.HashMapLOW;
/**
* Copy on write, right now.
* Factory for NetData.
* @author asofold
*
*/
public class NetDataFactory implements CheckDataFactory {
public class NetDataFactory implements CheckDataFactory, ICanHandleTimeRunningBackwards {
private final LinkedHashMapCOW<String, NetData> dataMap = new LinkedHashMapCOW<String, NetData>();
private final HashMapLOW<String, NetData> dataMap = new HashMapLOW<String, NetData>(Math.min(Bukkit.getServer().getMaxPlayers(), 500));
@Override
public void removeAllData() {
@ -37,4 +42,13 @@ public class NetDataFactory implements CheckDataFactory {
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

@ -0,0 +1,26 @@
package fr.neatmonster.nocheatplus.components;
/**
* Use, if something better can be done instead of removing all data, in case
* the system time ran backwards, applying with
* DataManager.handleSystemTimeRanBackwards. <br>
* With implementing ICanHandleTimeRunningBackwards, this takes effect as
* follows:
* <ul>
* <li>
* Instead of CheckDataFactory.removeAllData.</li>
* <li>
* Instead of IRemoveData.removeAllData.</li>
* </ul>
*
* @author asofold
*
*/
public interface ICanHandleTimeRunningBackwards {
/**
* Adjust to system time having run backwards (just "a second ago").
*/
public void handleTimeRanBackwards();
}

View File

@ -36,6 +36,7 @@ import fr.neatmonster.nocheatplus.components.ComponentRegistry;
import fr.neatmonster.nocheatplus.components.ComponentWithName;
import fr.neatmonster.nocheatplus.components.ConsistencyChecker;
import fr.neatmonster.nocheatplus.components.DisableListener;
import fr.neatmonster.nocheatplus.components.ICanHandleTimeRunningBackwards;
import fr.neatmonster.nocheatplus.components.IHaveCheckType;
import fr.neatmonster.nocheatplus.components.INeedConfig;
import fr.neatmonster.nocheatplus.components.INotifyReload;
@ -306,6 +307,43 @@ public class DataManager implements Listener, INotifyReload, INeedConfig, Compon
}
}
/**
* Adjust to the system time having run backwards. This is much like
* clearData(CheckType.ALL), with the exception of calling
* ICanHandleTimeRunningBackwards.handleTimeRanBackwards for data instances
* which implement this.
*/
public static void handleSystemTimeRanBackwards() {
// Collect data factories and clear execution history.
final Set<CheckDataFactory> factories = new HashSet<CheckDataFactory>();
for (final CheckType type : APIUtils.getWithChildren(CheckType.ALL)) {
final Map<String, ExecutionHistory> map = instance.executionHistories.get(type);
if (map != null) {
map.clear();
}
final CheckDataFactory factory = type.getDataFactory();
if (factory != null) {
factories.add(factory);
}
}
for (final CheckDataFactory factory : factories) {
if (factory instanceof ICanHandleTimeRunningBackwards) {
((ICanHandleTimeRunningBackwards) factory).handleTimeRanBackwards();
} else {
factory.removeAllData();
}
}
for (final IRemoveData rmd : instance.iRemoveData) {
if (rmd instanceof ICanHandleTimeRunningBackwards) {
((ICanHandleTimeRunningBackwards) rmd).handleTimeRanBackwards();
} else {
rmd.removeAllData();
}
}
ViolationHistory.clear(CheckType.ALL);
// (Not removing PlayerData instances.)
}
/**
* Restore the default debug flags within player data, as given in
* corresponding configurations. This only yields the correct result, if the

View File

@ -565,10 +565,10 @@ public class TickTask implements Runnable {
// Time running backwards check (not only players can!).
if (timeLast > time) {
StaticLog.logWarning("System time ran backwards (" + timeLast + "->" + time + "), clear all data and history...");
DataManager.clearData(CheckType.ALL);
DataManager.handleSystemTimeRanBackwards();
lastDur = 50;
for (int i = 0; i < spikeDurations.length; i++) {
spikes[i].clear(0);
spikes[i].update(time);
}
}
else if (tick > 0) {