diff --git a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java index 37bf0816..0e4097a2 100644 --- a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -31,11 +31,12 @@ import fr.neatmonster.nocheatplus.checks.inventory.InventoryListener; import fr.neatmonster.nocheatplus.checks.moving.MovingListener; import fr.neatmonster.nocheatplus.command.CommandHandler; import fr.neatmonster.nocheatplus.command.INotifyReload; +import fr.neatmonster.nocheatplus.components.INeedConfig; +import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigManager; import fr.neatmonster.nocheatplus.config.DefaultConfig; -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; @@ -61,7 +62,7 @@ import fr.neatmonster.nocheatplus.utilities.Updates; /** * This is the main class of NoCheatPlus. The commands, events listeners and tasks are registered here. */ -public class NoCheatPlus extends JavaPlugin implements Listener { +public class NoCheatPlus extends JavaPlugin implements Listener, NoCheatPlusAPI { /** Lower case player name to milliseconds point of time of release */ private static final Map denyLoginNames = Collections.synchronizedMap(new HashMap()); @@ -120,7 +121,7 @@ public class NoCheatPlus extends JavaPlugin implements Listener { return isLoginDenied(playerName, System.currentTimeMillis()); } - public String[] getLoginDeniedPlayers() { + public static String[] getLoginDeniedPlayers() { checkDenyLoginsNames(); String[] kicked = new String[denyLoginNames.size()]; denyLoginNames.keySet().toArray(kicked); @@ -139,6 +140,14 @@ public class NoCheatPlus extends JavaPlugin implements Listener { if (oldTs == null) return false; else return time < oldTs.longValue(); } + + /** + * Convenience method, delegates to + * @return + */ + public static NoCheatPlusAPI getAPI() { + return (NoCheatPlusAPI) Bukkit.getPluginManager().getPlugin("NoCheatPlus"); + } /** The event listeners. */ private final List listeners = new ArrayList(); @@ -156,25 +165,28 @@ public class NoCheatPlus extends JavaPlugin implements Listener { /** Player data future stuff. */ protected final DataManager dataMan = new DataManager(); - /** - * Convenience method to add components according to implemented interfaces, - * like Listener, INotifyReload, INeedConfig.
- * This must be done after the configuration has been initialized. - * @param obj - */ - 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(); - } - } - } + @Override + public 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(); + } + } + dataMan.addComponent(obj); + } + + @Override + public void removeComponent(final Object obj) { + listeners.remove(obj); + notifyReload.remove(obj); + dataMan.removeComponent(obj); + } /* (non-Javadoc) * @see org.bukkit.plugin.java.JavaPlugin#onDisable() @@ -205,6 +217,9 @@ public class NoCheatPlus extends JavaPlugin implements Listener { // Remove config listeners. notifyReload.clear(); + // More cleanup. + dataMan.onDisable(); + // Cleanup the configuration manager. ConfigManager.cleanup(); diff --git a/src/fr/neatmonster/nocheatplus/checks/access/CheckDataFactory.java b/src/fr/neatmonster/nocheatplus/checks/access/CheckDataFactory.java index 2fefbada..e4fc1bc2 100644 --- a/src/fr/neatmonster/nocheatplus/checks/access/CheckDataFactory.java +++ b/src/fr/neatmonster/nocheatplus/checks/access/CheckDataFactory.java @@ -2,6 +2,8 @@ package fr.neatmonster.nocheatplus.checks.access; import org.bukkit.entity.Player; +import fr.neatmonster.nocheatplus.components.IRemoveData; + /* * MM'""""'YMM dP dP M""""""'YMM dP @@ -26,7 +28,7 @@ import org.bukkit.entity.Player; * * @author asofold */ -public interface CheckDataFactory { +public interface CheckDataFactory extends IRemoveData{ /** * Gets the data of the specified player. @@ -37,16 +39,7 @@ public interface CheckDataFactory { */ public ICheckData getData(final Player player); - /** - * Remove data of a player. - * @param playerName Must match exactly, must be player name for command use and cleanup tasks. - * @return - */ + @Override public ICheckData removeData(final String playerName); - /** - * Remove all data for all players. - */ - public void removeAllData(); - } diff --git a/src/fr/neatmonster/nocheatplus/checks/access/ICheckData.java b/src/fr/neatmonster/nocheatplus/checks/access/ICheckData.java index 89b969b7..cdf76d55 100644 --- a/src/fr/neatmonster/nocheatplus/checks/access/ICheckData.java +++ b/src/fr/neatmonster/nocheatplus/checks/access/ICheckData.java @@ -1,5 +1,7 @@ package fr.neatmonster.nocheatplus.checks.access; +import fr.neatmonster.nocheatplus.components.IData; + /* * MM'""""'YMM dP dP M""""""'YMM dP * M' .mmm. `M 88 88 M mmmm. `M 88 @@ -17,7 +19,7 @@ package fr.neatmonster.nocheatplus.checks.access; * * @author asofold */ -public interface ICheckData { +public interface ICheckData extends IData{ /** * Check if an entry for the given permission exists. diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/Text.java b/src/fr/neatmonster/nocheatplus/checks/chat/Text.java index 0a506c6a..57778b06 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/Text.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/Text.java @@ -7,6 +7,7 @@ import java.util.Map; import org.bukkit.entity.Player; +import fr.neatmonster.nocheatplus.NoCheatPlus; import fr.neatmonster.nocheatplus.actions.ParameterName; import fr.neatmonster.nocheatplus.checks.AsyncCheck; import fr.neatmonster.nocheatplus.checks.CheckType; @@ -64,7 +65,12 @@ public class Text extends AsyncCheck implements INotifyReload{ private void init() { // Set some things from the global config. ConfigFile config = ConfigManager.getConfigFile(); + if (engine != null){ + engine.clear(); + NoCheatPlus.getAPI().removeComponent(engine); + } engine = new LetterEngine(config); + NoCheatPlus.getAPI().addComponent(engine); } @Override diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/EnginePlayerData.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/EnginePlayerData.java index 5d624ec0..f0a1c77d 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/EnginePlayerData.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/EnginePlayerData.java @@ -4,17 +4,18 @@ import java.util.ArrayList; import java.util.List; import fr.neatmonster.nocheatplus.checks.chat.ChatConfig; +import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.FlatWords; import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.SimilarWordsBKL; import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.WordPrefixes; -import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.FlatWords; import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.WordProcessor; +import fr.neatmonster.nocheatplus.components.IData; /** * Engine specific player data. * @author mc_dev * */ -public class EnginePlayerData { +public class EnginePlayerData implements IData{ public final List processors = new ArrayList(5); diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/LetterEngine.java b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/LetterEngine.java index e6a23701..113eee0b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/LetterEngine.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/analysis/engine/LetterEngine.java @@ -7,6 +7,7 @@ import java.util.Map; import org.bukkit.Bukkit; +import fr.neatmonster.nocheatplus.checks.CheckType; import fr.neatmonster.nocheatplus.checks.chat.ChatConfig; import fr.neatmonster.nocheatplus.checks.chat.ChatData; import fr.neatmonster.nocheatplus.checks.chat.analysis.MessageLetterCount; @@ -17,6 +18,9 @@ import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.Similar import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.WordPrefixes; import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.WordPrefixes.WordPrefixesSettings; import fr.neatmonster.nocheatplus.checks.chat.analysis.engine.processors.WordProcessor; +import fr.neatmonster.nocheatplus.components.IData; +import fr.neatmonster.nocheatplus.components.IHaveCheckType; +import fr.neatmonster.nocheatplus.components.IRemoveData; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; @@ -26,11 +30,14 @@ import fr.neatmonster.nocheatplus.config.ConfigFile; * @author mc_dev * */ -public class LetterEngine { +public class LetterEngine implements IRemoveData, IHaveCheckType{ /** Global processors */ protected final List processors = new ArrayList(); + /** + * Mapping players to data. + */ protected final EnginePlayerDataMap dataMap; public LetterEngine(ConfigFile config){ @@ -101,4 +108,19 @@ public class LetterEngine { processors.clear(); dataMap.clear(); } + + @Override + public IData removeData(final String playerName) { + return dataMap.remove(playerName); + } + + @Override + public void removeAllData() { + dataMap.clear(); + } + + @Override + public final CheckType getCheckType() { + return CheckType.CHAT_TEXT; + } } diff --git a/src/fr/neatmonster/nocheatplus/command/actions/KickListCommand.java b/src/fr/neatmonster/nocheatplus/command/actions/KickListCommand.java index 3fc00870..636127bb 100644 --- a/src/fr/neatmonster/nocheatplus/command/actions/KickListCommand.java +++ b/src/fr/neatmonster/nocheatplus/command/actions/KickListCommand.java @@ -18,7 +18,7 @@ public class KickListCommand extends NCPCommand { @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - final String[] kicked = plugin.getLoginDeniedPlayers(); + final String[] kicked = NoCheatPlus.getLoginDeniedPlayers(); if (kicked.length < 100) Arrays.sort(kicked); sender.sendMessage(TAG + "Temporarily kicked players:"); sender.sendMessage(CheckUtils.join(Arrays.asList(kicked), " ")); diff --git a/src/fr/neatmonster/nocheatplus/command/admin/RemovePlayerCommand.java b/src/fr/neatmonster/nocheatplus/command/admin/RemovePlayerCommand.java index ebf4eee8..9142cdf6 100644 --- a/src/fr/neatmonster/nocheatplus/command/admin/RemovePlayerCommand.java +++ b/src/fr/neatmonster/nocheatplus/command/admin/RemovePlayerCommand.java @@ -41,7 +41,7 @@ public class RemovePlayerCommand extends NCPCommand { else checkType = CheckType.ALL; if (playerName.equals("*")){ - DataManager.clear(checkType); + DataManager.clearData(checkType); sender.sendMessage(TAG + "Removed all data and history: " + checkType); return true; } @@ -61,7 +61,7 @@ public class RemovePlayerCommand extends NCPCommand { if (DataManager.removeExecutionHistory(checkType, playerName)) histRemoved = true; - final boolean dataRemoved = CheckType.removeData(playerName, checkType); + final boolean dataRemoved = CheckType.removeData(playerName, checkType) || DataManager.clearComponentData(checkType, playerName); if (dataRemoved || histRemoved){ String which; diff --git a/src/fr/neatmonster/nocheatplus/config/INeedConfig.java b/src/fr/neatmonster/nocheatplus/config/INeedConfig.java index cf1f3f53..026fd973 100644 --- a/src/fr/neatmonster/nocheatplus/config/INeedConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/INeedConfig.java @@ -1,11 +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. + * @deprecated Use instead: fr.neatmonster.nocheatplus.components.INeedConfig * @author mc_dev * */ -public interface INeedConfig extends INotifyReload{ +public interface INeedConfig extends fr.neatmonster.nocheatplus.components.INeedConfig{ } diff --git a/src/fr/neatmonster/nocheatplus/players/DataManager.java b/src/fr/neatmonster/nocheatplus/players/DataManager.java index dcd1ed21..1011c057 100644 --- a/src/fr/neatmonster/nocheatplus/players/DataManager.java +++ b/src/fr/neatmonster/nocheatplus/players/DataManager.java @@ -1,5 +1,6 @@ package fr.neatmonster.nocheatplus.players; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -30,13 +31,16 @@ import fr.neatmonster.nocheatplus.checks.fight.FightConfig; import fr.neatmonster.nocheatplus.checks.inventory.InventoryConfig; import fr.neatmonster.nocheatplus.checks.moving.MovingConfig; import fr.neatmonster.nocheatplus.command.INotifyReload; +import fr.neatmonster.nocheatplus.components.IComponentRegistry; +import fr.neatmonster.nocheatplus.components.IHaveCheckType; +import fr.neatmonster.nocheatplus.components.INeedConfig; +import fr.neatmonster.nocheatplus.components.IRemoveData; 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{ +public class DataManager implements Listener, INotifyReload, INeedConfig, IComponentRegistry{ protected static DataManager instance = null; @@ -50,6 +54,12 @@ public class DataManager implements Listener, INotifyReload, INeedConfig{ */ private final Map lastLogout = new LinkedHashMap(50, 0.75f, true); + /** + * IRemoveData instances. + * // TODO: might use a map for those later (extra or not). + */ + protected final ArrayList iRemoveData = new ArrayList(); + /** * Execution histories of the checks. */ @@ -84,6 +94,7 @@ public class DataManager implements Listener, INotifyReload, INeedConfig{ for (final CheckDataFactory factory : factories){ factory.removeData(playerName); } + clearComponentData(CheckType.ALL, playerName); } if (deleteData || deleteHistory) removeExecutionHistory(CheckType.ALL, playerName); if (deleteHistory) ViolationHistory.removeHistory(playerName); @@ -152,12 +163,21 @@ public class DataManager implements Listener, INotifyReload, INeedConfig{ } return removed; } + + /** + * Removes all data and history for a player. + * @deprecated Use clearData instead, this likely to be removed later. + * @param checkType + */ + public static void clear(final CheckType checkType){ + clearData(checkType); + } /** * Remove data and history of all players for the given check type and sub checks. * @param checkType */ - public static void clear(final CheckType checkType) { + public static void clearData(final CheckType checkType) { final Set factories = new HashSet(); for (final CheckType type : APIUtils.getWithChildren(checkType)){ final Map map = instance.executionHistories.get(type); @@ -168,9 +188,35 @@ public class DataManager implements Listener, INotifyReload, INeedConfig{ for (final CheckDataFactory factory : factories){ factory.removeAllData(); } + for (final IRemoveData rmd : instance.iRemoveData){ + if (rmd instanceof IHaveCheckType){ + final CheckType refType = ((IHaveCheckType) rmd).getCheckType(); + if (refType == checkType || APIUtils.isParent(checkType, refType)) rmd.removeAllData(); + } + } ViolationHistory.clear(checkType); } + /** + * Clear player related data, only for registered components (not execution history, violation history, normal check data).
+ * That should at least go for chat engione data. + * @param CheckType + * @param PlayerName + * @return If something was removed. + */ + public static boolean clearComponentData(final CheckType checkType, final String PlayerName){ + boolean removed = false; + for (final IRemoveData rmd : instance.iRemoveData){ + if (rmd instanceof IHaveCheckType){ + final CheckType refType = ((IHaveCheckType) rmd).getCheckType(); + if (refType == checkType || APIUtils.isParent(checkType, refType)){ + if (rmd.removeData(PlayerName) != null) removed = true; + } + } + } + return removed; + } + /** * Clear all stored (check) config instances.
* This does not cleanup ConfigManager, i.e. stored yml-versions. @@ -186,4 +232,33 @@ public class DataManager implements Listener, INotifyReload, INeedConfig{ InventoryConfig.clear(); MovingConfig.clear(); } + + + @Override + public void addComponent(Object obj) { + if (obj instanceof IRemoveData) { + iRemoveData.add((IRemoveData) obj); + } + } + + @Override + public void removeComponent(Object obj) { + if (obj instanceof IRemoveData) { + iRemoveData.remove((IRemoveData) obj); + } + } + + /** + * Cleanup method. + */ + public void onDisable() { + clearData(CheckType.ALL); + for (IRemoveData rmd : iRemoveData){ + if (!(rmd instanceof IHaveCheckType)) rmd.removeAllData(); + } + iRemoveData.clear(); + clearConfigs(); + lastLogout.clear(); + executionHistories.clear(); + } } diff --git a/src/fr/neatmonster/nocheatplus/utilities/TickTask.java b/src/fr/neatmonster/nocheatplus/utilities/TickTask.java index f4d4b2e4..b1f9c5fa 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/TickTask.java +++ b/src/fr/neatmonster/nocheatplus/utilities/TickTask.java @@ -176,9 +176,9 @@ public class TickTask implements Runnable { // The isEmpty checks are faster than synchronizing fully always, the actions get delayed one tick at most. if (!delayedActions.isEmpty()) executeActions(); if (!permissionUpdates.isEmpty()) updatePermissions(); - if (timeLast > time){ - CheckUtils.logSevere("[NoCheatPlus] System time ran backwards (" + timeLast + "->" + time + "), clear all data and history..."); - DataManager.clear(CheckType.ALL); + if (timeLast > time) { + CheckUtils.logSevere("[NoCheatPlus] System time ran backwards (" + timeLast + "->" + time + "), clear all data and history..."); + DataManager.clearData(CheckType.ALL); } timeLast = time; }