1
0
mirror of https://github.com/NoCheatPlus/NoCheatPlus.git synced 2025-04-08 12:35:45 +02:00

Complete rewrite of internal configuration and action execution system

for performance
removed noclip check,  itemdrop check andgui editor
This commit is contained in:
Evenprime 2011-10-10 02:00:47 +02:00
parent 3d28e5738f
commit a8342b0681
83 changed files with 1739 additions and 3530 deletions
manifestplugin.yml
src/cc/co/evenprime/bukkit/nocheat
DefaultConfiguration.javaExplainations.javaNoCheat.java
actions
checks
config
data
events
file
log
wizard

View File

@ -1,2 +0,0 @@
Manifest-Version: 1.0
Main-Class: cc.co.evenprime.bukkit.nocheat.wizard.Wizard

View File

@ -3,14 +3,14 @@ name: NoCheat
author: Evenprime
main: cc.co.evenprime.bukkit.nocheat.NoCheat
version: 2.08c
version: 2.09
commands:
nocheat:
description: NoCheat command(s)
permission: nocheat.admin.permlist
usage: |
/<command> permlist player [permission] to list the NoCheat relevant permissions of the player, optionally only those starting with [permission]
nocheat:
description: NoCheat command(s)
usage: |
/<command> permlist player [permission] - to list the NoCheat relevant permissions of the player, optionally only those starting with [permission]
/<command> reload - to reload NoCheats configuration file(s), without reloading the plugin itself
permissions:
nocheat:
@ -23,6 +23,8 @@ permissions:
description: Show log messages in the players chat
nocheat.admin.permlist:
description: allow use of the "nocheat permlist" command
nocheat.admin.reload:
description: allow use of the "nocheat reload" command
nocheat.checks:
description: Allow the player to bypass all checks
children:
@ -37,8 +39,6 @@ permissions:
description: Allow a player to move through water without slowdown
nocheat.checks.moving.sneaking:
description: Allow a player to sneak without slowdown
nocheat.checks.moving.noclip:
description: Allow a player to walk through walls
nocheat.checks.moving.nofall:
description: Allow a player to cheat and not take fall damage at all
nocheat.checks.moving.morepackets:

View File

@ -1,377 +0,0 @@
package cc.co.evenprime.bukkit.nocheat;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionListOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.BooleanOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationTree;
import cc.co.evenprime.bukkit.nocheat.config.tree.IntegerOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.LogLevelOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.MediumStringOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ParentOption;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
* The place where the structure of the configuration tree is defined, the
* default settings are defined, the default files are defined.
*
* @author Evenprime
*
*/
public class DefaultConfiguration {
/**
* Create a full default options tree
*
* @return
*/
public static ConfigurationTree buildDefaultConfigurationTree() {
ConfigurationTree root = new ConfigurationTree();
/*** LOGGING section ***/
{
ParentOption loggingNode = new ParentOption("logging");
root.add(loggingNode);
loggingNode.add(new BooleanOption("active", true, true));
loggingNode.add(new MediumStringOption("filename", "nocheat.log"));
loggingNode.add(new LogLevelOption("filelevel", LogLevel.LOW));
loggingNode.add(new LogLevelOption("consolelevel", LogLevel.HIGH));
loggingNode.add(new LogLevelOption("chatlevel", LogLevel.MED));
}
/*** LOGGING section ***/
{
ParentOption debugNode = new ParentOption("debug");
root.add(debugNode);
debugNode.add(new BooleanOption("showactivechecks", false, false));
}
/*** MOVING ***/
{
ParentOption movingNode = new ParentOption("moving");
root.add(movingNode);
movingNode.add(new BooleanOption("check", true, true));
movingNode.add(new BooleanOption("identifycreativemode", true, false));
/**** MOVING.WALKING ****/
{
ParentOption runflyNode = new ParentOption("runfly");
movingNode.add(runflyNode);
runflyNode.add(new BooleanOption("check", true, true));
runflyNode.add(new IntegerOption("walkingspeedlimit", 22));
runflyNode.add(new IntegerOption("sprintingspeedlimit", 40));
runflyNode.add(new IntegerOption("jumpheight", 135));
runflyNode.add(new BooleanOption("checksneaking", true, false));
runflyNode.add(new IntegerOption("sneakingspeedlimit", 14));
runflyNode.add(new BooleanOption("checkswimming", true, false));
runflyNode.add(new IntegerOption("swimmingspeedlimit", 18));
ActionListOption walkactions = new ActionListOption("actions");
runflyNode.add(walkactions);
walkactions.add(0, "moveLogLowShort moveCancel");
walkactions.add(100, "moveLogMedShort moveCancel");
walkactions.add(400, "moveLogHighShort moveCancel");
runflyNode.add(new BooleanOption("checknofall", true, false));
runflyNode.add(new IntegerOption("nofallmultiplier", 120));
ActionListOption nofallactions = new ActionListOption("nofallactions");
runflyNode.add(nofallactions);
nofallactions.add(0, "nofallLog nofallDamage");
runflyNode.add(new BooleanOption("allowlimitedflying", false, false));
runflyNode.add(new IntegerOption("flyingspeedlimitvertical", 100));
runflyNode.add(new IntegerOption("flyingspeedlimithorizontal", 60));
ActionListOption flyactions = new ActionListOption("flyingactions");
runflyNode.add(flyactions);
flyactions.add(0, "moveLogLowShort moveCancel");
flyactions.add(100, "moveLogMedShort moveCancel");
flyactions.add(400, "moveLogHighShort moveCancel");
}
/**** MOVING.MOREPACKETS ****/
{
ParentOption morePacketsNode = new ParentOption("morepackets");
movingNode.add(morePacketsNode);
morePacketsNode.add(new BooleanOption("check", true, true));
ActionListOption actions = new ActionListOption("actions");
morePacketsNode.add(actions);
actions.add(0, "morepacketsLow moveCancel");
actions.add(30, "morepacketsMed moveCancel");
actions.add(60, "morepacketsHigh moveCancel");
}
/**** MOVING.NOCLIP ****/
{
ParentOption noclipNode = new ParentOption("noclip");
movingNode.add(noclipNode);
noclipNode.add(new BooleanOption("check", false, true));
ActionListOption actions = new ActionListOption("actions");
noclipNode.add(actions);
actions.add(1, "noclipLog");
}
}
/****** BLOCKBREAK ******/
{
ParentOption interactNode = new ParentOption("blockbreak");
root.add(interactNode);
interactNode.add(new BooleanOption("check", true, true));
/**** BLOCKBREAK.REACH ****/
{
ParentOption reachNode = new ParentOption("reach");
interactNode.add(reachNode);
reachNode.add(new BooleanOption("check", true, true));
reachNode.add(new IntegerOption("reachlimit", 485));
ActionListOption actions = new ActionListOption("actions");
reachNode.add(actions);
actions.add(0, "reachLog blockbreakCancel");
}
/**** BLOCKBREAK.DIRECTION ****/
{
ParentOption directionNode = new ParentOption("direction");
interactNode.add(directionNode);
directionNode.add(new BooleanOption("check", true, true));
directionNode.add(new BooleanOption("checkinstabreakblocks", false, false));
ActionListOption actions = new ActionListOption("actions");
directionNode.add(actions);
actions.add(0, "directionLog blockbreakCancel");
}
}
/****** BLOCKPLACE ******/
{
ParentOption blockPlaceNode = new ParentOption("blockplace");
root.add(blockPlaceNode);
blockPlaceNode.add(new BooleanOption("check", true, true));
/**** BLOCKPLACE.REACH ****/
{
ParentOption reachNode = new ParentOption("reach");
blockPlaceNode.add(reachNode);
reachNode.add(new BooleanOption("check", true, true));
reachNode.add(new IntegerOption("reachlimit", 485));
ActionListOption actions = new ActionListOption("actions");
reachNode.add(actions);
actions.add(0, "reachLog blockplaceCancel");
}
/**** BLOCKPLACE.ONLIQUID ****/
{
ParentOption onliquidNode = new ParentOption("onliquid");
blockPlaceNode.add(onliquidNode);
onliquidNode.add(new BooleanOption("check", true, true));
ActionListOption actions = new ActionListOption("actions");
onliquidNode.add(actions);
actions.add(0, "onliquidLog blockplaceCancel");
}
}
/****** INTERACT ******/
{
ParentOption interactNode = new ParentOption("interact");
root.add(interactNode);
interactNode.add(new BooleanOption("check", true, true));
/**** BLOCKBREAK.REACH ****/
{
ParentOption durabilityNode = new ParentOption("durability");
interactNode.add(durabilityNode);
durabilityNode.add(new BooleanOption("check", true, true));
ActionListOption actions = new ActionListOption("actions");
durabilityNode.add(actions);
actions.add(0, "durabilityLog interactCancel");
}
}
/****** CHAT ******/
{
ParentOption chatNode = new ParentOption("chat");
root.add(chatNode);
chatNode.add(new BooleanOption("check", true, true));
/**** CHAT.SPAM ****/
{
ParentOption spamNode = new ParentOption("spam");
chatNode.add(spamNode);
spamNode.add(new BooleanOption("check", false, true));
spamNode.add(new IntegerOption("timeframe", 5));
spamNode.add(new IntegerOption("limit", 5));
ActionListOption actions = new ActionListOption("actions");
spamNode.add(actions);
actions.add(0, "spamLog spamCancel");
}
}
return root;
}
public static void writeActionFile(File file) {
BufferedWriter w;
try {
if(!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
}
w = new BufferedWriter(new FileWriter(file));
w(w, "# This file contains the definitions of the default actions of NoCheat.");
w(w, "# DO NOT EDIT THIS FILE DIRECTLY. If you want to change any of these, copy");
w(w, "# them to your \"actions.txt\" file and modify them there. If an action with");
w(w, "# the same name exists here and in your file, yours will be used.");
w(w, "");
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
public static void writeDefaultActionFile(File file) {
BufferedWriter w;
try {
if(!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
}
w = new BufferedWriter(new FileWriter(file));
w(w, "# This file contains the definitions of the default actions of NoCheat.");
w(w, "# DO NOT EDIT THIS FILE DIRECTLY. If you want to change any of these, copy");
w(w, "# them to your \"actions.txt\" file and modify them there. If an action with");
w(w, "# the same name exists here and in your file, yours will be used.");
w(w, "#");
w(w, "# LOG Actions: They will print messages in your log file, console, chat, ...");
w(w, "# - They start with the word 'log'");
w(w, "# - Then comes their name. That name is used in the config file to identify them");
w(w, "# - Then comes the 'delay', that is how often has this action to be called before it really gets executed");
w(w, "# - Then comes the 'repeat', that is how many seconds have to be between two executions of the action");
w(w, "# - Then comes the 'loglevel', that is how the log message gets categorized (low, med, high)");
w(w, "# - Then comes the 'message', depending on where the action is used, different keywords in [ ] may be used");
w(w, "");
w(w, "# Gives a very short log message of the violation, only containing name, violation type and total violation value, at most once every 15 seconds, only if more than 3 violations happened within the last minute (low) and immediatly (med,high)");
w(w, "log moveLogLowShort 3 15 low NC: [player] failed [check]");
w(w, "log moveLogMedShort 0 15 med NC: [player] failed [check]");
w(w, "log moveLogHighShort 0 15 high NC: [player] failed [check]");
w(w, "");
w(w, "# Gives a log message of the violation, only containing name, violation type and total violation value, at most once every second, only if more than 5 violations happened within the last minute (low) and immediatly (med,high)");
w(w, "log morepacketsLow 5 1 low NC: [player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations].");
w(w, "log morepacketsMed 0 1 med NC: [player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations].");
w(w, "log morepacketsHigh 0 1 high NC: [player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations].");
w(w, "");
w(w, "# Gives a lengthy log message of the violation, containing name, location, violation type and total violation, at most once every 15 seconds, only if more than 3 violations happened within the last minute (low) and immediatly (med,high)");
w(w, "log moveLogLowLong 3 15 low NC: [player] in [world] at [location] moving to [locationto] over distance [distance] failed check [check]. Total violation level so far [violations].");
w(w, "log moveLogMedLong 0 15 med NC: [player] in [world] at [location] moving to [locationto] over distance [distance] failed check [check]. Total violation level so far [violations].");
w(w, "log moveLogHighLong 0 15 high NC: [player] in [world] at [location] moving to [locationto] over distance [distance] failed check [check]. Total violation level so far [violations].");
w(w, "");
w(w, "# Some other log messages that are limited a bit by default, to avoid too extreme spam");
w(w, "log noclipLog 0 1 high NC: [player] failed [check]: at [location] to [locationto].");
w(w, "log reachLog 0 1 med NC: [player] failed [check]: tried to interact with a block over distance [distance].");
w(w, "log directionLog 2 1 med NC: [player] failed [check]: tried to destroy a block out of line of sight.");
w(w, "log durabilityLog 0 1 med NC: [player] failed [check]: tried to use infinity durability hack.");
w(w, "log onliquidLog 2 1 med NC: [player] failed [check]: tried to place a [blocktype] block at [placelocation] against block at [placeagainst].");
w(w, "log spamLog 0 4 med NC: [player] failed [check]: Last sent message \"[text]\".");
w(w, "log nofallLog 0 1 med NC: [player] failed [check]: tried to avoid fall damage for ~[distance] blocks.");
w(w, "");
w(w, "# SPECIAL Actions: They will do something check dependant, usually cancel an event.");
w(w, "# - They start with the word 'special'");
w(w, "# - Then comes their name. That name is used in the config file to identify them");
w(w, "# - Then comes the 'delay', that is how often has this action to be called before it really gets executed");
w(w, "# - Then comes the 'repeat', that is how many seconds have to be between two executions of the action");
w(w, "# - Then come further instructions, if necessary");
w(w, "");
w(w, "# Cancels the event in case of an violation. Always. No delay. These are equivalent. The different names are just for better readability");
w(w, "special moveCancel 0 0");
w(w, "special blockbreakCancel 0 0");
w(w, "special blockplaceCancel 0 0");
w(w, "special interactCancel 0 0");
w(w, "special spamCancel 0 0");
w(w, "special nofallDamage 0 0");
w(w, "");
w(w, "# CONSOLECOMMAND Actions: They will execute a command as if it were typed into the console.");
w(w, "# - They start with the word 'consolecommand'");
w(w, "# - Then comes their name. That name is used in the config file to identify them");
w(w, "# - Then comes the 'delay', that is how often has this action to be called before it really gets executed");
w(w, "# - Then comes the 'repeat', that is how many seconds have to be between two executions of the action");
w(w, "# - Then comes the command. You can use the same [ ] that you use for log actions. You'll most likely want to use [player] at some point.");
w(w, "");
w(w, "# E.g. Kick a player");
w(w, "consolecommand kick 0 0 kick [player]");
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
private static void w(BufferedWriter writer, String text) throws IOException {
writer.write(text);
writer.newLine();
}
}

View File

@ -1,103 +0,0 @@
package cc.co.evenprime.bukkit.nocheat;
import java.util.HashMap;
import java.util.Map;
/**
* Textual explainations of options, will be displayed in the gui tool and the
* descriptions.txt file.
*
* @author Evenprime
*
*/
public class Explainations {
private static final Map<String, String> explainations = new HashMap<String, String>();
static {
set("logging.active", "Should NoCheat related messages get logged at all. Some messages may still appear, e.g. error\n messages, even if this option is deactivated");
set("logging.filename", "Where logs that go to the logfile are stored. You can have different files for different worlds.");
set("logging.filelevel", "What log-level need messages to have to get stored in the logfile. Values are:\n low: all messages\n med: med and high messages only\n high: high messages only\n off: no messages at all.");
set("logging.consolelevel", "What log-level need messages to have to get displayed in your server console. Values are:\n low: all messages\n med: med and high messages only\n high: high messages only\n off: no messages at all.");
set("logging.chatlevel", "What log-level need messages to have to get displayed in the ingame chat. Values are:\n low: all messages\n med: med and high messages only\n high: high messages only\n off: no messages at all.");
set("debug.showactivechecks", "Print to the console an overview of all checks that are enabled when NoCheat gets loaded.");
set("moving.check", "If true, do various checks on PlayerMove events.");
set("moving.identifycreativemode", "If true, NoCheat will automatically identify if players are in creative mode and will allow them to fly, avoid fall damage etc.");
set("moving.runfly.check", "If true, check if a player is walking/sprinting/sneaking/swimming too fast/high.");
set("moving.runfly.walkingspeedlimit", "Set the speed limit for moving horizontal under 'normal' conditions.\nUnit is 1/100 of a block, default is 22.");
set("moving.runfly.sprintingspeedlimit", "Set the speed limit for moving horizontal while sprinting.\nUnit is 1/100 of a block, default is 40.");
set("moving.runfly.jumpheight", "Set how high a player is allowed to jump.\nUnit is 1/100 of a block, default is 135.");
set("moving.runfly.checkswimming", "Use a seperate speed limit for swimming players.");
set("moving.runfly.swimmingspeedlimit", "Set the speed limit for moving horizontal while in water.\nUnit is 1/100 of a block, default is 18");
set("moving.runfly.checksneaking", "Use a seperate speed limit for sneaking players.");
set("moving.runfly.sneakingspeedlimit", "Set the speed limit for moving horizontal while sneaking.\nUnit is 1/100 of a block, default is 14");
set("moving.runfly.actions", "What should be done if a player moves faster than the speed limit(s) or jumps higher than allowed.\nUnits are in 1/100 of a block above the limit.");
set("moving.runfly.checknofall", "If true, check if a player is avoiding fall damage by using a nofall hack. EXPERIMENTAL! Feedback is appreciated.");
set("moving.runfly.nofallmultiplier", "How many percent falldamage should be dealt to the player.\nNoCheat will almost always underestimate fall damage, using a value bigger than 100 is advised.\nUnit is percent of the estimated original fall damage, default is 200.");
set("moving.runfly.nofallactions", "What should be done if a player is detected as avoiding fall damage.\nUnit is number of blocks the player fell down.");
set("moving.runfly.allowlimitedflying", "If true, instead of doing the above checks for walking/sprinting/swimming/sneaking,\nallow flying and only limit the flying speed.");
set("moving.runfly.flyingspeedlimitvertical", "Set the speed limit for moving vertical while flying.\nUnit is 1/100 of a block, default is 100.");
set("moving.runfly.flyingspeedlimithorizontal", "Set the speed limit for moving horizontal while flying.\nUnit is 1/100 of a block, default is 60.");
set("moving.runfly.flyingactions", "What should be done if a player flies faster than the speed limit(s). \nUnits are in 1/100 of a block above the speedlimit.");
set("moving.morepackets.check", "If true, check if a player is sending too many 'move-packets' per second. In a normal game, the player won't send more than 22 packets per second.");
set("moving.morepackets.actions", "What should be done if a player sends more 'move-packets' than normal.\nUnits are packets per second above the limit.");
set("moving.noclip.check", "If true, check if a player is moving into a solid wall. EXPERIMENTAL! DOESN'T WORK RELIABLY! USE WITH CAUTION AND ONLY FOR NOTIFICATIONS!");
set("moving.noclip.actions", "What should be done if a player moves into a wall.\nUnit is number of walls a player walks into/through.");
set("blockbreak.check", "If true, do various checks on BlockBreak events.");
set("blockbreak.reach.check", "If true, check if a player is breaking blocks that are too far away.");
set("blockbreak.reach.reachlimit", "Set the distance limit for breaking blocks.\nUnit is 1/100 of a block, default is 485");
set("blockbreak.reach.actions", "What should be done if a player is breaking blocks that are too far away.\nUnit is number of break(attempt)s beyond the limit.");
set("blockbreak.direction.check", "If true, check if a player is looking at the block that he's breaking.");
set("blockbreak.direction.checkinstabreakblocks", "If true, NoCheat will also check for direction for Instant-Breaking blocks.\nTHIS WILL CAUSE FALSE POSITIVES, when a player keeps his mouse button pressed and moves the mouse fast over the screen.");
set("blockbreak.direction.actions", "What should be done if a player is breaking blocks that are not in his line of sight.\nUnit is number of break(attempt)s outside the line of sight.");
set("blockplace.check", "If true, do various checks on BlockPlace events.");
set("blockplace.reach.check", "If true, check if a player is placing blocks at locations too far away.");
set("blockplace.reach.reachlimit", "Set the distance limit for placing blocks.\nUnit is 1/100 of a block, default is 485");
set("blockplace.reach.actions", "What should be done if a player is placing blocks that are too far away.\nUnit is number of place(attempt)s beyond the limit.");
set("blockplace.onliquid.check", "If true, check if a player is trying to place non-liquid blocks against liquid blocks\nIn a normal Minecraft game, it is impossible to place a block without it touching something that is considered solid (neither air nor a liquid).\nBut if people use a modified client, to can do that. This check tries to identify that trick.");
set("blockplace.onliquid.actions", "What should be done if a player is is trying to place non-liquid blocks against liquid blocks.\nUnit is number of place(attempt)s.");
set("interact.check", "If true, do various checks on PlayerInteract events.");
set("interact.durability.check", "If true, check if a player is using a hack that provides infinite durability items.");
set("interact.durability.actions", "What should be done if a player is trying to use the hack.\nUnit is number of uses or attempts to use the hack.");
set("chat.check", "If true, do various checks on PlayerChat events.");
set("chat.spam.check", "If true, check if a player is spamming the chat.");
set("chat.spam.timeframe", "Over what timeframe (in seconds) should the messages be counted?\nWhen the time is over, counting starts at 0 again.");
set("chat.spam.limit", "How many messages per timeframe may the player send without it counting as spamming?");
set("chat.spam.actions", "What should be done if a player is trying to spam the chat.\nUnit is number of chat messages above the limit you declared above.");
}
private static void set(String id, String text) {
explainations.put(id, text);
}
public static String get(String id) {
String result = explainations.get(id);
if(result == null) {
result = "No description available";
}
return result;
}
}

View File

@ -14,6 +14,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import cc.co.evenprime.bukkit.nocheat.actions.ActionManager;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
@ -21,7 +22,6 @@ import cc.co.evenprime.bukkit.nocheat.events.BlockPlaceEventManager;
import cc.co.evenprime.bukkit.nocheat.events.BlockBreakEventManager;
import cc.co.evenprime.bukkit.nocheat.events.EventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerChatEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerItemDropEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerInteractEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerMoveEventManager;
import cc.co.evenprime.bukkit.nocheat.events.PlayerTeleportEventManager;
@ -42,6 +42,7 @@ public class NoCheat extends JavaPlugin {
private ConfigurationManager conf;
private LogManager log;
private DataManager data;
private ActionManager action;
private List<EventManager> eventManagers = new LinkedList<EventManager>();
@ -51,8 +52,6 @@ public class NoCheat extends JavaPlugin {
private long lastIngamesecondDuration = 0L;
private boolean skipCheck = false;
private ActionManager action;
public NoCheat() {
}
@ -76,18 +75,16 @@ public class NoCheat extends JavaPlugin {
// First set up logging
this.log = new LogManager(this);
log.logToConsole(LogLevel.LOW, "[NoCheat] This version is for CB #1185. It may break at any time and for any other version.");
log.logToConsole(LogLevel.LOW, "[NoCheat] This version is for CB #1240. It may break at any time and for any other version.");
this.data = new DataManager();
this.action = new ActionManager(log);
this.action = new ActionManager();
// parse the nocheat.yml config file
this.conf = new ConfigurationManager(this.getDataFolder().getPath(), action);
eventManagers.add(new PlayerMoveEventManager(this));
eventManagers.add(new PlayerTeleportEventManager(this));
eventManagers.add(new PlayerItemDropEventManager(this));
eventManagers.add(new PlayerInteractEventManager(this));
eventManagers.add(new PlayerChatEventManager(this));
eventManagers.add(new BlockBreakEventManager(this));
@ -197,6 +194,12 @@ public class NoCheat extends JavaPlugin {
if(command.getName().equalsIgnoreCase("nocheat") && args.length > 0) {
if(args[0].equalsIgnoreCase("permlist") && args.length >= 2) {
// permlist command was used CORRECTLY
// Does the sender have permission?
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_PERMLIST)) {
return false;
}
// Get the player names
Player player = this.getServer().getPlayerExact(args[1]);
if(player == null) {
@ -219,6 +222,16 @@ public class NoCheat extends JavaPlugin {
}
return true;
}
} else if(args[0].equalsIgnoreCase("reload")) {
// reload command was used
// Does the sender have permission?
if(sender instanceof Player && !sender.hasPermission(Permissions.ADMIN_RELOAD)) {
return false;
}
this.conf.cleanup();
this.conf = new ConfigurationManager(this.getDataFolder().getPath(), this.action);
}
}
return false;

View File

@ -1,19 +1,77 @@
package cc.co.evenprime.bukkit.nocheat.actions;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.history.ActionHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
import cc.co.evenprime.bukkit.nocheat.actions.types.ConsolecommandAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
* An ActionExecutor does exactly that, executing actions.
* Will trace the history of action executions to decide if an action 'really'
* gets executed.
*
* @author Evenprime
*
*/
public interface ActionExecutor {
public class ActionExecutor {
public abstract boolean executeActions(Player player, ActionList actions, int violationLevel, HashMap<String, String> hashMap, ConfigurationCache cc);
private final Map<Player, ActionHistory> actionHistory = new HashMap<Player, ActionHistory>();
private final NoCheat plugin;
private final ConsoleCommandSender ccsender;
public ActionExecutor(NoCheat plugin) {
this.plugin = plugin;
this.ccsender = new ConsoleCommandSender(plugin.getServer());
}
public boolean executeActions(Player player, ActionList actions, int violationLevel, LogData data, ConfigurationCache cc) {
boolean special = false;
// Always set this here "by hand"
data.violationLevel = violationLevel;
long time = System.currentTimeMillis() / 1000;
for(Action ac : actions.getActions(violationLevel)) {
if(getHistory(player).executeAction(ac, time)) {
if(ac instanceof LogAction) {
LogAction l = (LogAction) ac;
plugin.getLogManager().log(l.level, l.getMessage(data), cc);
} else if(ac instanceof SpecialAction) {
special = true;
} else if(ac instanceof ConsolecommandAction) {
executeConsoleCommand(((ConsolecommandAction) ac).getCommand(data));
}
}
}
return special;
}
private ActionHistory getHistory(Player player) {
ActionHistory history = actionHistory.get(player);
if(history == null) {
history = new ActionHistory();
actionHistory.put(player, history);
}
return history;
}
private void executeConsoleCommand(String command) {
ccsender.executeConsoleCommand(command);
}
}

View File

@ -1,112 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.actions;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.history.ActionHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
import cc.co.evenprime.bukkit.nocheat.actions.types.ConsolecommandAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
import cc.co.evenprime.bukkit.nocheat.log.LogManager;
/**
* Implementation of ActionExecutor, that will trace the history of action
* executions to decide if an action 'really' gets executed.
*
* @author Evenprime
*
*/
public class ActionExecutorWithHistory implements ActionExecutor {
private final Map<Player, ActionHistory> actionHistory = new HashMap<Player, ActionHistory>();
private final ActionManager actionManager;
private final LogManager log;
private final ConsoleCommandSender ccsender;
public ActionExecutorWithHistory(NoCheat plugin) {
this.actionManager = plugin.getActionManager();
this.log = plugin.getLogManager();
this.ccsender = new ConsoleCommandSender(plugin.getServer());
}
/*
* (non-Javadoc)
*
* @see
* cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor#executeActions(
* org.bukkit.entity.Player,
* cc.co.evenprime.bukkit.nocheat.actions.ActionList, double,
* java.util.HashMap,
* cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache)
*/
@Override
public boolean executeActions(Player player, ActionList actions, int violationLevel, HashMap<String, String> hashMap, ConfigurationCache cc) {
boolean special = false;
for(String a : actions.getActions(violationLevel)) {
Action ac = actionManager.getActionByName(a);
Map<String, String> map = null;
if(ac != null) {
if(getHistory(player).executeAction(ac, System.currentTimeMillis())) {
if(ac instanceof LogAction) {
if(map == null)
map = generateHashMap(player, violationLevel, hashMap);
LogAction l = (LogAction) ac;
log.log(l.level, l.getLogMessage(map), cc);
} else if(ac instanceof SpecialAction) {
special = true;
} else if(ac instanceof ConsolecommandAction) {
if(map == null)
map = generateHashMap(player, violationLevel, hashMap);
executeConsoleCommand(((ConsolecommandAction) ac).getCommand(map));
}
}
} else {
log.logToConsole(LogLevel.HIGH, "NoCheat: Couldn't find action " + a + ". You need to define it properly to use it in your config file!");
}
}
return special;
}
private HashMap<String, String> generateHashMap(Player player, double violationLevel, HashMap<String, String> map) {
HashMap<String, String> newMap = new HashMap<String, String>();
newMap.put(LogAction.PLAYER, player.getName());
Location l = player.getLocation();
newMap.put(LogAction.LOCATION, String.format(Locale.US, "%.2f,%.2f,%.2f", l.getX(), l.getY(), l.getZ()));
newMap.put(LogAction.WORLD, player.getWorld().getName());
newMap.put(LogAction.VIOLATIONS, String.format(Locale.US, "%.2f", violationLevel));
newMap.putAll(map);
return newMap;
}
private ActionHistory getHistory(Player player) {
ActionHistory history = actionHistory.get(player);
if(history == null) {
history = new ActionHistory();
actionHistory.put(player, history);
}
return history;
}
private void executeConsoleCommand(String command) {
ccsender.executeConsoleCommand(command);
}
}

View File

@ -2,7 +2,11 @@ package cc.co.evenprime.bukkit.nocheat.actions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
/**
* A list of actions, that associates actions and a treshold. It allows to
@ -14,35 +18,11 @@ import java.util.List;
public class ActionList {
public ActionList() {}
private final static Action[] emptyArray = new Action[0];
private final List<ActionListEntry> actionList = new ArrayList<ActionListEntry>();
private class ActionListEntry implements Comparable<ActionListEntry> {
public final ArrayList<String> actions = new ArrayList<String>();
public final double treshold;
public ActionListEntry(double treshold, String[] actionNames) {
this.treshold = treshold;
for(String actionName : actionNames) {
if(actionName != null && actionName.length() > 0) {
actions.add(actionName.toLowerCase());
}
}
}
@Override
public int compareTo(ActionListEntry entry) {
if(treshold < entry.treshold) {
return -1;
} else if(treshold == entry.treshold) {
return 0;
} else
return 1;
}
}
private final Map<Integer, Action[]> actions = new HashMap<Integer, Action[]>();
private final List<Integer> tresholds = new ArrayList<Integer>();
/**
* Add an entry to this actionList. The list will be sorted by tresholds
@ -51,9 +31,14 @@ public class ActionList {
* @param treshold
* @param actionNames
*/
public void addEntry(double treshold, String[] actionNames) {
this.actionList.add(new ActionListEntry(treshold, actionNames));
Collections.sort(this.actionList);
public void setActions(Integer treshold, Action[] actions) {
if(!this.tresholds.contains(treshold)) {
this.tresholds.add(treshold);
Collections.sort(this.tresholds);
}
this.actions.put(treshold, actions);
}
/**
@ -64,19 +49,23 @@ public class ActionList {
* @param violationLevel
* @return
*/
public List<String> getActions(int vl) {
public Action[] getActions(Integer vl) {
ActionListEntry result = null;
for(ActionListEntry entry : actionList) {
if(entry.treshold <= vl) {
result = entry;
Integer result = null;
for(Integer treshold : tresholds) {
if(treshold <= vl) {
result = treshold;
}
}
if(result != null)
return result.actions;
return actions.get(result);
else
return Collections.emptyList();
return emptyArray;
}
public List<Integer> getTresholds() {
return tresholds;
}
}

View File

@ -4,123 +4,36 @@ import java.util.HashMap;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.ConsolecommandAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
import cc.co.evenprime.bukkit.nocheat.log.LogManager;
/**
* The ActionManager creates the specific actions and stores them with their
* unique name.
*
* @author Evenprime
*
*/
public class ActionManager {
private final Map<String, Action> actionIdsToActionMap = new HashMap<String, Action>();
private final Map<String, Action> actions;
private final LogManager log;
private final String[] knownTypes = {"log", "consolecommand", "special"};
public ActionManager(LogManager log) {
this.log = log;
public ActionManager() {
this.actions = new HashMap<String, Action>();
}
/**
*
* @param name
* To identify the action by a name. Same name means same action
*
* @param actionId
* Actual string describing the action (may be more than a string
* in future)
* @return
*/
public void createActionFromStrings(String type, String actionId, String stringDelay, String stringRepeat, String theRest) {
public void addAction(Action action) {
this.actions.put(action.name.toLowerCase(), action);
}
Action action = null;
public Action getAction(String actionName) {
type = type.toLowerCase();
actionId = actionId.toLowerCase();
return this.actions.get(actionName.toLowerCase());
}
int delay;
try {
delay = Integer.parseInt(stringDelay);
} catch(NumberFormatException e) {
log.logToConsole(LogLevel.HIGH, "Can't parse action: \"" + actionId + "\", first parameter " + stringDelay + " not a number");
return;
public Action[] getActions(String[] actionNames) {
Action[] result = new Action[actionNames.length];
for(int i = 0; i < actionNames.length; i++) {
result[i] = getAction(actionNames[i]);
}
int repeat;
try {
repeat = Integer.parseInt(stringRepeat);
} catch(NumberFormatException e) {
log.logToConsole(LogLevel.HIGH, "Can't parse action: \"" + actionId + "\", second parameter " + stringRepeat + " not a number");
return;
}
// Log actions have the form delay|repeat|level|message
if(type.equals("log")) {
String[] pieces = null;
if(theRest != null) {
pieces = theRest.split("\\s+", 2);
if(pieces == null || pieces.length < 2) {
log.logToConsole(LogLevel.HIGH, "Can't parse log action: \"" + actionId + "\", missing parameters");
return;
}
}
action = createLogActionFromString(delay, repeat, pieces[0], pieces[1]);
} else if(type.equals("special")) {
action = createCancelActionFromString(delay, repeat);
} else if(type.equals("consolecommand")) {
if(theRest == null) {
log.logToConsole(LogLevel.HIGH, "Can't parse consolecommand action: \"" + actionId + "\", missing parameter");
return;
}
action = createConsolecommandActionFromString(delay, repeat, theRest);
} else {
log.logToConsole(LogLevel.HIGH, "Can't parse action: \"" + actionId + "\", unknown action type");
return;
}
if(action != null) {
this.actionIdsToActionMap.put(actionId, action);
}
}
public String[] getKnownTypes() {
return knownTypes;
}
private ConsolecommandAction createConsolecommandActionFromString(int delay, int repeat, String command) {
return new ConsolecommandAction(delay, repeat, command);
}
private SpecialAction createCancelActionFromString(int delay, int repeat) {
return new SpecialAction(delay, repeat);
}
private Action createLogActionFromString(int delay, int repeat, String logLevel, String message) {
LogLevel level = LogLevel.getLogLevelFromString(logLevel);
if(level.equals(LogLevel.OFF)) {
return null;
}
return new LogAction(delay, repeat, level, message);
}
public Action getActionByName(String name) {
return actionIdsToActionMap.get(name.toLowerCase());
return result;
}
}

View File

@ -1,13 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.actions.history;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
/**
* Store last 60 seconds of action executions
* Store amount of action executions for last 60 seconds
*
* @author Evenprime
*
@ -16,25 +15,61 @@ public class ActionHistory {
private class ExecutionHistoryEntry {
private final LinkedList<Long> executionTimes = new LinkedList<Long>();
private final long monitoredTimeFrame = 60000;
private long lastExecution = 0;
private final int executionTimes[];
private long lastExecution = 0;
private int totalEntries = 0;
private long lastClearedTime = 0;
public ExecutionHistoryEntry() {}
public ExecutionHistoryEntry(int monitoredTimeFrame) {
this.executionTimes = new int[monitoredTimeFrame];
}
public void addCounter(Long time) {
/**
* Remember an execution at the specific time
*/
public void addCounter(long time) {
// clear out now outdated values from the array
if(time - lastClearedTime > 0) {
// Clear the next few fields of the array
clearTimes(lastClearedTime + 1, time - lastClearedTime);
lastClearedTime = time + 1;
}
executionTimes[(int) (time % executionTimes.length)]++;
totalEntries++;
}
synchronized(executionTimes) {
while(!executionTimes.isEmpty() && executionTimes.getFirst() < time - monitoredTimeFrame) {
executionTimes.removeFirst();
/**
* Clean parts of the array
*
* @param start
* @param length
*/
private void clearTimes(long start, long length) {
if(length <= 0) {
return; // nothing to do (yet)
}
if(length > executionTimes.length) {
length = executionTimes.length;
}
int j = (int) start % executionTimes.length;
for(int i = 0; i < length; i++) {
if(j == executionTimes.length) {
j = 0;
}
totalEntries -= executionTimes[j];
executionTimes[j] = 0;
executionTimes.addLast(time);
j++;
}
}
public int getCounter() {
return executionTimes.size();
return totalEntries;
}
public long getLastExecution() {
@ -55,11 +90,12 @@ public class ActionHistory {
/**
* Returns true, if the action should be executed, because all time
* criteria have been met. Will add a entry with the time to a list
* which will influence further requests, so only use once per
* check!
* which will influence further requests, so only use once and remember
* the result
*
* @param action
* @param time
* a time IN SECONDS
* @return
*/
public boolean executeAction(Action action, long time) {
@ -67,7 +103,7 @@ public class ActionHistory {
ExecutionHistoryEntry entry = executionHistory.get(action);
if(entry == null) {
entry = new ExecutionHistoryEntry();
entry = new ExecutionHistoryEntry(60);
executionHistory.put(action, entry);
}
@ -75,8 +111,8 @@ public class ActionHistory {
entry.addCounter(time);
if(entry.getCounter() > action.delay) {
// Execute action?
if(entry.getLastExecution() <= time - action.repeat * 1000) {
// Execute action?
if(entry.getLastExecution() <= time - action.repeat) {
// Execute action!
entry.setLastExecution(time);
return true;

View File

@ -14,15 +14,17 @@ public abstract class Action {
* Delay in violations (only do if there were more than "delay" exceptions
* in last 60 seconds)
*/
public final int delay;
public final int delay;
/**
* Repeat only every "repeat" seconds
*/
public final int repeat;
public final int repeat;
public Action(int delay, int repeat) {
public final String name;
public Action(String name, int delay, int repeat) {
this.name = name;
this.delay = delay;
this.repeat = repeat;
}

View File

@ -0,0 +1,164 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
import java.util.ArrayList;
import java.util.Locale;
import org.bukkit.Location;
import org.bukkit.block.Block;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
public abstract class ActionWithParameters extends Action {
protected enum WildCard {
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");
private final String s;
private WildCard(String s) {
this.s = s;
}
private static final WildCard get(String s) {
for(WildCard c : WildCard.values()) {
if(c.s.equals(s)) {
return c;
}
}
return null;
}
}
protected final ArrayList<Object> messageParts;
public ActionWithParameters(String name, int delay, int repeat, String message) {
super(name, delay, repeat);
messageParts = new ArrayList<Object>();
parseMessage(message);
}
protected void parseMessage(String message) {
String parts[] = message.split("\\[", 2);
// No opening braces left
if(parts.length != 2) {
messageParts.add(message);
}
// Found an opening brace
else {
String parts2[] = parts[1].split("\\]", 2);
// Found no matching closing brace
if(parts2.length != 2) {
messageParts.add(message);
}
// Found a matching closing brace
else {
WildCard w = WildCard.get(parts2[0]);
if(w != null) {
// Found an existing wildcard inbetween the braces
messageParts.add(parts[0]);
messageParts.add(w);
// Go further down recursive
parseMessage(parts2[1]);
} else {
messageParts.add(message);
}
}
}
}
/**
* Get a log message with all the wildcards replaced with data from LogData
*
* @param data
* @return
*/
public String getMessage(LogData data) {
StringBuilder log = new StringBuilder(100); // Should be big enough most
// of the time
for(Object part : messageParts) {
if(part instanceof String) {
log.append((String) part);
} else {
log.append(getParameter((WildCard) part, data));
}
}
return log.toString();
}
private String getParameter(WildCard wildcard, LogData data) {
// The == is correct here, as these really are identical objects, not
// only equal
switch (wildcard) {
case PLAYER:
return data.player.getName();
case CHECK:
return data.check;
case LOCATION:
Location l = data.player.getLocation();
return String.format(Locale.US, "%.2f,%.2f,%.2f", l.getX(), l.getY(), l.getZ());
case WORLD:
return data.player.getWorld().getName();
case VIOLATIONS:
return String.format(Locale.US, "%.2f", data.violationLevel);
case MOVEDISTANCE:
Location l2 = data.player.getLocation();
Location t = data.toLocation;
if(t != null) {
return String.format(Locale.US, "%.2f,%.2f,%.2f", t.getX() - l2.getX(), t.getY() - l2.getY(), t.getZ() - l2.getZ());
} else {
return "null";
}
case REACHDISTANCE:
return String.format(Locale.US, "%.2f", data.reachdistance);
case FALLDISTANCE:
return String.format(Locale.US, "%.2f", data.falldistance);
case LOCATION_TO:
Location to = data.toLocation;
return String.format(Locale.US, "%.2f,%.2f,%.2f", to.getX(), to.getY(), to.getZ());
case PACKETS:
return String.valueOf(data.packets);
case TEXT:
return data.text;
case PLACE_LOCATION:
Block block = data.placed;
if(block != null) {
return String.format(Locale.US, "%d %d %d", block.getX(), block.getY(), block.getZ());
} else {
return "null";
}
case PLACE_AGAINST:
Block blocka = data.placedAgainst;
if(blocka == null) {
return "null";
}
return String.format(Locale.US, "%d %d %d", blocka.getX(), blocka.getY(), blocka.getZ());
case BLOCK_TYPE:
return data.placedMaterial.toString();
default:
return "Evenprime was lazy and forgot to define " + wildcard + ".";
}
}
}

View File

@ -1,7 +1,6 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
import java.util.Map;
import java.util.Map.Entry;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
* Execute a command by imitating an admin typing the command directly into the
@ -10,24 +9,15 @@ import java.util.Map.Entry;
* @author Evenprime
*
*/
public class ConsolecommandAction extends Action {
public class ConsolecommandAction extends ActionWithParameters {
private final String command;
public ConsolecommandAction(String name, int delay, int repeat, String command) {
super(name, delay, repeat, command);
public ConsolecommandAction(int delay, int repeat, String command) {
super(delay, repeat);
this.command = command;
}
public String getCommand(Map<String, String> map) {
public String getCommand(LogData ldata) {
String com = command;
for(Entry<String, String> entry : map.entrySet()) {
com = com.replaceAll(entry.getKey(), entry.getValue());
}
return com;
return super.getMessage(ldata);
}
}

View File

@ -1,8 +1,6 @@
package cc.co.evenprime.bukkit.nocheat.actions.types;
import java.util.Map;
import java.util.Map.Entry;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
@ -11,43 +9,17 @@ import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
* @author Evenprime
*
*/
public class LogAction extends Action {
public class LogAction extends ActionWithParameters {
// Default stuff
public static final String PLAYER = "\\[player\\]";
public static final String LOCATION = "\\[location\\]";
public static final String WORLD = "\\[world\\]";
public static final String VIOLATIONS = "\\[violations\\]";
// Event dependent stuff
public static final String DISTANCE = "\\[distance\\]";
public static final String LOCATION_TO = "\\[locationto\\]";
public static final String CHECK = "\\[check\\]";
public static final String PACKETS = "\\[packets\\]";
public static final String TEXT = "\\[text\\]";
public static final String PLACE_LOCATION = "\\[placelocation\\]";
public static final String PLACE_AGAINST = "\\[placeagainst\\]";
public static final String BLOCK_TYPE = "\\[blocktype\\]";
public final LogLevel level;
private final String message;
public LogAction(int delay, int repeat, LogLevel level, String message) {
super(delay, repeat);
public final LogLevel level;
public LogAction(String name, int delay, int repeat, LogLevel level, String message) {
super(name, delay, repeat, message);
this.level = level;
this.message = message;
}
public String getLogMessage(Map<String, String> values) {
String log = message;
for(Entry<String, String> entry : values.entrySet()) {
log = log.replaceAll(entry.getKey(), entry.getValue());
}
return log;
public String getMessage(LogData ldata) {
return super.getMessage(ldata);
}
}

View File

@ -9,7 +9,7 @@ package cc.co.evenprime.bukkit.nocheat.actions.types;
*/
public class SpecialAction extends Action {
public SpecialAction(int delay, int repeat) {
super(delay, repeat);
public SpecialAction(String name, int delay, int repeat) {
super(name, delay, repeat);
}
}

View File

@ -1,13 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;

View File

@ -1,17 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
import java.util.HashMap;
import org.bukkit.block.Block;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
* The DirectionCheck will find out if a player tried to interact with something
@ -23,9 +20,11 @@ import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;
public class DirectionCheck {
private final ActionExecutor action;
private final NoCheat plugin;
public DirectionCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
this.action = new ActionExecutor(plugin);
}
public boolean check(Player player, double factor, double x1, double y1, double z1, Block brokenBlock, BlockBreakData data, ConfigurationCache cc) {
@ -51,10 +50,10 @@ public class DirectionCheck {
data.directionViolationLevel += 1;
// Prepare some event-specific values for logging and custom actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.CHECK, "blockbreak.direction");
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.check = "blockbreak.direction";
cancel = action.executeActions(player, cc.blockbreak.directionActions, (int) data.directionViolationLevel, params, cc);
cancel = action.executeActions(player, cc.blockbreak.directionActions, (int) data.directionViolationLevel, ldata, cc);
}
return cancel;

View File

@ -1,17 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockbreak;
import java.util.HashMap;
import java.util.Locale;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
* The reach check will find out if a player interacts with something that's too
@ -22,29 +18,30 @@ import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;
*/
public class ReachCheck {
private final NoCheat plugin;
private final ActionExecutor action;
public ReachCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
this.action = new ActionExecutor(plugin);
}
public boolean check(Player player, double distance, BlockBreakData data, ConfigurationCache cc) {
boolean cancel = false;
double limit = player.getGameMode() == GameMode.CREATIVE ? cc.blockbreak.reachDistance + 2 : cc.blockbreak.reachDistance;
double limit = player.getGameMode() == GameMode.CREATIVE ? cc.blockbreak.reachDistance + 2 : cc.blockbreak.reachDistance;
if(distance > limit) {
// Player failed the check
// Increment violation counter
data.reachViolationLevel += 1;
// Prepare some event-specific values for logging and custom actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.CHECK, "blockbreak.reach");
params.put(LogAction.DISTANCE, String.format(Locale.US, "%.2f", distance));
cancel = action.executeActions(player, cc.blockbreak.reachActions, (int) data.reachViolationLevel, params, cc);
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.check = "blockbreak.reach";
ldata.reachdistance = distance;
cancel = action.executeActions(player, cc.blockbreak.reachActions, (int) data.reachViolationLevel, ldata, cc);
} else {
data.reachViolationLevel *= 0.9D;
}

View File

@ -4,7 +4,7 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.BlockPlaceData;

View File

@ -1,8 +1,5 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
import java.util.HashMap;
import java.util.Locale;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
@ -10,10 +7,9 @@ import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.BlockPlaceData;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
*
@ -22,10 +18,12 @@ import cc.co.evenprime.bukkit.nocheat.data.BlockPlaceData;
*/
public class OnLiquidCheck {
private final NoCheat plugin;
private final ActionExecutor action;
public OnLiquidCheck(NoCheat plugin) {
action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
action = new ActionExecutor(plugin);
}
public boolean check(Player player, Block blockPlaced, Block blockPlacedAgainst, BlockPlaceData data, ConfigurationCache cc) {
@ -40,18 +38,12 @@ public class OnLiquidCheck {
// all ok
} else {
data.onliquidViolationLevel += 1;
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.CHECK, "blockplace.onliquid");
params.put(LogAction.BLOCK_TYPE, blockPlaced.getType().toString());
params.put(LogAction.PLACE_LOCATION, String.format(Locale.US, "%d %d %d", blockPlaced.getX(), blockPlaced.getY(), blockPlaced.getZ()));
if(blockPlacedAgainst != null) {
params.put(LogAction.PLACE_AGAINST, String.format(Locale.US, "%d %d %d", blockPlacedAgainst.getX(), blockPlacedAgainst.getY(), blockPlacedAgainst.getZ()));
}
else {
params.put(LogAction.PLACE_AGAINST, "null");
}
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.check = "blockplace.onliquid";
ldata.placed = blockPlaced;
ldata.placedAgainst = blockPlacedAgainst;
cancel = action.executeActions(player, cc.blockplace.onliquidActions, (int) data.onliquidViolationLevel, params, cc);
cancel = action.executeActions(player, cc.blockplace.onliquidActions, (int) data.onliquidViolationLevel, ldata, cc);
}
data.onliquidViolationLevel *= 0.95D; // Reduce level over time

View File

@ -1,8 +1,5 @@
package cc.co.evenprime.bukkit.nocheat.checks.blockplace;
import java.util.HashMap;
import java.util.Locale;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -10,10 +7,9 @@ import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.BlockPlaceData;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
* The reach check will find out if a player interacts with something that's too
@ -24,23 +20,25 @@ import cc.co.evenprime.bukkit.nocheat.data.BlockPlaceData;
*/
public class ReachCheck {
private final NoCheat plugin;
private final ActionExecutor action;
public ReachCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
this.action = new ActionExecutor(plugin);
}
public boolean check(Player player, Block blockPlaced, Block placedAgainstBlock, BlockPlaceData data, ConfigurationCache cc) {
boolean cancel = false;
Location eyes = player.getEyeLocation();
final double x1 = ((double) placedAgainstBlock.getX()) - eyes.getX();
final double y1 = ((double) placedAgainstBlock.getY()) - eyes.getY();
final double z1 = ((double) placedAgainstBlock.getZ()) - eyes.getZ();
double distance = new Vector(x1 + 0.5, y1 + + 0.5, z1 + + 0.5).length();
double distance = new Vector(x1 + 0.5, y1 + +0.5, z1 + +0.5).length();
if(distance > cc.blockplace.reachDistance) {
// Player failed the check
@ -49,10 +47,11 @@ public class ReachCheck {
data.reachViolationLevel += 1;
// Prepare some event-specific values for logging and custom actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.CHECK, "blockplace.reach");
params.put(LogAction.DISTANCE, String.format(Locale.US, "%.2f", distance));
cancel = action.executeActions(player, cc.blockplace.reachActions, (int) data.reachViolationLevel, params, cc);
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.check = "blockplace.reach";
ldata.reachdistance = distance;
cancel = action.executeActions(player, cc.blockplace.reachActions, (int) data.reachViolationLevel, ldata, cc);
} else {
data.reachViolationLevel *= 0.9D;
}

View File

@ -1,22 +1,18 @@
package cc.co.evenprime.bukkit.nocheat.checks.chat;
import java.util.HashMap;
import java.util.regex.Matcher;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.ChatData;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
*
* @author Evenprime
*
*
*/
public class ChatCheck {
@ -25,8 +21,8 @@ public class ChatCheck {
public ChatCheck(NoCheat plugin) {
action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
action = new ActionExecutor(plugin);
}
public boolean check(Player player, String message, ChatData data, ConfigurationCache cc) {
@ -50,14 +46,15 @@ public class ChatCheck {
// Prepare some event-specific values for logging and custom
// actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.CHECK, "chat.spam");
// Escape the message, to avoid errors
params.put(LogAction.TEXT, Matcher.quoteReplacement(message));
cancel = action.executeActions(player, cc.chat.spamActions, data.messageCount - cc.chat.spamLimit, params, cc);
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.check = "chat.spam";
ldata.text = message;
cancel = action.executeActions(player, cc.chat.spamActions, data.messageCount - cc.chat.spamLimit, ldata, cc);
}
}
return cancel;
}

View File

@ -1,16 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.checks.interact;
import java.util.HashMap;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.InteractData;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
/**
*
@ -19,10 +16,12 @@ import cc.co.evenprime.bukkit.nocheat.data.InteractData;
*/
public class InteractCheck {
private final NoCheat plugin;
private final ActionExecutor action;
public InteractCheck(NoCheat plugin) {
action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
action = new ActionExecutor(plugin);
}
public boolean check(Player player, InteractData data, ConfigurationCache cc) {
@ -36,10 +35,11 @@ public class InteractCheck {
if(player.getInventory().getHeldItemSlot() == 9) {
data.violationLevel += 1;
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.CHECK, "interact.durability");
cancel = action.executeActions(player, cc.interact.durabilityActions, (int) data.violationLevel, params, cc);
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.check = "interact.durability";
cancel = action.executeActions(player, cc.interact.durabilityActions, (int) data.violationLevel, ldata, cc);
}
data.violationLevel *= 0.95D; // Reduce level over time

View File

@ -1,11 +1,5 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import net.minecraft.server.EntityPlayer;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftPlayer;
@ -13,9 +7,8 @@ import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
@ -28,14 +21,14 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
*/
public class FlyingCheck {
private final NoCheat plugin;
private final ActionExecutor action;
private static Method isRunningMethod;
private static final double creativeSpeed = 0.60D;
public FlyingCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
this.action = new ActionExecutor(plugin);
}
public Location check(Player player, Location from, Location to, ConfigurationCache cc, MovingData data) {
@ -60,30 +53,26 @@ public class FlyingCheck {
result += Math.max(0.0D, horizontalDistance - data.horizFreedom - speedLimitHorizontal);
if(isRunningMethod == null) {
isRunningMethod = getIsRunningMethod();
}
boolean sprinting = true;
try {
sprinting = !(player instanceof CraftPlayer) || isRunningMethod.invoke(((CraftPlayer) player).getHandle()).equals(true);
sprinting = !(player instanceof CraftPlayer) || player.isSprinting();
} catch(Exception e) {
e.printStackTrace();
}
data.bunnyhopdelay--;
// Did he go too far?
if(result > 0 && sprinting) {
// Try to treat it as a the "bunnyhop" problem
if(data.bunnyhopdelay <= 0 && result < 0.4D) {
data.bunnyhopdelay = 3;
result = 0;
}
}
// super simple, just check distance compared to max distance
result += Math.max(0.0D, yDistance - data.vertFreedom - cc.moving.flyingSpeedLimitVertical);
result = result * 100;
@ -94,12 +83,12 @@ public class FlyingCheck {
data.runflyViolationLevel += result;
// Prepare some event-specific values for logging and custom actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.DISTANCE, String.format(Locale.US, "%.2f,%.2f,%.2f", xDistance, yDistance, zDistance));
params.put(LogAction.LOCATION_TO, String.format(Locale.US, "%.2f,%.2f,%.2f", to.getX(), to.getY(), to.getZ()));
params.put(LogAction.CHECK, "flying/toofast");
LogData ldata = plugin.getDataManager().getLogData(player);
boolean cancel = action.executeActions(player, cc.moving.flyingActions, (int) data.runflyViolationLevel, params, cc);
ldata.toLocation = to;
ldata.check = "flying/toofast";
boolean cancel = action.executeActions(player, cc.moving.flyingActions, (int) data.runflyViolationLevel, ldata, cc);
// Was one of the actions a cancel? Then really do it
if(cancel) {
@ -117,18 +106,4 @@ public class FlyingCheck {
return newToLocation;
}
private Method getIsRunningMethod() {
try {
return EntityPlayer.class.getMethod("isSprinting");
} catch(NoSuchMethodException e) {
try {
return EntityPlayer.class.getMethod("at");
} catch(Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return null;
}
}
}
}

View File

@ -1,15 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
import java.util.HashMap;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
@ -28,12 +25,12 @@ public class MorePacketsCheck {
private final ActionExecutor action;
private final long packetsPerTimeframe = 22;
private final double bufferLimit = 30;
private final int packetsPerTimeframe = 22;
private final int bufferLimit = 30;
private final NoCheat plugin;
public MorePacketsCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
this.action = new ActionExecutor(plugin);
this.plugin = plugin;
}
@ -105,9 +102,9 @@ public class MorePacketsCheck {
// ticks since last time
if(ingameSeconds != data.lastElapsedIngameSeconds) {
long limit = (packetsPerTimeframe * plugin.getIngameSecondDuration()) / 1000L;
int limit = (int) ((packetsPerTimeframe * plugin.getIngameSecondDuration()) / 1000L);
long difference = limit - data.morePacketsCounter;
int difference = limit - data.morePacketsCounter;
data.morePacketsBuffer = data.morePacketsBuffer + difference;
if(data.morePacketsBuffer > bufferLimit)
@ -125,14 +122,13 @@ public class MorePacketsCheck {
if(!plugin.skipCheck() && packetsAboveLimit > 0) {
data.morePacketsViolationLevel += packetsAboveLimit;
HashMap<String, String> params = new HashMap<String, String>();
LogData ldata = plugin.getDataManager().getLogData(player);
// Packets above limit
params.put(LogAction.PACKETS, String.valueOf(data.morePacketsCounter - limit));
params.put(LogAction.CHECK, "morepackets");
ldata.packets = data.morePacketsCounter - limit;
ldata.check = "moving/morepackets";
boolean cancel = false;
cancel = action.executeActions(player, cc.moving.morePacketsActions, (int) data.morePacketsViolationLevel, params, cc);
cancel = action.executeActions(player, cc.moving.morePacketsActions, (int) data.morePacketsViolationLevel, ldata, cc);
// Only do the cancel if the player didn't change worlds
// inbetween

View File

@ -15,17 +15,15 @@ import org.bukkit.World;
*/
public class MovingEventHelper {
// private final double magic = 0.30000001192092896D;
// private final double magic2 = 0.69999998807907103D;
private final double magic = 0.45D;
private final double magic2 = 0.55D;
// Block types that may need to be treated specially
private static final int NONSOLID = 1; // 0x00000001
private static final int SOLID = 2; // 0x00000010
private static final int LIQUID = 4 | NONSOLID; // 0x00000101
private static final int NONSOLID = 1; // 0x00000001
private static final int SOLID = 2; // 0x00000010
private static final int LIQUID = 4 | NONSOLID; // 0x00000101
private static final int LADDER = 8 | NONSOLID | SOLID; // 0x00001011
private static final int FENCE = 16 | SOLID; // 0x00010000
private static final int FENCE = 16 | SOLID; // 0x00010000
private static final int INGROUND = 128;
private static final int ONGROUND = 256;
// Until I can think of a better way to determine if a block is solid or

View File

@ -1,22 +1,12 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
import java.util.HashMap;
import java.util.Locale;
import net.minecraft.server.DamageSource;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Type;
import org.bukkit.event.entity.EntityDamageEvent;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
@ -29,11 +19,11 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
public class NoFallCheck {
private final ActionExecutor action;
private final NoCheat plugin;
private final NoCheat plugin;
public NoFallCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
this.action = new ActionExecutor(plugin);
}
/**
@ -41,7 +31,7 @@ public class NoFallCheck {
*
*/
public void check(final Player player, final Location from, final boolean fromOnOrInGround, final Location to, final boolean toOnOrInGround, final ConfigurationCache cc, final MovingData data) {
double oldY = from.getY();
double newY = to.getY();
@ -50,34 +40,36 @@ public class NoFallCheck {
// Start with zero fall distance
data.fallDistance = 0F;
}
// If we increased fall height before for no good reason, reduce now by the same amount
if(player.getFallDistance() > data.lastAddedFallDistance) {
player.setFallDistance(player.getFallDistance() - data.lastAddedFallDistance);
}
data.lastAddedFallDistance = 0;
// We want to know if the fallDistance recorded by the game is smaller
// than the fall distance recorded by the plugin
// than the fall distance recorded by the plugin
float difference = data.fallDistance - player.getFallDistance();
if(difference > 1.0F && toOnOrInGround && data.fallDistance > 2.0F) {
data.nofallViolationLevel += difference;
// Prepare some event-specific values for logging and custom actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.DISTANCE, String.format(Locale.US, "%.2f", difference));
params.put(LogAction.CHECK, "nofall");
// Prepare some event-specific values for logging and custom actions
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.falldistance = data.fallDistance;
ldata.check = "moving/nofall";
boolean cancel = action.executeActions(player, cc.moving.nofallActions, (int) data.nofallViolationLevel, params, cc);
// If "cancelled", the fall damage gets dealt in a way that's visible to other plugins
if(cancel) {
boolean cancel = action.executeActions(player, cc.moving.nofallActions, (int) data.nofallViolationLevel, ldata, cc);
// If "cancelled", the fall damage gets dealt in a way that's visible to other plugins
if(cancel) {
// Increase the fall distance a bit :)
float totalDistance = data.fallDistance + difference * (cc.moving.nofallMultiplier - 1.0F);
player.setFallDistance(totalDistance);
}
data.fallDistance = 0F;
}

View File

@ -1,148 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
import java.util.HashMap;
import java.util.Locale;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
* A simple NoClip check. It tries to identify players that walk into/through
* walls by remembering their last location and whenever they move into or
* through a wall (with their upper body), this check should identify it.
* EXPERIMENTAL!!
*
* @author Evenprime
*
*/
public class NoclipCheck {
private final double bodyHeight = 1.1;
private final ActionExecutor action;
public NoclipCheck(NoCheat plugin) {
this.action = new ActionExecutorWithHistory(plugin);
}
/**
* Calculate if and how much the player "failed" this check. The check
* should not modify any data
*
*/
public Location check(final Player player, final Location from, final Location to, final MovingEventHelper helper, final ConfigurationCache cc, final MovingData data) {
/*** THE CHECK ***/
Location current = from.clone();
final double distanceX = to.getX() - current.getX();
final double distanceY = to.getY() - current.getY();
final double distanceZ = to.getZ() - current.getZ();
current.setY(current.getY() + bodyHeight);
double distance = Math.abs(distanceX) > Math.abs(distanceY) ? (Math.abs(distanceX) > Math.abs(distanceZ) ? Math.abs(distanceX) : Math.abs(distanceZ)) : (Math.abs(distanceY) > Math.abs(distanceZ) ? Math.abs(distanceY) : Math.abs(distanceZ));
int steps = (int) (distance / 0.1) + 1;
double divideBy = distance * 10D;
final double stepX = distanceX / divideBy;
final double stepY = distanceY / divideBy;
final double stepZ = distanceZ / divideBy;
final World world = from.getWorld();
int oldX, oldY, oldZ;
int newX, newY, newZ;
if(Math.abs(data.noclipX - current.getBlockX()) > 1 || Math.abs(data.noclipY - current.getBlockY()) > 1 || Math.abs(data.noclipZ - current.getBlockZ()) > 1) {
oldX = newX = current.getBlockX();
oldY = newY = current.getBlockY();
oldZ = newZ = current.getBlockZ();
} else {
oldX = newX = data.noclipX;
oldY = newY = data.noclipY;
oldZ = newZ = data.noclipZ;
}
int violationLevel = 0;
for(int i = 0; i < steps; i++) {
newX = current.getBlockX();
newY = current.getBlockY();
newZ = current.getBlockZ();
final boolean xChanged = newX != oldX;
final boolean yChanged = newY != oldY;
final boolean zChanged = newZ != oldZ;
boolean failed = false;
// Looks scarier than it is
if(!failed && (xChanged || yChanged || zChanged)) {
failed = check(helper, world, newX, newY, newZ);
if(!failed && xChanged && (yChanged || zChanged)) {
failed = check(helper, world, oldX, newY, newZ);
}
if(!failed && yChanged && (xChanged || zChanged)) {
failed = check(helper, world, newX, oldY, newZ);
}
if(!failed && zChanged && (xChanged || yChanged)) {
failed = check(helper, world, newX, newY, oldZ);
}
oldX = newX;
oldY = newY;
oldZ = newZ;
}
// Determine if the block can be passed by the player
if(failed) {
violationLevel++;
}
current.add(stepX, stepY, stepZ);
}
if(violationLevel > 0) {
// Prepare some event-specific values for logging and custom
// actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.DISTANCE, String.format(Locale.US, "%.2f,%.2f,%.2f", to.getX() - from.getX(), to.getY() - from.getY(), to.getZ() - from.getZ()));
params.put(LogAction.LOCATION_TO, String.format(Locale.US, "%.2f,%.2f,%.2f", to.getX(), to.getY(), to.getZ()));
params.put(LogAction.CHECK, "noclip");
/*boolean cancelled =*/ action.executeActions(player, cc.moving.noclipActions, violationLevel, params, cc);
// TODO: UNCOMMENT, WHEN THE CHECK WORKS RELIABLY
//if(cancelled) {
// return new Location(from.getWorld(), data.noclipX + 0.5, data.noclipY - ((int) bodyHeight), data.noclipZ + 0.5, to.getPitch(), to.getYaw());
//}
}
// We didn't cancel the noclipping, so store the new location
data.noclipX = newX;
data.noclipY = newY;
data.noclipZ = newZ;
return null;
}
private final boolean check(MovingEventHelper helper, World world, int x, int y, int z) {
if(y < 0 || y > 127) {
return false;
}
return !helper.isNonSolid(helper.types[world.getBlockAt(x, y, z).getTypeId()]);
}
}

View File

@ -6,7 +6,7 @@ import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
@ -22,7 +22,6 @@ public class RunFlyCheck {
private final FlyingCheck flyingCheck;
private final RunningCheck runningCheck;
private final NoclipCheck noclippingCheck;
private final NoFallCheck noFallCheck;
private final MorePacketsCheck morePacketsCheck;
@ -34,7 +33,6 @@ public class RunFlyCheck {
this.flyingCheck = new FlyingCheck(plugin);
this.noFallCheck = new NoFallCheck(plugin);
this.runningCheck = new RunningCheck(plugin, noFallCheck);
this.noclippingCheck = new NoclipCheck(plugin);
this.morePacketsCheck = new MorePacketsCheck(plugin);
}
@ -74,7 +72,6 @@ public class RunFlyCheck {
final boolean runflyCheck = cc.moving.runflyCheck && !player.hasPermission(Permissions.MOVE_RUNFLY);
final boolean flyAllowed = cc.moving.allowFlying || player.hasPermission(Permissions.MOVE_FLY) || (player.getGameMode() == GameMode.CREATIVE && cc.moving.identifyCreativeMode);
final boolean morepacketsCheck = cc.moving.morePacketsCheck && !player.hasPermission(Permissions.MOVE_MOREPACKETS);
final boolean noclipCheck = cc.moving.noclipCheck && !player.hasPermission(Permissions.MOVE_NOCLIP);
/********************* EXECUTE THE FLY/JUMP/RUNNING CHECK ********************/
// If the player is not allowed to fly and not allowed to run
@ -92,11 +89,7 @@ public class RunFlyCheck {
if(newToLocation == null && morepacketsCheck) {
newToLocation = morePacketsCheck.check(player, cc, data);
}
/********* EXECUTE THE NOCLIP CHECK ********************/
if(newToLocation == null && noclipCheck) {
newToLocation = noclippingCheck.check(player, from, to, helper, cc, data);
}
return newToLocation;
}

View File

@ -1,21 +1,14 @@
package cc.co.evenprime.bukkit.nocheat.checks.moving;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import net.minecraft.server.EntityPlayer;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutor;
import cc.co.evenprime.bukkit.nocheat.actions.ActionExecutorWithHistory;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.LogData;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
@ -29,20 +22,20 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
*/
public class RunningCheck {
private final static double maxBonus = 1D;
private static Method isRunningMethod = null;
private final static double maxBonus = 1D;
// How many move events can a player have in air before he is expected to
// lose altitude (or eventually land somewhere)
private final static int jumpingLimit = 6;
private final static int jumpingLimit = 6;
private final ActionExecutor action;
private final NoCheat plugin;
private final NoFallCheck noFallCheck;
public RunningCheck(NoCheat plugin, NoFallCheck noFallCheck) {
this.action = new ActionExecutorWithHistory(plugin);
this.plugin = plugin;
this.action = new ActionExecutor(plugin);
this.noFallCheck = noFallCheck;
}
@ -84,17 +77,16 @@ public class RunningCheck {
data.runflyViolationLevel += result;
// Prepare some event-specific values for logging and custom actions
HashMap<String, String> params = new HashMap<String, String>();
params.put(LogAction.DISTANCE, String.format(Locale.US, "%.2f,%.2f,%.2f", xDistance, to.getY() - from.getY(), zDistance));
params.put(LogAction.LOCATION_TO, String.format(Locale.US, "%.2f,%.2f,%.2f", to.getX(), to.getY(), to.getZ()));
LogData ldata = plugin.getDataManager().getLogData(player);
ldata.toLocation = to;
if(resultHoriz > 0 && resultVert > 0)
params.put(LogAction.CHECK, "runfly/both");
ldata.check = "runfly/both";
else if(resultHoriz > 0)
params.put(LogAction.CHECK, "runfly/horizontal");
ldata.check = "runfly/horizontal";
else if(resultVert > 0)
params.put(LogAction.CHECK, "runfly/vertical");
ldata.check = "runfly/vertical";
boolean cancel = action.executeActions(player, cc.moving.actions, (int) data.runflyViolationLevel, params, cc);
boolean cancel = action.executeActions(player, cc.moving.actions, (int) data.runflyViolationLevel, ldata, cc);
// Was one of the actions a cancel? Then do it
if(cancel) {
@ -139,13 +131,9 @@ public class RunningCheck {
// How much further did the player move than expected??
double distanceAboveLimit = 0.0D;
if(isRunningMethod == null) {
isRunningMethod = getIsRunningMethod();
}
boolean sprinting = true;
try {
sprinting = !(player instanceof CraftPlayer) || isRunningMethod.invoke(((CraftPlayer) player).getHandle()).equals(true);
sprinting = !(player instanceof CraftPlayer) || player.isSprinting();
} catch(Exception e) {
e.printStackTrace();
}
@ -211,18 +199,4 @@ public class RunningCheck {
return distanceAboveLimit;
}
private Method getIsRunningMethod() {
try {
return EntityPlayer.class.getMethod("isSprinting");
} catch(NoSuchMethodException e) {
try {
return EntityPlayer.class.getMethod("at");
} catch(Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return null;
}
}
}
}

View File

@ -1,24 +1,230 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.util.HashMap;
import java.util.Map;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.OptionNode.DataType;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
* A configuration. It should allow access to settings associated with a string
* This class describes a basic configuration for NoCheat. NoCheats
* configuration
* is based on String,String pairs, and this class provides some convenience
* methods
* to retrieve and store more complex datatypes based on strings.
*
* @author Evenprime
*
*/
public interface Configuration {
public abstract class Configuration {
public abstract boolean getBoolean(String string);
public final static OptionNode ROOT = new OptionNode(null, null, DataType.PARENT);
public abstract ActionList getActionList(String string);
public final static OptionNode LOGGING = new OptionNode("logging", ROOT, DataType.PARENT);
public final static OptionNode LOGGING_ACTIVE = new OptionNode("active", LOGGING, DataType.BOOLEAN);
public final static OptionNode LOGGING_FILENAME = new OptionNode("filename", LOGGING, DataType.STRING);
public final static OptionNode LOGGING_FILELEVEL = new OptionNode("filelevel", LOGGING, DataType.LOGLEVEL);
public final static OptionNode LOGGING_CONSOLELEVEL = new OptionNode("consolelevel", LOGGING, DataType.LOGLEVEL);
public final static OptionNode LOGGING_CHATLEVEL = new OptionNode("chatlevel", LOGGING, DataType.LOGLEVEL);
public abstract int getInteger(String string);
public final static OptionNode DEBUG = new OptionNode("debug", ROOT, DataType.PARENT);
public final static OptionNode DEBUG_SHOWACTIVECHECKS = new OptionNode("showactivechecks", DEBUG, DataType.BOOLEAN);
public abstract String getString(String string);
public final static OptionNode MOVING = new OptionNode("moving", ROOT, DataType.PARENT);
public final static OptionNode MOVING_CHECK = new OptionNode("check", MOVING, DataType.BOOLEAN);
public final static OptionNode MOVING_IDENTIFYCREATIVEMODE = new OptionNode("identifycreativemode", MOVING, DataType.BOOLEAN);
public abstract LogLevel getLogLevel(String string);
public final static OptionNode MOVING_RUNFLY = new OptionNode("runfly", MOVING, DataType.PARENT);
public final static OptionNode MOVING_RUNFLY_CHECK = new OptionNode("check", MOVING_RUNFLY, DataType.BOOLEAN);
public final static OptionNode MOVING_RUNFLY_WALKINGSPEEDLIMIT = new OptionNode("alkingspeedlimit", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_SPRINTINGSPEEDLIMIT = new OptionNode("sprintingspeedlimit", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_JUMPHEIGHT = new OptionNode("jumpheight", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_CHECKSNEAKING = new OptionNode("checksneaking", MOVING_RUNFLY, DataType.BOOLEAN);
public final static OptionNode MOVING_RUNFLY_SNEAKINGSPEEDLIMIT = new OptionNode("sneakingspeedlimit", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_CHECKSWIMMING = new OptionNode("checkswimming", MOVING_RUNFLY, DataType.BOOLEAN);
public final static OptionNode MOVING_RUNFLY_SWIMMINGSPEEDLIMIT = new OptionNode("swimmingspeedlimit", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_ACTIONS = new OptionNode("actions", MOVING_RUNFLY, DataType.ACTIONLIST);
public final static OptionNode MOVING_RUNFLY_CHECKNOFALL = new OptionNode("checknofall", MOVING_RUNFLY, DataType.BOOLEAN);
public final static OptionNode MOVING_RUNFLY_NOFALLMULTIPLIER = new OptionNode("nofallmultiplier", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_NOFALLACTIONS = new OptionNode("nofallactions", MOVING_RUNFLY, DataType.ACTIONLIST);
public final static OptionNode MOVING_RUNFLY_ALLOWLIMITEDFLYING = new OptionNode("allowlimitedflying", MOVING_RUNFLY, DataType.BOOLEAN);
public final static OptionNode MOVING_RUNFLY_FLYINGSPEEDLIMITVERTICAL = new OptionNode("flyingspeedlimitvertical", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_FLYINGSPEEDLIMITHORIZONTAL = new OptionNode("flyingspeedlimithorizontal", MOVING_RUNFLY, DataType.INTEGER);
public final static OptionNode MOVING_RUNFLY_FLYINGACTIONS = new OptionNode("flyingactions", MOVING_RUNFLY, DataType.ACTIONLIST);
public final static OptionNode MOVING_MOREPACKETS = new OptionNode("morepackets", MOVING, DataType.PARENT);
public final static OptionNode MOVING_MOREPACKETS_CHECK = new OptionNode("check", MOVING_MOREPACKETS, DataType.BOOLEAN);
public final static OptionNode MOVING_MOREPACKETS_ACTIONS = new OptionNode("actions", MOVING_MOREPACKETS, DataType.ACTIONLIST);
public final static OptionNode BLOCKBREAK = new OptionNode("blockbreak", ROOT, DataType.PARENT);
public final static OptionNode BLOCKBREAK_CHECK = new OptionNode("check", BLOCKBREAK, DataType.BOOLEAN);
public final static OptionNode BLOCKBREAK_REACH = new OptionNode("reach", BLOCKBREAK, DataType.PARENT);
public final static OptionNode BLOCKBREAK_REACH_CHECK = new OptionNode("check", BLOCKBREAK_REACH, DataType.BOOLEAN);
public final static OptionNode BLOCKBREAK_REACH_LIMIT = new OptionNode("limit", BLOCKBREAK_REACH, DataType.INTEGER);
public final static OptionNode BLOCKBREAK_REACH_ACTIONS = new OptionNode("actions", BLOCKBREAK_REACH, DataType.ACTIONLIST);
public final static OptionNode BLOCKBREAK_DIRECTION = new OptionNode("direction", BLOCKBREAK, DataType.PARENT);
public final static OptionNode BLOCKBREAK_DIRECTION_CHECK = new OptionNode("check", BLOCKBREAK_DIRECTION, DataType.BOOLEAN);
public static final OptionNode BLOCKBREAK_DIRECTION_CHECKINSTABREAKBLOCKS = new OptionNode("checkinstabreakblocks", BLOCKBREAK_DIRECTION, DataType.BOOLEAN);
public final static OptionNode BLOCKBREAK_DIRECTION_ACTIONS = new OptionNode("actions", BLOCKBREAK_DIRECTION, DataType.ACTIONLIST);
public final static OptionNode BLOCKPLACE = new OptionNode("blockplace", ROOT, DataType.PARENT);
public final static OptionNode BLOCKPLACE_CHECK = new OptionNode("check", BLOCKPLACE, DataType.BOOLEAN);
public final static OptionNode BLOCKPLACE_REACH = new OptionNode("reach", BLOCKPLACE, DataType.PARENT);
public final static OptionNode BLOCKPLACE_REACH_CHECK = new OptionNode("check", BLOCKPLACE_REACH, DataType.BOOLEAN);
public final static OptionNode BLOCKPLACE_REACH_LIMIT = new OptionNode("limit", BLOCKPLACE_REACH, DataType.INTEGER);
public final static OptionNode BLOCKPLACE_REACH_ACTIONS = new OptionNode("actions", BLOCKPLACE_REACH, DataType.ACTIONLIST);
public final static OptionNode BLOCKPLACE_ONLIQUID = new OptionNode("onliquid", BLOCKPLACE, DataType.PARENT);
public final static OptionNode BLOCKPLACE_ONLIQUID_CHECK = new OptionNode("check", BLOCKPLACE_ONLIQUID, DataType.BOOLEAN);
public final static OptionNode BLOCKPLACE_ONLIQUID_ACTIONS = new OptionNode("actions", BLOCKPLACE_ONLIQUID, DataType.ACTIONLIST);
public final static OptionNode INTERACT = new OptionNode("interact", ROOT, DataType.PARENT);
public final static OptionNode INTERACT_CHECK = new OptionNode("check", INTERACT, DataType.BOOLEAN);
public final static OptionNode INTERACT_DURABILITY = new OptionNode("durability", INTERACT, DataType.PARENT);
public final static OptionNode INTERACT_DURABILITY_CHECK = new OptionNode("check", INTERACT_DURABILITY, DataType.BOOLEAN);
public final static OptionNode INTERACT_DURABILITY_ACTIONS = new OptionNode("actions", INTERACT_DURABILITY, DataType.ACTIONLIST);
public final static OptionNode CHAT = new OptionNode("chat", ROOT, DataType.PARENT);
public final static OptionNode CHAT_CHECK = new OptionNode("check", CHAT, DataType.BOOLEAN);
public final static OptionNode CHAT_SPAM = new OptionNode("spam", CHAT, DataType.PARENT);
public final static OptionNode CHAT_SPAM_CHECK = new OptionNode("check", CHAT_SPAM, DataType.BOOLEAN);
public final static OptionNode CHAT_SPAM_TIMEFRAME = new OptionNode("timeframe", CHAT_SPAM, DataType.INTEGER);
public final static OptionNode CHAT_SPAM_LIMIT = new OptionNode("limit", CHAT_SPAM, DataType.INTEGER);
public final static OptionNode CHAT_SPAM_ACTIONS = new OptionNode("actions", CHAT_SPAM, DataType.ACTIONLIST);
private final Map<OptionNode, Object> values;
private final Configuration defaults;
public Configuration(Configuration defaults, boolean copyDefaults) {
this.values = new HashMap<OptionNode, Object>();
this.defaults = defaults;
if(defaults != null && copyDefaults) {
deepCopy(defaults, ROOT);
}
}
private void deepCopy(Configuration defaults, OptionNode root) {
if(root.isLeaf()) {
this.set(root, defaults.getRecursive(root));
} else {
for(OptionNode child : root.getChildren()) {
deepCopy(defaults, child);
}
}
}
public boolean getBoolean(OptionNode id) {
if(id.getType() != DataType.BOOLEAN) {
throw new IllegalArgumentException(id + " is no boolean value!");
}
return (Boolean) getRecursive(id);
}
public String getString(OptionNode id) {
if(id.getType() != DataType.STRING) {
throw new IllegalArgumentException(id + " is no string value!");
}
return (String) getRecursive(id);
}
public int getInteger(OptionNode id) {
if(id.getType() != DataType.INTEGER) {
throw new IllegalArgumentException(id + " is no integer value!");
}
return (Integer) getRecursive(id);
}
public LogLevel getLogLevel(OptionNode id) {
if(id.getType() != DataType.LOGLEVEL) {
throw new IllegalArgumentException(id + " is no loglevel value!");
}
return (LogLevel) getRecursive(id);
}
public ActionList getActionList(OptionNode id) {
if(id.getType() != DataType.ACTIONLIST) {
throw new IllegalArgumentException(id + " is no actionlist value!");
}
return (ActionList) getRecursive(id);
}
public void setValue(OptionNode id, Integer value) {
if(id.getType() != DataType.INTEGER) {
throw new IllegalArgumentException(id + " is no integer value!");
}
set(id, value);
}
public void setValue(OptionNode id, LogLevel value) {
if(id.getType() != DataType.LOGLEVEL) {
throw new IllegalArgumentException(id + " is no loglevel value!");
}
set(id, value);
}
public void setValue(OptionNode id, Boolean value) {
if(id.getType() != DataType.BOOLEAN) {
throw new IllegalArgumentException(id + " is no boolean value!");
}
set(id, value);
}
public void setValue(OptionNode id, String value) {
if(id.getType() != DataType.STRING) {
throw new IllegalArgumentException(id + " is no string value!");
}
set(id, value);
}
public void setValue(OptionNode id, ActionList value) {
if(id.getType() != DataType.ACTIONLIST) {
throw new IllegalArgumentException(id + " is no actionlist value!");
}
set(id, value);
}
protected void set(OptionNode id, Object value) {
if(value == null) {
this.values.remove(id);
} else {
this.values.put(id, value);
}
}
protected Object getRecursive(OptionNode id) {
Object o = get(id);
if(o != null) {
return o;
}
if(defaults != null) {
return defaults.getRecursive(id);
}
return null;
}
protected Configuration getDefaults() {
return defaults;
}
protected Object get(OptionNode id) {
return this.values.get(id);
}
}

View File

@ -1,15 +1,13 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
@ -17,18 +15,9 @@ import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import cc.co.evenprime.bukkit.nocheat.DefaultConfiguration;
import cc.co.evenprime.bukkit.nocheat.actions.ActionManager;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionListOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ChildOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationTree;
import cc.co.evenprime.bukkit.nocheat.config.tree.Option;
import cc.co.evenprime.bukkit.nocheat.config.tree.ParentOption;
import cc.co.evenprime.bukkit.nocheat.file.DescriptionGenerator;
import cc.co.evenprime.bukkit.nocheat.file.FlatActionParser;
import cc.co.evenprime.bukkit.nocheat.file.FlatConfigGenerator;
import cc.co.evenprime.bukkit.nocheat.file.FlatConfigParser;
/**
* Central location for everything that's described in the configuration file(s)
@ -49,7 +38,7 @@ public class ConfigurationManager {
// map
private final Map<File, FileHandler> fileToFileHandlerMap = new HashMap<File, FileHandler>();
private final ConfigurationTree defaultTree = DefaultConfiguration.buildDefaultConfigurationTree();
private final Configuration defaultConfig;
private class LogFileFormatter extends Formatter {
@ -85,23 +74,46 @@ public class ConfigurationManager {
// private final static String loggerName = "cc.co.evenprime.nocheat";
// public final Logger logger = Logger.getLogger(loggerName);
public ConfigurationManager(String rootConfigFolder, ActionManager action) {
public ConfigurationManager(String rootConfigFolder, ActionManager actionManager) {
// Parse actions file
initializeActions(rootConfigFolder, action);
// MOVE TO ACTIONMANAGER PARSER OR SOMETHING
initializeActions(rootConfigFolder, actionManager);
defaultConfig = new DefaultConfiguration(actionManager);
// Setup the configuration tree
initializeConfig(rootConfigFolder, action);
initializeConfig(rootConfigFolder, actionManager);
}
private void initializeActions(String rootConfigFolder, ActionManager action) {
private void initializeActions(String rootConfigFolder, ActionManager actionManager) {
FlatActionParser parser = new FlatActionParser();
File defaultActionsFile = new File(rootConfigFolder, defaultActionFileName);
DefaultConfiguration.writeDefaultActionFile(new File(rootConfigFolder, defaultActionFileName));
parser.read(action, new File(rootConfigFolder, defaultActionFileName));
parser.read(action, new File(rootConfigFolder, actionFileName));
// Write the current default action file into the target folder
DefaultConfiguration.writeDefaultActionFile(defaultActionsFile);
// now parse that file again
FlatFileAction parser = new FlatFileAction(defaultActionsFile);
List<Action> defaultActions = parser.read();
for(Action a : defaultActions) {
actionManager.addAction(a);
}
// Check if the "custom" action file exists, if not, create one
File customActionsFile = new File(rootConfigFolder, actionFileName);
if(!customActionsFile.exists()) {
DefaultConfiguration.writeActionFile(customActionsFile);
}
parser = new FlatFileAction(customActionsFile);
List<Action> customActions = parser.read();
for(Action a : customActions) {
actionManager.addAction(a);
}
}
/**
@ -110,23 +122,28 @@ public class ConfigurationManager {
*
* @param configurationFile
*/
private void initializeConfig(String rootConfigFolder, ActionManager actionManager) {
private void initializeConfig(String rootConfigFolder, ActionManager action) {
// First try to obtain and parse the global config file
ConfigurationTree root;
FlatFileConfiguration root;
File globalConfigFile = getGlobalConfigFile(rootConfigFolder);
root = new FlatFileConfiguration(defaultConfig, true, globalConfigFile);
try {
root = createFullConfigurationTree(defaultTree, globalConfigFile);
root.load(action);
} catch(Exception e) {
root = DefaultConfiguration.buildDefaultConfigurationTree();
}
writeConfigFile(globalConfigFile, root);
try {
root.save();
} catch(Exception e) {
e.printStackTrace();
}
// Create a corresponding Configuration Cache
// put the global config on the config map
worldnameToConfigCacheMap.put(null, new ConfigurationCache(root, setupFileLogger(new File(rootConfigFolder, root.getString("logging.filename")))));
worldnameToConfigCacheMap.put(null, new ConfigurationCache(root, setupFileLogger(new File(rootConfigFolder, root.getString(DefaultConfiguration.LOGGING_FILENAME)))));
// Try to find world-specific config files
Map<String, File> worldFiles = getWorldSpecificConfigFiles(rootConfigFolder);
@ -134,25 +151,26 @@ public class ConfigurationManager {
for(String worldName : worldFiles.keySet()) {
File worldConfigFile = worldFiles.get(worldName);
FlatFileConfiguration world = new FlatFileConfiguration(root, false, worldConfigFile);
try {
ConfigurationTree world = createPartialConfigurationTree(root, worldConfigFile);
world.load(action);
worldnameToConfigCacheMap.put(worldName, createConfigurationCache(rootConfigFolder, world));
// write the config file back to disk immediately
writeConfigFile(worldFiles.get(worldName), world);
world.save();
} catch(IOException e) {
System.out.println("NoCheat: Couldn't load world-specific config for " + worldName);
}
}
// Write the descriptions-file for the default tree
writeDescriptionFile(new File(rootConfigFolder, descriptionsFileName), defaultTree);
}
private ConfigurationCache createConfigurationCache(String rootConfigFolder, Configuration configProvider) {
return new ConfigurationCache(configProvider, setupFileLogger(new File(rootConfigFolder, configProvider.getString("logging.filename"))));
return new ConfigurationCache(configProvider, setupFileLogger(new File(rootConfigFolder, configProvider.getString(DefaultConfiguration.LOGGING_FILENAME))));
}
@ -183,88 +201,6 @@ public class ConfigurationManager {
return files;
}
/**
* Create a full configuration tree based on a default tree and a
* configuration file
* The resulting tree will have all settings of the defaultTree with entries
* replaced,
* if existing, by data from the configurationFile
*
* @param defaultTree
* @param configurationFile
* @throws IOException
*/
public static ConfigurationTree createFullConfigurationTree(ConfigurationTree defaultTree, File configurationFile) throws IOException {
return yamlToTree(defaultTree, configurationFile, true);
}
/**
* Create a partial configuration tree based on a default tree and a
* configuration file
* The resulting tree will only have settings from the configurationFile,
* but reference
* the defaultTree as its parent.
*
* @param defaultTree
* @param configurationFile
* @throws IOException
*/
public static ConfigurationTree createPartialConfigurationTree(ConfigurationTree defaultTree, File configurationFile) throws IOException {
ConfigurationTree tree = yamlToTree(defaultTree, configurationFile, false);
tree.setParent(defaultTree);
return tree;
}
private static ConfigurationTree yamlToTree(ConfigurationTree defaults, File configurationFile, boolean fullCopy) throws IOException {
FlatConfigParser source = new FlatConfigParser();
source.read(configurationFile);
ConfigurationTree partial = new ConfigurationTree();
for(Option o : defaults.getAllOptions()) {
if(o instanceof ActionListOption) {
ActionListOption o2 = ((ActionListOption) o).clone();
partial.add(o.getParent().getFullIdentifier(), o2);
// Does the new source have a node for this property??
Object prop = source.getProperty(o2.getFullIdentifier());
if(prop instanceof Map<?, ?> && prop != null) {
// Yes, so we rather take the data from that node
@SuppressWarnings("unchecked")
Map<Object, Object> m = (Map<Object, Object>) prop;
o2.clear();
for(Entry<Object, Object> entry : m.entrySet()) {
try {
o2.add(Integer.parseInt((String) entry.getKey()), (String) entry.getValue());
} catch(Exception e) {
System.out.println("NoCheat: PROBLEM OFFICER?!?!");
}
}
}
if(!fullCopy && prop == null) {
o2.setActive(false);
}
} else if(o instanceof ParentOption) {
ParentOption o2 = new ParentOption(o.getIdentifier());
partial.add(o.getParent().getFullIdentifier(), o2);
} else if(o instanceof ChildOption) {
ChildOption o2 = ((ChildOption) o).clone();
partial.add(o.getParent().getFullIdentifier(), o2);
o2.setStringValue(source.getString(o2.getFullIdentifier(), o2.getStringValue()));
if(!fullCopy && source.getProperty(o.getFullIdentifier()) == null) {
o2.setActive(false);
}
}
}
return partial;
}
private Logger setupFileLogger(File logfile) {
FileHandler fh = fileToFileHandlerMap.get(logfile);
@ -323,51 +259,6 @@ public class ConfigurationManager {
}
}
/**
* Write configuration to specific file
*
* @param f
*/
public static void writeConfigFile(File f, ConfigurationTree configuration) {
try {
if(f.getParentFile() != null)
f.getParentFile().mkdirs();
f.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(f));
w.write(FlatConfigGenerator.treeToFlatFile(configuration));
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* Write a file with the descriptions of all options of a specific
* configuration tree
*
* @param f
*/
public static void writeDescriptionFile(File f, ConfigurationTree configuration) {
try {
if(f.getParentFile() != null)
f.getParentFile().mkdirs();
f.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(f));
w.write(DescriptionGenerator.treeToDescription(configuration));
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
/**
* Get the cache of the specified world, or the default cache,
* if no cache exists for that world.

View File

@ -0,0 +1,267 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.actions.ActionManager;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
* The place where the structure of the configuration tree is defined, the
* default settings are defined, the default files are defined.
*
* @author Evenprime
*
*/
public class DefaultConfiguration extends Configuration {
public DefaultConfiguration(ActionManager action) {
super(null, false);
/*** LOGGING ***/
{
setValue(LOGGING_ACTIVE, true);
setValue(LOGGING_FILENAME, "nocheat.log");
setValue(LOGGING_FILELEVEL, LogLevel.LOW);
setValue(LOGGING_CONSOLELEVEL, LogLevel.HIGH);
setValue(LOGGING_CHATLEVEL, LogLevel.MED);
}
/*** DEBUG ***/
{
setValue(DEBUG_SHOWACTIVECHECKS, false);
}
/*** MOVING ***/
{
setValue(MOVING_CHECK, true);
setValue(MOVING_IDENTIFYCREATIVEMODE, true);
setValue(MOVING_RUNFLY_CHECK, true);
setValue(MOVING_RUNFLY_WALKINGSPEEDLIMIT, 22);
setValue(MOVING_RUNFLY_SPRINTINGSPEEDLIMIT, 40);
setValue(MOVING_RUNFLY_JUMPHEIGHT, 135);
setValue(MOVING_RUNFLY_CHECKSNEAKING, true);
setValue(MOVING_RUNFLY_SNEAKINGSPEEDLIMIT, 14);
setValue(MOVING_RUNFLY_CHECKSWIMMING, true);
setValue(MOVING_RUNFLY_SWIMMINGSPEEDLIMIT, 18);
ActionList movingActionList = new ActionList();
movingActionList.setActions(0, action.getActions("moveLogLowShort moveCancel".split(" ")));
movingActionList.setActions(100, action.getActions("moveLogMedShort moveCancel".split(" ")));
movingActionList.setActions(400, action.getActions("moveLogHighShort moveCancel".split(" ")));
setValue(MOVING_RUNFLY_ACTIONS, movingActionList);
setValue(MOVING_RUNFLY_CHECKNOFALL, true);
setValue(MOVING_RUNFLY_NOFALLMULTIPLIER, 200);
ActionList nofallActionList = new ActionList();
nofallActionList.setActions(0, action.getActions("nofallLog nofallDamage".split(" ")));
setValue(MOVING_RUNFLY_NOFALLACTIONS, nofallActionList);
setValue(MOVING_RUNFLY_ALLOWLIMITEDFLYING, false);
setValue(MOVING_RUNFLY_FLYINGSPEEDLIMITVERTICAL, 100);
setValue(MOVING_RUNFLY_FLYINGSPEEDLIMITHORIZONTAL, 60);
ActionList flyingActionList = new ActionList();
flyingActionList.setActions(0, action.getActions("moveLogLowShort moveCancel".split(" ")));
flyingActionList.setActions(100, action.getActions("moveLogMedShort moveCancel".split(" ")));
flyingActionList.setActions(400, action.getActions("moveLogHighShort moveCancel".split(" ")));
setValue(MOVING_RUNFLY_FLYINGACTIONS, flyingActionList);
setValue(MOVING_MOREPACKETS_CHECK, true);
ActionList morepacketsActionList = new ActionList();
morepacketsActionList.setActions(0, action.getActions("morepacketsLow moveCancel".split(" ")));
morepacketsActionList.setActions(30, action.getActions("morepacketsMed moveCancel".split(" ")));
morepacketsActionList.setActions(60, action.getActions("morepacketsHigh moveCancel".split(" ")));
setValue(MOVING_MOREPACKETS_ACTIONS, morepacketsActionList);
}
/*** BLOCKBREAK ***/
{
setValue(BLOCKBREAK_CHECK, true);
setValue(BLOCKBREAK_REACH_CHECK, true);
setValue(BLOCKBREAK_REACH_LIMIT, 485);
ActionList reachActionList = new ActionList();
reachActionList.setActions(0, action.getActions("reachLog blockbreakCancel".split(" ")));
setValue(BLOCKBREAK_REACH_ACTIONS, reachActionList);
setValue(BLOCKBREAK_DIRECTION_CHECK, true);
setValue(BLOCKBREAK_DIRECTION_CHECKINSTABREAKBLOCKS, false);
ActionList directionActionList = new ActionList();
directionActionList.setActions(0, action.getActions("directionLog blockbreakCancel".split(" ")));
setValue(BLOCKBREAK_DIRECTION_ACTIONS, directionActionList);
}
/*** BLOCKPLACE ***/
{
setValue(BLOCKPLACE_CHECK, true);
setValue(BLOCKPLACE_REACH_CHECK, true);
setValue(BLOCKPLACE_REACH_LIMIT, 485);
ActionList reachActionList = new ActionList();
reachActionList.setActions(0, action.getActions("reachLog blockplaceCancel".split(" ")));
setValue(BLOCKPLACE_REACH_ACTIONS, reachActionList);
setValue(BLOCKPLACE_ONLIQUID_CHECK, true);
ActionList onliquidActionList = new ActionList();
onliquidActionList.setActions(0, action.getActions("onliquidLog blockplaceCancel".split(" ")));
setValue(BLOCKPLACE_ONLIQUID_ACTIONS, onliquidActionList);
}
/*** INTERACT ***/
{
setValue(INTERACT_CHECK, true);
setValue(INTERACT_DURABILITY_CHECK, true);
ActionList infiniteDurabilityActionList = new ActionList();
infiniteDurabilityActionList.setActions(0, action.getActions("durabilityLog interactCancel".split(" ")));
setValue(INTERACT_DURABILITY_ACTIONS, infiniteDurabilityActionList);
}
/*** CHAT ***/
{
setValue(CHAT_CHECK, true);
setValue(CHAT_SPAM_CHECK, true);
setValue(CHAT_SPAM_TIMEFRAME, 5);
setValue(CHAT_SPAM_LIMIT, 5);
ActionList spamActionList = new ActionList();
spamActionList.setActions(0, action.getActions("spamLog spamCancel".split(" ")));
setValue(CHAT_SPAM_ACTIONS, spamActionList);
}
}
public static void writeActionFile(File file) {
BufferedWriter w;
try {
if(!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
}
w = new BufferedWriter(new FileWriter(file));
w(w, "# This file contains the definitions of the default actions of NoCheat.");
w(w, "# DO NOT EDIT THIS FILE DIRECTLY. If you want to change any of these, copy");
w(w, "# them to your \"actions.txt\" file and modify them there. If an action with");
w(w, "# the same name exists here and in your file, yours will be used.");
w(w, "");
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
public static void writeDefaultActionFile(File file) {
BufferedWriter w;
try {
if(!file.exists()) {
try {
file.getParentFile().mkdirs();
file.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
}
w = new BufferedWriter(new FileWriter(file));
w(w, "# This file contains the definitions of the default actions of NoCheat.");
w(w, "# DO NOT EDIT THIS FILE DIRECTLY. If you want to change any of these, copy");
w(w, "# them to your \"actions.txt\" file and modify them there. If an action with");
w(w, "# the same name exists here and in your file, yours will be used.");
w(w, "#");
w(w, "# LOG Actions: They will print messages in your log file, console, chat, ...");
w(w, "# - They start with the word 'log'");
w(w, "# - Then comes their name. That name is used in the config file to identify them");
w(w, "# - Then comes the 'delay', that is how often has this action to be called before it really gets executed");
w(w, "# - Then comes the 'repeat', that is how many seconds have to be between two executions of the action");
w(w, "# - Then comes the 'loglevel', that is how the log message gets categorized (low, med, high)");
w(w, "# - Then comes the 'message', depending on where the action is used, different keywords in [ ] may be used");
w(w, "");
w(w, "# Gives a very short log message of the violation, only containing name, violation type and total violation value, at most once every 15 seconds, only if more than 3 violations happened within the last minute (low) and immediatly (med,high)");
w(w, "log moveLogLowShort 3 15 low NC: [player] failed [check]");
w(w, "log moveLogMedShort 0 15 med NC: [player] failed [check]");
w(w, "log moveLogHighShort 0 15 high NC: [player] failed [check]");
w(w, "");
w(w, "# Gives a log message of the violation, only containing name, violation type and total violation value, at most once every second, only if more than 5 violations happened within the last minute (low) and immediatly (med,high)");
w(w, "log morepacketsLow 5 1 low NC: [player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations].");
w(w, "log morepacketsMed 0 1 med NC: [player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations].");
w(w, "log morepacketsHigh 0 1 high NC: [player] failed [check]: Sent [packets] more packets than expected. Total violation level [violations].");
w(w, "");
w(w, "# Gives a lengthy log message of the violation, containing name, location, violation type and total violation, at most once every 15 seconds, only if more than 3 violations happened within the last minute (low) and immediatly (med,high)");
w(w, "log moveLogLowLong 3 15 low NC: [player] in [world] at [location] moving to [locationto] over distance [movedistance] failed check [check]. Total violation level so far [violations].");
w(w, "log moveLogMedLong 0 15 med NC: [player] in [world] at [location] moving to [locationto] over distance [movedistance] failed check [check]. Total violation level so far [violations].");
w(w, "log moveLogHighLong 0 15 high NC: [player] in [world] at [location] moving to [locationto] over distance [movedistance] failed check [check]. Total violation level so far [violations].");
w(w, "");
w(w, "# Some other log messages that are limited a bit by default, to avoid too extreme spam");
w(w, "log reachLog 0 1 med NC: [player] failed [check]: tried to interact with a block over distance [reachdistance].");
w(w, "log directionLog 2 1 med NC: [player] failed [check]: tried to destroy a block out of line of sight.");
w(w, "log durabilityLog 0 1 med NC: [player] failed [check]: tried to use infinity durability hack.");
w(w, "log onliquidLog 2 1 med NC: [player] failed [check]: tried to place a [blocktype] block at [placelocation] against block at [placeagainst].");
w(w, "log spamLog 0 4 med NC: [player] failed [check]: Last sent message \"[text]\".");
w(w, "log nofallLog 0 1 med NC: [player] failed [check]: tried to avoid fall damage for ~[falldistance] blocks.");
w(w, "");
w(w, "# SPECIAL Actions: They will do something check dependant, usually cancel an event.");
w(w, "# - They start with the word 'special'");
w(w, "# - Then comes their name. That name is used in the config file to identify them");
w(w, "# - Then comes the 'delay', that is how often has this action to be called before it really gets executed");
w(w, "# - Then comes the 'repeat', that is how many seconds have to be between two executions of the action");
w(w, "# - Then come further instructions, if necessary");
w(w, "");
w(w, "# Cancels the event in case of an violation. Always. No delay. These are equivalent. The different names are just for better readability");
w(w, "special moveCancel 0 0");
w(w, "special blockbreakCancel 0 0");
w(w, "special blockplaceCancel 0 0");
w(w, "special interactCancel 0 0");
w(w, "special spamCancel 0 0");
w(w, "special nofallDamage 0 0");
w(w, "");
w(w, "# CONSOLECOMMAND Actions: They will execute a command as if it were typed into the console.");
w(w, "# - They start with the word 'consolecommand'");
w(w, "# - Then comes their name. That name is used in the config file to identify them");
w(w, "# - Then comes the 'delay', that is how often has this action to be called before it really gets executed");
w(w, "# - Then comes the 'repeat', that is how many seconds have to be between two executions of the action");
w(w, "# - Then comes the command. You can use the same [ ] that you use for log actions. You'll most likely want to use [player] at some point.");
w(w, "");
w(w, "# E.g. Kick a player");
w(w, "consolecommand kick 0 0 kick [player]");
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
private static void w(BufferedWriter writer, String text) throws IOException {
writer.write(text);
writer.newLine();
}
}

View File

@ -0,0 +1,101 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.util.HashMap;
import java.util.Map;
/**
* Textual explainations of options, will be displayed in the gui tool and the
* descriptions.txt file.
*
* @author Evenprime
*
*/
public class Explainations {
private static final Map<OptionNode, String> explainations = new HashMap<OptionNode, String>();
static {
set(Configuration.LOGGING_ACTIVE, "Should NoCheat related messages get logged at all. Some messages may still appear, e.g. error\n messages, even if this option is deactivated");
set(Configuration.LOGGING_FILENAME, "Where logs that go to the logfile are stored. You can have different files for different worlds.");
set(Configuration.LOGGING_FILELEVEL, "What log-level need messages to have to get stored in the logfile. Values are:\n low: all messages\n med: med and high messages only\n high: high messages only\n off: no messages at all.");
set(Configuration.LOGGING_CONSOLELEVEL, "What log-level need messages to have to get displayed in your server console. Values are:\n low: all messages\n med: med and high messages only\n high: high messages only\n off: no messages at all.");
set(Configuration.LOGGING_CHATLEVEL, "What log-level need messages to have to get displayed in the ingame chat. Values are:\n low: all messages\n med: med and high messages only\n high: high messages only\n off: no messages at all.");
set(Configuration.DEBUG_SHOWACTIVECHECKS, "Print to the console an overview of all checks that are enabled when NoCheat gets loaded.");
set(Configuration.MOVING_CHECK, "If true, do various checks on PlayerMove events.");
set(Configuration.MOVING_IDENTIFYCREATIVEMODE, "If true, NoCheat will automatically identify if players are in creative mode and will allow them to fly, avoid fall damage etc.");
set(Configuration.MOVING_RUNFLY_CHECK, "If true, check if a player is walking/sprinting/sneaking/swimming too fast/high.");
set(Configuration.MOVING_RUNFLY_WALKINGSPEEDLIMIT, "Set the speed limit for moving horizontal under 'normal' conditions.\nUnit is 1/100 of a block, default is 22.");
set(Configuration.MOVING_RUNFLY_SPRINTINGSPEEDLIMIT, "Set the speed limit for moving horizontal while sprinting.\nUnit is 1/100 of a block, default is 40.");
set(Configuration.MOVING_RUNFLY_JUMPHEIGHT, "Set how high a player is allowed to jump.\nUnit is 1/100 of a block, default is 135.");
set(Configuration.MOVING_RUNFLY_CHECKSWIMMING, "Use a seperate speed limit for swimming players.");
set(Configuration.MOVING_RUNFLY_SWIMMINGSPEEDLIMIT, "Set the speed limit for moving horizontal while in water.\nUnit is 1/100 of a block, default is 18");
set(Configuration.MOVING_RUNFLY_CHECKSNEAKING, "Use a seperate speed limit for sneaking players.");
set(Configuration.MOVING_RUNFLY_SNEAKINGSPEEDLIMIT, "Set the speed limit for moving horizontal while sneaking.\nUnit is 1/100 of a block, default is 14");
set(Configuration.MOVING_RUNFLY_ACTIONS, "What should be done if a player moves faster than the speed limit(s) or jumps higher than allowed.\nUnits are in 1/100 of a block above the limit.");
set(Configuration.MOVING_RUNFLY_CHECKNOFALL, "If true, check if a player is avoiding fall damage by using a nofall hack. EXPERIMENTAL! Feedback is appreciated.");
set(Configuration.MOVING_RUNFLY_NOFALLMULTIPLIER, "How many percent falldamage should be dealt to the player.\nNoCheat will almost always underestimate fall damage, using a value bigger than 100 is advised.\nUnit is percent of the estimated original fall damage, default is 200.");
set(Configuration.MOVING_RUNFLY_NOFALLACTIONS, "What should be done if a player is detected as avoiding fall damage.\nUnit is number of blocks the player fell down.");
set(Configuration.MOVING_RUNFLY_ALLOWLIMITEDFLYING, "If true, instead of doing the above checks for walking/sprinting/swimming/sneaking,\nallow flying and only limit the flying speed.");
set(Configuration.MOVING_RUNFLY_FLYINGSPEEDLIMITVERTICAL, "Set the speed limit for moving vertical while flying.\nUnit is 1/100 of a block, default is 100.");
set(Configuration.MOVING_RUNFLY_FLYINGSPEEDLIMITHORIZONTAL, "Set the speed limit for moving horizontal while flying.\nUnit is 1/100 of a block, default is 60.");
set(Configuration.MOVING_RUNFLY_FLYINGACTIONS, "What should be done if a player flies faster than the speed limit(s). \nUnits are in 1/100 of a block above the speedlimit.");
set(Configuration.MOVING_MOREPACKETS_CHECK, "If true, check if a player is sending too many 'move-packets' per second. In a normal game, the player won't send more than 22 packets per second.");
set(Configuration.MOVING_MOREPACKETS_ACTIONS, "What should be done if a player sends more 'move-packets' than normal.\nUnits are packets per second above the limit.");
set(Configuration.BLOCKBREAK_CHECK, "If true, do various checks on BlockBreak events.");
set(Configuration.BLOCKBREAK_REACH_CHECK, "If true, check if a player is breaking blocks that are too far away.");
set(Configuration.BLOCKBREAK_REACH_LIMIT, "Set the distance limit for breaking blocks.\nUnit is 1/100 of a block, default is 485");
set(Configuration.BLOCKBREAK_REACH_ACTIONS, "What should be done if a player is breaking blocks that are too far away.\nUnit is number of break(attempt)s beyond the limit.");
set(Configuration.BLOCKBREAK_DIRECTION_CHECK, "If true, check if a player is looking at the block that he's breaking.");
set(Configuration.BLOCKBREAK_DIRECTION_CHECKINSTABREAKBLOCKS, "If true, NoCheat will also check for direction for Instant-Breaking blocks.\nTHIS WILL CAUSE FALSE POSITIVES, when a player keeps his mouse button pressed and moves the mouse fast over the screen.");
set(Configuration.BLOCKBREAK_DIRECTION_ACTIONS, "What should be done if a player is breaking blocks that are not in his line of sight.\nUnit is number of break(attempt)s outside the line of sight.");
set(Configuration.BLOCKPLACE_CHECK, "If true, do various checks on BlockPlace events.");
set(Configuration.BLOCKPLACE_REACH_CHECK, "If true, check if a player is placing blocks at locations too far away.");
set(Configuration.BLOCKPLACE_REACH_LIMIT, "Set the distance limit for placing blocks.\nUnit is 1/100 of a block, default is 485");
set(Configuration.BLOCKPLACE_REACH_ACTIONS, "What should be done if a player is placing blocks that are too far away.\nUnit is number of place(attempt)s beyond the limit.");
set(Configuration.BLOCKPLACE_ONLIQUID_CHECK, "If true, check if a player is trying to place non-liquid blocks against liquid blocks\nIn a normal Minecraft game, it is impossible to place a block without it touching something that is considered solid (neither air nor a liquid).\nBut if people use a modified client, to can do that. This check tries to identify that trick.");
set(Configuration.BLOCKPLACE_ONLIQUID_ACTIONS, "What should be done if a player is is trying to place non-liquid blocks against liquid blocks.\nUnit is number of place(attempt)s.");
set(Configuration.INTERACT_CHECK, "If true, do various checks on PlayerInteract events.");
set(Configuration.INTERACT_DURABILITY_CHECK, "If true, check if a player is using a hack that provides infinite durability items.");
set(Configuration.INTERACT_DURABILITY_ACTIONS, "What should be done if a player is trying to use the hack.\nUnit is number of uses or attempts to use the hack.");
set(Configuration.CHAT_CHECK, "If true, do various checks on PlayerChat events.");
set(Configuration.CHAT_SPAM_CHECK, "If true, check if a player is spamming the chat.");
set(Configuration.CHAT_SPAM_TIMEFRAME, "Over what timeframe (in seconds) should the messages be counted?\nWhen the time is over, counting starts at 0 again.");
set(Configuration.CHAT_SPAM_LIMIT, "How many messages per timeframe may the player send without it counting as spamming?");
set(Configuration.CHAT_SPAM_ACTIONS, "What should be done if a player is trying to spam the chat.\nUnit is number of chat messages above the limit you declared above.");
}
private static void set(OptionNode id, String text) {
explainations.put(id, text);
}
public static String get(OptionNode id) {
String result = explainations.get(id);
if(result == null) {
result = "No description available";
}
return result;
}
}

View File

@ -0,0 +1,128 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
import cc.co.evenprime.bukkit.nocheat.actions.types.ConsolecommandAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.LogAction;
import cc.co.evenprime.bukkit.nocheat.actions.types.SpecialAction;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
public class FlatFileAction {
private final File file;
public FlatFileAction(File file) {
this.file = file;
}
public List<Action> read() {
List<Action> actions = new ArrayList<Action>();
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(file));
String line = null;
while((line = reader.readLine()) != null) {
try {
if(line.trim().length() > 0 && !line.startsWith("#")) {
actions.add(parseLine(line));
}
} catch(IllegalArgumentException e) {
System.out.println("NoCheat: " + e.getMessage());
}
}
reader.close();
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
return actions;
}
private Action parseLine(String line) {
// Split the line into some parts
String parts[] = line.split("\\s+", 5);
// four pieces is the minimum we need, no matter what it is
if(parts.length < 4) {
throw new IllegalArgumentException("The line "+line+" of the file "+file.getName()+" is malformed. It has not enough parts.");
}
String type = parts[0];
String name = parts[1];
int delay = 0;
try {
delay = Integer.parseInt(parts[2]);
}
catch(Exception e) {
throw new IllegalArgumentException("Couldn't parse third parameter of action "+name+" from file "+file.getName()+". It is "+parts[2]+" but should be a number.");
}
int repeat = 0;
try {
repeat = Integer.parseInt(parts[3]);
}
catch(Exception e) {
throw new IllegalArgumentException("Couldn't parse fourth parameter of action "+name+" from file "+file.getName()+". It is "+parts[2]+" but should be a number.");
}
if(type.equalsIgnoreCase("log")) {
// A log action, it seems
if(parts.length < 5) {
throw new IllegalArgumentException("Missing fifth parameter of action "+name+" from file "+file.getName()+".");
}
return readLogAction(name, delay, repeat, parts[4]);
}
else if(type.equalsIgnoreCase("consolecommand")) {
// A consolecommand action, it seems
if(parts.length < 5) {
throw new IllegalArgumentException("Missing fifth parameter of action "+name+" from file "+file.getName()+".");
}
return new ConsolecommandAction(name, delay, repeat, parts[4]);
}
else if(type.equalsIgnoreCase("special")) {
// A "special" actions, it seems
return new SpecialAction(name, delay, repeat);
}
else {
throw new IllegalArgumentException("Unknown action type "+type+ " of action with name "+name+".");
}
}
// Moved outside because of bigger complexity of log message parsing
private Action readLogAction(String name, int delay, int repeat, String lastPart) {
String[] rest = lastPart.split("\\s+", 2);
if(rest.length < 2) {
throw new IllegalArgumentException("Missing sixth parameter of action "+name+" from file "+file.getName()+".");
}
LogLevel level;
try {
level = LogLevel.getLogLevelFromString(rest[0]);
}
catch(IllegalArgumentException e) {
throw new IllegalArgumentException("Illegal fifth parameter of action "+name+". "+e.getMessage());
}
return new LogAction(name, delay, repeat, level, rest[1]);
}
}

View File

@ -0,0 +1,258 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.actions.ActionManager;
import cc.co.evenprime.bukkit.nocheat.actions.types.Action;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
public class FlatFileConfiguration extends Configuration {
private final File file;
public FlatFileConfiguration(Configuration defaults, boolean copyDefaults, File file) {
super(defaults, copyDefaults);
this.file = file;
}
public void load(ActionManager action) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
String line = null;
while((line = r.readLine()) != null) {
parse(line, action);
}
r.close();
}
private void parse(String line, ActionManager action) throws IOException {
line = line.trim();
// Is it a key/value pair?
if(line.startsWith("#") || !line.contains("=")) {
return;
}
String pair[] = line.split("=", 2);
String key = pair[0].trim();
String value = pair[1].trim();
// Find out which option we have in front of us
OptionNode node = getOptionNodeForString(ROOT, key);
if(node == null) {
return;
}
switch (node.getType()) {
case ACTIONLIST:
this.set(node, parseActionList(node, key, removeQuotationMarks(value), action));
break;
case STRING:
this.set(node, removeQuotationMarks(value));
break;
case INTEGER:
this.set(node, Integer.valueOf(removeQuotationMarks(value)));
break;
case LOGLEVEL:
this.set(node, LogLevel.getLogLevelFromString(removeQuotationMarks(value)));
break;
case BOOLEAN:
this.set(node, Boolean.valueOf(removeQuotationMarks(value)));
break;
default:
throw new IllegalArgumentException("Unknown node type " + node.getType());
}
}
private ActionList parseActionList(OptionNode node, String key, String value, ActionManager action) {
String[] s = key.split("\\.");
String treshold = s[s.length - 1];
// See if we already got that actionlist created
ActionList al = (ActionList) this.get(node);
if(al == null || al == this.getDefaults().getRecursive(node)) {
al = new ActionList();
}
int th = Integer.parseInt(treshold);
al.setActions(th, action.getActions(value.split("\\s+")));
return al;
}
private OptionNode getOptionNodeForString(OptionNode root, String key) {
String parts[] = key.split("\\.", 2);
for(OptionNode node : root.getChildren()) {
// Found the correct node?
if(node.getName().equals(parts[0])) {
if(node.isLeaf()) {
return node;
} else {
return getOptionNodeForString(node, parts[1]);
}
}
}
return null;
}
public void save() {
try {
if(file.getParentFile() != null)
file.getParentFile().mkdirs();
file.createNewFile();
BufferedWriter w = new BufferedWriter(new FileWriter(file));
w.write("# Want to know what these options do? Read at the end of this file.\r\n");
saveRecursive(w, ROOT);
w.write("\r\n\r\n");
saveDescriptionsRecursive(w, ROOT);
w.flush();
w.close();
} catch(IOException e) {
e.printStackTrace();
}
}
private void saveDescriptionsRecursive(BufferedWriter w, OptionNode node) throws IOException {
if(!node.isLeaf()) {
for(OptionNode o : node.getChildren()) {
saveDescriptionsRecursive(w, o);
}
}
// Save a leaf node, if it's really stored here
Object object = this.get(node);
if(object == null) {
return;
}
// Get the full id of the node
String id = node.getName();
OptionNode i = node;
while((i = i.getParent()) != null && i.getName() != null && i.getName().length() > 0) {
id = i.getName() + "." + id;
}
w.write("\r\n\r\n# " + id + ":\r\n#\r\n");
String explaination = Explainations.get(node);
w.write("# " + explaination.replaceAll("\n", "\r\n# "));
}
private void saveRecursive(BufferedWriter w, OptionNode node) throws IOException {
if(!node.isLeaf()) {
for(OptionNode o : node.getChildren()) {
if(node == ROOT) {
w.write("\r\n");
}
saveRecursive(w, o);
}
return;
}
// Save a leaf node, if it's really stored here
Object object = this.get(node);
if(object == null) {
return;
}
// Get the full id of the node
String id = node.getName();
OptionNode i = node;
while((i = i.getParent()) != null && i.getName() != null && i.getName().length() > 0) {
id = i.getName() + "." + id;
}
switch (node.getType()) {
case ACTIONLIST:
saveActionList(w, id, (ActionList) object);
break;
case STRING:
saveString(w, id, (String) object);
break;
case INTEGER:
saveValue(w, id, object.toString());
break;
case LOGLEVEL:
saveValue(w, id, object.toString());
break;
case BOOLEAN:
saveValue(w, id, object.toString());
break;
default:
throw new IllegalArgumentException("Unknown node type " + node.getType());
}
}
private void saveActionList(BufferedWriter w, String id, ActionList actionList) throws IOException {
for(Integer treshold : actionList.getTresholds()) {
String s = "";
for(Action s2 : actionList.getActions(treshold)) {
s = s + " " + s2.name;
}
saveValue(w, id + "." + treshold, s.trim());
}
}
private void saveString(BufferedWriter w, String id, String value) throws IOException {
saveValue(w, id, addQuotationMarks(value));
}
private void saveValue(BufferedWriter w, String id, String value) throws IOException {
w.write(id + " = " + value + "\r\n");
}
protected String removeQuotationMarks(String s) {
s = s.trim();
if(s.startsWith("\"") && s.endsWith("\"")) {
return s.substring(1, s.length() - 1);
} else if(s.startsWith("\'") && s.endsWith("\'")) {
return s.substring(1, s.length() - 1);
}
return s;
}
protected String addQuotationMarks(String s) {
return "\"" + s + "\"";
}
}

View File

@ -0,0 +1,60 @@
package cc.co.evenprime.bukkit.nocheat.config;
import java.util.LinkedList;
import java.util.List;
public class OptionNode {
public enum DataType {
PARENT, STRING, BOOLEAN, INTEGER, LOGLEVEL, ACTIONLIST
};
private final String name;
private final List<OptionNode> children;
private final OptionNode parent;
private final DataType type;
public OptionNode(String name, OptionNode parent, DataType type) {
this.name = name;
if(type == DataType.PARENT) {
this.children = new LinkedList<OptionNode>();
} else {
this.children = null;
}
if(parent != null) {
parent.addChild(this);
}
this.parent = parent;
this.type = type;
}
public void addChild(OptionNode node) {
if(this.type != DataType.PARENT) {
throw new IllegalArgumentException("Can't a child to a leaf node.");
}
this.children.add(node);
}
public boolean isLeaf() {
return this.type != DataType.PARENT;
}
public List<OptionNode> getChildren() {
return this.children;
}
public String getName() {
return name;
}
public OptionNode getParent() {
return parent;
}
public DataType getType() {
return type;
}
}

View File

@ -1,4 +1,4 @@
package cc.co.evenprime.bukkit.nocheat;
package cc.co.evenprime.bukkit.nocheat.config;
/**
* The various permission nodes used by NoCheat
@ -17,7 +17,6 @@ public class Permissions {
public final static String MOVE_SNEAK = MOVE + ".sneaking";
public final static String MOVE_SWIM = MOVE + ".swimming";
public final static String MOVE_FLY = MOVE + ".flying";
public final static String MOVE_NOCLIP = MOVE + ".noclip";
public final static String MOVE_NOFALL = MOVE + ".nofall";
public final static String MOVE_MOREPACKETS = MOVE + ".morepackets";
@ -36,6 +35,8 @@ public class Permissions {
public final static String CHAT_SPAM = CHAT + ".spam";
public final static String ADMIN_CHATLOG = ADMIN + ".chatlog";
public static final String ADMIN_PERMLIST = ADMIN + ".permlist";
public static final String ADMIN_RELOAD = ADMIN + ".reload";
private Permissions() {}
}

View File

@ -2,6 +2,7 @@ package cc.co.evenprime.bukkit.nocheat.config.cache;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
/**
* Configurations specific for the "BlockBreak" checks
@ -22,14 +23,12 @@ public class CCBlockBreak {
public CCBlockBreak(Configuration data) {
check = data.getBoolean("blockbreak.check");
reachCheck = data.getBoolean("blockbreak.reach.check");
reachDistance = ((double) data.getInteger("blockbreak.reach.reachlimit")) / 100D;
reachActions = data.getActionList("blockbreak.reach.actions");
directionCheck = data.getBoolean("blockbreak.direction.check");
directionActions = data.getActionList("blockbreak.direction.actions");
checkinstabreakblocks = data.getBoolean("blockbreak.direction.checkinstabreakblocks");
check = data.getBoolean(DefaultConfiguration.BLOCKBREAK_CHECK);
reachCheck = data.getBoolean(DefaultConfiguration.BLOCKBREAK_REACH_CHECK);
reachDistance = ((double) data.getInteger(DefaultConfiguration.BLOCKBREAK_REACH_LIMIT)) / 100D;
reachActions = data.getActionList(DefaultConfiguration.BLOCKBREAK_REACH_ACTIONS);
checkinstabreakblocks = data.getBoolean(DefaultConfiguration.BLOCKBREAK_DIRECTION_CHECKINSTABREAKBLOCKS);
directionCheck = data.getBoolean(DefaultConfiguration.BLOCKBREAK_DIRECTION_CHECK);
directionActions = data.getActionList(DefaultConfiguration.BLOCKBREAK_DIRECTION_ACTIONS);
}
}

View File

@ -2,6 +2,7 @@ package cc.co.evenprime.bukkit.nocheat.config.cache;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
/**
*
@ -20,13 +21,14 @@ public class CCBlockPlace {
public CCBlockPlace(Configuration data) {
check = data.getBoolean("blockplace.check");
onliquidCheck = data.getBoolean("blockplace.onliquid.check");
onliquidActions = data.getActionList("blockplace.onliquid.actions");
check = data.getBoolean(DefaultConfiguration.BLOCKPLACE_CHECK);
onliquidCheck = data.getBoolean(DefaultConfiguration.BLOCKPLACE_ONLIQUID_CHECK);
onliquidActions = data.getActionList(DefaultConfiguration.BLOCKPLACE_ONLIQUID_ACTIONS);
reachCheck = data.getBoolean("blockplace.reach.check");
reachDistance = data.getInteger("blockplace.reach.reachlimit");
reachActions = data.getActionList("blockplace.reach.actions");
reachCheck = data.getBoolean(DefaultConfiguration.BLOCKPLACE_REACH_CHECK);
reachDistance = data.getInteger(DefaultConfiguration.BLOCKPLACE_REACH_LIMIT);
reachActions = data.getActionList(DefaultConfiguration.BLOCKPLACE_REACH_ACTIONS);
}
}

View File

@ -2,6 +2,7 @@ package cc.co.evenprime.bukkit.nocheat.config.cache;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
public class CCChat {
@ -13,11 +14,11 @@ public class CCChat {
public CCChat(Configuration data) {
check = data.getBoolean("chat.check");
spamCheck = data.getBoolean("chat.spam.check");
spamTimeframe = data.getInteger("chat.spam.timeframe");
spamLimit = data.getInteger("chat.spam.limit");
spamActions = data.getActionList("chat.spam.actions");
check = data.getBoolean(DefaultConfiguration.CHAT_CHECK);
spamCheck = data.getBoolean(DefaultConfiguration.CHAT_SPAM_CHECK);
spamTimeframe = data.getInteger(DefaultConfiguration.CHAT_SPAM_TIMEFRAME);
spamLimit = data.getInteger(DefaultConfiguration.CHAT_SPAM_LIMIT);
spamActions = data.getActionList(DefaultConfiguration.CHAT_SPAM_ACTIONS);
}
}

View File

@ -1,6 +1,7 @@
package cc.co.evenprime.bukkit.nocheat.config.cache;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
public class CCDebug {
@ -10,6 +11,6 @@ public class CCDebug {
public CCDebug(Configuration data) {
showchecks = data.getBoolean("debug.showactivechecks");
showchecks = data.getBoolean(DefaultConfiguration.DEBUG_SHOWACTIVECHECKS);
}
}

View File

@ -2,25 +2,24 @@ package cc.co.evenprime.bukkit.nocheat.config.cache;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
/**
*
* @author Evenprime
*
*
*/
public class CCInteract {
public final boolean check;
public final boolean durabilityCheck;
public final boolean check;
public final boolean durabilityCheck;
public final ActionList durabilityActions;
public CCInteract(Configuration data) {
check = data.getBoolean("interact.check");
durabilityCheck = data.getBoolean("interact.durability.check");
durabilityActions = data.getActionList("interact.durability.actions");
check = data.getBoolean(DefaultConfiguration.INTERACT_CHECK);
durabilityCheck = data.getBoolean(DefaultConfiguration.INTERACT_DURABILITY_CHECK);
durabilityActions = data.getActionList(DefaultConfiguration.INTERACT_DURABILITY_ACTIONS);
}
}

View File

@ -3,6 +3,7 @@ package cc.co.evenprime.bukkit.nocheat.config.cache;
import java.util.logging.Logger;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
@ -21,10 +22,10 @@ public class CCLogging {
public CCLogging(Configuration data, Logger worldSpecificFileLogger) {
active = data.getBoolean("logging.active");
fileLevel = data.getLogLevel("logging.filelevel");
consoleLevel = data.getLogLevel("logging.consolelevel");
chatLevel = data.getLogLevel("logging.chatlevel");
active = data.getBoolean(DefaultConfiguration.LOGGING_ACTIVE);
fileLevel = data.getLogLevel(DefaultConfiguration.LOGGING_FILELEVEL);
consoleLevel = data.getLogLevel(DefaultConfiguration.LOGGING_CONSOLELEVEL);
chatLevel = data.getLogLevel(DefaultConfiguration.LOGGING_CHATLEVEL);
filelogger = worldSpecificFileLogger;
}

View File

@ -2,6 +2,7 @@ package cc.co.evenprime.bukkit.nocheat.config.cache;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.config.DefaultConfiguration;
/**
* Configurations specific for the Move Checks. Every world gets one of these
@ -29,9 +30,6 @@ public class CCMoving {
public final double flyingSpeedLimitHorizontal;
public final ActionList flyingActions;
public final boolean noclipCheck;
public final ActionList noclipActions;
public final boolean nofallCheck;
public final float nofallMultiplier;
public final ActionList nofallActions;
@ -41,35 +39,31 @@ public class CCMoving {
public CCMoving(Configuration data) {
check = data.getBoolean("moving.check");
identifyCreativeMode = data.getBoolean("moving.identifycreativemode");
check = data.getBoolean(DefaultConfiguration.MOVING_CHECK);
identifyCreativeMode = data.getBoolean(DefaultConfiguration.MOVING_IDENTIFYCREATIVEMODE);
runflyCheck = data.getBoolean(DefaultConfiguration.MOVING_RUNFLY_CHECK);
walkingSpeedLimit = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_WALKINGSPEEDLIMIT)) / 100D;
sprintingSpeedLimit = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_SPRINTINGSPEEDLIMIT)) / 100D;
jumpheight = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_JUMPHEIGHT)) / 100D;
actions = data.getActionList(DefaultConfiguration.MOVING_RUNFLY_ACTIONS);
runflyCheck = data.getBoolean("moving.runfly.check");
swimmingCheck = data.getBoolean(DefaultConfiguration.MOVING_RUNFLY_CHECKSWIMMING);
swimmingSpeedLimit = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_SWIMMINGSPEEDLIMIT)) / 100D;
sneakingCheck = data.getBoolean(DefaultConfiguration.MOVING_RUNFLY_CHECKSNEAKING);
sneakingSpeedLimit = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_SNEAKINGSPEEDLIMIT)) / 100D;
walkingSpeedLimit = ((double) data.getInteger("moving.runfly.walkingspeedlimit")) / 100D;
sprintingSpeedLimit = ((double) data.getInteger("moving.runfly.sprintingspeedlimit")) / 100D;
jumpheight = ((double) data.getInteger("moving.runfly.jumpheight")) / 100D;
actions = data.getActionList("moving.runfly.actions");
allowFlying = data.getBoolean(DefaultConfiguration.MOVING_RUNFLY_ALLOWLIMITEDFLYING);
flyingSpeedLimitVertical = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_FLYINGSPEEDLIMITVERTICAL)) / 100D;
flyingSpeedLimitHorizontal = ((double) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_FLYINGSPEEDLIMITHORIZONTAL)) / 100D;
flyingActions = data.getActionList(DefaultConfiguration.MOVING_RUNFLY_FLYINGACTIONS);
swimmingCheck = data.getBoolean("moving.runfly.checkswimming");
swimmingSpeedLimit = ((double) data.getInteger("moving.runfly.swimmingspeedlimit")) / 100D;
sneakingCheck = data.getBoolean("moving.runfly.checksneaking");
sneakingSpeedLimit = ((double) data.getInteger("moving.runfly.sneakingspeedlimit")) / 100D;
nofallCheck = data.getBoolean(DefaultConfiguration.MOVING_RUNFLY_CHECKNOFALL);
nofallMultiplier = ((float) data.getInteger(DefaultConfiguration.MOVING_RUNFLY_NOFALLMULTIPLIER)) / 100F;
nofallActions = data.getActionList(DefaultConfiguration.MOVING_RUNFLY_NOFALLACTIONS);
allowFlying = data.getBoolean("moving.runfly.allowlimitedflying");
flyingSpeedLimitVertical = ((double) data.getInteger("moving.runfly.flyingspeedlimitvertical")) / 100D;
flyingSpeedLimitHorizontal = ((double) data.getInteger("moving.runfly.flyingspeedlimithorizontal")) / 100D;
flyingActions = data.getActionList("moving.runfly.flyingactions");
nofallCheck = data.getBoolean("moving.runfly.checknofall");
nofallMultiplier = ((float) data.getInteger("moving.runfly.nofallmultiplier")) / 100F;
nofallActions = data.getActionList("moving.runfly.nofallactions");
noclipCheck = data.getBoolean("moving.noclip.check");
noclipActions = data.getActionList("moving.noclip.actions");
morePacketsCheck = data.getBoolean("moving.morepackets.check");
morePacketsActions = data.getActionList("moving.morepackets.actions");
morePacketsCheck = data.getBoolean(DefaultConfiguration.MOVING_MOREPACKETS_CHECK);
morePacketsActions = data.getActionList(DefaultConfiguration.MOVING_MOREPACKETS_ACTIONS);
}
}

View File

@ -6,7 +6,7 @@ import cc.co.evenprime.bukkit.nocheat.config.Configuration;
/**
* A class to keep all configurables of the plugin associated with
* a world, everything unmodifiable.
* a world, everything unmodifiable for security/performance
*
* @author Evenprime
*

View File

@ -1,50 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* A special node of the configuration tree
*
* @author Evenprime
*
*/
public class ActionListOption extends ChildOption {
private final LinkedList<ActionOption> actionOptions = new LinkedList<ActionOption>();
public ActionListOption(String identifier) {
super(identifier);
}
public void add(Integer treshold, String actions) {
actionOptions.add(new ActionOption(treshold, actions));
Collections.sort(actionOptions);
}
public List<ActionOption> getChildOptions() {
return actionOptions;
}
public void remove(ActionOption actionOption) {
this.actionOptions.remove(actionOption);
}
@Override
public ActionListOption clone() {
ActionListOption o = new ActionListOption(this.getIdentifier());
for(ActionOption ao : getChildOptions()) {
o.add(ao.getTreshold(), ao.getStringValue());
}
return o;
}
public void clear() {
actionOptions.clear();
}
}

View File

@ -1,56 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A special node of the configuration tree
*
* @author Evenprime
*
*/
public class ActionOption extends ChildOption implements Comparable<ActionOption> {
private final int treshold;
private String value;
public ActionOption(Integer treshold, String value) {
super(treshold.toString());
this.treshold = treshold;
this.value = value;
}
@Override
public String getStringValue() {
return value;
}
@Override
public boolean setStringValue(String value) {
this.value = value;
return true;
}
public int getTreshold() {
return treshold;
}
@Override
public ActionOption clone() {
return new ActionOption(treshold, value);
}
@Override
public int compareTo(ActionOption o) {
if(treshold < o.treshold) {
return -1;
} else if(treshold == o.treshold) {
return 0;
} else
return 1;
}
public String toString() {
return "ActionOption " + getFullIdentifier() + " " + getStringValue();
}
}

View File

@ -1,65 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A node of the configuration tree
*
* @author Evenprime
*
*/
public class BooleanOption extends ChildOption {
/**
*
*/
private static final long serialVersionUID = 2258827414736580449L;
private boolean value;
private boolean isMaster = false;
public BooleanOption(String name, boolean initialValue, boolean isMaster) {
super(name);
this.value = initialValue;
this.isMaster = isMaster;
}
public void setBooleanValue(boolean value) {
this.value = value;
}
@Override
public String getStringValue() {
return Boolean.toString(value);
}
@Override
public boolean setStringValue(String value) {
try {
this.value = Boolean.parseBoolean(value);
return true;
} catch(Exception e) {
return false;
}
}
public boolean getBooleanValue() {
return value;
}
@Override
public BooleanOption clone() {
return new BooleanOption(this.getIdentifier(), value, isMaster);
}
public boolean isMaster() {
return isMaster;
}
public void setMaster(boolean master) {
this.isMaster = master;
}
public String toString() {
return "BooleanOption " + this.getFullIdentifier() + " " + getStringValue() + (isMaster ? " master" : "");
}
}

View File

@ -1,32 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A leaf of the configuration tree
*
* @author Evenprime
*
*/
public abstract class ChildOption extends Option implements Cloneable {
/**
*
*/
private static final long serialVersionUID = -4648294833934457776L;
private String value;
public ChildOption(String identifier) {
super(identifier);
}
public String getStringValue() {
return value;
}
public boolean setStringValue(String string) {
this.value = string;
return true;
}
public abstract ChildOption clone();
}

View File

@ -1,239 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
import java.util.ArrayList;
import java.util.List;
import cc.co.evenprime.bukkit.nocheat.actions.ActionList;
import cc.co.evenprime.bukkit.nocheat.config.Configuration;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
* Only used during parsing of the configuration files and for the GUI wizard
*
* @author Evenprime
*
*/
public class ConfigurationTree implements Configuration {
// Each tree has a root option that does nothing
private final ParentOption root = new ParentOption("");
// Each tree can have a "parent" tree
private ConfigurationTree parent = null;
/**
* Start a new tree
*
* @param parent
*/
public ConfigurationTree() {}
public void setParent(ConfigurationTree parent) {
this.parent = parent;
}
public ConfigurationTree getParent() {
return parent;
}
/**
* Get a specific option from this tree or its parent(s), if this
* tree doesn't contain this option
*
* @param fullIdentifier
* @return
*/
private Option getOptionRecursive(String fullIdentifier) {
// Find out the partial identifiers
String[] identifiers = fullIdentifier.split("\\.");
// Start at the root
Option o = root;
// Go through all partial identifiers
for(int i = 0; i < identifiers.length; i++) {
if(o instanceof ParentOption) {
for(Option o2 : ((ParentOption) o).getChildOptions()) {
if(o2.getIdentifier().equals(identifiers[i])) {
o = o2;
break;
}
}
} else
break;
}
// Does the node we last met match our searched node and is it enabled?
if(o.getFullIdentifier().equals(fullIdentifier) && o.isActive()) {
return o;
}
// No, then ask our parent (if possible)
else if(parent != null) {
return parent.getOptionRecursive(fullIdentifier);
} else {
return null;
}
}
/**
* Get a specific option from this tree
*
* @param fullIdentifier
* @return
*/
public Option getOption(String fullIdentifier) {
// Find out the partial identifiers
String[] identifiers = fullIdentifier.split("\\.");
// Start at the root
Option o = root;
// Go through all partial identifiers
for(int i = 0; i < identifiers.length; i++) {
if(o instanceof ParentOption) {
for(Option o2 : ((ParentOption) o).getChildOptions()) {
if(o2.getIdentifier().equals(identifiers[i])) {
o = o2;
break;
}
}
} else
break;
}
// Does the node we last met match our searched node?
if(o.getFullIdentifier().equals(fullIdentifier)) {
return o;
} else {
return null;
}
}
/**
* Add a option to this tree, at the specified parent
*
* @param parent
* @param option
*/
public void add(String parent, Option option) {
try {
if(parent == null || parent == "") {
add(option);
} else {
ParentOption po = (ParentOption) getOption(parent);
po.add(option);
}
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* Add a option at the root
*
* @param option
*/
public void add(Option option) {
root.add(option);
}
/**
*
* @return
*/
public List<Option> getAllOptions() {
List<Option> options = new ArrayList<Option>();
ParentOption o = root;
for(Option o2 : o.getChildOptions()) {
if(o2.isActive()) {
options.addAll(getAllOptions(o2));
}
}
return options;
}
private List<Option> getAllOptions(Option subtree) {
List<Option> options = new ArrayList<Option>();
options.add(subtree);
if(subtree instanceof ParentOption) {
for(Option child : ((ParentOption) subtree).getChildOptions()) {
options.addAll(getAllOptions(child));
}
}
return options;
}
/*
* (non-Javadoc)
*
* @see
* cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationProvider#getBoolean
* (java.lang.String)
*/
@Override
public boolean getBoolean(String string) {
return ((BooleanOption) this.getOptionRecursive(string)).getBooleanValue();
}
/*
* (non-Javadoc)
*
* @see cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationProvider#
* getActionList(java.lang.String)
*/
@Override
public ActionList getActionList(String string) {
ActionList actionList = new ActionList();
ActionListOption option = (ActionListOption) this.getOptionRecursive(string);
for(ActionOption ao : option.getChildOptions()) {
actionList.addEntry(ao.getTreshold(), ao.getStringValue().split(" "));
}
return actionList;
}
/*
* (non-Javadoc)
*
* @see
* cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationProvider#getInteger
* (java.lang.String)
*/
@Override
public int getInteger(String string) {
return ((IntegerOption) this.getOptionRecursive(string)).getIntegerValue();
}
/*
* (non-Javadoc)
*
* @see
* cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationProvider#getString
* (java.lang.String)
*/
@Override
public String getString(String string) {
return ((ChildOption) this.getOptionRecursive(string)).getStringValue();
}
/*
* (non-Javadoc)
*
* @see
* cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationProvider#getLogLevel
* (java.lang.String)
*/
@Override
public LogLevel getLogLevel(String string) {
return ((LogLevelOption) this.getOptionRecursive(string)).getLogLevelValue();
}
}

View File

@ -1,42 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A node for the configuration tree
*
* @author Evenprime
*
*/
public class IntegerOption extends StringOption {
/**
*
*/
private static final long serialVersionUID = 2258827414736580449L;
public IntegerOption(String name, int initialValue) {
super(name, String.valueOf(initialValue), 5);
}
@Override
public boolean isValid(String value) {
if(!super.isValid(value))
return false;
try {
Integer.parseInt(value);
return true;
} catch(Exception e) {
return false;
}
}
public int getIntegerValue() {
return Integer.parseInt(this.getStringValue());
}
public IntegerOption clone() {
return new IntegerOption(this.getIdentifier(), this.getIntegerValue());
}
}

View File

@ -1,47 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
* A node for the configuration tree
*
* @author Evenprime
*
*/
public class LogLevelOption extends ChildOption {
/**
*
*/
private static final long serialVersionUID = -1609308017422576285L;
private LogLevel option;
public LogLevelOption(String identifier, LogLevel initialValue) {
super(identifier);
this.option = initialValue;
}
@Override
public String getStringValue() {
return option.name;
}
public boolean setStringValue(String value) {
option = LogLevel.getLogLevelFromString(value);
return true;
}
public void setLogLevelValue(LogLevel value) {
this.option = value;
}
public LogLevel getLogLevelValue() {
return this.option;
}
public LogLevelOption clone() {
return new LogLevelOption(this.getIdentifier(), this.option);
}
}

View File

@ -1,23 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A node for the configuration tree
*
* @author Evenprime
*
*/
public class MediumStringOption extends StringOption {
/**
*
*/
private static final long serialVersionUID = 2258827414736580449L;
public MediumStringOption(String name, String initialValue) {
super(name, initialValue, 30);
}
public MediumStringOption clone() {
return new MediumStringOption(this.getIdentifier(), this.getStringValue());
}
}

View File

@ -1,43 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A node for the configuration tree
*
* @author Evenprime
*
*/
public abstract class Option {
private final String identifier;
private Option parent;
private boolean active = true;
public Option(String identifier) {
this.identifier = identifier;
}
public final String getIdentifier() {
return identifier;
}
public final void setParent(Option parent) {
this.parent = parent;
}
public final Option getParent() {
return parent;
}
public final String getFullIdentifier() {
return (parent == null || parent.getFullIdentifier() == "") ? identifier : parent.getFullIdentifier() + "." + identifier;
}
public void setActive(boolean b) {
active = b;
}
public boolean isActive() {
return active;
}
}

View File

@ -1,45 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
/**
* A node for the configuration tree
*
* @author Evenprime
*
*/
public class ParentOption extends Option {
/**
*
*/
private static final long serialVersionUID = 3162246550749560727L;
private final LinkedList<Option> children = new LinkedList<Option>();
public ParentOption(String identifier) {
super(identifier);
}
public final Collection<Option> getChildOptions() {
return Collections.unmodifiableCollection(children);
}
public final void add(Option option) {
children.addLast(option);
option.setParent(this);
}
public Option getChild(String identifier) {
for(Option o : children) {
if(o.getIdentifier().equals(identifier)) {
return o;
}
}
return null;
}
}

View File

@ -1,50 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.config.tree;
/**
* A node for the configuration tree
*
* @author Evenprime
*
*/
public abstract class StringOption extends ChildOption {
/**
*
*/
private static final long serialVersionUID = -8189248456599421250L;
private String value;
private final int length;
protected StringOption(String name, String initialValue, int preferredLength) {
super(name);
this.value = initialValue;
this.length = preferredLength;
}
@Override
public String getStringValue() {
return this.value;
}
public boolean setStringValue(String value) {
if(isValid(value)) {
this.value = value;
return true;
} else
return false;
}
protected boolean isValid(String value) {
return value != null;
}
public int getPreferredLength() {
return length;
}
public boolean hasPreferredLength() {
return length != -1;
}
}

View File

@ -20,6 +20,7 @@ public class DataManager {
private final Map<Player, InteractData> interactData = new HashMap<Player, InteractData>();
private final Map<Player, BlockPlaceData> blockPlaceData = new HashMap<Player, BlockPlaceData>();
private final Map<Player, ChatData> chatData = new HashMap<Player, ChatData>();
private final Map<Player, LogData> logData = new HashMap<Player, LogData>();
public DataManager() {
@ -102,4 +103,20 @@ public class DataManager {
return data;
}
public LogData getLogData(Player player) {
LogData data;
// intentionally not thread-safe, because bukkit events are handled
// in sequence anyway, so zero chance of two events of the same
// player being handled at the same time
// And if it still happens by accident, it's no real loss anyway
data = logData.get(player);
if(data == null) {
data = new LogData(player);
logData.put(player, data);
}
return data;
}
}

View File

@ -0,0 +1,32 @@
package cc.co.evenprime.bukkit.nocheat.data;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
/**
* Everything that could be relevant for logging or consolecommand actions
*
* @author Evenprime
*
*/
public class LogData {
// The player never changes
public final Player player;
public String check;
public int violationLevel;
public Location toLocation;
public int packets;
public String text;
public Material placedMaterial;
public Block placed;
public Block placedAgainst;
public double reachdistance;
public float falldistance;
public LogData(Player player) {
this.player = player;
}
}

View File

@ -26,15 +26,11 @@ public class MovingData {
public float fallDistance = 0.0F;
public float lastAddedFallDistance = 0.0F;
public int noclipX;
public int noclipY;
public int noclipZ;
public double horizontalBuffer;
public int bunnyhopdelay = 0;
public int morePacketsCounter;
public double morePacketsBuffer = 50;
public int morePacketsBuffer = 50;
public Location morePacketsSetbackPoint;
public double morePacketsViolationLevel = 0;

View File

@ -13,11 +13,9 @@ import org.bukkit.event.block.BlockListener;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.checks.blockbreak.BlockBreakCheck;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;
/**
@ -30,14 +28,11 @@ import cc.co.evenprime.bukkit.nocheat.data.BlockBreakData;
public class BlockBreakEventManager extends BlockListener implements EventManager {
private final BlockBreakCheck blockBreakCheck;
private final DataManager data;
private final ConfigurationManager config;
private final NoCheat plugin;
public BlockBreakEventManager(NoCheat plugin) {
this.data = plugin.getDataManager();
this.config = plugin.getConfigurationManager();
this.plugin = plugin;
this.blockBreakCheck = new BlockBreakCheck(plugin);
PluginManager pm = Bukkit.getServer().getPluginManager();
@ -54,7 +49,7 @@ public class BlockBreakEventManager extends BlockListener implements EventManage
}
final Player player = event.getPlayer();
final ConfigurationCache cc = config.getConfigurationCacheForWorld(player.getWorld().getName());
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName());
// Find out if checks need to be done for that player
if(cc.blockbreak.check && !player.hasPermission(Permissions.BLOCKBREAK)) {
@ -62,7 +57,7 @@ public class BlockBreakEventManager extends BlockListener implements EventManage
boolean cancel = false;
// Get the player-specific stored data that applies here
final BlockBreakData data = this.data.getBlockBreakData(player);
final BlockBreakData data = plugin.getDataManager().getBlockBreakData(player);
cancel = blockBreakCheck.check(player, event.getBlock(), data, cc);
@ -82,7 +77,7 @@ public class BlockBreakEventManager extends BlockListener implements EventManage
final Player player = event.getPlayer();
// Get the player-specific stored data that applies here
final BlockBreakData data = this.data.getBlockBreakData(player);
final BlockBreakData data = plugin.getDataManager().getBlockBreakData(player);
// Remember this location. We ignore block breaks in the block-break
// direction check that are insta-breaks

View File

@ -12,12 +12,10 @@ import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.checks.blockplace.BlockPlaceCheck;
import cc.co.evenprime.bukkit.nocheat.checks.moving.RunFlyCheck;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
/**
* Central location to listen to Block-related events and dispatching them to
@ -28,17 +26,14 @@ import cc.co.evenprime.bukkit.nocheat.data.DataManager;
*/
public class BlockPlaceEventManager extends BlockListener implements EventManager {
private final RunFlyCheck movingCheck;
private final BlockPlaceCheck blockPlaceCheck;
private final NoCheat plugin;
private final RunFlyCheck movingCheck;
private final BlockPlaceCheck blockPlaceCheck;
private final DataManager data;
private final ConfigurationManager config;
public BlockPlaceEventManager(NoCheat plugin) {
this.data = plugin.getDataManager();
this.config = plugin.getConfigurationManager();
public BlockPlaceEventManager(NoCheat p) {
this.plugin = p;
this.movingCheck = new RunFlyCheck(plugin);
this.blockPlaceCheck = new BlockPlaceCheck(plugin);
@ -54,7 +49,7 @@ public class BlockPlaceEventManager extends BlockListener implements EventManage
if(!event.isCancelled()) {
final Player player = event.getPlayer();
// Get the player-specific stored data that applies here
movingCheck.blockPlaced(player, data.getMovingData(player), event.getBlockPlaced());
movingCheck.blockPlaced(player, plugin.getDataManager().getMovingData(player), event.getBlockPlaced());
}
}
}, Priority.Monitor, plugin);
@ -67,12 +62,12 @@ public class BlockPlaceEventManager extends BlockListener implements EventManage
boolean cancel = false;
final Player player = event.getPlayer();
final ConfigurationCache cc = config.getConfigurationCacheForWorld(player.getWorld().getName());
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName());
// Find out if checks need to be done for that player
if(cc.blockplace.check && !player.hasPermission(Permissions.BLOCKPLACE)) {
cancel = blockPlaceCheck.check(player, event.getBlockPlaced(), event.getBlockAgainst(), data.getBlockPlaceData(player), cc);
cancel = blockPlaceCheck.check(player, event.getBlockPlaced(), event.getBlockAgainst(), plugin.getDataManager().getBlockPlaceData(player), cc);
}
if(cancel) {

View File

@ -13,28 +13,24 @@ import org.bukkit.event.player.PlayerListener;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.checks.chat.ChatCheck;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.ChatData;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
/**
*
* @author Evenprime
*
*
*/
public class PlayerChatEventManager extends PlayerListener implements EventManager {
private final ChatCheck chatCheck;
private final DataManager data;
private final ConfigurationManager config;
private final NoCheat plugin;
private final ChatCheck chatCheck;
public PlayerChatEventManager(NoCheat plugin) {
this.data = plugin.getDataManager();
this.config = plugin.getConfigurationManager();
this.plugin = plugin;
this.chatCheck = new ChatCheck(plugin);
PluginManager pm = Bukkit.getServer().getPluginManager();
@ -51,7 +47,7 @@ public class PlayerChatEventManager extends PlayerListener implements EventManag
}
final Player player = event.getPlayer();
final ConfigurationCache cc = config.getConfigurationCacheForWorld(player.getWorld().getName());
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName());
// Find out if checks need to be done for that player
if(cc.chat.check && !player.hasPermission(Permissions.CHAT)) {
@ -59,7 +55,7 @@ public class PlayerChatEventManager extends PlayerListener implements EventManag
boolean cancel = false;
// Get the player-specific stored data that applies here
final ChatData data = this.data.getChatData(player);
final ChatData data = plugin.getDataManager().getChatData(player);
cancel = chatCheck.check(player, event.getMessage(), data, cc);

View File

@ -12,11 +12,9 @@ import org.bukkit.event.player.PlayerListener;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.checks.interact.InteractCheck;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
import cc.co.evenprime.bukkit.nocheat.data.InteractData;
/**
@ -24,16 +22,14 @@ import cc.co.evenprime.bukkit.nocheat.data.InteractData;
* @author Evenprime
*
*/
public class PlayerInteractEventManager extends PlayerListener implements EventManager {
public class PlayerInteractEventManager extends PlayerListener implements EventManager {
private final InteractCheck interactCheck;
private final DataManager data;
private final ConfigurationManager config;
private final NoCheat plugin;
private final InteractCheck interactCheck;
public PlayerInteractEventManager(NoCheat plugin) {
this.data = plugin.getDataManager();
this.config = plugin.getConfigurationManager();
this.plugin = plugin;
this.interactCheck = new InteractCheck(plugin);
PluginManager pm = Bukkit.getServer().getPluginManager();
@ -49,7 +45,7 @@ public class PlayerInteractEventManager extends PlayerListener implements Event
}
final Player player = event.getPlayer();
final ConfigurationCache cc = config.getConfigurationCacheForWorld(player.getWorld().getName());
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName());
// Find out if checks need to be done for that player
if(cc.interact.check && !player.hasPermission(Permissions.INTERACT)) {
@ -57,7 +53,7 @@ public class PlayerInteractEventManager extends PlayerListener implements Event
boolean cancel = false;
// Get the player-specific stored data that applies here
final InteractData data = this.data.getInteractData(player);
final InteractData data = plugin.getDataManager().getInteractData(player);
cancel = interactCheck.check(player, data, cc);
@ -65,7 +61,6 @@ public class PlayerInteractEventManager extends PlayerListener implements Event
event.setCancelled(true);
}
}
}
@Override

View File

@ -1,50 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.events;
import java.util.LinkedList;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerListener;
import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
/**
*
* Temporary, until Bukkit implements a real fix for the problem.
*
* @author Evenprime
*
*/
public class PlayerItemDropEventManager extends PlayerListener implements EventManager {
public PlayerItemDropEventManager(NoCheat plugin) {
PluginManager pm = Bukkit.getServer().getPluginManager();
pm.registerEvent(Event.Type.PLAYER_DROP_ITEM, this, Priority.Lowest, plugin);
}
@Override
public void onPlayerDropItem(PlayerDropItemEvent event) {
if(!event.getPlayer().isOnline()) {
event.setCancelled(true);
}
}
@Override
public List<String> getActiveChecks(ConfigurationCache cc) {
return new LinkedList<String>();
}
@Override
public List<String> getInactiveChecks(ConfigurationCache cc) {
return new LinkedList<String>();
}
}

View File

@ -15,11 +15,9 @@ import org.bukkit.plugin.PluginManager;
import org.bukkit.util.Vector;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.checks.moving.RunFlyCheck;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
@ -33,15 +31,12 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
*/
public class PlayerMoveEventManager extends PlayerListener implements EventManager {
private final RunFlyCheck movingCheck;
private final ConfigurationManager config;
private final DataManager data;
private final NoCheat plugin;
private final RunFlyCheck movingCheck;
public PlayerMoveEventManager(NoCheat plugin) {
this.config = plugin.getConfigurationManager();
this.data = plugin.getDataManager();
this.plugin = plugin;
this.movingCheck = new RunFlyCheck(plugin);
PluginManager pm = Bukkit.getServer().getPluginManager();
@ -59,13 +54,13 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
// Get the world-specific configuration that applies here
final Player player = event.getPlayer();
final ConfigurationCache cc = config.getConfigurationCacheForWorld(player.getWorld().getName());
final ConfigurationCache cc = plugin.getConfigurationManager().getConfigurationCacheForWorld(player.getWorld().getName());
// Find out if checks need to be done for that player
if(cc.moving.check && !player.hasPermission(Permissions.MOVE)) {
// Get the player-specific stored data that applies here
final MovingData data = this.data.getMovingData(player);
final MovingData data = plugin.getDataManager().getMovingData(player);
// Get some data that's needed from this event, to avoid passing the
// event itself on to the checks (and risk to
@ -101,7 +96,7 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
if(!event.isCancelled()) {
Player player = event.getPlayer();
MovingData mdata = data.getMovingData(player);
MovingData mdata = plugin.getDataManager().getMovingData(player);
Vector v = event.getVelocity();
@ -111,7 +106,7 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
mdata.vertFreedom += mdata.vertVelocity;
}
mdata.vertVelocityCounter = 50;
mdata.vertVelocityCounter = 50;
newVal = Math.sqrt(Math.pow(v.getX(), 2) + Math.pow(v.getZ(), 2));
if(newVal > 0.0D) {
@ -137,8 +132,6 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
s.add("moving.nofall");
if(cc.moving.check && cc.moving.morePacketsCheck)
s.add("moving.morepackets");
if(cc.moving.check && cc.moving.noclipCheck)
s.add("moving.noclip");
return s;
}
@ -159,8 +152,6 @@ public class PlayerMoveEventManager extends PlayerListener implements EventManag
s.add("moving.nofall");
if(!(cc.moving.check && cc.moving.morePacketsCheck))
s.add("moving.morepackets");
if(!(cc.moving.check && cc.moving.noclipCheck))
s.add("moving.noclip");
return s;
}

View File

@ -17,7 +17,6 @@ import org.bukkit.plugin.PluginManager;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
import cc.co.evenprime.bukkit.nocheat.data.DataManager;
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
/**
@ -29,11 +28,11 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
*/
public class PlayerTeleportEventManager extends PlayerListener implements EventManager {
private final DataManager data;
private final NoCheat plugin;
public PlayerTeleportEventManager(NoCheat p) {
public PlayerTeleportEventManager(NoCheat plugin) {
this.data = plugin.getDataManager();
this.plugin = p;
PluginManager pm = Bukkit.getServer().getPluginManager();
@ -49,7 +48,7 @@ public class PlayerTeleportEventManager extends PlayerListener implements EventM
@Override
public void onPlayerTeleport(PlayerTeleportEvent event) {
final MovingData data2 = data.getMovingData(event.getPlayer());
final MovingData data2 = plugin.getDataManager().getMovingData(event.getPlayer());
if(event.isCancelled()) {
if(data2.teleportTo != null && data2.teleportTo.equals(event.getTo())) {
event.setCancelled(false);
@ -84,7 +83,7 @@ public class PlayerTeleportEventManager extends PlayerListener implements EventM
private void handleTeleportation(Player player, Location newLocation) {
/********* Moving check ************/
final MovingData data = this.data.getMovingData(player);
final MovingData data = plugin.getDataManager().getMovingData(player);
data.runflySetBackPoint = null;
data.morePacketsCounter = 0;
@ -92,14 +91,6 @@ public class PlayerTeleportEventManager extends PlayerListener implements EventM
data.jumpPhase = 0;
data.fallDistance = 0F;
data.lastAddedFallDistance = 0F;
if(newLocation != null) {
data.noclipX = newLocation.getBlockX();
data.noclipY = Location.locToBlock(newLocation.getY()+1.1D);
data.noclipZ = newLocation.getBlockZ();
}
}
@Override

View File

@ -1,47 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.file;
import cc.co.evenprime.bukkit.nocheat.Explainations;
import cc.co.evenprime.bukkit.nocheat.config.tree.ChildOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationTree;
import cc.co.evenprime.bukkit.nocheat.config.tree.Option;
import cc.co.evenprime.bukkit.nocheat.config.tree.ParentOption;
/**
* Create a description file based on a configuration tree (to know what should
* be in the description file) and data from "Explainations.java".
*
* @author Evenprime
*
*/
public class DescriptionGenerator {
public static String treeToDescription(ConfigurationTree tree) {
ParentOption o = (ParentOption) tree.getOption("");
String s = "";
for(Option option : o.getChildOptions()) {
s += optionToDescriptionString(option);
}
return s;
}
private static String optionToDescriptionString(Option option) {
String s = "";
if(option instanceof ParentOption) {
for(Option o : ((ParentOption) option).getChildOptions()) {
s += optionToDescriptionString(o) + "\r\n";
}
} else if(option instanceof ChildOption && option.isActive()) {
String padding = " ";
s += option.getFullIdentifier() + "\r\n" + padding + Explainations.get(option.getFullIdentifier()).replace("\n", "\r\n" + padding) + "\r\n";
}
return s;
}
}

View File

@ -1,73 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.file;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import cc.co.evenprime.bukkit.nocheat.DefaultConfiguration;
import cc.co.evenprime.bukkit.nocheat.actions.ActionManager;
/**
* Parses a action config file that was written in a flat style, one action per
* line
*
* @author Evenprime
*
*/
public class FlatActionParser {
public void read(ActionManager manager, File file) {
List<String[]> actionLines = readActionLinesFromFile(file, manager.getKnownTypes());
for(String[] actionLine : actionLines) {
manager.createActionFromStrings(actionLine[0], actionLine[1], actionLine[2], actionLine[3], actionLine.length > 4 ? actionLine[4] : null);
}
}
private List<String[]> readActionLinesFromFile(File file, String[] knownTypes) {
List<String[]> lines = new LinkedList<String[]>();
if(!file.exists()) {
DefaultConfiguration.writeActionFile(file);
return lines;
}
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(file));
String line = null;
while((line = reader.readLine()) != null) {
for(String s : knownTypes) {
if(line.startsWith(s)) {
// Split at whitespace characters
String parts[] = line.split("\\s+", 5);
if(parts.length < 4) {
System.out.println("NoCheat: Incomplete action definition found. Ignoring it: " + line);
} else {
lines.add(parts);
}
}
}
}
reader.close();
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
return lines;
}
}

View File

@ -1,51 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.file;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionListOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ChildOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationTree;
import cc.co.evenprime.bukkit.nocheat.config.tree.Option;
import cc.co.evenprime.bukkit.nocheat.config.tree.ParentOption;
/**
* Create a flat config file based on a ConfigurationTree
*
* @author Evenprime
*
*/
public class FlatConfigGenerator {
public static String treeToFlatFile(ConfigurationTree tree) {
ParentOption o = (ParentOption) tree.getOption("");
String s = "# Want to know what these options do? Read the descriptions.txt file.\r\n\r\n";
for(Option option : o.getChildOptions()) {
s += optionToFlatString(option) + "\r\n";
}
return s;
}
private static String optionToFlatString(Option option) {
String s = "";
if(option instanceof ParentOption) {
for(Option o : ((ParentOption) option).getChildOptions()) {
s += optionToFlatString(o);
}
} else if(option instanceof ActionListOption && option.isActive()) {
for(ActionOption o : ((ActionListOption) option).getChildOptions()) {
s += option.getFullIdentifier() + "." + o.getIdentifier() + " = \"" + o.getStringValue() + "\"\r\n";
}
} else if(option instanceof ChildOption && option.isActive()) {
s += option.getFullIdentifier() + " = \"" + ((ChildOption) option).getStringValue() + "\"\r\n";
}
return s;
}
}

View File

@ -1,127 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.file;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
/**
* An extremely simple flat config file parser
*
* @author Evenprime
*
*/
public class FlatConfigParser {
private final Map<String, Object> root;
public FlatConfigParser() {
root = new HashMap<String, Object>();
}
public void read(File file) throws IOException {
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
LinkedList<String> lines = new LinkedList<String>();
String line = null;
while((line = r.readLine()) != null) {
lines.add(line);
}
r.close();
parse(root, lines, "");
}
private void parse(Map<String, Object> root, LinkedList<String> lines, String prefix) throws IOException {
String line = null;
while(!lines.isEmpty()) {
line = lines.getFirst();
if(line.trim().startsWith("#")) {
lines.removeFirst();
} else if(line.trim().isEmpty()) {
lines.removeFirst();
} else {
lines.removeFirst();
if(line.contains("=")) {
String pair[] = line.split("=", 2);
putString(pair[0].trim(), root, removeQuotationMarks(pair[1].trim()));
}
}
}
}
private static String removeQuotationMarks(String s) {
if(s.startsWith("\"") && s.endsWith("\"")) {
return s.substring(1, s.length() - 1);
} else if(s.startsWith("\'") && s.endsWith("\'")) {
return s.substring(1, s.length() - 1);
}
return s;
}
/* Convenience methods for retrieving values start here */
public Object getProperty(String path) {
return getProperty(path, root);
}
@SuppressWarnings("unchecked")
private static Object getProperty(String path, Map<String, Object> node) {
if(node == null) {
return null;
}
if(!path.contains(".")) {
return node.get(path);
} else {
String[] parts = path.split("\\.", 2);
return getProperty(parts[1], (Map<String, Object>) node.get(parts[0]));
}
}
public String getString(String path, String defaultValue) {
return getString(path, defaultValue, root);
}
@SuppressWarnings("unchecked")
private static void putString(String path, Map<String, Object> node, String property) {
String[] pathParts = path.split("\\.");
for(int i = 0; i < pathParts.length; i++) {
if(i == pathParts.length - 1) { // last in the chain
node.put(pathParts[i], property);
} else if(node.containsKey(pathParts[i]) && node.get(pathParts[i]) instanceof Map) {
node = (Map<String, Object>) node.get(pathParts[i]);
} else {
HashMap<String, Object> newMap = new HashMap<String, Object>();
node.put(pathParts[i], newMap);
node = newMap;
}
}
}
private static String getString(String path, String defaultValue, Map<String, Object> node) {
try {
String result = (String) getProperty(path, node);
if(result == null)
return defaultValue;
return result;
} catch(Exception e) {
return defaultValue;
}
}
}

View File

@ -10,21 +10,17 @@ import java.util.logging.Level;
*/
public enum LogLevel {
OFF("off", "never", Level.OFF), LOW("low", "all messages", Level.INFO), MED("med", "important messages", Level.WARNING), HIGH("high", "very important messages", Level.SEVERE);
OFF("off", Level.OFF), LOW("low", Level.INFO), MED("med", Level.WARNING), HIGH("high", Level.SEVERE);
public final String name;
private final String description;
public final Level level;
private LogLevel(String name, String description, Level level) {
private LogLevel(String name, Level level) {
this.name = name;
this.description = description;
this.level = level;
}
public static LogLevel getLogLevelFromString(String s) {
if(s == null)
return OFF;
if("off".equals(s))
return OFF;
else if("low".equals(s))
@ -34,11 +30,11 @@ public enum LogLevel {
else if("high".equals(s))
return HIGH;
else
return OFF;
throw new IllegalArgumentException("Unknown log level "+s);
}
public String toString() {
return this.name() + ": " + description;
return this.name;
}
/**

View File

@ -6,7 +6,7 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import cc.co.evenprime.bukkit.nocheat.NoCheat;
import cc.co.evenprime.bukkit.nocheat.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.Permissions;
import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
/**
@ -19,10 +19,10 @@ import cc.co.evenprime.bukkit.nocheat.config.cache.ConfigurationCache;
*/
public class LogManager {
private final NoCheat plugin;
//private final NoCheat plugin;
public LogManager(NoCheat plugin) {
this.plugin = plugin;
//this.plugin = plugin;
}
/**

View File

@ -1,181 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import cc.co.evenprime.bukkit.nocheat.DefaultConfiguration;
import cc.co.evenprime.bukkit.nocheat.config.ConfigurationManager;
import cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationTree;
import cc.co.evenprime.bukkit.nocheat.wizard.gui.ConfigurationTreeGui;
/**
* The actual GUI for the configuration tool
*
* @author Evenprime
*
*/
public class Wizard extends JFrame {
public static void main(String[] args) {
Wizard w = new Wizard();
w.setVisible(true);
}
private static final long serialVersionUID = 8798111079958773207L;
public static final Color disabled = Color.GRAY;
public static final Color enabled = Color.BLACK;
private class Wizard_JPanel extends JPanel {
private static final long serialVersionUID = 5748088661296418403L;
private final JPanel inside;
private ConfigurationTree tree;
/**
* Create a complete configuration screen based on a specific
* configuration tree
*
* @param tree
*/
private Wizard_JPanel(ConfigurationTree tree) {
JScrollPane scrollPane = new JScrollPane();
inside = new JPanel();
this.tree = tree;
scrollPane.setViewportView(inside);
this.setLayout(new BorderLayout());
inside.setLayout(new BoxLayout(inside, BoxLayout.Y_AXIS));
// Recursively walk through "defaults" tree and move stuff to our
// new real config tree, if it is not defined
// in our real tree already
final ConfigurationTree modelRoot = tree;
final ConfigurationTreeGui guiRoot = new ConfigurationTreeGui(modelRoot);
inside.add(guiRoot);
this.add(scrollPane, BorderLayout.CENTER);
}
/**
* Recreate the whole tree (e.g. in case the underlying model tree
* changed
*/
private void refresh() {
this.inside.removeAll();
this.inside.add(new ConfigurationTreeGui(tree));
}
}
private final JTabbedPane tabs;
private final Map<String, File> worldFiles;
private final Map<String, ConfigurationTree> worldTrees;
public Wizard() {
tabs = new JTabbedPane();
worldFiles = ConfigurationManager.getWorldSpecificConfigFiles("NoCheat");
worldTrees = new HashMap<String, ConfigurationTree>();
final File globalConfig = ConfigurationManager.getGlobalConfigFile("NoCheat");
ConfigurationTree globalTree;
try {
globalTree = ConfigurationManager.createFullConfigurationTree(DefaultConfiguration.buildDefaultConfigurationTree(), globalConfig);
} catch(Exception e) {
System.out.println("NoCheat: Couldn't use existing global config file " + globalConfig + ", creating a new file.");
globalTree = DefaultConfiguration.buildDefaultConfigurationTree();
}
worldTrees.put(null, globalTree);
for(String worldName : worldFiles.keySet()) {
ConfigurationTree worldTree;
try {
worldTree = ConfigurationManager.createPartialConfigurationTree(globalTree, worldFiles.get(worldName));
worldTrees.put(worldName, worldTree);
} catch(Exception e) {
System.out.println("NoCheat: Couldn't read existing world-specific config file for world " + worldName);
worldFiles.remove(worldName);
}
}
worldFiles.put(null, globalConfig);
setup();
}
private void setup() {
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
JButton saveAllButton = new JButton("Save All");
tabs.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent arg0) {
((Wizard_JPanel) tabs.getSelectedComponent()).refresh();
}
});
Wizard_JPanel global = new Wizard_JPanel(worldTrees.get(null));
tabs.addTab("Global Settings", null, global, "The settings valid for all worlds, unless a specific setting overrides them.");
for(String name : worldTrees.keySet()) {
if(name != null) {
Wizard_JPanel world = new Wizard_JPanel(worldTrees.get(name));
tabs.addTab(name + " Settings", null, world, "Some world-specific settings.");
}
}
saveAllButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
for(String worldName : worldTrees.keySet()) {
ConfigurationManager.writeConfigFile(worldFiles.get(worldName), worldTrees.get(worldName));
}
ConfigurationManager.writeDescriptionFile(ConfigurationManager.getDescriptionFile("NoCheat"), worldTrees.get(null));
DefaultConfiguration.writeDefaultActionFile(ConfigurationManager.getDefaultActionFile("NoCheat"));
DefaultConfiguration.writeActionFile(ConfigurationManager.getActionFile("NoCheat"));
JOptionPane.showMessageDialog(null, "Saved All");
}
});
saveAllButton.setAlignmentY(0.0F);
this.add(saveAllButton, BorderLayout.SOUTH);
this.pack();
this.setSize(1000, 700);
this.setTitle("NoCheat configuration utility");
this.add(tabs, BorderLayout.CENTER);
}
}

View File

@ -1,180 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionListOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionOption;
import cc.co.evenprime.bukkit.nocheat.wizard.Wizard;
/**
*
* @author Evenprime
*
*/
public class ActionListOptionGui extends ChildOptionGui {
/**
*
*/
private static final long serialVersionUID = 527734534503546802L;
private final ActionListOption option;
private final ActionListOption defaults;
public ActionListOptionGui(ActionListOption option, ActionListOption defaults) {
super(option.isActive());
this.option = option;
this.defaults = defaults;
this.setLayout(new GridBagLayout());
recreateContent();
}
private void recreateContent() {
this.removeAll();
int line = 0;
if(this.isActive()) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.gridy = line;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 10;
c.weightx = 0;
this.add(createAddButton(), c);
for(ActionOption o : option.getChildOptions()) {
line++;
add(o, line);
}
} else {
for(ActionOption o : defaults.getChildOptions()) {
line++;
add(o, line);
}
}
this.revalidate();
}
private Component createAddButton() {
JButton b = new JButton("new Line");
b.setToolTipText("Adds a new line to this action list.");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
String result = JOptionPane.showInputDialog("Please enter a new threshold: ");
try {
int treshold = Integer.parseInt(result);
if(treshold >= 0) {
for(ActionOption ao : option.getChildOptions()) {
if(ao.getTreshold() == treshold) {
return;
}
}
}
option.add(treshold, "");
recreateContent();
} catch(Exception e) {}
}
});
return b;
}
private Component createDeleteButton(final ActionOption o) {
JButton b = new JButton("remove");
b.setToolTipText("Removes this line from the action list.");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
option.remove(o);
recreateContent();
}
});
return b;
}
private void add(final ActionOption child, int line) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.EAST;
c.ipadx = 10;
c.weightx = 0;
JLabel l = new JLabel(child.getIdentifier() + " : ");
if(!option.isActive()) {
l.setForeground(Wizard.disabled);
} else {
l.setForeground(Wizard.enabled);
}
this.add(l, c);
c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 0;
c.fill = GridBagConstraints.HORIZONTAL;
JComponent tmp = ChildOptionGuiFactory.create(child);
this.add(tmp, c);
if(!option.isActive()) {
tmp.setEnabled(false);
} else {
c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 1;
c.weightx = 0;
this.add(createDeleteButton(child), c);
}
c.gridx++;
c.gridy = line;
c.gridwidth = 1;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 5;
c.weightx = 1;
this.add(Box.createHorizontalGlue(), c);
}
public void setActive(boolean active) {
super.setActive(active);
option.setActive(active);
option.getChildOptions().clear();
for(ActionOption ao : defaults.getChildOptions()) {
option.getChildOptions().add(ao.clone());
}
}
}

View File

@ -1,66 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionOption;
/**
*
* @author Evenprime
*
*/
public class ActionOptionGui extends JPanel {
/**
*
*/
private static final long serialVersionUID = -3262934728041595488L;
private final JTextField textField;
private final ActionOption option;
public ActionOptionGui(ActionOption o) {
textField = new JTextField();
this.option = o;
this.setBorder(new EmptyBorder(0, 0, 0, 0));
this.setLayout(new FlowLayout(0, 0, 0));
textField.setEnabled(option.isActive());
textField.setText(option.getStringValue());
textField.setColumns(50);
textField.setInputVerifier(new InputVerifier() {
@Override
public boolean verify(JComponent arg0) {
if(option.setStringValue(textField.getText())) {
return true;
} else {
JOptionPane.showMessageDialog(textField, "Illegal value for this field");
textField.setText(option.getStringValue());
return false;
}
}
});
this.add(textField, BorderLayout.CENTER);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
textField.setEnabled(enabled);
}
}

View File

@ -1,80 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JCheckBox;
import javax.swing.SwingConstants;
import javax.swing.border.EmptyBorder;
import cc.co.evenprime.bukkit.nocheat.config.tree.BooleanOption;
/**
*
* @author Evenprime
*
*/
public class BooleanOptionGui extends ChildOptionGui {
/**
*
*/
private static final long serialVersionUID = 6082180273557581041L;
private final BooleanOption option;
private final BooleanOption defaults;
private final ParentOptionGui parentGui;
private final JCheckBox checkBox;
public BooleanOptionGui(BooleanOption o, BooleanOption defaults, ParentOptionGui parent) {
super(o.isActive());
checkBox = new JCheckBox();
this.parentGui = parent;
this.option = o;
this.defaults = defaults;
this.setBorder(new EmptyBorder(0, 0, 0, 0));
this.setLayout(new FlowLayout(0, 0, 0));
checkBox.setEnabled(option.isActive());
if(defaults != null && !option.isActive()) {
checkBox.setSelected(defaults.getBooleanValue());
} else {
checkBox.setSelected(option.getBooleanValue());
}
checkBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
option.setBooleanValue(checkBox.isSelected());
parentGui.recreateContent();
}
});
this.add(checkBox, BorderLayout.CENTER);
checkBox.setHorizontalTextPosition(SwingConstants.LEADING);
}
@Override
public void setActive(boolean active) {
super.setActive(active);
if(active) {
checkBox.setEnabled(true);
option.setActive(true);
} else {
checkBox.setEnabled(false);
option.setActive(false);
}
checkBox.setSelected(defaults.getBooleanValue());
option.setBooleanValue(defaults.getBooleanValue());
}
}

View File

@ -1,30 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import javax.swing.JPanel;
/**
*
* @author Evenprime
*
*/
public abstract class ChildOptionGui extends JPanel {
/**
*
*/
private static final long serialVersionUID = -8647116398870984111L;
private boolean active = true;
public ChildOptionGui(boolean isActive) {
this.active = isActive;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean isActive() {
return active;
}
}

View File

@ -1,35 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionListOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ActionOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.BooleanOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.LogLevelOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.Option;
import cc.co.evenprime.bukkit.nocheat.config.tree.StringOption;
/**
*
* @author Evenprime
*
*/
class ChildOptionGuiFactory {
protected static ChildOptionGui create(Option option, Option defaults, ParentOptionGui parent) {
if(option instanceof BooleanOption) {
return new BooleanOptionGui((BooleanOption) option, (BooleanOption) defaults, parent);
} else if(option instanceof StringOption) {
return new StringOptionGui((StringOption) option, (StringOption) defaults);
} else if(option instanceof LogLevelOption) {
return new LogLevelOptionGui((LogLevelOption) option, (LogLevelOption) defaults);
} else if(option instanceof ActionListOption) {
return new ActionListOptionGui((ActionListOption) option, (ActionListOption) defaults);
}
throw new RuntimeException("Unknown Option " + option);
}
public static ActionOptionGui create(ActionOption child) {
return new ActionOptionGui(child);
}
}

View File

@ -1,33 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import javax.swing.JPanel;
import cc.co.evenprime.bukkit.nocheat.config.tree.ConfigurationTree;
import cc.co.evenprime.bukkit.nocheat.config.tree.ParentOption;
/**
*
* @author Evenprime
*
*/
public class ConfigurationTreeGui extends JPanel {
/**
*
*/
private static final long serialVersionUID = -3311598864103292261L;
public ConfigurationTreeGui(ConfigurationTree modelRoot) {
// If the tree has a parent, use that as the main model and the actual
// model only
// to supply additional data
ConfigurationTree parent = modelRoot.getParent();
if(parent != null) {
this.add(new ParentOptionGui((ParentOption) modelRoot.getOption(""), (ParentOption) parent.getOption("")));
} else {
this.add(new ParentOptionGui((ParentOption) modelRoot.getOption(""), null));
}
}
}

View File

@ -1,78 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComboBox;
import javax.swing.border.EmptyBorder;
import cc.co.evenprime.bukkit.nocheat.config.tree.LogLevelOption;
import cc.co.evenprime.bukkit.nocheat.log.LogLevel;
/**
*
* @author Evenprime
*
*/
public class LogLevelOptionGui extends ChildOptionGui {
private final LogLevelOption option;
private final LogLevelOption defaults;
private final JComboBox comboBox;
/**
*
*/
private static final long serialVersionUID = -8285257162704341771L;
public LogLevelOptionGui(final LogLevelOption o, final LogLevelOption defaults) {
super(o.isActive());
this.option = o;
this.defaults = defaults;
comboBox = new JComboBox();
for(LogLevel op : LogLevel.values())
comboBox.addItem(op);
comboBox.setEnabled(option.isActive());
if(defaults != null && !option.isActive()) {
comboBox.setSelectedItem(defaults.getLogLevelValue());
} else {
comboBox.setSelectedItem(option.getLogLevelValue());
}
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
option.setLogLevelValue((LogLevel) comboBox.getSelectedItem());
}
});
this.setLayout(new FlowLayout(0, 0, 0));
this.setBorder(new EmptyBorder(0, 0, 0, 0));
this.add(comboBox);
}
@Override
public void setActive(boolean active) {
super.setActive(active);
if(active) {
comboBox.setEnabled(true);
option.setActive(true);
} else {
comboBox.setEnabled(false);
option.setActive(false);
}
comboBox.setSelectedItem(defaults.getLogLevelValue());
option.setLogLevelValue(defaults.getLogLevelValue());
}
}

View File

@ -1,193 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import cc.co.evenprime.bukkit.nocheat.Explainations;
import cc.co.evenprime.bukkit.nocheat.config.tree.BooleanOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.ChildOption;
import cc.co.evenprime.bukkit.nocheat.config.tree.Option;
import cc.co.evenprime.bukkit.nocheat.config.tree.ParentOption;
/**
*
* @author Evenprime
*
*/
public class ParentOptionGui extends JPanel {
/**
*
*/
private static final long serialVersionUID = 5277750257203546802L;
private final ParentOption option;
private final ParentOption defaults;
public ParentOptionGui(ParentOption option, ParentOption defaults) {
this.option = option;
this.defaults = defaults;
recreateContent();
}
void recreateContent() {
this.removeAll();
if(option.getIdentifier().length() > 0) {
this.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.BLACK), " " + option.getIdentifier() + ": "), BorderFactory.createEmptyBorder(5, 5, 5, 5))));
}
this.setLayout(new GridBagLayout());
int line = 0;
boolean hideNonMasterOptions = false;
for(Option o : option.getChildOptions()) {
if(o instanceof BooleanOption) {
BooleanOption b = (BooleanOption) o;
if(b.isMaster() && b.isActive() && !b.getBooleanValue()) {
hideNonMasterOptions = true;
} else if(b.isMaster() && !b.isActive()) {
BooleanOption b2 = (BooleanOption) defaults.getChild(b.getIdentifier());
if(b2 != null && !b2.getBooleanValue()) {
hideNonMasterOptions = true;
}
}
}
}
for(Option o : option.getChildOptions()) {
if(!hideNonMasterOptions || (o instanceof BooleanOption && ((BooleanOption) o).isMaster())) {
if(defaults != null) {
add(o, defaults.getChild(o.getIdentifier()), line);
line++;
} else {
add(o, null, line);
line++;
}
}
}
this.revalidate();
}
private void add(final Option child, final Option childDefault, int line) {
if(child instanceof ParentOption) {
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = line;
c.gridwidth = 5;
c.anchor = GridBagConstraints.WEST;
c.ipadx = 2;
c.ipady = 15;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(new ParentOptionGui((ParentOption) child, (ParentOption) childDefault), c);
} else if(child instanceof ChildOption) {
JLabel id = new JLabel(child.getIdentifier() + " : ");
ChildOptionGui tmp = ChildOptionGuiFactory.create(child, childDefault, this);
JButton defaults = createAddRemoveButton(this, tmp);
JButton help = createHelpButton(child.getFullIdentifier());
if(!tmp.isActive()) {
id.setEnabled(false);
}
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = line;
c.anchor = GridBagConstraints.NORTHWEST;
c.ipadx = 2;
c.insets = new Insets(0, 1, 0, 1);
if(childDefault != null) {
this.add(defaults, c);
c.gridx++;
}
this.add(id, c);
c.gridx++;
this.add(tmp, c);
c.gridx++;
c.ipadx = 2;
this.add(help, c);
c.gridx++;
c.gridwidth = 5 - c.gridx + 1;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(Box.createHorizontalGlue(), c);
} else {
throw new RuntimeException("Unknown Option " + child);
}
}
private JButton createAddRemoveButton(final ParentOptionGui container, final ChildOptionGui option) {
final JButton addRemove = new JButton("+");
addRemove.setToolTipText("Allow setting custom options for this world.");
if(option.isActive()) {
addRemove.setText("-");
addRemove.setToolTipText("Use global settings instead of these custom options.");
}
addRemove.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(addRemove.getText().equals("+")) {
option.setActive(true);
addRemove.setText("-");
addRemove.setToolTipText("Use global settings instead.");
} else {
option.setActive(false);
addRemove.setText("+");
addRemove.setToolTipText("Allow setting custom options for this world.");
}
container.recreateContent();
}
});
addRemove.setMargin(new Insets(0, 0, 0, 0));
return addRemove;
}
private JButton createHelpButton(final String identifier) {
JButton help = new JButton("?");
help.setToolTipText("Show help. Usually some instructions or further information about this option.");
help.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(null, Explainations.get(identifier), "Description of " + identifier, JOptionPane.INFORMATION_MESSAGE);
}
});
help.setMargin(new Insets(0, 0, 0, 0));
return help;
}
}

View File

@ -1,94 +0,0 @@
package cc.co.evenprime.bukkit.nocheat.wizard.gui;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import cc.co.evenprime.bukkit.nocheat.config.tree.StringOption;
/**
*
* @author Evenprime
*
*/
public class StringOptionGui extends ChildOptionGui {
/**
*
*/
private static final long serialVersionUID = 6082180273557581041L;
private final StringOption option;
private final StringOption defaults;
private final JTextField textField;
public StringOptionGui(StringOption o, StringOption defaults) {
super(o.isActive());
textField = new JTextField();
this.option = o;
this.defaults = defaults;
this.setLayout(new FlowLayout(0, 0, 0));
this.setBorder(new EmptyBorder(0, 0, 0, 0));
textField.setEnabled(option.isActive());
if(defaults != null && !option.isActive()) {
textField.setText(defaults.getStringValue());
} else {
textField.setText(option.getStringValue());
}
if(option.hasPreferredLength()) {
textField.setColumns(option.getPreferredLength());
}
textField.setInputVerifier(new InputVerifier() {
@Override
public boolean verify(JComponent arg0) {
if(option.setStringValue(textField.getText())) {
return true;
} else {
JOptionPane.showMessageDialog(textField, "Illegal value for this field");
textField.setText(option.getStringValue());
return false;
}
}
});
textField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
option.setStringValue(textField.getText());
}
});
this.add(textField);
}
@Override
public void setActive(boolean active) {
super.setActive(active);
if(active) {
textField.setEnabled(true);
option.setActive(true);
textField.setText(defaults.getStringValue());
} else {
textField.setEnabled(false);
option.setActive(false);
textField.setText(defaults.getStringValue());
}
textField.setText(defaults.getStringValue());
option.setStringValue(defaults.getStringValue());
}
}