mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-03-02 10:31:25 +01:00
Bleeding: Add data expiration management. Also remove execution history
(remove command). Expiration duration is in minutes.
This commit is contained in:
parent
d046d1d06e
commit
4e4556624a
src/fr/neatmonster/nocheatplus
@ -35,12 +35,14 @@ import fr.neatmonster.nocheatplus.command.INotifyReload;
|
||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||
import fr.neatmonster.nocheatplus.config.INeedConfig;
|
||||
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
|
||||
import fr.neatmonster.nocheatplus.metrics.Metrics;
|
||||
import fr.neatmonster.nocheatplus.metrics.Metrics.Graph;
|
||||
import fr.neatmonster.nocheatplus.metrics.Metrics.Plotter;
|
||||
import fr.neatmonster.nocheatplus.metrics.MetricsData;
|
||||
import fr.neatmonster.nocheatplus.net.NCPNetServerHandler;
|
||||
import fr.neatmonster.nocheatplus.players.DataManager;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockProperties;
|
||||
import fr.neatmonster.nocheatplus.utilities.LagMeasureTask;
|
||||
@ -150,15 +152,26 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
|
||||
/** Is a new update available? */
|
||||
private boolean updateAvailable = false;
|
||||
|
||||
/** Player data future stuff. */
|
||||
protected final DataManager dataMan = new DataManager();
|
||||
|
||||
/**
|
||||
* Convenience method to add to listeners and notifyReload lists.
|
||||
* @param listener
|
||||
* Convenience method to add components according to implemented interfaces,
|
||||
* like Listener, INotifyReload, INeedConfig.<br>
|
||||
* This must be done after the configuration has been initialized.
|
||||
* @param obj
|
||||
*/
|
||||
private void addListener(final Listener listener){
|
||||
Bukkit.getPluginManager().registerEvents(listener, this);
|
||||
listeners.add(listener);
|
||||
if (listener instanceof INotifyReload){
|
||||
notifyReload.add((INotifyReload) listener);
|
||||
private void addComponent(final Object obj){
|
||||
if (obj instanceof Listener){
|
||||
final Listener listener = (Listener) obj;
|
||||
Bukkit.getPluginManager().registerEvents(listener, this);
|
||||
listeners.add(listener);
|
||||
}
|
||||
if (obj instanceof INotifyReload){
|
||||
notifyReload.add((INotifyReload) obj);
|
||||
if (obj instanceof INeedConfig){
|
||||
((INeedConfig) obj).onReload();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +229,8 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
|
||||
|
||||
// List the events listeners and register.
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
for (final Listener listener : new Listener[]{
|
||||
for (final Object obj : new Object[]{
|
||||
dataMan,
|
||||
new BlockBreakListener(),
|
||||
new BlockInteractListener(),
|
||||
new BlockPlaceListener(),
|
||||
@ -228,7 +242,7 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
|
||||
new Workarounds(),
|
||||
NCPExemptionManager.getListener(),
|
||||
}){
|
||||
addListener(listener);
|
||||
addComponent(obj);
|
||||
}
|
||||
|
||||
// Register the commands handler.
|
||||
@ -239,6 +253,13 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
|
||||
|
||||
// Set up the tick task.
|
||||
TickTask.start(this);
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dataMan.checkExpiration();
|
||||
}
|
||||
}, 1207, 1207);
|
||||
|
||||
ConfigFile config = ConfigManager.getConfigFile();
|
||||
|
||||
|
@ -10,6 +10,7 @@ import fr.neatmonster.nocheatplus.actions.ParameterName;
|
||||
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
|
||||
import fr.neatmonster.nocheatplus.hooks.NCPHookManager;
|
||||
import fr.neatmonster.nocheatplus.metrics.MetricsData;
|
||||
import fr.neatmonster.nocheatplus.players.DataManager;
|
||||
import fr.neatmonster.nocheatplus.players.ExecutionHistory;
|
||||
import fr.neatmonster.nocheatplus.utilities.TickTask;
|
||||
|
||||
@ -55,6 +56,7 @@ public abstract class Check {
|
||||
public Check(final CheckType type) {
|
||||
this.type = type;
|
||||
ViolationHistory.checkTypeMap.put(getClass().getName(), type);
|
||||
DataManager.registerExecutionHistory(type, histories);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -161,6 +161,10 @@ public class ViolationHistory {
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ViolationHistory removeHistory(final String playerName){
|
||||
return violationHistories.remove(playerName);
|
||||
}
|
||||
|
||||
/** The violation levels for every check. */
|
||||
private final List<ViolationLevel> violationLevels = new ArrayList<ViolationLevel>();
|
||||
|
@ -11,6 +11,7 @@ import fr.neatmonster.nocheatplus.NoCheatPlus;
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationHistory;
|
||||
import fr.neatmonster.nocheatplus.command.NCPCommand;
|
||||
import fr.neatmonster.nocheatplus.players.DataManager;
|
||||
import fr.neatmonster.nocheatplus.players.Permissions;
|
||||
import fr.neatmonster.nocheatplus.utilities.CheckUtils;
|
||||
|
||||
@ -44,7 +45,15 @@ public class RemovePlayerCommand extends NCPCommand {
|
||||
|
||||
ViolationHistory hist = ViolationHistory.getHistory(playerName, false);
|
||||
boolean histRemoved = false;
|
||||
if (hist != null) histRemoved = hist.remove(checkType);
|
||||
if (hist != null){
|
||||
histRemoved = hist.remove(checkType);
|
||||
if (checkType == CheckType.ALL){
|
||||
histRemoved = true;
|
||||
ViolationHistory.removeHistory(playerName);
|
||||
}
|
||||
}
|
||||
|
||||
if (DataManager.removeExecutionHistory(checkType, playerName)) histRemoved = true;
|
||||
|
||||
final boolean dataRemoved = CheckType.removeData(playerName, checkType);
|
||||
|
||||
|
@ -51,6 +51,13 @@ public abstract class ConfPaths {
|
||||
public static final String MISCELLANEOUS_NOMOVEDTOOQUICKLY_ENABLED = MISCELLANEOUS_NOMOVEDTOOQUICKLY + "enabled";
|
||||
public static final String MISCELLANEOUS_NOMOVEDTOOQUICKLY_USEPROXY = MISCELLANEOUS_NOMOVEDTOOQUICKLY + "useproxy";
|
||||
|
||||
@GlobalConfig
|
||||
private static final String DATA = "data.";
|
||||
private static final String DATA_EXPIRATION = DATA + "expiration.";
|
||||
public static final String DATA_EXPIRATION_DURATION = DATA_EXPIRATION + "duration";
|
||||
public static final String DATA_EXPIRATION_DATA = DATA_EXPIRATION + "data";
|
||||
public static final String DATA_EXPIRATION_HISTORY = DATA_EXPIRATION + "history";
|
||||
|
||||
private static final String CHECKS = "checks.";
|
||||
|
||||
/*
|
||||
|
@ -57,6 +57,10 @@ public class DefaultConfig extends ConfigFile {
|
||||
|
||||
// set(ConfPaths.MISCELLANEOUS_NOMOVEDTOOQUICKLY_ENABLED, false);
|
||||
// set(ConfPaths.MISCELLANEOUS_NOMOVEDTOOQUICKLY_USEPROXY, false);
|
||||
|
||||
|
||||
set(ConfPaths.DATA_EXPIRATION_DURATION, 0);
|
||||
set(ConfPaths.DATA_EXPIRATION_HISTORY, false);
|
||||
|
||||
/*
|
||||
* 888 88b, 888 888 888 88b, 888
|
||||
|
11
src/fr/neatmonster/nocheatplus/config/INeedConfig.java
Normal file
11
src/fr/neatmonster/nocheatplus/config/INeedConfig.java
Normal file
@ -0,0 +1,11 @@
|
||||
package fr.neatmonster.nocheatplus.config;
|
||||
|
||||
import fr.neatmonster.nocheatplus.command.INotifyReload;
|
||||
|
||||
/**
|
||||
* Indicate that an instance needs config after time of creation but in onEnable.
|
||||
* @author mc_dev
|
||||
*
|
||||
*/
|
||||
public interface INeedConfig extends INotifyReload{
|
||||
}
|
@ -27,6 +27,9 @@ public class APIUtils {
|
||||
|
||||
/** Only the children. */
|
||||
private static final Map<CheckType, CheckType[]> childrenMap = new HashMap<CheckType, CheckType[]>();
|
||||
|
||||
/** Check including children, for convenient iteration. */
|
||||
private static final Map<CheckType, CheckType[]> withChildrenMap = new HashMap<CheckType, CheckType[]>();
|
||||
|
||||
static {
|
||||
final Map<CheckType, Set<CheckType>> map = new HashMap<CheckType, Set<CheckType>>();
|
||||
@ -38,8 +41,15 @@ public class APIUtils {
|
||||
if (isParent(other, type)) map.get(other).add(type);
|
||||
}
|
||||
}
|
||||
for (final CheckType parent : map.keySet())
|
||||
childrenMap.put(parent, map.get(parent).toArray(new CheckType[] {}));
|
||||
for (final CheckType parent : map.keySet()){
|
||||
final Set<CheckType> set = map.get(parent);
|
||||
final CheckType[] a = new CheckType[set.size()];
|
||||
childrenMap.put(parent, set.toArray(a));
|
||||
final CheckType[] aw = new CheckType[set.size() + 1];
|
||||
set.toArray(aw);
|
||||
aw[set.size()] = parent;
|
||||
withChildrenMap.put(parent, aw);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,6 +63,18 @@ public class APIUtils {
|
||||
public static final Collection<CheckType> getChildren(final CheckType type) {
|
||||
return Arrays.asList(childrenMap.get(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an unmodifiable collection of the given check type with children. Always returns a collection, does
|
||||
* contain the check type itself.
|
||||
*
|
||||
* @param type
|
||||
* the check type
|
||||
* @return the children
|
||||
*/
|
||||
public static final Collection<CheckType> getWithChildren(final CheckType type) {
|
||||
return Arrays.asList(withChildrenMap.get(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the supposed parent is ancestor of the supposed child. Does not check versus the supposed child
|
||||
|
125
src/fr/neatmonster/nocheatplus/players/DataManager.java
Normal file
125
src/fr/neatmonster/nocheatplus/players/DataManager.java
Normal file
@ -0,0 +1,125 @@
|
||||
package fr.neatmonster.nocheatplus.players;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import fr.neatmonster.nocheatplus.checks.CheckType;
|
||||
import fr.neatmonster.nocheatplus.checks.ViolationHistory;
|
||||
import fr.neatmonster.nocheatplus.checks.access.CheckDataFactory;
|
||||
import fr.neatmonster.nocheatplus.command.INotifyReload;
|
||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigManager;
|
||||
import fr.neatmonster.nocheatplus.config.INeedConfig;
|
||||
import fr.neatmonster.nocheatplus.hooks.APIUtils;
|
||||
|
||||
public class DataManager implements Listener, INotifyReload, INeedConfig{
|
||||
|
||||
protected static DataManager instance = null;
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Access order for playerName (exact) -> ms time of logout.
|
||||
* <hr>
|
||||
* Later this might hold central player data objects instead of the long only.
|
||||
*/
|
||||
private final Map<String, Long> lastLogout = new LinkedHashMap<String, Long>(50, 0.75f, true);
|
||||
|
||||
/**
|
||||
* Execution histories of the checks.
|
||||
*/
|
||||
protected final Map<CheckType, Map<String, ExecutionHistory>> executionHistories = new HashMap<CheckType, Map<String,ExecutionHistory>>();
|
||||
|
||||
protected long durExpireData = 0;
|
||||
|
||||
protected boolean deleteData = true;
|
||||
protected boolean deleteHistory = false;
|
||||
|
||||
public DataManager(){
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public void checkExpiration(){
|
||||
if (durExpireData <= 0) return;
|
||||
final long now = System.currentTimeMillis();
|
||||
final Set<CheckDataFactory> factories = new LinkedHashSet<CheckDataFactory>();
|
||||
final Set<Entry<String, Long>> entries = lastLogout.entrySet();
|
||||
final Iterator<Entry<String, Long>> iterator = entries.iterator();
|
||||
while (iterator.hasNext()){
|
||||
final Entry<String, Long> entry = iterator.next();
|
||||
final long ts = entry.getValue();
|
||||
if (now - ts <= durExpireData) break;
|
||||
final String playerName = entry.getKey();
|
||||
if (deleteData){
|
||||
factories.clear();
|
||||
for (final CheckType type : CheckType.values()){
|
||||
final CheckDataFactory factory = type.getDataFactory();
|
||||
if (factory != null) factories.add(factory);
|
||||
}
|
||||
for (final CheckDataFactory factory : factories){
|
||||
factory.removeData(playerName);
|
||||
}
|
||||
}
|
||||
if (deleteData || deleteHistory) removeExecutionHistory(CheckType.ALL, playerName);
|
||||
if (deleteHistory) ViolationHistory.removeHistory(playerName);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(final PlayerJoinEvent event){
|
||||
lastLogout.remove(event.getPlayer().getName());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerQuit(final PlayerQuitEvent event){
|
||||
lastLogout.put(event.getPlayer().getName(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onPlayerKick(final PlayerKickEvent event){
|
||||
lastLogout.put(event.getPlayer().getName(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
// future
|
||||
adjustSettings();
|
||||
}
|
||||
|
||||
private void adjustSettings() {
|
||||
final ConfigFile config = ConfigManager.getConfigFile();
|
||||
durExpireData = config.getLong(ConfPaths.DATA_EXPIRATION_DURATION) * 60000L; // in minutes
|
||||
deleteData = config.getBoolean(ConfPaths.DATA_EXPIRATION_DATA, true); // hidden.
|
||||
deleteHistory = config.getBoolean(ConfPaths.DATA_EXPIRATION_HISTORY);
|
||||
}
|
||||
|
||||
public static void registerExecutionHistory(CheckType type, Map<String, ExecutionHistory> histories) {
|
||||
instance.executionHistories.put(type, histories);
|
||||
}
|
||||
|
||||
public static boolean removeExecutionHistory(final CheckType type, final String playerName){
|
||||
boolean removed = false;
|
||||
// TODO: design ...
|
||||
for (final CheckType refType : APIUtils.getWithChildren(type)){
|
||||
final Map<String, ExecutionHistory> map = instance.executionHistories.get(refType);
|
||||
if (map != null && map.remove(playerName) != null) removed = true;
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user