Threaded proxyServerCheck/SpamBotCheck, rewrote "Instructions.txt"

This commit is contained in:
Evenprime 2012-02-18 01:16:14 +01:00
parent d970bfc286
commit b68111da6c
19 changed files with 1033 additions and 449 deletions

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,9 @@ permissions:
children:
nocheat.checks.chat.spam:
description: Allow a player to send an infinite amount of chat messages
children:
nocheat.checks.chat.spam.bot:
description: Exempt players from the proxy server check and always declare them as "not spambot"
nocheat.checks.chat.color:
description: Allow a player to send colored chat messages
nocheat.checks.fight:

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>cc.co.evenprime.bukkit</groupId>
<artifactId>NoCheat</artifactId>
<version>3.3.0</version>
<version>3.4.0</version>
<packaging>jar</packaging>
<name>NoCheat</name>
<properties>
@ -13,7 +13,7 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.1-R3-SNAPSHOT</version>
<version>1.1-R4-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

View File

@ -0,0 +1,18 @@
package cc.co.evenprime.bukkit.dnsbl;
import java.util.List;
import org.bukkit.entity.Player;
/**
* The class that handles the results of the proxy checks
* has to implement this.
*/
public interface ProxyServerCheckResultHandler {
/**
* If the list of failures is empty, the player and his ip
* passed all checks. If it is nonempty, it will contain
* the servers that have blacklisted the ip
*/
public void finishedTestForProxies(Player player, String ip, List<String> failures);
}

View File

@ -0,0 +1,118 @@
package cc.co.evenprime.bukkit.dnsbl;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
/**
* Test if the connecting IP address of players belongs to a
* known spam network. Most public proxy servers are used for
* E-Mail spam, therefore almost all public proxy servers that
* are used for Minecraft will be blacklisted for spam
*/
public class ProxyServerChecker {
private static final String[] attributes = {"A"};
private final Plugin plugin;
private final DirContext context;
private final String[] blocklistProviders;
/**
* We need a plugin as the owner for the created Bukkit tasks
* and a string array of adresses of dnsbl providers. See this
* page: http://www.dnsbl.info/dnsbl-list.php for potential
* lists.
*
*/
public ProxyServerChecker(Plugin plugin, String[] dnsblProviders) throws NamingException {
this.plugin = plugin;
this.blocklistProviders = dnsblProviders.clone();
Hashtable<Object, String> environment = new Hashtable<Object, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
context = new InitialDirContext(environment);
}
/**
* Test a player and his IP in a seperate bukkit thread for proxy usage.
* When finished, the handler will be informed in a Bukkit threadsafe way.
*/
public void check(final Player player, final String ip, final ProxyServerCheckResultHandler handler) {
Runnable r = new CheckRunnable(player, ip, handler);
// We have time, therefore let the bukkit scheduler do this
Bukkit.getScheduler().scheduleAsyncDelayedTask(plugin, r);
}
/**
* Runnable that does the actual dns checking
*
*/
public class CheckRunnable implements Runnable {
private final Player player;
private final ProxyServerCheckResultHandler handler;
private final String ip;
private final List<String> failures = new LinkedList<String>();
public CheckRunnable(Player player, String ip, ProxyServerCheckResultHandler handler) {
this.ip = ip;
this.player = player;
this.handler = handler;
}
@Override
public void run() {
// Invert the IP
String[] parts = ip.split("\\.");
StringBuilder buffer = new StringBuilder();
for(int i = parts.length - 1; i >= 0; i--) {
buffer.append(parts[i]).append('.');
}
final String invertedIp = buffer.toString();
for(String provider : blocklistProviders) {
String lookupHost = invertedIp + provider;
try {
context.getAttributes(lookupHost, attributes);
// If we got a response, the address is listed
// so the player failed that one.
failures.add(provider);
} catch(NameNotFoundException e) {
// great, the player is not on the blacklist
// e.printStackTrace();
} catch(NamingException e) {
// not so great, but I don't care here
// e.printStackTrace();
}
}
// We are done, let's schedule a sync task to handle
// the results
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
@Override
public void run() {
handler.finishedTestForProxies(player, ip, failures);
}
});
}
}
}

View File

@ -14,6 +14,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin;
import cc.co.evenprime.bukkit.dnsbl.ProxyServerChecker;
import cc.co.evenprime.bukkit.nocheat.checks.WorkaroundsListener;
import cc.co.evenprime.bukkit.nocheat.checks.blockbreak.BlockBreakCheckListener;
import cc.co.evenprime.bukkit.nocheat.checks.blockplace.BlockPlaceCheckListener;
@ -203,4 +204,8 @@ public class NoCheat extends JavaPlugin implements Listener {
public void setFileLogger(Logger logger) {
this.fileLogger = logger;
}
public ProxyServerChecker getProxyServerChecker() {
return this.conf.getProxyServerChecker();
}
}

View File

@ -5,7 +5,13 @@ package cc.co.evenprime.bukkit.nocheat.actions;
*
*/
public enum ParameterName {
PLAYER("player"), LOCATION("location"), WORLD("world"), VIOLATIONS("violations"), MOVEDISTANCE("movedistance"), REACHDISTANCE("reachdistance"), FALLDISTANCE("falldistance"), LOCATION_TO("locationto"), CHECK("check"), PACKETS("packets"), TEXT("text"), PLACE_LOCATION("placelocation"), PLACE_AGAINST("placeagainst"), BLOCK_TYPE("blocktype"), LIMIT("limit"), FOOD("food");
PLAYER("player"), LOCATION("location"), WORLD("world"),
VIOLATIONS("violations"), MOVEDISTANCE("movedistance"),
REACHDISTANCE("reachdistance"), FALLDISTANCE("falldistance"),
LOCATION_TO("locationto"), CHECK("check"), PACKETS("packets"),
TEXT("text"), PLACE_LOCATION("placelocation"),
PLACE_AGAINST("placeagainst"), BLOCK_TYPE("blocktype"), LIMIT("limit"),
FOOD("food"), SERVERS("servers");
private final String s;

View File

@ -7,6 +7,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import cc.co.evenprime.bukkit.nocheat.EventManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
@ -15,10 +16,11 @@ import cc.co.evenprime.bukkit.nocheat.config.Permissions;
public class ChatCheckListener implements Listener, EventManager {
private final SpamCheck spamCheck;
private final ColorCheck colorCheck;
private final SpamCheck spamCheck;
private final SpambotTest spambotCheck;
private final ColorCheck colorCheck;
private final NoCheat plugin;
private final NoCheat plugin;
public ChatCheckListener(NoCheat plugin) {
@ -26,6 +28,7 @@ public class ChatCheckListener implements Listener, EventManager {
spamCheck = new SpamCheck(plugin);
colorCheck = new ColorCheck(plugin);
spambotCheck = new SpambotTest(plugin);
}
@EventHandler(priority = EventPriority.LOWEST)
@ -43,7 +46,6 @@ public class ChatCheckListener implements Listener, EventManager {
final NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
final ChatConfig cc = ChatCheck.getConfig(player.getConfigurationStore());
final ChatData data = ChatCheck.getData(player.getDataStore());
data.message = event.getMessage();
@ -61,7 +63,22 @@ public class ChatCheckListener implements Listener, EventManager {
} else {
event.setMessage(data.message);
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void connect(PlayerJoinEvent event) {
NoCheatPlayer player = plugin.getPlayer(event.getPlayer());
ChatConfig config = ChatCheck.getConfig(player.getConfigurationStore());
final ChatData data = ChatCheck.getData(player.getDataStore());
if(!config.spambotCheck || player.hasPermission(Permissions.CHAT_SPAM_BOT)) {
data.botcheckpassed = true;
} else {
data.botcheckpassed = false;
}
spambotCheck.startTestForProxies(event.getPlayer(), event.getPlayer().getAddress().getAddress().getHostAddress());
}
public List<String> getActiveChecks(ConfigurationCacheStore cc) {
@ -72,6 +89,8 @@ public class ChatCheckListener implements Listener, EventManager {
s.add("chat.spam");
if(c.colorCheck)
s.add("chat.color");
if(c.spamCheck && c.spambotCheck)
s.add("chat.spambot");
return s;
}
}

View File

@ -12,22 +12,32 @@ public class ChatConfig implements ConfigItem {
public final boolean spamCheck;
public final String[] spamWhitelist;
public final int spamTimeframe;
public final int spamLimit;
public final int spamMessageLimit;
public final ActionList spamActions;
public final boolean colorCheck;
public final ActionList colorActions;
public final int commandLimit;
public final int spamCommandLimit;
public final boolean spambotCheck;
public final ActionList spambotActions;
public final int spambotCommandLimit;
public final int spambotMessageLimit;
public final int spambotTimeframe;
public ChatConfig(NoCheatConfiguration data) {
spamCheck = data.getBoolean(ConfPaths.CHAT_SPAM_CHECK);
spamWhitelist = splitWhitelist(data.getString(ConfPaths.CHAT_SPAM_WHITELIST));
spamTimeframe = data.getInt(ConfPaths.CHAT_SPAM_TIMEFRAME);
spamLimit = data.getInt(ConfPaths.CHAT_SPAM_LIMIT);
commandLimit = data.getInt(ConfPaths.CHAT_SPAM_COMMANDLIMIT);
spamMessageLimit = data.getInt(ConfPaths.CHAT_SPAM_MESSAGELIMIT);
spamCommandLimit = data.getInt(ConfPaths.CHAT_SPAM_COMMANDLIMIT);
spamActions = data.getActionList(ConfPaths.CHAT_SPAM_ACTIONS);
colorCheck = data.getBoolean(ConfPaths.CHAT_COLOR_CHECK);
colorActions = data.getActionList(ConfPaths.CHAT_COLOR_ACTIONS);
spambotCheck = data.getBoolean(ConfPaths.CHAT_SPAMBOT_CHECK);
spambotActions = data.getActionList(ConfPaths.CHAT_SPAMBOT_ACTIONS);
spambotCommandLimit = data.getInt(ConfPaths.CHAT_SPAMBOT_COMMANDLIMIT);
spambotMessageLimit = data.getInt(ConfPaths.CHAT_SPAMBOT_MESSAGELIMIT);
spambotTimeframe = data.getInt(ConfPaths.CHAT_SPAMBOT_TIMEFRAME);
}
private String[] splitWhitelist(String string) {

View File

@ -1,5 +1,6 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
import java.util.LinkedList;
import cc.co.evenprime.bukkit.nocheat.DataItem;
/**
@ -7,11 +8,13 @@ import cc.co.evenprime.bukkit.nocheat.DataItem;
*/
public class ChatData implements DataItem {
public int spamVL;
public int colorVL;
public int spamVL;
public int colorVL;
public int messageCount = 0;
public int commandCount = 0;
public long spamLastTime = 0;
public String message = "";
public int messageCount = 0;
public int commandCount = 0;
public long spamLastTime = 0;
public String message = "";
public boolean botcheckpassed = true;
public LinkedList<String> spamBotFailed = new LinkedList<String>();
}

View File

@ -4,6 +4,7 @@ import java.util.Locale;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.data.Statistics.Id;
public class SpamCheck extends ChatCheck {
@ -23,9 +24,23 @@ public class SpamCheck extends ChatCheck {
}
}
int commandLimit = 0;
int messageLimit = 0;
int timeframe = 0;
// Set limits depending on "proxy server check" results
if(data.botcheckpassed || player.hasPermission(Permissions.CHAT_SPAM_BOT)) {
commandLimit = cc.spamCommandLimit;
messageLimit = cc.spamMessageLimit;
timeframe = cc.spamTimeframe;
} else {
commandLimit = cc.spambotCommandLimit;
messageLimit = cc.spambotMessageLimit;
timeframe = cc.spambotTimeframe;
}
final long time = System.currentTimeMillis() / 1000;
if(data.spamLastTime + cc.spamTimeframe <= time) {
if(data.spamLastTime + timeframe <= time) {
data.spamLastTime = time;
data.messageCount = 0;
data.commandCount = 0;
@ -40,10 +55,10 @@ public class SpamCheck extends ChatCheck {
else
data.messageCount++;
if(data.messageCount > cc.spamLimit || data.commandCount > cc.commandLimit) {
if(data.messageCount > messageLimit || data.commandCount > commandLimit) {
data.spamVL = Math.max(0, data.messageCount - cc.spamLimit);
data.spamVL += Math.max(0, data.commandCount - cc.commandLimit);
data.spamVL = Math.max(0, data.messageCount - messageLimit);
data.spamVL += Math.max(0, data.commandCount - commandLimit);
incrementStatistics(player, Id.CHAT_SPAM, 1);
cancel = executeActions(player, cc.spamActions.getActions(data.spamVL));

View File

@ -0,0 +1,66 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.dnsbl.ProxyServerCheckResultHandler;
import cc.co.evenprime.bukkit.dnsbl.ProxyServerChecker;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.NoCheatPlayer;
import cc.co.evenprime.bukkit.nocheat.actions.ParameterName;
/**
* The actual spam check is done at "SpamCheck". This will only
* do the initial test for proxy usage.
*
*/
public class SpambotTest extends ChatCheck implements ProxyServerCheckResultHandler {
public SpambotTest(NoCheat plugin) {
super(plugin, "chat.spambot");
}
public void startTestForProxies(Player player, String ip) {
ProxyServerChecker checker = plugin.getProxyServerChecker();
checker.check(player, ip, this);
}
/**
* This gets called after the checker finished his work. The checker
* makes sure that this is called in a save, synchronized way
*/
public void finishedTestForProxies(Player player, String ip, List<String> failures) {
NoCheatPlayer ncplayer = plugin.getPlayer(player);
ChatData data = ChatCheck.getData(ncplayer.getDataStore());
ChatConfig config = ChatCheck.getConfig(ncplayer.getConfigurationStore());
boolean cancelled = false;
if(failures.size() > 0) {
data.spamBotFailed = new LinkedList<String>(failures);
// cancelled means the player stays in "spambot" status
cancelled = executeActions(ncplayer, config.spambotActions.getActions(failures.size()));
}
if(!cancelled) {
data.botcheckpassed = true;
}
}
public String getParameter(ParameterName wildcard, NoCheatPlayer player) {
if(wildcard == ParameterName.VIOLATIONS)
return String.format(Locale.US, "%d", (int) getData(player.getDataStore()).spamBotFailed.size());
else if(wildcard == ParameterName.SERVERS) {
StringBuilder sb = new StringBuilder();
List<String> strings = getData(player.getDataStore()).spamBotFailed;
for(String s : strings) {
sb.append(s).append(" ");
}
return sb.toString().trim();
} else
return super.getParameter(wildcard, player);
}
}

View File

@ -1,94 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat.dnsbl;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import javax.naming.Context;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
public class DnsBlocklistChecker {
private static final String[] attributes = {"A"};
private final NoCheat plugin;
private final DirContext context;
private final String[] blocklistProviders;
public DnsBlocklistChecker(NoCheat plugin, int limit, String... providers) throws NamingException {
Hashtable<Object, String> environment = new Hashtable<Object, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
context = new InitialDirContext(environment);
this.plugin = plugin;
this.blocklistProviders = providers;
}
public void check(final Player player, final String ip) {
// Invert IP
String[] parts = ip.split("\\.");
StringBuilder buffer = new StringBuilder();
for(int i = parts.length - 1; i >= 0; i--) {
buffer.append(parts[i]).append('.');
}
final String invertedIp = buffer.toString();
Runnable r = new CheckRunnable(invertedIp, player);
// We have time, therefore let the bukkit scheduler do this
Bukkit.getScheduler().scheduleAsyncDelayedTask(plugin, r);
}
public void finished(final Player player, final List<String> failures) {
}
/**
* Runnable that does the actual dns checking
*
*/
public class CheckRunnable implements Runnable {
private final String invertedIp;
private final Player player;
private final List<String> failures = new LinkedList<String>();
public CheckRunnable(String invertedIp, Player player) {
this.invertedIp = invertedIp;
this.player = player;
}
@Override
public void run() {
for(String provider : blocklistProviders) {
String lookupHost = invertedIp + provider;
try {
context.getAttributes(lookupHost, attributes);
// If we got a response, the address is listed
// so the player failed that one.
failures.add(provider);
} catch(NameNotFoundException e) {
// great, the player is not on the blacklist
// e.printStackTrace();
} catch(NamingException e) {
// not so great, but I don't care atm
// e.printStackTrace();
}
}
// We are done, let's work with the results
finished(player, failures);
}
}
}

View File

@ -23,7 +23,7 @@ public class InstantBowCheck extends InventoryCheck {
if(expectedTimeWhenStringDrawn < time) {
// Acceptable, reduce VL
data.instantBowVL *= 0.98D;
data.instantBowVL *= 0.90D;
} else if(data.lastBowInteractTime > time) {
// Security, if time ran backwards, reset
data.lastBowInteractTime = 0;

View File

@ -102,10 +102,18 @@ public abstract class ConfPaths {
public final static String CHAT_SPAM_CHECK = CHAT_SPAM + "active";
public final static String CHAT_SPAM_WHITELIST = CHAT_SPAM + "whitelist";
public final static String CHAT_SPAM_TIMEFRAME = CHAT_SPAM + "timeframe";
public final static String CHAT_SPAM_LIMIT = CHAT_SPAM + "messagelimit";
public final static String CHAT_SPAM_MESSAGELIMIT = CHAT_SPAM + "messagelimit";
public final static String CHAT_SPAM_COMMANDLIMIT = CHAT_SPAM + "commandlimit";
public final static String CHAT_SPAM_ACTIONS = CHAT_SPAM + "actions";
private final static String CHAT_SPAMBOT = CHAT_SPAM + "bot.";
public static final String CHAT_SPAMBOT_CHECK = CHAT_SPAMBOT + "active";
public static final String CHAT_SPAMBOT_TIMEFRAME = CHAT_SPAMBOT + "timeframe";
public static final String CHAT_SPAMBOT_COMMANDLIMIT = CHAT_SPAMBOT + "commandlimit";
public static final String CHAT_SPAMBOT_MESSAGELIMIT = CHAT_SPAMBOT + "messagelimit";
public static final String CHAT_SPAMBOT_SERVERS = CHAT_SPAMBOT + "servers";
public static final String CHAT_SPAMBOT_ACTIONS = CHAT_SPAMBOT + "actions";
private final static String FIGHT = CHECKS + "fight.";
private final static String FIGHT_DIRECTION = FIGHT + "direction.";

View File

@ -11,11 +11,11 @@ import cc.co.evenprime.bukkit.nocheat.ConfigItem;
*/
public class ConfigurationCacheStore {
public final LoggingConfig logging;
public final LoggingConfig logging;
private final Map<String, ConfigItem> configMap = new HashMap<String, ConfigItem>();
private final NoCheatConfiguration data;
private final NoCheatConfiguration data;
/**
* Instantiate a config cache and populate it with the data of a

View File

@ -13,6 +13,8 @@ import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.naming.NamingException;
import cc.co.evenprime.bukkit.dnsbl.ProxyServerChecker;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
/**
@ -28,6 +30,8 @@ public class ConfigurationManager {
private FileHandler fileHandler;
private final NoCheat plugin;
private ProxyServerChecker proxyServerChecker;
private static class LogFileFormatter extends Formatter {
private final SimpleDateFormat date;
@ -99,6 +103,15 @@ public class ConfigurationManager {
root.regenerateActionLists();
// Setup spambot checker
ProxyServerChecker checker = null;
try {
checker = new ProxyServerChecker(plugin, root.getString(ConfPaths.CHAT_SPAMBOT_SERVERS).split("\\s+"));
} catch(NamingException e1) {
System.out.println("Nocheat couldn't setup the 'ProxyServerChecker': " + e1.getMessage());
}
proxyServerChecker = checker;
// Create a corresponding Configuration Cache
// put the global config on the config map
worldnameToConfigCacheMap.put(null, new ConfigurationCacheStore(root));
@ -226,4 +239,8 @@ public class ConfigurationManager {
return cache;
}
}
public ProxyServerChecker getProxyServerChecker() {
return proxyServerChecker;
}
}

View File

@ -85,10 +85,17 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.CHAT_SPAM_CHECK, true);
set(ConfPaths.CHAT_SPAM_WHITELIST, "");
set(ConfPaths.CHAT_SPAM_TIMEFRAME, 3);
set(ConfPaths.CHAT_SPAM_LIMIT, 3);
set(ConfPaths.CHAT_SPAM_MESSAGELIMIT, 3);
set(ConfPaths.CHAT_SPAM_COMMANDLIMIT, 12);
set(ConfPaths.CHAT_SPAM_ACTIONS, "log:spam:0:3:if cancel vl>30 log:spam:0:3:cif cancel cmd:kick");
set(ConfPaths.CHAT_SPAMBOT_CHECK, true);
set(ConfPaths.CHAT_SPAMBOT_TIMEFRAME, 60);
set(ConfPaths.CHAT_SPAMBOT_MESSAGELIMIT, 3);
set(ConfPaths.CHAT_SPAMBOT_COMMANDLIMIT, 12);
set(ConfPaths.CHAT_SPAMBOT_SERVERS, "bl.spamcop.net cbl.abuseat.org socks.dnsbl.sorbs.net tor.dnsbl.sectoor.de zen.spamhaus.org");
set(ConfPaths.CHAT_SPAMBOT_ACTIONS, "log:sbot:0:0:cif vl>2 log:sbot:0:0:cif cancel vl>4 log:sbot:0:0:cif cancel cmd:kick");
/*** FIGHT ***/
set(ConfPaths.FIGHT_DIRECTION_CHECK, true);
@ -107,7 +114,7 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.FIGHT_SPEED_CHECK, true);
set(ConfPaths.FIGHT_SPEED_ATTACKLIMIT, 15);
set(ConfPaths.FIGHT_SPEED_ACTIONS, "log:fspeed:0:5:if cancel");
set(ConfPaths.FIGHT_GODMODE_CHECK, true);
set(ConfPaths.FIGHT_GODMODE_ACTIONS, "log:fgod:2:5:if cancel");
@ -123,6 +130,7 @@ public class DefaultConfiguration extends NoCheatConfiguration {
set(ConfPaths.STRINGS + ".bpdirection", "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".color", "[player] failed [check]: Sent colored chat message '[text]'. VL [violations]");
set(ConfPaths.STRINGS + ".spam", "[player] failed [check]: Last sent message '[text]'. VL [violations]");
set(ConfPaths.STRINGS + ".sbot", "[player] failed [check]: Blacklisted at [violations] servers: [servers]");
set(ConfPaths.STRINGS + ".fdirection", "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]");
set(ConfPaths.STRINGS + ".freach", "[player] failed [check]: tried to attack entity out of reach. VL [violations]");
set(ConfPaths.STRINGS + ".fspeed", "[player] failed [check]: tried to attack more than [limit] times per second. VL [violations]");

View File

@ -29,6 +29,7 @@ public class Permissions {
public final static String CHAT = CHECKS + ".chat";
public final static String CHAT_SPAM = CHAT + ".spam";
public static final String CHAT_SPAM_BOT = CHAT_SPAM + ".bot";
public static final String CHAT_COLOR = CHAT + ".color";
public static final String FIGHT = CHECKS + ".fight";