From 5d337b2b254bde99608cb1743f4290ba1190fce8 Mon Sep 17 00:00:00 2001 From: asofold Date: Mon, 1 Oct 2012 22:40:56 +0200 Subject: [PATCH] Bleeding: Split off commands check [unfinished]. --- .../nocheatplus/checks/chat/ChatConfig.java | 11 +++- .../nocheatplus/checks/chat/ChatData.java | 6 +++ .../nocheatplus/checks/chat/ChatListener.java | 50 +++++++++++++------ .../nocheatplus/checks/chat/Commands.java | 44 ++++++++++++++++ .../nocheatplus/checks/chat/NoPwnage.java | 14 +++--- .../nocheatplus/config/ConfPaths.java | 15 ++++-- .../nocheatplus/config/DefaultConfig.java | 19 ++++--- 7 files changed, 124 insertions(+), 35 deletions(-) diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java index a8eca4d5..e3dc939b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java @@ -79,7 +79,11 @@ public class ChatConfig extends AsyncCheckConfig { public final boolean colorCheck; public final ActionList colorActions; - private final boolean commandsCheck; + public final boolean commandsCheck; + public final double commandsLevel; + public final int commandsShortTermTicks; + public final double commandsShortTermLevel; + public final ActionList commandsActions; public final boolean globalChatCheck; public final boolean globalChatGlobalCheck; @@ -173,6 +177,11 @@ public class ChatConfig extends AsyncCheckConfig { colorActions = config.getActionList(ConfPaths.CHAT_COLOR_ACTIONS, Permissions.CHAT_COLOR); commandsCheck = config.getBoolean(ConfPaths.CHAT_COMMANDS_CHECK); + commandsLevel = config.getDouble(ConfPaths.CHAT_COMMANDS_LEVEL); + commandsShortTermTicks = config.getInt(ConfPaths.CHAT_COMMANDS_SHORTTERM_TICKS); + commandsShortTermLevel = config.getDouble(ConfPaths.CHAT_COMMANDS_SHORTTERM_LEVEL);; + commandsActions = config.getActionList(ConfPaths.CHAT_COMMANDS_ACTIONS, Permissions.CHAT_COMMANDS); + globalChatCheck = config.getBoolean(ConfPaths.CHAT_GLOBALCHAT_CHECK); globalChatGlobalCheck = config.getBoolean(ConfPaths.CHAT_GLOBALCHAT_GL_CHECK, true); diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java index 253d8fac..ae4197f2 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java @@ -69,6 +69,7 @@ public class ChatData extends AsyncCheckData { // Violation levels. public double captchaVL; public double colorVL; + public double commandsVL; public double globalChatVL; public double noPwnageVL; public double relogVL; @@ -78,6 +79,11 @@ public class ChatData extends AsyncCheckData { public String captchaGenerated; public boolean captchaStarted; + /// Commands data. + public final ActionFrequency commandsWeights = new ActionFrequency(5, 1000); + public long commandsShortTermTick; + public double commandsShortTermWeight; + // Data of the globalchat check. public final ActionFrequency globalChatFrequency = new ActionFrequency(10, 3000); diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java index be94fd9e..e690c34b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java @@ -36,24 +36,31 @@ import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree; * @see ChatEvent */ public class ChatListener implements Listener, INotifyReload { - - /** The color check. */ - private final Color color = new Color(); - - /** The no pwnage check. */ - private final NoPwnage noPwnage = new NoPwnage(); + + // Checks. /** Captcha handler. */ private final Captcha captcha = new Captcha(); + + /** The color check. */ + private final Color color = new Color(); - /** Global chat check (experiment: alternative / supplement). */ + private final Commands commands = new Commands(); + + /** Global chat check. */ private final GlobalChat globalChat = new GlobalChat(); + /** The no pwnage check. */ + private final NoPwnage noPwnage = new NoPwnage(); + + private final Relog relog = new Relog(); + + // Auxiliary stuff. + private final SimpleCharPrefixTree commandExclusions = new SimpleCharPrefixTree(); private final SimpleCharPrefixTree chatCommands = new SimpleCharPrefixTree(); - private final Relog relog = new Relog(); public ChatListener(){ ConfigFile config = ConfigManager.getConfigFile(); @@ -63,9 +70,9 @@ public class ChatListener implements Listener, INotifyReload { private void initFilters(ConfigFile config) { commandExclusions.clear(); - commandExclusions.feedAll(config.getStringList(ConfPaths.CHAT_NOPWNAGE_EXCLUSIONS), false, true); + commandExclusions.feedAll(config.getStringList(ConfPaths.CHAT_COMMANDS_EXCLUSIONS), false, true); chatCommands.clear(); - chatCommands.feedAll(config.getStringList(ConfPaths.CHAT_HANDLEASCHAT), false, true); + chatCommands.feedAll(config.getStringList(ConfPaths.CHAT_COMMANDS_HANDLEASCHAT), false, true); } @EventHandler(priority=EventPriority.MONITOR) @@ -100,7 +107,7 @@ public class ChatListener implements Listener, INotifyReload { if (color.isEnabled(player)) event.setMessage(color.check(player, event.getMessage(), false)); // Then the no pwnage check. - if (noPwnage.isEnabled(player) && noPwnage.check(player, event.getMessage(), captcha, false, false)) + if (noPwnage.isEnabled(player) && noPwnage.check(player, event.getMessage(), captcha, false)) event.setCancelled(true); else if (globalChat.isEnabled(player) && globalChat.check(player, event.getMessage(), captcha, false)) // Only check those that got through. @@ -138,7 +145,7 @@ public class ChatListener implements Listener, INotifyReload { // Trim is necessary because the server accepts leading spaces with commands. // TODO: Maybe: only remove the leading whitespace or spaces. - final String lcMessage = event.getMessage().trim().toLowerCase(); + String lcMessage = event.getMessage().trim().toLowerCase(); final String command = lcMessage.split(" ")[0].substring(1); final ChatConfig cc = ChatConfig.getConfig(player); @@ -166,13 +173,24 @@ public class ChatListener implements Listener, INotifyReload { // First the color check. if (color.isEnabled(player)) event.setMessage(color.check(player, event.getMessage(), true)); + // Reset lcMessage (might be canged by color check). + lcMessage = event.getMessage().trim().toLowerCase(); final boolean handleAsChat = chatCommands.hasPrefixWords(lcMessage); // Then the no pwnage check. - if (!commandExclusions.hasPrefixWords(lcMessage) && noPwnage.isEnabled(player) && noPwnage.check(player, event.getMessage(), captcha, !handleAsChat, true)) - event.setCancelled(true); - else if (handleAsChat && globalChat.isEnabled(player) && globalChat.check(player, event.getMessage(), captcha, true)) - event.setCancelled(true); + if (handleAsChat){ + // Treat as chat. + if (noPwnage.isEnabled(player) && noPwnage.check(player, event.getMessage(), captcha, true)) + event.setCancelled(true); + else if (globalChat.isEnabled(player) && globalChat.check(player, event.getMessage(), captcha, true)) + event.setCancelled(true); + } + else if (!commandExclusions.hasPrefixWords(lcMessage)){ + // Treat as command. + if (commands.isEnabled(player) && commands.check(player, event.getMessage(), captcha)) + event.setCancelled(true); + } + } /** diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/Commands.java b/src/fr/neatmonster/nocheatplus/checks/chat/Commands.java index 103d8f52..dec2b757 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/Commands.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/Commands.java @@ -1,11 +1,55 @@ package fr.neatmonster.nocheatplus.checks.chat; +import org.bukkit.entity.Player; + import fr.neatmonster.nocheatplus.checks.Check; import fr.neatmonster.nocheatplus.checks.CheckType; +import fr.neatmonster.nocheatplus.utilities.TickTask; +/** + * Check only for commands + * @author mc_dev + * + */ public class Commands extends Check { public Commands() { super(CheckType.CHAT_COMMANDS); } + public boolean check(final Player player, final String message, final Captcha captcha) { + + final long now = System.currentTimeMillis(); + final int tick = TickTask.getTick(); + + final ChatConfig cc = ChatConfig.getConfig(player); + final ChatData data = ChatData.getData(player); + + // Weight might later be read from some prefix tree (also known / unknown). + final float weight = 1f; + + data.commandsWeights.add(now, weight); + if (tick - data.commandsShortTermTick < cc.commandsShortTermTicks){ + // Add up. + data.commandsShortTermWeight += weight; + } + else{ + // Reset. + data.commandsShortTermTick = tick; + data.commandsShortTermWeight = 1.0; + } + + final double violation = Math.max(data.commandsWeights.getScore(1f) - cc.commandsLevel, data.commandsShortTermWeight - cc.commandsShortTermLevel); + + if (violation > 0.0){ + data.commandsVL += violation; + if (executeActions(player, data.commandsVL, violation, cc.commandsActions)) + return true; + } + else{ + // TODO: This might need invalidation with time. + data.commandsVL *= 0.99; + } + return false; + } + } diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java b/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java index 098e4412..2dcc2631 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java @@ -58,7 +58,7 @@ public class NoPwnage extends AsyncCheck{ * is the thread the main thread * @return If to cancel the event. */ - public boolean check(final Player player, final String message, final Captcha captcha, final boolean isCommand, + public boolean check(final Player player, final String message, final Captcha captcha, final boolean isMainThread) { final ChatConfig cc = ChatConfig.getConfig(player); @@ -66,7 +66,7 @@ public class NoPwnage extends AsyncCheck{ // Keep related to ChatData/NoPwnage/Color used lock. synchronized (data) { - return unsafeCheck(player, message, captcha, isCommand, isMainThread, cc, data); + return unsafeCheck(player, message, captcha, isMainThread, cc, data); } } @@ -87,7 +87,7 @@ public class NoPwnage extends AsyncCheck{ * the data * @return If to cancel the event. */ - private boolean unsafeCheck(final Player player, final String message, final Captcha captcha, final boolean isCommand, + private boolean unsafeCheck(final Player player, final String message, final Captcha captcha, final boolean isMainThread, final ChatConfig cc, final ChatData data) { boolean cancel = false; @@ -104,7 +104,7 @@ public class NoPwnage extends AsyncCheck{ int suspicion = 0; // NoPwnage will remember the last message that caused someone to get banned. If a player repeats that // message within "timeout" milliseconds, the suspicion will be increased by "weight". - if (!isCommand && cc.noPwnageBannedCheck && now - lastBanCausingMessageTime < cc.noPwnageBannedTimeout + if (cc.noPwnageBannedCheck && now - lastBanCausingMessageTime < cc.noPwnageBannedTimeout && CheckUtils.isSimilar(message, lastBanCausingMessage, 0.8f)) suspicion += cc.noPwnageBannedWeight; @@ -115,7 +115,7 @@ public class NoPwnage extends AsyncCheck{ // NoPwnage will check if a player repeats a message that has been sent by another player just before, // within "timeout". If he does, suspicion will be increased by "weight". - if (!isCommand && cc.noPwnageGlobalCheck && now - lastGlobalMessageTime < cc.noPwnageGlobalTimeout + if (cc.noPwnageGlobalCheck && now - lastGlobalMessageTime < cc.noPwnageGlobalTimeout && CheckUtils.isSimilar(message, lastGlobalMessage, 0.8f)) suspicion += cc.noPwnageGlobalWeight; @@ -134,13 +134,13 @@ public class NoPwnage extends AsyncCheck{ // NoPwnage will check if a player repeats his messages within the "timeout" timeframe. Even if the message // is a bit different, it will be counted as being a repetition. The suspicion is increased by "weight". - if (!isCommand && cc.noPwnageRepeatCheck && now - data.noPwnageLastMessageTime < cc.noPwnageRepeatTimeout + if (cc.noPwnageRepeatCheck && now - data.noPwnageLastMessageTime < cc.noPwnageRepeatTimeout && CheckUtils.isSimilar(message, data.noPwnageLastMessage, 0.8f)) suspicion += cc.noPwnageRepeatWeight; // NoPwnage will check if a player moved within the "timeout" timeframe. If he did not move, the suspicion will // be increased by "weight" value. - if (!isCommand && cc.noPwnageMoveCheck && now - cData.lastMoveTime > cc.noPwnageMoveTimeout) + if (cc.noPwnageMoveCheck && now - cData.lastMoveTime > cc.noPwnageMoveTimeout) suspicion += cc.noPwnageMoveWeight; // Should a player that reaches the "warnLevel" get a text message telling him that he is under suspicion of diff --git a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java index 79ad99c0..70c3c316 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -176,9 +176,6 @@ public abstract class ConfPaths { * "88,d88 888 888 "88 888 888 */ private static final String CHAT = CHECKS + "chat."; - - @GlobalConfig - public static final String CHAT_HANDLEASCHAT = CHAT + "handleaschat"; private static final String CHAT_CAPTCHA = CHAT + "captcha."; public static final String CHAT_CAPTCHA_CHECK = CHAT_CAPTCHA + "active"; @@ -195,6 +192,15 @@ public abstract class ConfPaths { private static final String CHAT_COMMANDS = CHAT + "commands."; public static final String CHAT_COMMANDS_CHECK = CHAT_COMMANDS + "active"; + @GlobalConfig + public static final String CHAT_COMMANDS_EXCLUSIONS = CHAT_COMMANDS + "exclusions"; + @GlobalConfig + public static final String CHAT_COMMANDS_HANDLEASCHAT = CHAT_COMMANDS + "handleaschat"; + public static final String CHAT_COMMANDS_LEVEL = CHAT_COMMANDS + "level"; + private static final String CHAT_COMMANDS_SHORTTERM = CHAT_COMMANDS + "shortterm."; + public static final String CHAT_COMMANDS_SHORTTERM_TICKS = CHAT_COMMANDS_SHORTTERM + "ticks"; + public static final String CHAT_COMMANDS_SHORTTERM_LEVEL = CHAT_COMMANDS_SHORTTERM + "level"; + public static final String CHAT_COMMANDS_ACTIONS = CHAT_COMMANDS + "actions"; // globalchat private static final String CHAT_GLOBALCHAT = CHAT + "globalchat."; @@ -235,6 +241,7 @@ public abstract class ConfPaths { // globalchat actions public static final String CHAT_GLOBALCHAT_ACTIONS = CHAT_GLOBALCHAT + "actions"; + // NOT YET IN USE private static final String CHAT_LOGINS = CHAT + "logins."; public static final String CHAT_LOGINS_CHECK = CHAT_LOGINS + "active"; @@ -242,8 +249,6 @@ public abstract class ConfPaths { private static final String CHAT_NOPWNAGE = CHAT + "nopwnage."; public static final String CHAT_NOPWNAGE_CHECK = CHAT_NOPWNAGE + "active"; public static final String CHAT_NOPWNAGE_DEBUG = CHAT_NOPWNAGE + "debug"; - @GlobalConfig - public static final String CHAT_NOPWNAGE_EXCLUSIONS = CHAT_NOPWNAGE + "exclusions"; public static final String CHAT_NOPWNAGE_LEVEL = CHAT_NOPWNAGE + "level"; private static final String CHAT_NOPWNAGE_BANNED = CHAT_NOPWNAGE + "banned."; diff --git a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java index 77b0e477..e5a5d3f4 100644 --- a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -148,9 +148,15 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.CHAT_COLOR_CHECK, true); set(ConfPaths.CHAT_COLOR_ACTIONS, "log:color:0:1:if cancel"); - // Multi purpose. - set(ConfPaths.CHAT_HANDLEASCHAT, - new LinkedList(Arrays.asList(new String[]{"/me"}))); + + set(ConfPaths.CHAT_COMMANDS_CHECK, true); + set(ConfPaths.CHAT_COMMANDS_EXCLUSIONS, new ArrayList()); + set(ConfPaths.CHAT_COMMANDS_HANDLEASCHAT, + new LinkedList(Arrays.asList(new String[]{"/me"}))); + set(ConfPaths.CHAT_COMMANDS_LEVEL, 10); + set(ConfPaths.CHAT_COMMANDS_SHORTTERM_TICKS, 18); + set(ConfPaths.CHAT_COMMANDS_SHORTTERM_LEVEL, 3); + set(ConfPaths.CHAT_COMMANDS_ACTIONS, "log:commands:0:5:cf cancel cmd:kickcommands vl>20 log:commands:0:5:cf cancel cmd:tempkick1"); // Captcha. set(ConfPaths.CHAT_CAPTCHA_CHECK, false); @@ -181,7 +187,6 @@ public class DefaultConfig extends ConfigFile { // nopwnage set(ConfPaths.CHAT_NOPWNAGE_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_EXCLUSIONS, new ArrayList()); set(ConfPaths.CHAT_NOPWNAGE_LEVEL, 500); set(ConfPaths.CHAT_NOPWNAGE_BANNED_CHECK, true); @@ -218,7 +223,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.CHAT_NOPWNAGE_WARN_PLAYER_MESSAGE, "&cPlease don't spam, be careful with what you say. DON'T repeat what you just said either, unless you want to be kicked or even banned."); - set(ConfPaths.CHAT_NOPWNAGE_ACTIONS, "cancel log:nopwnage:0:5:cf cmd:kicknopwnage vl>150 cancel log:nopwnage:0:5:cf cmd:tempkick5"); + set(ConfPaths.CHAT_NOPWNAGE_ACTIONS, "cancel log:nopwnage:0:5:cf cmd:kicknopwnage vl>150 log:nopwnage:0:5:cf cancel cmd:tempkick5"); // Reload set(ConfPaths.CHAT_RELOG_CHECK, true); @@ -227,7 +232,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.CHAT_RELOG_WARNING_NUMBER, 1); set(ConfPaths.CHAT_RELOG_KICKMESSAGE, "You've relogged too fast, joining cancelled!"); set(ConfPaths.CHAT_RELOG_WARNING_TIMEOUT, 60000L); - set(ConfPaths.CHAT_RELOG_ACTIONS, "log:relog:0:10 cancel vl>20 log:relog:0:10 cancel tempkick5"); + set(ConfPaths.CHAT_RELOG_ACTIONS, "log:relog:0:10:cf cancel vl>20 log:relog:0:10:cf cancel cmd:tempkick5"); /* * Combined ! @@ -381,6 +386,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.STRINGS + ".bwrong", start + "broke another block than clicked" + end); set(ConfPaths.STRINGS + ".captcha", "[player] failed captcha repeatedly" + end); set(ConfPaths.STRINGS + ".color", start + "sent colored chat message" + end); + set(ConfPaths.STRINGS + ".commands", start + "issued too many commands" + end); set(ConfPaths.STRINGS + ".combspeed", start + "performs different actions at very high speed" + end); set(ConfPaths.STRINGS + ".critical", start + "tried to do a critical hit but wasn't technically jumping" + end); set(ConfPaths.STRINGS + ".drop", start + "tried to drop more items than allowed" + end); @@ -401,6 +407,7 @@ public class DefaultConfig extends ConfigFile { set(ConfPaths.STRINGS + ".instanteat", start + "eats food [food] too fast" + end); set(ConfPaths.STRINGS + ".instantheal", start + "tried to regenerate health faster than normal" + end); set(ConfPaths.STRINGS + ".kick", "kick [player]"); + set(ConfPaths.STRINGS + ".kickcommands", "ncp tempkick [player] 1 You're not allowed to spam commands!"); set(ConfPaths.STRINGS + ".kicknopwnage", "ncp tempkick [player] 1 You're not allowed to spam this server!"); set(ConfPaths.STRINGS + ".kickcaptcha", "ncp kick [player] Enter the captcha!"); set(ConfPaths.STRINGS + ".kickfrequency", "ncp kick [player] How about doing that less often?");