From 3d88aed04121d4ff0a072fd261b2240ce95f7830 Mon Sep 17 00:00:00 2001 From: NeatMonster Date: Fri, 3 Aug 2012 16:48:06 +0200 Subject: [PATCH] [Development] BlockBreak, BlockPlace, Chat & Moving checks rewritten but untested. This version is far from being complete. --- .gitignore | 3 +- pom.xml | 94 ++- .../nocheatplus/CommandHandler.java | 176 ++--- .../neatmonster/nocheatplus/NoCheatPlus.java | 194 ++--- .../nocheatplus/actions/Action.java | 40 +- .../nocheatplus/actions/ActionFactory.java | 74 +- .../nocheatplus/actions/ParameterName.java | 73 +- .../nocheatplus/actions/types/ActionList.java | 74 +- .../actions/types/ActionWithParameters.java | 68 +- .../actions/types/CancelAction.java | 34 + .../actions/types/CommandAction.java | 69 ++ .../actions/types/ConsolecommandAction.java | 41 - .../actions/types/DummyAction.java | 35 +- .../nocheatplus/actions/types/LogAction.java | 60 +- .../actions/types/SpecialAction.java | 20 - .../neatmonster/nocheatplus/checks/Check.java | 251 +++--- .../nocheatplus/checks/CheckConfig.java | 3 - .../nocheatplus/checks/CheckData.java | 3 - .../nocheatplus/checks/CheckEvent.java | 107 +-- .../nocheatplus/checks/CheckListener.java | 21 - .../nocheatplus/checks/CheckUtils.java | 354 --------- .../nocheatplus/checks/Workarounds.java | 76 ++ .../checks/WorkaroundsListener.java | 38 - .../checks/blockbreak/BlockBreakCheck.java | 24 - .../checks/blockbreak/BlockBreakConfig.java | 101 ++- .../checks/blockbreak/BlockBreakData.java | 78 +- .../checks/blockbreak/BlockBreakEvent.java | 18 - .../checks/blockbreak/BlockBreakListener.java | 183 +++-- .../checks/blockbreak/Direction.java | 104 +++ .../checks/blockbreak/DirectionCheck.java | 106 --- .../checks/blockbreak/FastBreak.java | 131 ++++ .../checks/blockbreak/FastBreakCheck.java | 95 --- .../checks/blockbreak/NoSwing.java | 96 +++ .../checks/blockbreak/NoswingCheck.java | 72 -- .../nocheatplus/checks/blockbreak/Reach.java | 105 +++ .../checks/blockbreak/ReachCheck.java | 86 --- .../checks/blockplace/BlockPlaceCheck.java | 51 -- .../checks/blockplace/BlockPlaceConfig.java | 111 ++- .../checks/blockplace/BlockPlaceData.java | 83 +- .../checks/blockplace/BlockPlaceEvent.java | 18 - .../checks/blockplace/BlockPlaceListener.java | 194 +++-- .../checks/blockplace/Direction.java | 104 +++ .../checks/blockplace/DirectionCheck.java | 124 --- .../checks/blockplace/FastPlace.java | 106 +++ .../checks/blockplace/FastPlaceCheck.java | 79 -- .../checks/blockplace/ProjectileCheck.java | 78 -- .../nocheatplus/checks/blockplace/Reach.java | 105 +++ .../checks/blockplace/ReachCheck.java | 86 --- .../nocheatplus/checks/blockplace/Speed.java | 101 +++ .../nocheatplus/checks/chat/Arrivals.java | 103 +++ .../checks/chat/ArrivalsLimitCheck.java | 91 --- .../nocheatplus/checks/chat/ChatCheck.java | 36 - .../nocheatplus/checks/chat/ChatConfig.java | 284 +++---- .../nocheatplus/checks/chat/ChatData.java | 115 ++- .../nocheatplus/checks/chat/ChatEvent.java | 17 - .../nocheatplus/checks/chat/ChatListener.java | 166 +--- .../nocheatplus/checks/chat/Color.java | 90 +++ .../nocheatplus/checks/chat/ColorCheck.java | 60 -- .../nocheatplus/checks/chat/NoPwnage.java | 276 +++++++ .../checks/chat/NoPwnageCheck.java | 359 --------- .../nocheatplus/checks/fight/AngleCheck.java | 206 ----- .../checks/fight/CriticalCheck.java | 112 --- .../checks/fight/DirectionCheck.java | 125 --- .../nocheatplus/checks/fight/FightCheck.java | 31 - .../nocheatplus/checks/fight/FightConfig.java | 91 --- .../nocheatplus/checks/fight/FightData.java | 66 -- .../nocheatplus/checks/fight/FightEvent.java | 17 - .../checks/fight/FightListener.java | 258 ------- .../checks/fight/GodmodeCheck.java | 144 ---- .../checks/fight/InstanthealCheck.java | 97 --- .../checks/fight/KnockbackCheck.java | 81 -- .../checks/fight/NoswingCheck.java | 77 -- .../nocheatplus/checks/fight/ReachCheck.java | 116 --- .../nocheatplus/checks/fight/SpeedCheck.java | 89 --- .../checks/inventory/DropCheck.java | 80 -- .../checks/inventory/InstantBowCheck.java | 82 -- .../checks/inventory/InstantEatCheck.java | 84 --- .../checks/inventory/InventoryCheck.java | 25 - .../checks/inventory/InventoryConfig.java | 41 - .../checks/inventory/InventoryData.java | 28 - .../checks/inventory/InventoryEvent.java | 17 - .../checks/inventory/InventoryListener.java | 159 ---- .../checks/moving/BedFlyingCheck.java | 67 -- .../checks/moving/CreativeFly.java | 188 +++++ .../checks/moving/FlyingCheck.java | 165 ---- .../checks/moving/MorePackets.java | 156 ++++ .../checks/moving/MorePacketsCheck.java | 124 --- .../checks/moving/MorePacketsVehicle.java | 156 ++++ .../moving/MorePacketsVehicleCheck.java | 113 --- .../checks/moving/MovingCheck.java | 44 -- .../checks/moving/MovingConfig.java | 167 ++-- .../nocheatplus/checks/moving/MovingData.java | 181 ++--- .../checks/moving/MovingEvent.java | 17 - .../checks/moving/MovingListener.java | 714 +++++++++--------- .../nocheatplus/checks/moving/NoFall.java | 167 ++++ .../checks/moving/NoFallCheck.java | 159 ---- .../checks/moving/RunningCheck.java | 334 -------- .../checks/moving/SurvivalFly.java | 359 +++++++++ .../checks/moving/WaterWalkCheck.java | 164 ---- .../nocheatplus/config/ConfPaths.java | 421 +++++------ .../nocheatplus/config/ConfigFile.java | 47 +- .../nocheatplus/config/ConfigManager.java | 122 ++- .../nocheatplus/config/DefaultConfig.java | 407 +++++----- .../{informations => }/ExecutionHistory.java | 89 ++- .../nocheatplus/players/NCPPlayer.java | 182 ----- .../nocheatplus/players/Permissions.java | 121 +++ .../players/informations/Permissions.java | 97 --- .../players/informations/Statistics.java | 92 --- .../nocheatplus/utilities/CheckUtils.java | 207 +++++ .../nocheatplus/utilities/LagMeasureTask.java | 118 +-- .../nocheatplus/utilities/PlayerLocation.java | 348 +++++++++ .../utilities/locations/PreciseLocation.java | 50 -- .../utilities/locations/SimpleLocation.java | 68 -- 113 files changed, 5723 insertions(+), 7891 deletions(-) create mode 100644 src/fr/neatmonster/nocheatplus/actions/types/CancelAction.java create mode 100644 src/fr/neatmonster/nocheatplus/actions/types/CommandAction.java delete mode 100644 src/fr/neatmonster/nocheatplus/actions/types/ConsolecommandAction.java delete mode 100644 src/fr/neatmonster/nocheatplus/actions/types/SpecialAction.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/CheckConfig.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/CheckData.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/CheckListener.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/CheckUtils.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/Workarounds.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/WorkaroundsListener.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakEvent.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/Direction.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/DirectionCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreak.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreakCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/NoSwing.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/NoswingCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/Reach.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockbreak/ReachCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceEvent.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/Direction.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/DirectionCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlace.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlaceCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/ProjectileCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/Reach.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/ReachCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/blockplace/Speed.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/Arrivals.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/ArrivalsLimitCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/ChatCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/ChatEvent.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/Color.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/ColorCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/chat/NoPwnageCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/AngleCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/CriticalCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/DirectionCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/FightCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/FightData.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/FightEvent.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/GodmodeCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/InstanthealCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/KnockbackCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/NoswingCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/ReachCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/fight/SpeedCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/DropCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InstantBowCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InstantEatCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InventoryCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InventoryConfig.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InventoryData.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InventoryEvent.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/inventory/InventoryListener.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/BedFlyingCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/FlyingCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/MorePackets.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicle.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicleCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/MovingCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/MovingEvent.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/NoFallCheck.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/RunningCheck.java create mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java delete mode 100644 src/fr/neatmonster/nocheatplus/checks/moving/WaterWalkCheck.java rename src/fr/neatmonster/nocheatplus/players/{informations => }/ExecutionHistory.java (51%) delete mode 100644 src/fr/neatmonster/nocheatplus/players/NCPPlayer.java create mode 100644 src/fr/neatmonster/nocheatplus/players/Permissions.java delete mode 100644 src/fr/neatmonster/nocheatplus/players/informations/Permissions.java delete mode 100644 src/fr/neatmonster/nocheatplus/players/informations/Statistics.java create mode 100644 src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java create mode 100644 src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java delete mode 100644 src/fr/neatmonster/nocheatplus/utilities/locations/PreciseLocation.java delete mode 100644 src/fr/neatmonster/nocheatplus/utilities/locations/SimpleLocation.java diff --git a/.gitignore b/.gitignore index fd88ec96..56550141 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ *.iml *.ipr *.iws -.idea/ \ No newline at end of file +.idea/ +/auth.properties diff --git a/pom.xml b/pom.xml index a62dfeeb..e29d91b2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ NoCheatPlus - 3.6.1 + 3.7 Detect and fight the exploitation of various flaws/bugs in Minecraft. http://dev.bukkit.org/server-mods/nocheatplus @@ -42,7 +42,7 @@ org.bukkit craftbukkit - 1.2.5-R1.2 + 1.3.1-R0.1-SNAPSHOT jar compile @@ -50,7 +50,7 @@ - clean install + clean package ${basedir}/src @@ -64,35 +64,65 @@ - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - NoCheatPlus - - false - false - - false - false - - - - - - + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + NoCheatPlus + + false + false + + false + false + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.7 + + + deploy-build + install + + + + + + + + + run + + + + + + org.apache.ant + ant-jsch + 1.8.4 + + + + diff --git a/src/fr/neatmonster/nocheatplus/CommandHandler.java b/src/fr/neatmonster/nocheatplus/CommandHandler.java index f78100e3..e433ae6a 100644 --- a/src/fr/neatmonster/nocheatplus/CommandHandler.java +++ b/src/fr/neatmonster/nocheatplus/CommandHandler.java @@ -1,147 +1,103 @@ package fr.neatmonster.nocheatplus; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.bukkit.permissions.Permission; +import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakConfig; +import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceConfig; +import fr.neatmonster.nocheatplus.checks.moving.MovingConfig; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigManager; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; +import fr.neatmonster.nocheatplus.players.Permissions; +/* + * MM'""""'YMM dP + * M' .mmm. `M 88 + * M MMMMMooM .d8888b. 88d8b.d8b. 88d8b.d8b. .d8888b. 88d888b. .d888b88 + * M MMMMMMMM 88' `88 88'`88'`88 88'`88'`88 88' `88 88' `88 88' `88 + * M. `MMM' .M 88. .88 88 88 88 88 88 88 88. .88 88 88 88. .88 + * MM. .dM `88888P' dP dP dP dP dP dP `88888P8 dP dP `88888P8 + * MMMMMMMMMMM + * + * M""MMMMM""MM dP dP + * M MMMMM MM 88 88 + * M `M .d8888b. 88d888b. .d888b88 88 .d8888b. 88d888b. + * M MMMMM MM 88' `88 88' `88 88' `88 88 88ooood8 88' `88 + * M MMMMM MM 88. .88 88 88 88. .88 88 88. ... 88 + * M MMMMM MM `88888P8 dP dP `88888P8 dP `88888P' dP + * MMMMMMMMMMMM + */ /** - * Handle all NoCheatPlus related commands in a common place + * This the class handling all the commands. */ public class CommandHandler implements CommandExecutor { + private final NoCheatPlus plugin; - private final List perms; - - public CommandHandler() { - // Make a copy to allow sorting - perms = new LinkedList(NoCheatPlus.instance.getDescription().getPermissions()); - - // Sort NoCheats permission by name and parent-child relation with - // a custom sorting method - Collections.sort(perms, new Comparator() { - - @Override - public int compare(final Permission o1, final Permission o2) { - - final String name1 = o1.getName(); - final String name2 = o2.getName(); - - if (name1.equals(name2)) - return 0; - - if (name1.startsWith(name2)) - return 1; - - if (name2.startsWith(name1)) - return -1; - - return name1.compareTo(name2); - } - }); - } - - private boolean handlePermlistCommand(final CommandSender sender, final String[] args) { - - // Get the player by name - final Player player = Bukkit.getServer().getPlayerExact(args[1]); - if (player == null) { - sender.sendMessage("Unknown player: " + args[1]); - return true; - } - - // Should permissions be filtered by prefix? - String prefix = ""; - if (args.length == 3) - prefix = args[2]; - - sender.sendMessage("Player " + player.getName() + " has the permission(s):"); - - for (final Permission permission : perms) - if (permission.getName().startsWith(prefix)) - sender.sendMessage(permission.getName() + ": " + NCPPlayer.hasPermission(player, permission.getName())); - return true; - } - - private boolean handlePlayerInfoCommand(final CommandSender sender, final String[] args) { - - final Player player = Bukkit.getPlayer(args[1]); - final Map map = player == null ? new HashMap() : NCPPlayer.getPlayer(player) - .collectData(); - String filter = ""; - - if (args.length > 2) - filter = args[2]; - - sender.sendMessage("PlayerInfo for " + args[1]); - for (final Entry entry : map.entrySet()) - if (entry.getKey().contains(filter)) - sender.sendMessage(entry.getKey() + ": " + entry.getValue()); - return true; - } - - private boolean handleReloadCommand(final CommandSender sender) { - - // Players need a special permission for this - if (!(sender instanceof Player) || NCPPlayer.hasPermission(sender, Permissions.ADMIN_RELOAD)) { - sender.sendMessage("[NoCheatPlus] Reloading configuration"); - ConfigManager.cleanup(); - ConfigManager.init(); - NCPPlayer.reloadConfig(); - sender.sendMessage("[NoCheatPlus] Configuration reloaded"); - } else - sender.sendMessage("You lack the " + Permissions.ADMIN_RELOAD + " permission to use 'reload'"); - - return true; + /** + * Instantiates a new command handler. + * + * @param plugin + * the instance of NoCheatPlus + */ + public CommandHandler(final NoCheatPlus plugin) { + this.plugin = plugin; } /** - * Handle a command that is directed at NoCheatPlus + * Handle the '/nocheatplus reload' command. + * + * @param sender + * the sender + * @return true, if successful + */ + private boolean handleReloadCommand(final CommandSender sender) { + // Players need a special permission for this. + if (!(sender instanceof Player) || sender.hasPermission(Permissions.ADMINISTRATION_RELOAD)) { + sender.sendMessage(ChatColor.RED + "NCP: " + ChatColor.WHITE + "Reloading configuration..."); + + // Do the actual reload. + ConfigManager.cleanup(); + ConfigManager.init(plugin); + BlockBreakConfig.clear(); + BlockPlaceConfig.clear(); + MovingConfig.clear(); + + sender.sendMessage(ChatColor.RED + "NCP: " + ChatColor.WHITE + "Configuration reloaded!"); + } else + sender.sendMessage(ChatColor.RED + "You lack the " + Permissions.ADMINISTRATION_RELOAD + + " permission to use 'reload'!"); + return true; + } + + /* (non-Javadoc) + * @see org.bukkit.command.CommandExecutor#onCommand(org.bukkit.command.CommandSender, org.bukkit.command.Command, + * java.lang.String, java.lang.String[]) */ @Override public boolean onCommand(final CommandSender sender, final Command command, final String commandLabel, final String[] args) { - if (sender instanceof Player) { - final String worldName = ((Player) sender).getWorld().getName(); - final boolean protectPlugins = ConfigManager.getConfigFile(worldName).getBoolean( - ConfPaths.MISCELLANEOUS_PROTECTPLUGINS); + final boolean protectPlugins = ConfigManager.getConfigFile(((Player) sender).getWorld().getName()) + .getBoolean(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS); - // Hide NoCheatPlus's commands if the player doesn't have the required permission - if (protectPlugins && !NCPPlayer.hasPermission(sender, Permissions.ADMIN_COMMANDS)) { + // Hide NoCheatPlus's commands if the player doesn't have the required permission. + if (protectPlugins && !sender.hasPermission(Permissions.ADMINISTRATION_RELOAD)) { sender.sendMessage("Unknown command. Type \"help\" for help."); return true; } } boolean result = false; + // Not our command, how did it get here? if (!command.getName().equalsIgnoreCase("nocheatplus") || args.length == 0) result = false; - else if (args[0].equalsIgnoreCase("permlist") && args.length >= 2) - // permlist command was used - result = handlePermlistCommand(sender, args); else if (args[0].equalsIgnoreCase("reload")) - // reload command was used + // Reload command was used. result = handleReloadCommand(sender); - else if (args[0].equalsIgnoreCase("playerinfo") && args.length >= 2) - // playerinfo command was used - result = handlePlayerInfoCommand(sender, args); - return result; } } diff --git a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java index 736a225a..f177fbc5 100644 --- a/src/fr/neatmonster/nocheatplus/NoCheatPlus.java +++ b/src/fr/neatmonster/nocheatplus/NoCheatPlus.java @@ -12,146 +12,172 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.java.JavaPlugin; -import fr.neatmonster.nocheatplus.checks.WorkaroundsListener; +import fr.neatmonster.nocheatplus.checks.Workarounds; import fr.neatmonster.nocheatplus.checks.blockbreak.BlockBreakListener; import fr.neatmonster.nocheatplus.checks.blockplace.BlockPlaceListener; import fr.neatmonster.nocheatplus.checks.chat.ChatListener; -import fr.neatmonster.nocheatplus.checks.fight.FightListener; -import fr.neatmonster.nocheatplus.checks.inventory.InventoryListener; import fr.neatmonster.nocheatplus.checks.moving.MovingListener; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigManager; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; +import fr.neatmonster.nocheatplus.players.Permissions; import fr.neatmonster.nocheatplus.utilities.LagMeasureTask; +/* + * M"""""""`YM MM'""""'YMM dP dP MM"""""""`YM dP + * M mmmm. M M' .mmm. `M 88 88 MM mmmmm M 88 + * M MMMMM M .d8888b. M MMMMMooM 88d888b. .d8888b. .d8888b. d8888P M' .M 88 dP dP .d8888b. + * M MMMMM M 88' `88 M MMMMMMMM 88' `88 88ooood8 88' `88 88 MM MMMMMMMM 88 88 88 Y8ooooo. + * M MMMMM M 88. .88 M. `MMM' .M 88 88 88. ... 88. .88 88 MM MMMMMMMM 88 88. .88 88 + * M MMMMM M `88888P' MM. .dM dP dP `88888P' `88888P8 dP MM MMMMMMMM dP `88888P' `88888P' + * MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM + */ +/** + * This is the main class of NoCheatPlus. The commands, events listeners and tasks are registered here. + */ public class NoCheatPlus extends JavaPlugin implements Listener { - public static NoCheatPlus instance = null; - - public static boolean skipCheck() { - return instance.lagMeasureTask == null ? false : instance.lagMeasureTask.skipCheck(); - } - - private CommandHandler commandHandler; - private LagMeasureTask lagMeasureTask; private List listeners; + /* (non-Javadoc) + * @see org.bukkit.plugin.java.JavaPlugin#onDisable() + */ @Override public void onDisable() { - final PluginDescriptionFile pdfFile = getDescription(); - if (lagMeasureTask != null) { - lagMeasureTask.cancel(); - lagMeasureTask = null; - } + // Stop the lag measuring task. + LagMeasureTask.cancel(); + // Cleanup the configuration manager. ConfigManager.cleanup(); - // Just to be sure nothing gets left out + // Just to be sure nothing gets left out. getServer().getScheduler().cancelTasks(this); - commandHandler = null; - - System.out.println("[NoCheatPlus] version [" + pdfFile.getVersion() + "] is disabled."); + // Tell the server administrator the we finished unloading NoCheatPlus. + System.out.println("[NoCheatPlus] Version " + pdfFile.getVersion() + " is disabled."); } + /* (non-Javadoc) + * @see org.bukkit.plugin.java.JavaPlugin#onEnable() + */ @Override public void onEnable() { - instance = this; - - commandHandler = new CommandHandler(); - // Then read the configuration files - ConfigManager.init(); + // Read the configuration files. + ConfigManager.init(this); + // List the events listeners. listeners = new ArrayList(); - // Then set up the event listeners - listeners.add(new WorkaroundsListener()); listeners.add(new BlockBreakListener()); listeners.add(new BlockPlaceListener()); listeners.add(new ChatListener()); - listeners.add(new FightListener()); - listeners.add(new InventoryListener()); listeners.add(new MovingListener()); + listeners.add(new Workarounds()); - // Then set up a task to monitor server lag - if (lagMeasureTask == null) { - lagMeasureTask = new LagMeasureTask(); - lagMeasureTask.start(); - } + // Set up a task to monitor server lag. + LagMeasureTask.start(this); - // register all listeners + // Register all listeners. for (final Listener listener : listeners) Bukkit.getPluginManager().registerEvents(listener, this); - Bukkit.getPluginManager().registerEvents(this, this); - getCommand("nocheatplus").setExecutor(commandHandler); + // Register the commands handler. + getCommand("nocheatplus").setExecutor(new CommandHandler(this)); - ConfigManager.writeInstructions(); + // Write the 'Instructions.txt' file. + ConfigManager.writeInstructions(this); - // Tell the server admin that we finished loading NoCheatPlus now - System.out.println("[NoCheatPlus] version [" + getDescription().getVersion() + "] is enabled."); + // Tell the server administrator that we finished loading NoCheatPlus now. + System.out.println("[NoCheatPlus] Version " + getDescription().getVersion() + " is enabled."); } + /** + * This event handler is used to send all the disabling messages to the client. + * + * @param event + * the event handled + */ @EventHandler( ignoreCancelled = true, priority = EventPriority.MONITOR) public void onPlayerJoin(final PlayerJoinEvent event) { final Player player = event.getPlayer(); - if (ConfigManager.getConfigFile().getBoolean(ConfPaths.MISCELLANEOUS_ALLOWCLIENTMODS)) - return; + + // Check if we allow all the client mods. + final boolean allowAll = ConfigManager.getConfigFile().getBoolean(ConfPaths.MISCELLANEOUS_ALLOWCLIENTMODS); String message = ""; - // Disable Zombe's fly mod - if (!NCPPlayer.hasPermission(player, Permissions.ZOMBE_FLY)) - message = message + "§f §f §1 §0 §2 §4"; - // Disable Zombe's noclip - if (!NCPPlayer.hasPermission(player, Permissions.ZOMBE_NOCLIP)) - message = message + "§f §f §4 §0 §9 §6"; - // Disable Zombe's cheat - if (!NCPPlayer.hasPermission(player, Permissions.ZOMBE_CHEAT)) - message = message + "§f §f §2 §0 §4 §8"; - // Disable CJB's fly mod - if (!NCPPlayer.hasPermission(player, Permissions.CJB_FLY)) - message = message + "§3 §9 §2 §0 §0 §1"; - // Disable CJB's xray - if (!NCPPlayer.hasPermission(player, Permissions.CJB_XRAY)) - message = message + "§3 §9 §2 §0 §0 §2"; - // Disable CJB's radar - if (!NCPPlayer.hasPermission(player, Permissions.CJB_RADAR)) - message = message + "§3 §9 §2 §0 §0 §3"; - // Disable Rei's Minimap's cave mode - if (NCPPlayer.hasPermission(player, Permissions.REI_CAVE)) + + // Allow Rei's Minimap's cave mode. + if (allowAll || player.hasPermission(Permissions.REI_CAVE)) message = message + "§0§0§1§e§f"; - // Disable Rei's Minimap's radar - if (NCPPlayer.hasPermission(player, Permissions.REI_RADAR)) + + // Allow Rei's Minimap's radar. + if (allowAll || player.hasPermission(Permissions.REI_RADAR)) message = message + "§0§0§2§3§4§5§6§7§e§f"; - // Disable Minecraft AutoMap's ores - if (!NCPPlayer.hasPermission(player, Permissions.MINECRAFTAUTOMAP_ORES)) + + // If all the client mods are allowed, no need to go any further. + if (allowAll) + return; + + // Disable Zombe's fly mod. + if (!player.hasPermission(Permissions.ZOMBE_FLY)) + message = message + "§f §f §1 §0 §2 §4"; + + // Disable Zombe's noclip. + if (!player.hasPermission(Permissions.ZOMBE_NOCLIP)) + message = message + "§f §f §4 §0 §9 §6"; + + // Disable Zombe's cheat. + if (!player.hasPermission(Permissions.ZOMBE_CHEAT)) + message = message + "§f §f §2 §0 §4 §8"; + + // Disable CJB's fly mod. + if (!player.hasPermission(Permissions.CJB_FLY)) + message = message + "§3 §9 §2 §0 §0 §1"; + + // Disable CJB's xray. + if (!player.hasPermission(Permissions.CJB_XRAY)) + message = message + "§3 §9 §2 §0 §0 §2"; + + // Disable CJB's radar. + if (!player.hasPermission(Permissions.CJB_RADAR)) + message = message + "§3 §9 §2 §0 §0 §3"; + + // Disable Minecraft AutoMap's ores. + if (!player.hasPermission(Permissions.MINECRAFTAUTOMAP_ORES)) message = message + "§0§0§1§f§e"; - // Disable Minecraft AutoMap's cave mode - if (!NCPPlayer.hasPermission(player, Permissions.MINECRAFTAUTOMAP_CAVE)) + + // Disable Minecraft AutoMap's cave mode. + if (!player.hasPermission(Permissions.MINECRAFTAUTOMAP_CAVE)) message = message + "§0§0§2§f§e"; - // Disable Minecraft AutoMap's radar - if (!NCPPlayer.hasPermission(player, Permissions.MINECRAFTAUTOMAP_RADAR)) + + // Disable Minecraft AutoMap's radar. + if (!player.hasPermission(Permissions.MINECRAFTAUTOMAP_RADAR)) message = message + "§0§0§3§4§5§6§7§8§f§e"; - // Disable Smart Moving's climbing - if (!NCPPlayer.hasPermission(player, Permissions.SMARTMOVING_CLIMBING)) + + // Disable Smart Moving's climbing. + if (!player.hasPermission(Permissions.SMARTMOVING_CLIMBING)) message = message + "§0§1§0§1§2§f§f"; - // Disable Smart Moving's climbing - if (!NCPPlayer.hasPermission(player, Permissions.SMARTMOVING_SWIMMING)) + + // Disable Smart Moving's climbing. + if (!player.hasPermission(Permissions.SMARTMOVING_SWIMMING)) message = message + "§0§1§3§4§f§f"; - // Disable Smart Moving's climbing - if (!NCPPlayer.hasPermission(player, Permissions.SMARTMOVING_CRAWLING)) + + // Disable Smart Moving's climbing. + if (!player.hasPermission(Permissions.SMARTMOVING_CRAWLING)) message = message + "§0§1§5§f§f"; - // Disable Smart Moving's climbing - if (!NCPPlayer.hasPermission(player, Permissions.SMARTMOVING_SLIDING)) + + // Disable Smart Moving's climbing. + if (!player.hasPermission(Permissions.SMARTMOVING_SLIDING)) message = message + "§0§1§6§f§f"; - // Disable Smart Moving's climbing - if (!NCPPlayer.hasPermission(player, Permissions.SMARTMOVING_JUMPING)) + + // Disable Smart Moving's climbing. + if (!player.hasPermission(Permissions.SMARTMOVING_JUMPING)) message = message + "§0§1§8§9§a§b§f§f"; - // Disable Smart Moving's climbing - if (!NCPPlayer.hasPermission(player, Permissions.SMARTMOVING_FLYING)) + + // Disable Smart Moving's climbing. + if (!player.hasPermission(Permissions.SMARTMOVING_FLYING)) message = message + "§0§1§7§f§f"; + player.sendMessage(message); } } diff --git a/src/fr/neatmonster/nocheatplus/actions/Action.java b/src/fr/neatmonster/nocheatplus/actions/Action.java index 9cd4971c..c04b7aa8 100644 --- a/src/fr/neatmonster/nocheatplus/actions/Action.java +++ b/src/fr/neatmonster/nocheatplus/actions/Action.java @@ -1,32 +1,46 @@ package fr.neatmonster.nocheatplus.actions; +/* + * MMP"""""""MM dP oo + * M' .mmmm MM 88 + * M `M .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMM MM 88' `"" 88 88 88' `88 88' `88 + * M MMMMM MM 88. ... 88 88 88. .88 88 88 + * M MMMMM MM `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMMM + */ /** - * An action gets executed as the result of a failed check. If it 'really' gets - * executed depends on how many executions have occurred within the last 60 - * seconds and how much time was between this and the previous execution - * + * An action gets executed as the result of a failed check. If it 'really' gets executed depends on how many executions + * have occurred within the last 60 seconds and how much time was between this and the previous execution. */ public abstract class Action { + /** + * The name of the action, to identify it, e.g. in the configuration file. + */ + public final String name; /** - * Delay in violations. An "ExecutionHistory" will use this info to make - * sure that there were at least "delay" attempts to execute this action - * before it really gets executed. + * Delay in violations. An "ExecutionHistory" will use this info to make sure that there were at least "delay" + * attempts to execute this action before it really gets executed. */ public final int delay; /** - * Repeat only every "repeat" seconds. An "ExecutionHistory" will use this - * info to make sure that there were at least "repeat" seconds between the - * last execution of this action and this execution. + * Repeat only every "repeat" seconds. An "ExecutionHistory" will use this info to make sure that there were at + * least "repeat" seconds between the last execution of this action and this execution. */ public final int repeat; /** - * The name of the action, to identify it, e.g. in the config file + * Instantiates a new action. + * + * @param name + * the name + * @param delay + * the delay + * @param repeat + * the repetition delay */ - public final String name; - public Action(final String name, final int delay, final int repeat) { this.name = name; this.delay = delay; diff --git a/src/fr/neatmonster/nocheatplus/actions/ActionFactory.java b/src/fr/neatmonster/nocheatplus/actions/ActionFactory.java index 5c93931c..df271710 100644 --- a/src/fr/neatmonster/nocheatplus/actions/ActionFactory.java +++ b/src/fr/neatmonster/nocheatplus/actions/ActionFactory.java @@ -6,29 +6,49 @@ import java.util.List; import java.util.Map; import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.actions.types.ConsolecommandAction; +import fr.neatmonster.nocheatplus.actions.types.CancelAction; +import fr.neatmonster.nocheatplus.actions.types.CommandAction; import fr.neatmonster.nocheatplus.actions.types.DummyAction; import fr.neatmonster.nocheatplus.actions.types.LogAction; -import fr.neatmonster.nocheatplus.actions.types.SpecialAction; +/* + * MMP"""""""MM dP oo MM""""""""`M dP + * M' .mmmm MM 88 MM mmmmmmmM 88 + * M `M .d8888b. d8888P dP .d8888b. 88d888b. M' MMMM .d8888b. .d8888b. d8888P .d8888b. 88d888b. dP dP + * M MMMMM MM 88' `"" 88 88 88' `88 88' `88 MM MMMMMMMM 88' `88 88' `"" 88 88' `88 88' `88 88 88 + * M MMMMM MM 88. ... 88 88 88. .88 88 88 MM MMMMMMMM 88. .88 88. ... 88 88. .88 88 88. .88 + * M MMMMM MM `88888P' dP dP `88888P' dP dP MM MMMMMMMM `88888P8 `88888P' dP `88888P' dP `8888P88 + * MMMMMMMMMMMM MMMMMMMMMMMM .88 + * d8888P + */ /** - * Helps with creating Actions out of text string definitions - * + * Helps with creating Actions out of text string definitions. */ public class ActionFactory { - private static final Map lib = new HashMap(); + /** + * Instantiates a new action factory. + * + * @param library + * the library + */ public ActionFactory(final Map library) { lib.putAll(library); } + /** + * Creates a new Action object. + * + * @param actionDefinition + * the action definition + * @return the action + */ public Action createAction(String actionDefinition) { - actionDefinition = actionDefinition.toLowerCase(); if (actionDefinition.equals("cancel")) - return new SpecialAction(); + return new CancelAction(); if (actionDefinition.startsWith("log:")) return parseLogAction(actionDefinition.split(":", 2)[1]); @@ -39,6 +59,15 @@ public class ActionFactory { throw new IllegalArgumentException("NoCheatPlus doesn't understand action '" + actionDefinition + "' at all"); } + /** + * Creates a new Action object. + * + * @param definition + * the definition + * @param permission + * the permission + * @return the action list + */ public ActionList createActionList(final String definition, final String permission) { final ActionList list = new ActionList(permission); @@ -66,13 +95,20 @@ public class ActionFactory { } list.setActions(vl, createActions(def.split("\\s+"))); } catch (final Exception e) { - System.out.println("NoCheatPlus couldn't parse action definition 'vl:" + s + "'"); + System.out.println("[NoCheatPlus] Couldn't parse action definition 'vl:" + s + "'."); } } return list; } + /** + * Creates a new Action object. + * + * @param definitions + * the definitions + * @return the action[] + */ public Action[] createActions(final String... definitions) { final List actions = new ArrayList(); @@ -82,7 +118,7 @@ public class ActionFactory { try { actions.add(createAction(def)); } catch (final IllegalArgumentException e) { - System.out.println(e.getMessage()); + System.out.println("[NoCheatPlus] " + e.getMessage()); actions.add(new DummyAction(def)); } } @@ -90,6 +126,13 @@ public class ActionFactory { return actions.toArray(new Action[actions.size()]); } + /** + * Parses the cmd action. + * + * @param definition + * the definition + * @return the action + */ private Action parseCmdAction(final String definition) { final String[] parts = definition.split(":"); final String name = parts[0]; @@ -106,15 +149,22 @@ public class ActionFactory { delay = Integer.parseInt(parts[1]); repeat = Integer.parseInt(parts[2]); } catch (final Exception e) { - System.out.println("NoCheatPlus couldn't parse details of command '" + definition + System.out.println("[NoCheatPlus] Couldn't parse details of command '" + definition + "', will use default values instead."); delay = 0; repeat = 1; } - return new ConsolecommandAction(name, delay, repeat, command.toString()); + return new CommandAction(name, delay, repeat, command.toString()); } + /** + * Parses the log action. + * + * @param definition + * the definition + * @return the action + */ private Action parseLogAction(final String definition) { final String[] parts = definition.split(":"); final String name = parts[0]; @@ -136,7 +186,7 @@ public class ActionFactory { toChat = parts[3].contains("i"); toFile = parts[3].contains("f"); } catch (final Exception e) { - System.out.println("NoCheatPlus couldn't parse details of log action '" + definition + System.out.println("[NoCheatPlus] Couldn't parse details of log action '" + definition + "', will use default values instead."); e.printStackTrace(); delay = 0; diff --git a/src/fr/neatmonster/nocheatplus/actions/ParameterName.java b/src/fr/neatmonster/nocheatplus/actions/ParameterName.java index 8e572f10..16587dd9 100644 --- a/src/fr/neatmonster/nocheatplus/actions/ParameterName.java +++ b/src/fr/neatmonster/nocheatplus/actions/ParameterName.java @@ -1,39 +1,62 @@ package fr.neatmonster.nocheatplus.actions; +/* + * MM"""""""`YM dP + * MM mmmmm M 88 + * M' .M .d8888b. 88d888b. .d8888b. 88d8b.d8b. .d8888b. d8888P .d8888b. 88d888b. + * MM MMMMMMMM 88' `88 88' `88 88' `88 88'`88'`88 88ooood8 88 88ooood8 88' `88 + * MM MMMMMMMM 88. .88 88 88. .88 88 88 88 88. ... 88 88. ... 88 + * MM MMMMMMMM `88888P8 dP `88888P8 dP dP dP `88888P' dP `88888P' dP + * MMMMMMMMMMMM + * + * M"""""""`YM + * M mmmm. M + * M MMMMM M .d8888b. 88d8b.d8b. .d8888b. + * M MMMMM M 88' `88 88'`88'`88 88ooood8 + * M MMMMM M 88. .88 88 88 88 88. ... + * M MMMMM M `88888P8 dP dP dP `88888P' + * MMMMMMMMMMM + */ /** - * Some wildcards that are used in commands and log messages + * Some wildcards that are used in commands and log messages. */ public enum ParameterName { - PLAYER("player"), - LOCATION("location"), - WORLD("world"), - VIOLATIONS("violations"), - MOVEDISTANCE("movedistance"), - REACHDISTANCE("reachdistance"), - FALLDISTANCE("falldistance"), - LOCATION_TO("locationto"), CHECK("check"), + DISTANCE("distance"), + FALLDISTANCE("falldistance"), + IP("ip"), + LOCATION_FROM("locationfrom"), + LOCATION_TO("locationto"), PACKETS("packets"), - TEXT("text"), - PLACE_LOCATION("placelocation"), - PLACE_AGAINST("placeagainst"), - BLOCK_TYPE("blocktype"), - LIMIT("limit"), - FOOD("food"), - REASON("reason"), - IP("ip"); - - public static final ParameterName get(final String s) { - for (final ParameterName c : ParameterName.values()) - if (c.s.equals(s)) - return c; + PLAYER("player"), + REACHDISTANCE("reachdistance"), + VIOLATIONS("violations"), + WORLD("world"); + /** + * Gets the parameter associated to the text. + * + * @param s + * the s + * @return the parameter name + */ + public static final ParameterName get(final String text) { + for (final ParameterName parameterName : ParameterName.values()) + if (parameterName.text.equals(text)) + return parameterName; return null; } - private final String s; + /** The text. */ + private final String text; - private ParameterName(final String s) { - this.s = s; + /** + * Instantiates a new parameter name. + * + * @param text + * the text + */ + private ParameterName(final String text) { + this.text = text; } } diff --git a/src/fr/neatmonster/nocheatplus/actions/types/ActionList.java b/src/fr/neatmonster/nocheatplus/actions/types/ActionList.java index 9b0927ff..045e36b4 100644 --- a/src/fr/neatmonster/nocheatplus/actions/types/ActionList.java +++ b/src/fr/neatmonster/nocheatplus/actions/types/ActionList.java @@ -8,47 +8,56 @@ import java.util.Map; import fr.neatmonster.nocheatplus.actions.Action; +/* + * MMP"""""""MM dP oo M""MMMMMMMM oo dP + * M' .mmmm MM 88 M MMMMMMMM 88 + * M `M .d8888b. d8888P dP .d8888b. 88d888b. M MMMMMMMM dP .d8888b. d8888P + * M MMMMM MM 88' `"" 88 88 88' `88 88' `88 M MMMMMMMM 88 Y8ooooo. 88 + * M MMMMM MM 88. ... 88 88 88. .88 88 88 M MMMMMMMM 88 88 88 + * M MMMMM MM `88888P' dP dP `88888P' dP dP M M dP `88888P' dP + * MMMMMMMMMMMM MMMMMMMMMMM + */ /** - * A list of actions, that associates actions to tresholds. It allows to - * retrieve all actions that match a certain treshold - * + * A list of actions, that associates actions to thresholds. It allows to retrieve all actions that match a certain + * threshold. */ public class ActionList { - // This is a very bad design decision, but it's also really - // convenient to define this here + /** This is a very bad design decision, but it's also really convenient to define this here. */ public final String permissionSilent; - // If there are no actions registered, we still return an Array. It's - // just empty/size=0 + /** If there are no actions registered, we still return an Array. It's just empty/size=0. */ private final static Action[] emptyArray = new Action[0]; - // The actions of this ActionList, "bundled" by treshold (violation level) + /** The actions of this ActionList, "bundled" by treshold (violation level). */ private final Map actions = new HashMap(); - // The tresholds of this list - private final List tresholds = new ArrayList(); + /** The thresholds of this list. **/ + private final List thresholds = new ArrayList(); + /** + * Instantiates a new action list. + * + * @param permission + * the permission + */ public ActionList(final String permission) { permissionSilent = permission + ".silent"; } /** - * Get a list of actions that match the violation level. - * The only method that has to be called by a check + * Get a list of actions that match the violation level. The only method that has to be called by a check. * * @param violationLevel * The violation level that should be matched. - * @return The array of actions whose treshold was closest to the - * violationLevel but not bigger + * @return The array of actions whose threshold was closest to the violation level but not bigger. */ public Action[] getActions(final double violationLevel) { - Integer result = null; - for (final Integer treshold : tresholds) - if (treshold <= violationLevel) - result = treshold; + for (final Integer threshold : thresholds) + if (threshold <= violationLevel) + result = threshold; if (result != null) return actions.get(result); @@ -57,33 +66,28 @@ public class ActionList { } /** - * Get a sorted list of the tresholds/violation levels that were used - * in this list + * Get a sorted list of the thresholds/violation levels that were used in this list. * - * @return The sorted list of tresholds + * @return The sorted list of thresholds. */ - public List getTresholds() { - return tresholds; + public List getThresholds() { + return thresholds; } /** - * Add an entry to this actionList. The list will be sorted by tresholds - * automatically after the insertion. + * Add an entry to this actionList. The list will be sorted by thresholds automatically after the insertion. * * @param treshold - * The minimum violation level a player needs to have - * to be suspected to the given actions + * The minimum violation level a player needs to have to be suspected to the given actions. * @param actions - * The actions that will be used if the player reached the - * accompanying treshold/violation level + * The actions that will be used if the player reached the accompanying threshold/violation level. */ - public void setActions(final Integer treshold, final Action[] actions) { - - if (!tresholds.contains(treshold)) { - tresholds.add(treshold); - Collections.sort(tresholds); + public void setActions(final Integer threshold, final Action[] actions) { + if (!thresholds.contains(threshold)) { + thresholds.add(threshold); + Collections.sort(thresholds); } - this.actions.put(treshold, actions); + this.actions.put(threshold, actions); } } diff --git a/src/fr/neatmonster/nocheatplus/actions/types/ActionWithParameters.java b/src/fr/neatmonster/nocheatplus/actions/types/ActionWithParameters.java index db286c7d..642bad3c 100644 --- a/src/fr/neatmonster/nocheatplus/actions/types/ActionWithParameters.java +++ b/src/fr/neatmonster/nocheatplus/actions/types/ActionWithParameters.java @@ -2,19 +2,48 @@ package fr.neatmonster.nocheatplus.actions.types; import java.util.ArrayList; +import org.bukkit.entity.Player; + import fr.neatmonster.nocheatplus.actions.Action; import fr.neatmonster.nocheatplus.actions.ParameterName; import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -/** - * Action with parameters is used to +/* + * MMP"""""""MM dP oo M""MMM""MMM""M oo dP dP + * M' .mmmm MM 88 M MMM MMM M 88 88 + * M `M .d8888b. d8888P dP .d8888b. 88d888b. M MMP MMP M dP d8888P 88d888b. + * M MMMMM MM 88' `"" 88 88 88' `88 88' `88 M MM' MM' .M 88 88 88' `88 + * M MMMMM MM 88. ... 88 88 88. .88 88 88 M `' . '' .MM 88 88 88 88 + * M MMMMM MM `88888P' dP dP `88888P' dP dP M .d .dMMM dP dP dP dP + * MMMMMMMMMMMM MMMMMMMMMMMMMM * + * MM"""""""`YM dP + * MM mmmmm M 88 + * M' .M .d8888b. 88d888b. .d8888b. 88d8b.d8b. .d8888b. d8888P .d8888b. 88d888b. .d8888b. + * MM MMMMMMMM 88' `88 88' `88 88' `88 88'`88'`88 88ooood8 88 88ooood8 88' `88 Y8ooooo. + * MM MMMMMMMM 88. .88 88 88. .88 88 88 88 88. ... 88 88. ... 88 88 + * MM MMMMMMMM `88888P8 dP `88888P8 dP dP dP `88888P' dP `88888P' dP `88888P' + * MMMMMMMMMMMM + */ +/** + * Action with parameters is used for the messages (chat, console, log) or the commands. */ public abstract class ActionWithParameters extends Action { - + /** The parts of the message. */ private final ArrayList messageParts; + /** + * Instantiates a new action with parameters. + * + * @param name + * the name + * @param delay + * the delay + * @param repeat + * the repeat + * @param message + * the message + */ public ActionWithParameters(final String name, final int delay, final int repeat, final String message) { super(name, delay, repeat); @@ -24,16 +53,17 @@ public abstract class ActionWithParameters extends Action { } /** - * Get a string with all the wildcards replaced with data from LogData + * Get a string with all the wildcards replaced with data from LogData. * - * @param data - * @return + * @param player + * the player + * @param check + * the check + * @return the message */ - - protected String getMessage(final NCPPlayer player, final Check check) { - - final StringBuilder log = new StringBuilder(100); // Should be big enough most - // of the time + protected String getMessage(final Player player, final Check check) { + // Should be big enough most of the time. + final StringBuilder log = new StringBuilder(100); for (final Object part : messageParts) if (part instanceof String) @@ -44,27 +74,33 @@ public abstract class ActionWithParameters extends Action { return log.toString(); } + /** + * Parses the message. + * + * @param message + * the message + */ private void parseMessage(final String message) { final String parts[] = message.split("\\[", 2); - // No opening braces left + // No opening braces left. if (parts.length != 2) messageParts.add(message); else { final String parts2[] = parts[1].split("\\]", 2); - // Found no matching closing brace + // Found no matching closing brace. if (parts2.length != 2) messageParts.add(message); else { final ParameterName w = ParameterName.get(parts2[0]); if (w != null) { - // Found an existing wildcard inbetween the braces + // Found an existing wildcard inbetween the braces. messageParts.add(parts[0]); messageParts.add(w); - // Go further down recursive + // Go further down recursive. parseMessage(parts2[1]); } else messageParts.add(message); diff --git a/src/fr/neatmonster/nocheatplus/actions/types/CancelAction.java b/src/fr/neatmonster/nocheatplus/actions/types/CancelAction.java new file mode 100644 index 00000000..f2466b2b --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/actions/types/CancelAction.java @@ -0,0 +1,34 @@ +package fr.neatmonster.nocheatplus.actions.types; + +import fr.neatmonster.nocheatplus.actions.Action; + +/* + * MM'""""'YMM dP MMP"""""""MM dP oo + * M' .mmm. `M 88 M' .mmmm MM 88 + * M MMMMMooM .d8888b. 88d888b. .d8888b. .d8888b. 88 M `M .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMMMMM 88' `88 88' `88 88' `"" 88ooood8 88 M MMMMM MM 88' `"" 88 88 88' `88 88' `88 + * M. `MMM' .M 88. .88 88 88 88. ... 88. ... 88 M MMMMM MM 88. ... 88 88 88. .88 88 88 + * MM. .dM `88888P8 dP dP `88888P' `88888P' dP M MMMMM MM `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMM MMMMMMMMMMMM + */ +/** + * Do something check-specific. Usually that is to cancel the event, undo something the player did, or do something the + * server should've done. + */ +public class CancelAction extends Action { + + /** + * Instantiates a new cancel action. + */ + public CancelAction() { + super("cancel", 0, 0); + } + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "cancel"; + } +} diff --git a/src/fr/neatmonster/nocheatplus/actions/types/CommandAction.java b/src/fr/neatmonster/nocheatplus/actions/types/CommandAction.java new file mode 100644 index 00000000..bbc54021 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/actions/types/CommandAction.java @@ -0,0 +1,69 @@ +package fr.neatmonster.nocheatplus.actions.types; + +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.checks.Check; + +/* + * MM'""""'YMM dP + * M' .mmm. `M 88 + * M MMMMMooM .d8888b. 88d8b.d8b. 88d8b.d8b. .d8888b. 88d888b. .d888b88 + * M MMMMMMMM 88' `88 88'`88'`88 88'`88'`88 88' `88 88' `88 88' `88 + * M. `MMM' .M 88. .88 88 88 88 88 88 88 88. .88 88 88 88. .88 + * MM. .dM `88888P' dP dP dP dP dP dP `88888P8 dP dP `88888P8 + * MMMMMMMMMMM + * + * MMP"""""""MM dP oo + * M' .mmmm MM 88 + * M `M .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMM MM 88' `"" 88 88 88' `88 88' `88 + * M MMMMM MM 88. ... 88 88 88. .88 88 88 + * M MMMMM MM `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMMM + */ +/** + * Execute a command by imitating an administrator typing the command directly into the console. + */ +public class CommandAction extends ActionWithParameters { + + /** + * Instantiates a new command action. + * + * @param name + * the name + * @param delay + * the delay + * @param repeat + * the repeat + * @param command + * the command + */ + public CommandAction(final String name, final int delay, final int repeat, final String command) { + // Log messages may have color codes now. + super(name, delay, repeat, command); + } + + /** + * Fill in the placeholders (stuff that looks like '[something]') with information, make a nice String out of it + * that can be directly used as a command in the console. + * + * @param player + * The player that is used to fill in missing data. + * @param check + * The check that is used to fill in missing data. + * @return The complete, ready to use, command. + */ + public String getCommand(final Player player, final Check check) { + return super.getMessage(player, check); + } + + /** + * Convert the commands data into a string that can be used in the configuration files. + * + * @return the string + */ + @Override + public String toString() { + return "cmd:" + name + ":" + delay + ":" + repeat; + } +} diff --git a/src/fr/neatmonster/nocheatplus/actions/types/ConsolecommandAction.java b/src/fr/neatmonster/nocheatplus/actions/types/ConsolecommandAction.java deleted file mode 100644 index d9e4da88..00000000 --- a/src/fr/neatmonster/nocheatplus/actions/types/ConsolecommandAction.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.neatmonster.nocheatplus.actions.types; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * Execute a command by imitating an admin typing the command directly into the - * console - * - */ -public class ConsolecommandAction extends ActionWithParameters { - - public ConsolecommandAction(final String name, final int delay, final int repeat, final String command) { - // Log messages may have color codes now - super(name, delay, repeat, command); - } - - /** - * Fill in the placeholders ( stuff that looks like '[something]') with - * information, make a nice String out of it that can be directly used - * as a command in the console. - * - * @param player - * The player that is used to fill in missing data - * @param check - * The check that is used to fill in missing data - * @return The complete, ready to use, command - */ - public String getCommand(final NCPPlayer player, final Check check) { - return super.getMessage(player, check); - } - - /** - * Convert the commands data into a string that can be used in the config - * files - */ - @Override - public String toString() { - return "cmd:" + name + ":" + delay + ":" + repeat; - } -} diff --git a/src/fr/neatmonster/nocheatplus/actions/types/DummyAction.java b/src/fr/neatmonster/nocheatplus/actions/types/DummyAction.java index f914d25c..8a6e697a 100644 --- a/src/fr/neatmonster/nocheatplus/actions/types/DummyAction.java +++ b/src/fr/neatmonster/nocheatplus/actions/types/DummyAction.java @@ -2,23 +2,40 @@ package fr.neatmonster.nocheatplus.actions.types; import fr.neatmonster.nocheatplus.actions.Action; +/* + * M""""""'YMM MMP"""""""MM dP oo + * M mmmm. `M M' .mmmm MM 88 + * M MMMMM M dP dP 88d8b.d8b. 88d8b.d8b. dP dP M `M .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMM M 88 88 88'`88'`88 88'`88'`88 88 88 M MMMMM MM 88' `"" 88 88 88' `88 88' `88 + * M MMMM' .M 88. .88 88 88 88 88 88 88 88. .88 M MMMMM MM 88. ... 88 88 88. .88 88 88 + * M .MM `88888P' dP dP dP dP dP dP `8888P88 M MMMMM MM `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMM .88 MMMMMMMMMMMM + * d8888P + */ /** - * If an action can't be parsed correctly, at least keep it - * stored in this form to not lose it when loading/storing the config file - * + * If an action can't be parsed correctly, at least keep it stored in this form to not lose it when loading/storing the + * configuration file. */ public class DummyAction extends Action { + /** The original string used for this action definition. */ + private final String definition; - // The original string used for this action definition - private final String def; - - public DummyAction(final String def) { + /** + * Instantiates a new dummy. + * + * @param definition + * the definition + */ + public DummyAction(final String definition) { super("dummyAction", 10000, 10000); - this.def = def; + this.definition = definition; } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { - return def; + return definition; } } diff --git a/src/fr/neatmonster/nocheatplus/actions/types/LogAction.java b/src/fr/neatmonster/nocheatplus/actions/types/LogAction.java index 28c11e0f..36d6a2c5 100644 --- a/src/fr/neatmonster/nocheatplus/actions/types/LogAction.java +++ b/src/fr/neatmonster/nocheatplus/actions/types/LogAction.java @@ -1,20 +1,51 @@ package fr.neatmonster.nocheatplus.actions.types; -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; +import org.bukkit.entity.Player; +import fr.neatmonster.nocheatplus.checks.Check; + +/* + * M""MMMMMMMM MMP"""""""MM dP oo + * M MMMMMMMM M' .mmmm MM 88 + * M MMMMMMMM .d8888b. .d8888b. M `M .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMMMMM 88' `88 88' `88 M MMMMM MM 88' `"" 88 88 88' `88 88' `88 + * M MMMMMMMM 88. .88 88. .88 M MMMMM MM 88. ... 88 88 88. .88 88 88 + * M M `88888P' `8888P88 M MMMMM MM `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMM .88 MMMMMMMMMMMM + * d8888P + */ /** - * Print a log message to various locations - * + * Print a log message to various locations. */ public class LogAction extends ActionWithParameters { - - // Some flags to decide where the log message should show up, based on - // the config file + // Some flags to decide where the log message should show up, based on the configuration file. + /** Log to chat? */ private final boolean toChat; + + /** Log to console? */ private final boolean toConsole; + + /** Log to file? */ private final boolean toFile; + /** + * Instantiates a new log action. + * + * @param name + * the name + * @param delay + * the delay + * @param repeat + * the repeat + * @param toChat + * the to chat + * @param toConsole + * the to console + * @param toFile + * the to file + * @param message + * the message + */ public LogAction(final String name, final int delay, final int repeat, final boolean toChat, final boolean toConsole, final boolean toFile, final String message) { super(name, delay, repeat, message); @@ -24,16 +55,15 @@ public class LogAction extends ActionWithParameters { } /** - * Parse the final log message out of various data from the player and - * check that triggered the action. + * Parse the final log message out of various data from the player and check that triggered the action. * * @param player - * The player that is used as a source for the log message + * The player that is used as a source for the log message. * @param check - * The check that is used as a source for the log message - * @return + * The check that is used as a source for the log message. + * @return the log message */ - public String getLogMessage(final NCPPlayer player, final Check check) { + public String getLogMessage(final Player player, final Check check) { return super.getMessage(player, check); } @@ -65,7 +95,9 @@ public class LogAction extends ActionWithParameters { } /** - * Create the string that's used to define the action in the logfile + * Create the string that's used to define the action in the logfile. + * + * @return the string */ @Override public String toString() { diff --git a/src/fr/neatmonster/nocheatplus/actions/types/SpecialAction.java b/src/fr/neatmonster/nocheatplus/actions/types/SpecialAction.java deleted file mode 100644 index ac638fc2..00000000 --- a/src/fr/neatmonster/nocheatplus/actions/types/SpecialAction.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.neatmonster.nocheatplus.actions.types; - -import fr.neatmonster.nocheatplus.actions.Action; - -/** - * Do something check-specific. Usually that is to cancel the event, undo - * something the player did, or do something the server should've done - * - */ -public class SpecialAction extends Action { - - public SpecialAction() { - super("cancel", 0, 0); - } - - @Override - public String toString() { - return "cancel"; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/Check.java b/src/fr/neatmonster/nocheatplus/checks/Check.java index 006e4ba1..28e56eba 100644 --- a/src/fr/neatmonster/nocheatplus/checks/Check.java +++ b/src/fr/neatmonster/nocheatplus/checks/Check.java @@ -1,7 +1,6 @@ package fr.neatmonster.nocheatplus.checks; import java.util.HashMap; -import java.util.Locale; import java.util.Map; import java.util.logging.Logger; @@ -10,210 +9,226 @@ import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.command.CommandException; import org.bukkit.entity.Player; +import org.bukkit.event.Listener; import fr.neatmonster.nocheatplus.actions.Action; import fr.neatmonster.nocheatplus.actions.ParameterName; import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.actions.types.ConsolecommandAction; +import fr.neatmonster.nocheatplus.actions.types.CancelAction; +import fr.neatmonster.nocheatplus.actions.types.CommandAction; import fr.neatmonster.nocheatplus.actions.types.DummyAction; import fr.neatmonster.nocheatplus.actions.types.LogAction; -import fr.neatmonster.nocheatplus.actions.types.SpecialAction; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; import fr.neatmonster.nocheatplus.config.ConfigManager; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; +import fr.neatmonster.nocheatplus.players.ExecutionHistory; +import fr.neatmonster.nocheatplus.players.Permissions; -public abstract class Check { - private static final Map checks = new HashMap(); - private static Logger fileLogger = null; +/* + * MM'""""'YMM dP dP + * M' .mmm. `M 88 88 + * M MMMMMooM 88d888b. .d8888b. .d8888b. 88 .dP + * M MMMMMMMM 88' `88 88ooood8 88' `"" 88888" + * M. `MMM' .M 88 88 88. ... 88. ... 88 `8b. + * MM. .dM dP dP `88888P' `88888P' dP `YP + * MMMMMMMMMMM + */ +/** + * The Class Check. + */ +public abstract class Check implements Listener { + protected static Map histories = new HashMap(); - public static CheckConfig newConfig(final String group, final String worldName) { - if (checks.containsKey(group)) - return checks.get(group).newConfig(worldName); - return null; - } + private static Logger fileLogger = null; - public static CheckData newData(final String group) { - if (checks.containsKey(group)) - return checks.get(group).newData(); - return null; + /** + * Gets the player's history. + * + * @param player + * the player + * @return the history + */ + protected static ExecutionHistory getHistory(final Player player) { + if (!histories.containsKey(player.getName())) + histories.put(player.getName(), new ExecutionHistory()); + return histories.get(player.getName()); } /** - * Remove instances of &X + * Checks if a player is close enough to a target, based on his eye location. + * + * @param player + * the player + * @param targetX + * the target x + * @param targetY + * the target y + * @param targetZ + * the target z + * @param limit + * the limit + * @return the result + */ + public static final double reachCheck(final Player player, final double targetX, final double targetY, + final double targetZ, final double limit) { + final Location eyes = player.getPlayer().getEyeLocation(); + + final double distance = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2) + + Math.pow(eyes.getZ() - targetZ, 2)); + + return Math.max(distance - limit, 0.0D); + } + + /** + * Removes the colors of a message. * * @param text - * @return + * the text + * @return the string */ public static String removeColors(String text) { - for (final ChatColor c : ChatColor.values()) text = text.replace("&" + c.getChar(), ""); - return text; } /** - * Replace instances of &X with a color + * Replace colors of a message. * * @param text - * @return + * the text + * @return the string */ public static String replaceColors(String text) { - for (final ChatColor c : ChatColor.values()) text = text.replace("&" + c.getChar(), c.toString()); - return text; } + /** + * Sets the file logger. + * + * @param logger + * the new file logger + */ public static void setFileLogger(final Logger logger) { fileLogger = logger; } - private final String name; - - private final Class configClass; - - private final Class dataClass; - - public Check(final String name, final Class configClass, - final Class dataClass) { - this.name = name; - this.configClass = configClass; - this.dataClass = dataClass; - - checks.put(getGroup(), this); - } - /** - * Execute some actions for the specified player + * Execute some actions for the specified player. * * @param player - * @param actions - * @return + * the player + * @param actionList + * the action list + * @param violationLevel + * the violation level + * @return true, if successful */ - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - + protected boolean executeActions(final Player player, final ActionList actionList, final double violationLevel) { boolean special = false; - // Get the to be executed actions + // Get the to be executed actions. final Action[] actions = actionList.getActions(violationLevel); final long time = System.currentTimeMillis() / 1000L; for (final Action ac : actions) - if (player.getExecutionHistory().executeAction(getGroup(), ac, time)) - // The executionHistory said it really is time to execute the - // action, find out what it is and do what is needed + if (getHistory(player).executeAction(getClass().getName(), ac, time)) + // The execution history said it really is time to execute the action, find out what it is and do what + // is + // needed. if (ac instanceof LogAction && !player.hasPermission(actionList.permissionSilent)) executeLogAction((LogAction) ac, this, player); - else if (ac instanceof SpecialAction) + else if (ac instanceof CancelAction) special = true; - else if (ac instanceof ConsolecommandAction) - executeConsoleCommand((ConsolecommandAction) ac, this, player); + else if (ac instanceof CommandAction) + executeConsoleCommand((CommandAction) ac, this, player); else if (ac instanceof DummyAction) { - // nothing - it's a "DummyAction" after all + // Do nothing, it's a dummy action after all. } return special; } - private void executeConsoleCommand(final ConsolecommandAction action, final Check check, final NCPPlayer player) { + /** + * Execute a console command. + * + * @param action + * the action + * @param check + * the check + * @param player + * the player + */ + private void executeConsoleCommand(final CommandAction action, final Check check, final Player player) { final String command = action.getCommand(player, check); try { Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command); } catch (final CommandException e) { - System.out.println("[NoCheatPlus] failed to execute the command '" + command + "': " + e.getMessage() + System.out.println("[NoCheatPlus] Failed to execute the command '" + command + "': " + e.getMessage() + ", please check if everything is setup correct."); } catch (final Exception e) { // I don't care in this case, your problem if your command fails. } } - private void executeLogAction(final LogAction l, final Check check, final NCPPlayer player) { - + /** + * Execute a log action. + * + * @param logAction + * the log action + * @param check + * the check + * @param player + * the player + */ + private void executeLogAction(final LogAction logAction, final Check check, final Player player) { final ConfigFile configurationFile = ConfigManager.getConfigFile(); if (!configurationFile.getBoolean(ConfPaths.LOGGING_ACTIVE)) return; - final String prefix = configurationFile.getString(ConfPaths.LOGGING_PREFIX); - final String message = l.getLogMessage(player, check); - if (configurationFile.getBoolean(ConfPaths.LOGGING_LOGTOCONSOLE) && l.toConsole()) - // Console logs are not colored - System.out.println(removeColors(prefix + message)); - if (configurationFile.getBoolean(ConfPaths.LOGGING_LOGTOINGAMECHAT) && l.toChat()) - for (final Player bukkitPlayer : Bukkit.getServer().getOnlinePlayers()) - if (NCPPlayer.hasPermission(bukkitPlayer, Permissions.ADMIN_CHATLOG)) - // Chat logs are potentially colored - bukkitPlayer.sendMessage(replaceColors(prefix + message)); - if (configurationFile.getBoolean(ConfPaths.LOGGING_LOGTOFILE) && l.toFile()) - // File logs are not colored + final String message = logAction.getLogMessage(player, check); + if (configurationFile.getBoolean(ConfPaths.LOGGING_LOGTOCONSOLE) && logAction.toConsole()) + // Console logs are not colored. + System.out.println("[NoCheatPlus] " + removeColors(message)); + if (configurationFile.getBoolean(ConfPaths.LOGGING_LOGTOINGAMECHAT) && logAction.toChat()) + for (final Player otherPlayer : Bukkit.getServer().getOnlinePlayers()) + if (otherPlayer.hasPermission(Permissions.ADMINISTRATION_NOTIFY)) + // Chat logs are potentially colored. + otherPlayer.sendMessage(replaceColors(ChatColor.RED + "NCP: " + ChatColor.WHITE + message)); + if (configurationFile.getBoolean(ConfPaths.LOGGING_LOGTOFILE) && logAction.toFile()) + // File logs are not colored. fileLogger.info(removeColors(message)); } - public String getGroup() { - return name.contains(".") ? name.split("\\.")[0] : name; - } - - public String getName() { - return name.contains(".") ? name.split("\\.")[name.split("\\.").length - 1] : name; - } - /** - * Replace a parameter for commands or log actions with an actual - * value. Individual checks should override this to get their own - * parameters handled too. + * Replace a parameter for commands or log actions with an actual value. Individual checks should override this to + * get their own parameters handled too. * * @param wildcard + * the wildcard * @param player - * @return + * the player + * @return the parameter */ - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.PLAYER) + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.CHECK) + return getClass().getSimpleName(); + else if (wildcard == ParameterName.PLAYER) return player.getName(); - else if (wildcard == ParameterName.CHECK) - return name; - else if (wildcard == ParameterName.LOCATION) { - final Location l = player.getLocation(); - return String.format(Locale.US, "%.2f,%.2f,%.2f", l.getX(), l.getY(), l.getZ()); - } else if (wildcard == ParameterName.WORLD) - return player.getWorld().getName(); else - return "the Author was lazy and forgot to define " + wildcard + "."; - + return "The author was lazy and forgot to define " + wildcard + "."; } /** - * Collect information about the players violations + * Returns if the check is enabled or not for the specified player. * * @param player - * @param id - * @param vl + * the player + * @return true, if enabled */ - protected void incrementStatistics(final NCPPlayer player, final Id id, final double vl) { - player.getStatistics().increment(id, vl); - } - - public CheckConfig newConfig(final String worldName) { - try { - return configClass.getConstructor(ConfigFile.class).newInstance(ConfigManager.getConfFile(worldName)); - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } - - public CheckData newData() { - try { - return dataClass.getConstructor().newInstance(); - } catch (final Exception e) { - e.printStackTrace(); - } - return null; - } + protected abstract boolean isEnabled(final Player player); } diff --git a/src/fr/neatmonster/nocheatplus/checks/CheckConfig.java b/src/fr/neatmonster/nocheatplus/checks/CheckConfig.java deleted file mode 100644 index eb263320..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/CheckConfig.java +++ /dev/null @@ -1,3 +0,0 @@ -package fr.neatmonster.nocheatplus.checks; - -public abstract class CheckConfig {} diff --git a/src/fr/neatmonster/nocheatplus/checks/CheckData.java b/src/fr/neatmonster/nocheatplus/checks/CheckData.java deleted file mode 100644 index a02a4e74..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/CheckData.java +++ /dev/null @@ -1,3 +0,0 @@ -package fr.neatmonster.nocheatplus.checks; - -public abstract class CheckData {} diff --git a/src/fr/neatmonster/nocheatplus/checks/CheckEvent.java b/src/fr/neatmonster/nocheatplus/checks/CheckEvent.java index bfca83d4..cb2985b4 100644 --- a/src/fr/neatmonster/nocheatplus/checks/CheckEvent.java +++ b/src/fr/neatmonster/nocheatplus/checks/CheckEvent.java @@ -1,18 +1,23 @@ package fr.neatmonster.nocheatplus.checks; +import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * The event created when actions are executed. +/* + * MM'""""'YMM dP dP MM""""""""`M dP + * M' .mmm. `M 88 88 MM mmmmmmmM 88 + * M MMMMMooM 88d888b. .d8888b. .d8888b. 88 .dP M` MMMM dP .dP .d8888b. 88d888b. d8888P + * M MMMMMMMM 88' `88 88ooood8 88' `"" 88888" MM MMMMMMMM 88 d8' 88ooood8 88' `88 88 + * M. `MMM' .M 88 88 88. ... 88. ... 88 `8b. MM MMMMMMMM 88 .88' 88. ... 88 88 88 + * MM. .dM dP dP `88888P' `88888P' dP `YP MM .M 8888P' `88888P' dP dP dP + * MMMMMMMMMMM MMMMMMMMMMMM */ -public abstract class CheckEvent extends Event implements Cancellable { - - /** The Constant handlers. */ +/** + * An event that is triggered by NoCheatPlus' API. + */ +public class CheckEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); /** @@ -24,60 +29,23 @@ public abstract class CheckEvent extends Event implements Cancellable { return handlers; } - /** The check which has triggered this event. */ - private final Check check; + /** The player who has triggered the check. */ + private final Player player; - /** The player who has triggered this event. */ - private final NCPPlayer player; - - /** The actions which are going to be executed if the event isn't cancelled. */ - private ActionList actions; - - /** The violation level of the player for the specified check. */ - private double vL; - - /** The boolean used to know if the event is cancelled. */ - private boolean cancel = false; + /** Is the event cancelled? */ + private boolean cancel = false; /** * Instantiates a new check event. * - * @param check - * the check * @param player * the player - * @param actions - * the actions - * @param vL - * the vL */ - public CheckEvent(final Check check, final NCPPlayer player, final ActionList actions, final double vL) { - this.check = check; + public CheckEvent(final Player player) { this.player = player; - this.actions = actions; - this.vL = vL; } - /** - * Gets the actions which are going to be executed if the event isn't cancelled. - * - * @return the actions - */ - public ActionList getActions() { - return actions; - } - - /** - * Gets the check which has triggered this event. - * - * @return the check - */ - public Check getCheck() { - return check; - } - - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.bukkit.event.Event#getHandlers() */ @Override @@ -90,21 +58,11 @@ public abstract class CheckEvent extends Event implements Cancellable { * * @return the player */ - public NCPPlayer getPlayer() { + public Player getPlayer() { return player; } - /** - * Gets the violation level of the player for the specified check. - * - * @return the vL - */ - public double getVL() { - return vL; - } - - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.bukkit.event.Cancellable#isCancelled() */ @Override @@ -112,32 +70,11 @@ public abstract class CheckEvent extends Event implements Cancellable { return cancel; } - /** - * Sets the actions which are going to be executed if the event isn't cancelled. - * - * @param actions - * the new actions - */ - public void setActions(final ActionList actions) { - this.actions = actions; - } - - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.bukkit.event.Cancellable#setCancelled(boolean) */ @Override public void setCancelled(final boolean cancel) { this.cancel = cancel; } - - /** - * Sets the violation level of the player for the specified check. - * - * @param vL - * the new vL - */ - public void setVL(final double vL) { - this.vL = vL; - } } diff --git a/src/fr/neatmonster/nocheatplus/checks/CheckListener.java b/src/fr/neatmonster/nocheatplus/checks/CheckListener.java deleted file mode 100644 index 503c5d45..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/CheckListener.java +++ /dev/null @@ -1,21 +0,0 @@ -package fr.neatmonster.nocheatplus.checks; - -import org.bukkit.event.Listener; - -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public abstract class CheckListener implements Listener { - private final String group; - - public CheckListener(final String group) { - this.group = group; - } - - public CheckConfig getConfig(final NCPPlayer player) { - return player.getConfig(group); - } - - public CheckData getData(final NCPPlayer player) { - return player.getData(group); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/CheckUtils.java b/src/fr/neatmonster/nocheatplus/checks/CheckUtils.java deleted file mode 100644 index 15a1b915..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/CheckUtils.java +++ /dev/null @@ -1,354 +0,0 @@ -package fr.neatmonster.nocheatplus.checks; - -import net.minecraft.server.Block; - -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.BlockFace; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; - -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * Some stuff that's used by different checks or just too complex to keep - * in other places - * - */ -public class CheckUtils { - - private static final double magic = 0.45D; - - private static final double magic2 = 0.55D; - - private static final int NONSOLID = 1; // 0x00000001 - private static final int SOLID = 2; // 0x00000010 - - // All liquids are "nonsolid" too - private static final int LIQUID = 4 | NONSOLID; // 0x00000101 - // All ladders are "nonsolid" and "solid" too - private static final int LADDER = 8 | NONSOLID | SOLID; // 0x00001011 - - // All fences are solid - fences are treated specially due - // to being 1.5 blocks high - private static final int FENCE = 16 | NONSOLID | SOLID; // 0x00010011 - - // Webs slow players down so they must also be treated specially - private static final int WEB = 32 | NONSOLID | SOLID; - - // We also treat unclimbable vines specially because players - // can't climb them but they slow players down - private static final int VINE = 64 | NONSOLID; - - 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 - // not, this is what I'll do - private static final int types[]; - - static { - types = new int[256]; - - // Find and define properties of all other blocks - for (int i = 0; i < types.length; i++) { - - // Everything unknown is considered nonsolid and solid - types[i] = NONSOLID | SOLID; - - if (Block.byId[i] != null) - if (Block.byId[i].material.isSolid()) - // STONE, CAKE, LEAFS, ... - types[i] = SOLID; - else if (Block.byId[i].material.isLiquid()) - // WATER, LAVA, ... - types[i] = LIQUID; - else - // AIR, SAPLINGS, ... - types[i] = NONSOLID; - } - - // Some exceptions where the above method fails - - // du'h - types[Material.AIR.getId()] = NONSOLID; - - // Obvious - types[Material.LADDER.getId()] = LADDER; - types[Material.WATER_LILY.getId()] = LADDER; - // The type VINE is only for unclimbable vines - types[Material.VINE.getId()] = LADDER; - - types[Material.FENCE.getId()] = FENCE; - types[Material.FENCE_GATE.getId()] = FENCE; - types[Material.NETHER_FENCE.getId()] = FENCE; - - types[Material.WEB.getId()] = WEB; - - // These are sometimes solid, sometimes not - types[Material.IRON_FENCE.getId()] = SOLID | NONSOLID; - types[Material.THIN_GLASS.getId()] = SOLID | NONSOLID; - - // Signs are NOT solid, despite the game claiming they are - types[Material.WALL_SIGN.getId()] = NONSOLID; - types[Material.SIGN_POST.getId()] = NONSOLID; - - // (trap)doors can be solid or not - types[Material.WOODEN_DOOR.getId()] = SOLID | NONSOLID; - types[Material.IRON_DOOR_BLOCK.getId()] = SOLID | NONSOLID; - types[Material.TRAP_DOOR.getId()] = SOLID | NONSOLID; - - // repeaters are technically half blocks - types[Material.DIODE_BLOCK_OFF.getId()] = SOLID | NONSOLID; - types[Material.DIODE_BLOCK_ON.getId()] = SOLID | NONSOLID; - - // pressure plates are so slim, you can consider them - // nonsolid too - types[Material.STONE_PLATE.getId()] = SOLID | NONSOLID; - types[Material.WOOD_PLATE.getId()] = SOLID | NONSOLID; - } - - /** - * Check if a player looks at a target of a specific size, with a specific - * precision value (roughly) - */ - public static double directionCheck(final NCPPlayer player, final double targetX, final double targetY, - final double targetZ, final double targetWidth, final double targetHeight, final double precision) { - - // Eye location of the player - final Location eyes = player.getBukkitPlayer().getEyeLocation(); - - final double factor = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2) - + Math.pow(eyes.getZ() - targetZ, 2)); - - // View direction of the player - final Vector direction = eyes.getDirection(); - - final double x = targetX - eyes.getX(); - final double y = targetY - eyes.getY(); - final double z = targetZ - eyes.getZ(); - - final double xPrediction = factor * direction.getX(); - final double yPrediction = factor * direction.getY(); - final double zPrediction = factor * direction.getZ(); - - double off = 0.0D; - - off += Math.max(Math.abs(x - xPrediction) - (targetWidth / 2 + precision), 0.0D); - off += Math.max(Math.abs(z - zPrediction) - (targetWidth / 2 + precision), 0.0D); - off += Math.max(Math.abs(y - yPrediction) - (targetHeight / 2 + precision), 0.0D); - - if (off > 1) - off = Math.sqrt(off); - - return off; - } - - /** - * Ask NoCheatPlus what it thinks about a certain location. - * Is it a place where a player can safely stand, should - * it be considered as being inside a liquid etc. - * - * @param world - * The world the coordinates belong to - * @param location - * The precise location in the world - * - * @return - */ - public static int evaluateLocation(final World world, final PreciseLocation location) { - - final int lowerX = lowerBorder(location.x); - final int upperX = upperBorder(location.x); - final int Y = (int) location.y; - final int lowerZ = lowerBorder(location.z); - final int upperZ = upperBorder(location.z); - - // Check the four borders of the players hitbox for something he could - // be standing on, and combine the results - int result = 0; - - result |= evaluateSimpleLocation(world, lowerX, Y, lowerZ); - result |= evaluateSimpleLocation(world, upperX, Y, lowerZ); - result |= evaluateSimpleLocation(world, upperX, Y, upperZ); - result |= evaluateSimpleLocation(world, lowerX, Y, upperZ); - - if (!isInGround(result)) - // Original location: X, Z (allow standing in walls this time) - if (isSolid(getType(world, Location.locToBlock(location.x), Location.locToBlock(location.y), - Location.locToBlock(location.z)))) - result |= INGROUND; - - return result; - } - - /** - * Evaluate a location by only looking at a specific - * "column" of the map to find out if that "column" - * would allow a player to stand, swim etc. there - * - * @param world - * @param x - * @param y - * @param z - * @return Returns INGROUND, ONGROUND, LIQUID, combination of the three or 0 - */ - private static int evaluateSimpleLocation(final World world, final int x, final int y, final int z) { - - // First we need to know about the block itself, the block - // below it and the block above it - final int top = getType(world, x, y + 1, z); - final int base = getType(world, x, y, z); - final int below = getType(world, x, y - 1, z); - - int type = 0; - // Special case: Standing on a fence - // Behave as if there is a block on top of the fence - if (below == FENCE && base != FENCE && isNonSolid(top)) - type = INGROUND; - else if (below != FENCE && isNonSolid(base) && getType(world, x, y - 2, z) == FENCE) - type = ONGROUND; - else if (isNonSolid(top)) - // Simplest (and most likely) case: - // Below the player is a solid block - if (isSolid(below) && isNonSolid(base)) - type = ONGROUND; - else if (isLadder(base) || isLadder(top)) - type = ONGROUND; - else if (isSolid(base)) - type = INGROUND; - - // (In every case, check for water...) - if (isLiquid(base) || isLiquid(top)) - type |= LIQUID | INGROUND; - // (...and for web...) - if (isWeb(base) || isWeb(top)) - type |= WEB; - // (...and for vine) - if (isVine(base)) - type |= VINE; - - return type; - } - - public static int getType(final int typeId) { - return types[typeId]; - } - - private static int getType(final World world, final int x, final int y, final int z) { - if (world.getBlockAt(x, y, z).getType() == Material.VINE && !isClimbable(world, x, y, z)) - return VINE; - return types[world.getBlockTypeIdAt(x, y, z)]; - } - - public static boolean isClimbable(final World world, final int x, final int y, final int z) { - BlockFace attachedFace = null; - if (world.getBlockAt(x, y, z).getData() == 0x1) - attachedFace = BlockFace.WEST; - else if (world.getBlockAt(x, y, z).getData() == 0x2) - attachedFace = BlockFace.NORTH; - else if (world.getBlockAt(x, y, z).getData() == 0x4) - attachedFace = BlockFace.EAST; - else if (world.getBlockAt(x, y, z).getData() == 0x8) - attachedFace = BlockFace.SOUTH; - if (attachedFace == null) - return true; - return isSolid(getType(world.getBlockAt(x, y, z).getRelative(attachedFace).getTypeId())); - } - - public static boolean isFood(final ItemStack item) { - if (item == null) - return false; - return item.getType().isEdible(); - } - - public static boolean isInGround(final int fromType) { - return (fromType & INGROUND) == INGROUND; - } - - public static boolean isLadder(final int value) { - return (value & LADDER) == LADDER; - } - - public static boolean isLiquid(final int value) { - return (value & LIQUID) == LIQUID; - } - - private static boolean isNonSolid(final int value) { - return (value & NONSOLID) == NONSOLID; - } - - public static boolean isOnGround(final int fromType) { - return (fromType & ONGROUND) == ONGROUND; - } - - public static boolean isSolid(final int value) { - return (value & SOLID) == SOLID; - } - - public static boolean isVine(final int value) { - return (value & VINE) == VINE; - } - - public static boolean isWeb(final int value) { - return (value & WEB) == WEB; - } - - /** - * Personal Rounding function to determine if a player is still touching a - * block or not - * - * @param d1 - * @return - */ - private static int lowerBorder(final double d1) { - - final double floor = Math.floor(d1); - - if (floor + magic <= d1) - return (int) floor; - else - return (int) (floor - 1); - } - - /** - * Check if a player is close enough to a target, based on his eye location - * - * @param player - * @param targetX - * @param targetY - * @param targetZ - * @param limit - * @return - */ - public static double reachCheck(final NCPPlayer player, final double targetX, final double targetY, - final double targetZ, final double limit) { - - final Location eyes = player.getBukkitPlayer().getEyeLocation(); - - final double distance = Math.sqrt(Math.pow(eyes.getX() - targetX, 2) + Math.pow(eyes.getY() - targetY, 2) - + Math.pow(eyes.getZ() - targetZ, 2)); - - return Math.max(distance - limit, 0.0D); - } - - /** - * Personal Rounding function to determine if a player is still touching a - * block or not - * - * @param d1 - * @return - */ - private static int upperBorder(final double d1) { - - final double floor = Math.floor(d1); - - if (floor + magic2 < d1) - return (int) (floor + 1); - else - return (int) floor; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/Workarounds.java b/src/fr/neatmonster/nocheatplus/checks/Workarounds.java new file mode 100644 index 00000000..b28568f8 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/Workarounds.java @@ -0,0 +1,76 @@ +package fr.neatmonster.nocheatplus.checks; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerToggleSprintEvent; + +/* + * M""MMM""MMM""M dP dP + * M MMM MMM M 88 88 + * M MMP MMP M .d8888b. 88d888b. 88 .dP .d8888b. 88d888b. .d8888b. dP dP 88d888b. .d888b88 .d8888b. + * M MM' MM' .M 88' `88 88' `88 88888" 88' `88 88' `88 88' `88 88 88 88' `88 88' `88 Y8ooooo. + * M `' . '' .MM 88. .88 88 88 `8b. 88. .88 88 88. .88 88. .88 88 88 88. .88 88 + * M .d .dMMM `88888P' dP dP `YP `88888P8 dP `88888P' `88888P' dP dP `88888P8 `88888P' + * MMMMMMMMMMMMMM + */ +/** + * Only place that listens to player-teleport related events and dispatches them to relevant checks. + */ +public class Workarounds implements Listener { + + /** + * A listener listening to PlayerMoveEvents. + * + * @param event + * the event + */ + @EventHandler( + priority = EventPriority.HIGHEST) + public void onPlayerMove(final PlayerMoveEvent event) { + /* + * _____ _ __ __ + * | __ \| | | \/ | + * | |__) | | __ _ _ _ ___ _ __ | \ / | _____ _____ + * | ___/| |/ _` | | | |/ _ \ '__| | |\/| |/ _ \ \ / / _ \ + * | | | | (_| | |_| | __/ | | | | | (_) \ V / __/ + * |_| |_|\__,_|\__, |\___|_| |_| |_|\___/ \_/ \___| + * __/ | + * |___/ + */ + // No typo here. I really only handle cancelled events and ignore others. + if (!event.isCancelled()) + return; + + // Fix a common mistake that other developers make (cancelling move events is crazy, rather set the target + // location to the from location). + event.setCancelled(false); + event.setTo(event.getFrom().clone()); + } + + /** + * A listener listening to PlayerToggleSprintEvents. + * + * @param event + * the event + */ + @EventHandler( + priority = EventPriority.HIGHEST) + public void onPlayerToggleSprint(final PlayerToggleSprintEvent event) { + /* + * _____ _ _______ _ _____ _ _ + * | __ \| | |__ __| | | / ____| (_) | | + * | |__) | | __ _ _ _ ___ _ __ | | ___ __ _ __ _| | ___ | (___ _ __ _ __ _ _ __ | |_ + * | ___/| |/ _` | | | |/ _ \ '__| | |/ _ \ / _` |/ _` | |/ _ \ \___ \| '_ \| '__| | '_ \| __| + * | | | | (_| | |_| | __/ | | | (_) | (_| | (_| | | __/ ____) | |_) | | | | | | | |_ + * |_| |_|\__,_|\__, |\___|_| |_|\___/ \__, |\__, |_|\___| |_____/| .__/|_| |_|_| |_|\__| + * __/ | __/ | __/ | | | + * |___/ |___/ |___/ |_| + */ + // Some plugins cancel "sprinting", which makes no sense at all because it doesn't stop people from sprinting + // and rewards them by reducing their hunger bar as if they were walking instead of sprinting. + if (event.isCancelled() && event.isSprinting()) + event.setCancelled(false); + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/WorkaroundsListener.java b/src/fr/neatmonster/nocheatplus/checks/WorkaroundsListener.java deleted file mode 100644 index a1a68b98..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/WorkaroundsListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package fr.neatmonster.nocheatplus.checks; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerToggleSprintEvent; - -/** - * Only place that listens to Player-teleport related events and dispatches them - * to relevant checks - * - */ -public class WorkaroundsListener implements Listener { - - @EventHandler( - priority = EventPriority.HIGHEST) - public void playerMove(final PlayerMoveEvent event) { - // No typo here. I really only handle cancelled events and ignore others - if (!event.isCancelled()) - return; - - // Fix a common mistake that other developers make (cancelling move - // events is crazy, rather set the target location to the from location) - event.setCancelled(false); - event.setTo(event.getFrom().clone()); - } - - @EventHandler( - priority = EventPriority.HIGHEST) - public void toggleSprint(final PlayerToggleSprintEvent event) { - // Some plugins cancel "sprinting", which makes no sense at all because - // it doesn't stop people from sprinting and rewards them by reducing - // their hunger bar as if they were walking instead of sprinting - if (event.isCancelled() && event.isSprinting()) - event.setCancelled(false); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakCheck.java deleted file mode 100644 index 33ca567a..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakCheck.java +++ /dev/null @@ -1,24 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockbreak; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * Abstract base class for BlockBreakChecks. - */ -public abstract class BlockBreakCheck extends Check { - - public BlockBreakCheck(final String name) { - super("blockbreak." + name, BlockBreakConfig.class, BlockBreakData.class); - } - - public abstract boolean check(final NCPPlayer player, final Object... args); - - public BlockBreakConfig getConfig(final NCPPlayer player) { - return (BlockBreakConfig) player.getConfig(this); - } - - public BlockBreakData getData(final NCPPlayer player) { - return (BlockBreakData) player.getData(this); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakConfig.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakConfig.java index 4f8f4ee7..7e09b67d 100644 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakConfig.java @@ -1,50 +1,97 @@ package fr.neatmonster.nocheatplus.checks.blockbreak; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.entity.Player; + import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckConfig; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; -import fr.neatmonster.nocheatplus.players.informations.Permissions; +import fr.neatmonster.nocheatplus.config.ConfigManager; +import fr.neatmonster.nocheatplus.players.Permissions; -/** - * Configurations specific for the "BlockBreak" checks - * Every world gets one of these assigned to it, or if a world doesn't get - * it's own, it will use the "global" version +/* + * M#"""""""'M dP dP M#"""""""'M dP + * ## mmmm. `M 88 88 ## mmmm. `M 88 + * #' .M 88 .d8888b. .d8888b. 88 .dP #' .M 88d888b. .d8888b. .d8888b. 88 .dP + * M# MMMb.'YM 88 88' `88 88' `"" 88888" M# MMMb.'YM 88' `88 88ooood8 88' `88 88888" + * M# MMMM' M 88 88. .88 88. ... 88 `8b. M# MMMM' M 88 88. ... 88. .88 88 `8b. + * M# .;M dP `88888P' `88888P' dP `YP M# .;M dP `88888P' `88888P8 dP `YP + * M#########M M#########M * + * MM'""""'YMM .8888b oo + * M' .mmm. `M 88 " + * M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. + * M MMMMMMMM 88' `88 88' `88 88 88 88' `88 + * M. `MMM' .M 88. .88 88 88 88 88 88. .88 + * MM. .dM `88888P' dP dP dP dP `8888P88 + * MMMMMMMMMMM .88 + * d8888P */ -public class BlockBreakConfig extends CheckConfig { +/** + * Configurations specific for the block break checks. Every world gets one of these assigned to it, or if a world + * doesn't get it's own, it will use the "global" version. + */ +public class BlockBreakConfig { - public final boolean fastBreakCheck; - public final int fastBreakIntervalSurvival; - public final int fastBreakIntervalCreative; - public final ActionList fastBreakActions; + /** The map containing the configurations per world. */ + private static Map worldsMap = new HashMap(); - public final boolean reachCheck; - public final double reachDistance; - public final ActionList reachActions; + /** + * Clear all the configurations. + */ + public static void clear() { + worldsMap.clear(); + } + + /** + * Gets the configuration for a specified player. + * + * @param player + * the player + * @return the configuration + */ + public static BlockBreakConfig getConfig(final Player player) { + if (!worldsMap.containsKey(player.getWorld().getName())) + worldsMap.put(player.getWorld().getName(), + new BlockBreakConfig(ConfigManager.getConfigFile(player.getWorld().getName()))); + return worldsMap.get(player.getWorld().getName()); + } public final boolean directionCheck; public final ActionList directionActions; - public final double directionPrecision; - public final long directionPenaltyTime; - public final boolean noswingCheck; - public final ActionList noswingActions; + public final boolean fastBreakCheck; + public final boolean fastBreakExperimental; + public final int fastBreakInterval; + public final ActionList fastBreakActions; + public final boolean noSwingCheck; + public final ActionList noSwingActions; + + public final boolean reachCheck; + public final ActionList reachActions; + + /** + * Instantiates a new block break configuration. + * + * @param data + * the data + */ public BlockBreakConfig(final ConfigFile data) { + directionCheck = data.getBoolean(ConfPaths.BLOCKBREAK_DIRECTION_CHECK); + directionActions = data.getActionList(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, Permissions.BLOCKBREAK_DIRECTION); fastBreakCheck = data.getBoolean(ConfPaths.BLOCKBREAK_FASTBREAK_CHECK); - fastBreakIntervalSurvival = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVALSURVIVAL); - fastBreakIntervalCreative = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVALCREATIVE); + fastBreakExperimental = data.getBoolean(ConfPaths.BLOCKBREAK_FASTBREAK_EXPERIMENTAL); + fastBreakInterval = data.getInt(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVAL); fastBreakActions = data.getActionList(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, Permissions.BLOCKBREAK_FASTBREAK); + + noSwingCheck = data.getBoolean(ConfPaths.BLOCKBREAK_NOSWING_CHECK); + noSwingActions = data.getActionList(ConfPaths.BLOCKBREAK_NOSWING_ACTIONS, Permissions.BLOCKBREAK_NOSWING); + reachCheck = data.getBoolean(ConfPaths.BLOCKBREAK_REACH_CHECK); - reachDistance = 535D / 100D; reachActions = data.getActionList(ConfPaths.BLOCKBREAK_REACH_ACTIONS, Permissions.BLOCKBREAK_REACH); - directionCheck = data.getBoolean(ConfPaths.BLOCKBREAK_DIRECTION_CHECK); - directionPrecision = data.getInt(ConfPaths.BLOCKBREAK_DIRECTION_PRECISION) / 100D; - directionPenaltyTime = data.getInt(ConfPaths.BLOCKBREAK_DIRECTION_PENALTYTIME); - directionActions = data.getActionList(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, Permissions.BLOCKBREAK_DIRECTION); - noswingCheck = data.getBoolean(ConfPaths.BLOCKBREAK_NOSWING_CHECK); - noswingActions = data.getActionList(ConfPaths.BLOCKBREAK_NOSWING_ACTIONS, Permissions.BLOCKBREAK_NOSWING); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java index ca547ade..03efdcb5 100644 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakData.java @@ -1,40 +1,62 @@ package fr.neatmonster.nocheatplus.checks.blockbreak; -import fr.neatmonster.nocheatplus.checks.CheckData; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; +import java.util.HashMap; +import java.util.Map; -/** - * Player specific data for the blockbreak checks +import org.bukkit.entity.Player; + +/* + * M#"""""""'M dP dP M#"""""""'M dP + * ## mmmm. `M 88 88 ## mmmm. `M 88 + * #' .M 88 .d8888b. .d8888b. 88 .dP #' .M 88d888b. .d8888b. .d8888b. 88 .dP + * M# MMMb.'YM 88 88' `88 88' `"" 88888" M# MMMb.'YM 88' `88 88ooood8 88' `88 88888" + * M# MMMM' M 88 88. .88 88. ... 88 `8b. M# MMMM' M 88 88. ... 88. .88 88 `8b. + * M# .;M dP `88888P' `88888P' dP `YP M# .;M dP `88888P' `88888P8 dP `YP + * M#########M M#########M * + * M""""""'YMM dP + * M mmmm. `M 88 + * M MMMMM M .d8888b. d8888P .d8888b. + * M MMMMM M 88' `88 88 88' `88 + * M MMMM' .M 88. .88 88 88. .88 + * M .MM `88888P8 dP `88888P8 + * MMMMMMMMMMM */ -public class BlockBreakData extends CheckData { +/** + * Player specific data for the block break checks. + */ +public class BlockBreakData { - // Keep track of violation levels for the three checks - public double fastBreakVL = 0.0D; - public double reachVL = 0.0D; - public double directionVL = 0.0D; - public double noswingVL = 0.0D; + /** The map containing the data per players. */ + private static Map playersMap = new HashMap(); - // Used to know when the player has broken his previous block - public long lastBreakTime = 0; + /** + * Gets the data of a specified player. + * + * @param player + * the player + * @return the data + */ + public static BlockBreakData getData(final Player player) { + if (!playersMap.containsKey(player.getName())) + playersMap.put(player.getName(), new BlockBreakData()); + return playersMap.get(player.getName()); + } - // Used to know if the previous event was refused - public boolean previousRefused = false; + // Violation levels. + public double directionVL; + public double fastBreakVL; + public double noSwingVL; + public double reachVL; - // Used for the penalty time feature of the direction check - public long directionLastViolationTime = 0; + // Data of the fast break check. + public int fastBreakBuffer = 3; + public long fastBreakBreakTime = System.currentTimeMillis() - 1000L; + public long fastBreakDamageTime = System.currentTimeMillis(); - // Have a nicer/simpler way to work with block locations instead of - // Bukkits own "Location" class - public final SimpleLocation instaBrokenBlockLocation = new SimpleLocation(); - public final SimpleLocation brokenBlockLocation = new SimpleLocation(); - public final SimpleLocation lastDamagedBlock = new SimpleLocation(); - - // indicate if the player swung his arm since he got checked last time - public boolean armswung = true; - - // For logging, remember the reachDistance that was calculated in the - // reach check - public double reachDistance; + // Data of the no swing check. + public boolean noSwingArmSwung; + // Data of the reach check. + public double reachDistance; } diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakEvent.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakEvent.java deleted file mode 100644 index 1da83225..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockbreak; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckEvent; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public class BlockBreakEvent extends CheckEvent { - - public BlockBreakEvent(final BlockBreakCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - - @Override - public BlockBreakCheck getCheck() { - return (BlockBreakCheck) super.getCheck(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakListener.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakListener.java index 674a0c8a..9d489b47 100644 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/BlockBreakListener.java @@ -1,144 +1,139 @@ package fr.neatmonster.nocheatplus.checks.blockbreak; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.BlockDamageEvent; import org.bukkit.event.player.PlayerAnimationEvent; import org.bukkit.event.player.PlayerInteractEvent; -import fr.neatmonster.nocheatplus.checks.CheckListener; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Central location to listen to events that are - * relevant for the blockbreak checks +/* + * M#"""""""'M dP dP M#"""""""'M dP + * ## mmmm. `M 88 88 ## mmmm. `M 88 + * #' .M 88 .d8888b. .d8888b. 88 .dP #' .M 88d888b. .d8888b. .d8888b. 88 .dP + * M# MMMb.'YM 88 88' `88 88' `"" 88888" M# MMMb.'YM 88' `88 88ooood8 88' `88 88888" + * M# MMMM' M 88 88. .88 88. ... 88 `8b. M# MMMM' M 88 88. ... 88. .88 88 `8b. + * M# .;M dP `88888P' `88888P' dP `YP M# .;M dP `88888P' `88888P8 dP `YP + * M#########M M#########M * + * M""MMMMMMMM oo dP + * M MMMMMMMM 88 + * M MMMMMMMM dP .d8888b. d8888P .d8888b. 88d888b. .d8888b. 88d888b. + * M MMMMMMMM 88 Y8ooooo. 88 88ooood8 88' `88 88ooood8 88' `88 + * M MMMMMMMM 88 88 88 88. ... 88 88 88. ... 88 + * M M dP `88888P' dP `88888P' dP dP `88888P' dP + * MMMMMMMMMMM */ -public class BlockBreakListener extends CheckListener { +/** + * Central location to listen to events that are relevant for the block break checks. + * + * @see BlockBreakEvent + */ +public class BlockBreakListener implements Listener { - private final FastBreakCheck fastBreakCheck; - private final NoswingCheck noswingCheck; - private final ReachCheck reachCheck; - private final DirectionCheck directionCheck; + /** The direction check. */ + private final Direction direction = new Direction(); - public BlockBreakListener() { - super("blockbreak"); + /** The fast break check. */ + private final FastBreak fastBreak = new FastBreak(); - fastBreakCheck = new FastBreakCheck(); - noswingCheck = new NoswingCheck(); - reachCheck = new ReachCheck(); - directionCheck = new DirectionCheck(); - } + /** The no swing check. */ + private final NoSwing noSwing = new NoSwing(); + + /** The reach check. */ + private final Reach reach = new Reach(); /** - * We listen to PlayerAnimationEvent because it is (currently) equivalent - * to "player swings arm" and we want to check if he did that between - * blockbreaks. + * We listen to BlockBreak events for obvious reasons. * * @param event - * The PlayerAnimation Event - */ - @EventHandler( - priority = EventPriority.MONITOR) - public void armSwing(final PlayerAnimationEvent event) { - // Just set a flag to true when the arm was swung - ((BlockBreakData) getData(NCPPlayer.getPlayer(event.getPlayer()))).armswung = true; - } - - /** - * We listen to blockBreak events for obvious reasons - * - * @param event - * The blockbreak event + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.LOWEST) - public void blockBreak(final BlockBreakEvent event) { - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final BlockBreakConfig cc = (BlockBreakConfig) getConfig(player); - final BlockBreakData data = (BlockBreakData) getData(player); + public void onBlockBreak(final BlockBreakEvent event) { + /* + * ____ _ _ ____ _ + * | __ )| | ___ ___| | __ | __ ) _ __ ___ __ _| | __ + * | _ \| |/ _ \ / __| |/ / | _ \| '__/ _ \/ _` | |/ / + * | |_) | | (_) | (__| < | |_) | | | __/ (_| | < + * |____/|_|\___/ \___|_|\_\ |____/|_| \___|\__,_|_|\_\ + */ + final Player player = event.getPlayer(); + final Block block = event.getBlock(); boolean cancelled = false; - // Remember the location of the block that will be broken - data.brokenBlockLocation.set(event.getBlock()); + // Do the actual checks, if still needed. It's a good idea to make computationally cheap checks first, because + // it may save us from doing the computationally expensive checks. - // Only if the block got damaged directly before, do the check(s) - if (!data.brokenBlockLocation.equals(data.lastDamagedBlock)) { - // Something caused a blockbreak event that's not from the player - // Don't check it at all - data.lastDamagedBlock.reset(); - return; - } + // Has the player broken blocks too quickly? + if (fastBreak.isEnabled(player)) + cancelled = fastBreak.check(player, block); - // Now do the actual checks, if still needed. It's a good idea to make - // computationally cheap checks first, because it may save us from - // doing the computationally expensive checks. + // Did the arm of the player move before breaking this block? + if (!cancelled && noSwing.isEnabled(player)) + cancelled = noSwing.check(player); - // First FastPlace: Has the player broken blocks too quickly? - if (cc.fastBreakCheck && !player.hasPermission(Permissions.BLOCKBREAK_FASTBREAK)) - cancelled = fastBreakCheck.check(player); + // Is the block really in reach distance? + if (!cancelled && reach.isEnabled(player)) + cancelled = reach.check(player, block.getLocation()); - // Second NoSwing: Did the arm of the player move before breaking this - // block? - if (!cancelled && cc.noswingCheck && !player.hasPermission(Permissions.BLOCKBREAK_NOSWING)) - cancelled = noswingCheck.check(player); + // Did the player look at the block at all? + if (!cancelled && direction.isEnabled(player)) + cancelled = direction.check(player, block.getLocation()); - // Third Reach: Is the block really in reach distance - if (!cancelled && cc.reachCheck && !player.hasPermission(Permissions.BLOCKBREAK_REACH)) - cancelled = reachCheck.check(player); - - // Forth Direction: Did the player look at the block at all - if (!cancelled && cc.directionCheck && !player.hasPermission(Permissions.BLOCKBREAK_DIRECTION)) - cancelled = directionCheck.check(player); - - // At least one check failed and demanded to cancel the event + // At least one check failed and demanded to cancel the event. if (cancelled) event.setCancelled(cancelled); } /** - * We listen to BlockDamage events to grab the information if it has been - * an "insta-break". That info may come in handy later. + * We listen to PlayerAnimation events because it is (currently) equivalent to "player swings arm" and we want to + * check if he did that between block breaks. * * @param event - * The BlockDamage event + * the event */ @EventHandler( - ignoreCancelled = true, priority = EventPriority.MONITOR) - public void blockHit(final BlockDamageEvent event) { - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final BlockBreakData data = (BlockBreakData) getData(player); - - // Only interested in insta-break events here - if (event.getInstaBreak()) - // Remember this location. We handle insta-breaks slightly - // different in some of the blockbreak checks. - data.instaBrokenBlockLocation.set(event.getBlock()); + priority = EventPriority.MONITOR) + public void onPlayerAnimation(final PlayerAnimationEvent event) { + /* + * ____ _ _ _ _ _ + * | _ \| | __ _ _ _ ___ _ __ / \ _ __ (_)_ __ ___ __ _| |_(_) ___ _ __ + * | |_) | |/ _` | | | |/ _ \ '__| / _ \ | '_ \| | '_ ` _ \ / _` | __| |/ _ \| '_ \ + * | __/| | (_| | |_| | __/ | / ___ \| | | | | | | | | | (_| | |_| | (_) | | | | + * |_| |_|\__,_|\__, |\___|_| /_/ \_\_| |_|_|_| |_| |_|\__,_|\__|_|\___/|_| |_| + * |___/ + */ + // Just set a flag to true when the arm was swung. + BlockBreakData.getData(event.getPlayer()).noSwingArmSwung = true; } /** - * We listen to BlockInteract events to be (at least in many cases) able - * to distinguish between blockbreak events that were triggered by players - * actually digging and events that were artificially created by plugins. + * We listen to BlockInteract events to be (at least in many cases) able to distinguish between block break events + * that were triggered by players actually digging and events that were artificially created by plugins. * * @param event + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.MONITOR) - public void blockInteract(final PlayerInteractEvent event) { - - // Do not care about null blocks + public void onPlayerInteract(final PlayerInteractEvent event) { + /* + * ____ _ ___ _ _ + * | _ \| | __ _ _ _ ___ _ __ |_ _|_ __ | |_ ___ _ __ __ _ ___| |_ + * | |_) | |/ _` | | | |/ _ \ '__| | || '_ \| __/ _ \ '__/ _` |/ __| __| + * | __/| | (_| | |_| | __/ | | || | | | || __/ | | (_| | (__| |_ + * |_| |_|\__,_|\__, |\___|_| |___|_| |_|\__\___|_| \__,_|\___|\__| + * |___/ + */ + // Do not care about null blocks. if (event.getClickedBlock() == null) return; - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final BlockBreakData data = (BlockBreakData) getData(player); - - // Remember this location. Only blockbreakevents for this specific - // block will be handled at all - data.lastDamagedBlock.set(event.getClickedBlock()); + BlockBreakData.getData(event.getPlayer()).fastBreakDamageTime = System.currentTimeMillis(); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/Direction.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/Direction.java new file mode 100644 index 00000000..59205c13 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/Direction.java @@ -0,0 +1,104 @@ +package fr.neatmonster.nocheatplus.checks.blockbreak; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.CheckUtils; + +/* + * M""""""'YMM oo dP oo + * M mmmm. `M 88 + * M MMMMM M dP 88d888b. .d8888b. .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMM M 88 88' `88 88ooood8 88' `"" 88 88 88' `88 88' `88 + * M MMMM' .M 88 88 88. ... 88. ... 88 88 88. .88 88 88 + * M .MM dP dP `88888P' `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMM + */ +/** + * The Direction check will find out if a player tried to interact with something that's not in his field of view. + */ +public class Direction extends Check { + + /** + * The event triggered by this check. + */ + public class DirectionEvent extends CheckEvent { + + /** + * Instantiates a new direction event. + * + * @param player + * the player + */ + public DirectionEvent(final Player player) { + super(player); + } + } + + private final double OFFSET = 0.5D; + + /** + * Checks a player. + * + * @param player + * the player + * @param location + * the location + * @return true, if successful + */ + public boolean check(final Player player, final Location location) { + final BlockBreakConfig cc = BlockBreakConfig.getConfig(player); + final BlockBreakData data = BlockBreakData.getData(player); + + boolean cancel = false; + + if (!CheckUtils.intersects(player, location, OFFSET)) { + // Player failed the check. Let's try to guess how far he was from looking directly to the block... + final Vector direction = player.getEyeLocation().getDirection(); + final Vector blockEyes = location.add(0.5D, 0.5D, 0.5D).subtract(player.getEyeLocation()).toVector(); + final double distance = blockEyes.crossProduct(direction).length() / direction.length(); + + // Add the overall violation level of the check. + data.directionVL += distance; + + // Dispatch a direction event (API). + final DirectionEvent e = new DirectionEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + if (!e.isCancelled() && executeActions(player, cc.directionActions, data.directionVL)) + cancel = true; + } else + // Player did likely nothing wrong, reduce violation counter to reward him. + data.directionVL *= 0.9D; + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockBreakData.getData(player).directionVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKBREAK_DIRECTION) + && BlockBreakConfig.getConfig(player).directionCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/DirectionCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/DirectionCheck.java deleted file mode 100644 index 6dd4e14e..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/DirectionCheck.java +++ /dev/null @@ -1,106 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockbreak; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * The DirectionCheck will find out if a player tried to interact with something - * that's not in his field of view. - * - */ -public class DirectionCheck extends BlockBreakCheck { - - public class DirectionCheckEvent extends BlockBreakEvent { - - public DirectionCheckEvent(final DirectionCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public DirectionCheck() { - super("direction"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final BlockBreakConfig cc = getConfig(player); - final BlockBreakData data = getData(player); - - final SimpleLocation brokenBlock = data.brokenBlockLocation; - - boolean cancel = false; - - // How far "off" is the player with his aim. We calculate from the - // players eye location and view direction to the center of the target - // block. If the line of sight is more too far off, "off" will be - // bigger than 0 - double off = CheckUtils.directionCheck(player, brokenBlock.x + 0.5D, brokenBlock.y + 0.5D, - brokenBlock.z + 0.5D, 1D, 1D, cc.directionPrecision); - - final long time = System.currentTimeMillis(); - - if (off < 0.1D) - // Player did likely nothing wrong - // reduce violation counter to reward him - data.directionVL *= 0.9D; - else { - // Player failed the check - // Increment violation counter - if (data.instaBrokenBlockLocation.equals(brokenBlock)) - // Instabreak block failures are very common, so don't be as - // hard on people failing them - off /= 5; - - // Add to the overall violation level of the check and add to - // statistics - data.directionVL += off; - incrementStatistics(player, Id.BB_DIRECTION, off); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.directionActions, data.directionVL); - - if (cancel) - // if we should cancel, remember the current time too - data.directionLastViolationTime = time; - } - - // If the player is still in penalty time, cancel the event anyway - if (data.directionLastViolationTime + cc.directionPenaltyTime > time) { - // A saveguard to avoid people getting stuck in penalty time - // indefinitely in case the system time of the server gets changed - if (data.directionLastViolationTime > time) - data.directionLastViolationTime = 0; - - // He is in penalty time, therefore request cancelling of the event - return true; - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final DirectionCheckEvent event = new DirectionCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(getData(player).directionVL); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreak.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreak.java new file mode 100644 index 00000000..a8fb3eab --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreak.java @@ -0,0 +1,131 @@ +package fr.neatmonster.nocheatplus.checks.blockbreak; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * MM""""""""`M dP M#"""""""'M dP + * MM mmmmmmmM 88 ## mmmm. `M 88 + * M' MMMM .d8888b. .d8888b. d8888P #' .M 88d888b. .d8888b. .d8888b. 88 .dP + * MM MMMMMMMM 88' `88 Y8ooooo. 88 M# MMMb.'YM 88' `88 88ooood8 88' `88 88888" + * MM MMMMMMMM 88. .88 88 88 M# MMMM' M 88 88. ... 88. .88 88 `8b. + * MM MMMMMMMM `88888P8 `88888P' dP M# .;M dP `88888P' `88888P8 dP `YP + * MMMMMMMMMMMM M#########M + */ +/** + * A check used to verify if the player isn't breaking his blocks too quickly. + */ +public class FastBreak extends Check { + + /** + * The event triggered by this check. + */ + public class FastBreakEvent extends CheckEvent { + + /** + * Instantiates a new fast break event. + * + * @param player + * the player + */ + public FastBreakEvent(final Player player) { + super(player); + } + } + + /** The minimum time that needs to be elapsed between two block breaks for a player in creative mode. */ + private static final long CREATIVE = 145L; + + /** The minimum time that needs to be elapsed between two block breaks for a player in survival mode. */ + private static final long SURVIVAL = 45L; + + /** The multiplicative constant used when incrementing the limit. */ + private static final int TOLERANCE = 10; + + /** + * Checks a player. + * + * @param player + * the player + * @param block + * the block + * @return true, if successful + */ + public boolean check(final Player player, final Block block) { + final BlockBreakConfig cc = BlockBreakConfig.getConfig(player); + final BlockBreakData data = BlockBreakData.getData(player); + + boolean cancel = false; + + // First, check the game mode of the player and choose the right limit. + long timeLimit = Math.round(cc.fastBreakInterval / 100D * SURVIVAL); + if (player.getGameMode() == GameMode.CREATIVE) + timeLimit = Math.round(cc.fastBreakInterval / 100D * CREATIVE); + + // This is the experimental mode (incrementing the limit according to the violation level). + long elapsedTimeLimit = timeLimit; + if (cc.fastBreakExperimental) + elapsedTimeLimit = Math.min(timeLimit + Math.round(data.fastBreakVL / TOLERANCE), CREATIVE); + + // The elapsed time is the difference between the last damage time and the last break time. + final long elapsedTime = data.fastBreakDamageTime - data.fastBreakBreakTime; + if (elapsedTime < elapsedTimeLimit && data.fastBreakBreakTime > 0L && data.fastBreakDamageTime > 0L + && (player.getItemInHand().getType() != Material.SHEARS || block.getType() != Material.LEAVES)) { + // If the buffer has been consumed. + if (data.fastBreakBuffer == 0) { + // Increment the violation level (but using the original limit). + data.fastBreakVL += Math.max(timeLimit - elapsedTime, 0D); + + // Dispatch a new fast break event (API). + final FastBreakEvent e = new FastBreakEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Cancel the event if needed. + cancel = !e.isCancelled() && executeActions(player, cc.fastBreakActions, data.fastBreakVL); + } else + // Remove one from the buffer. + data.fastBreakBuffer--; + } else { + // If the buffer isn't full. + if (data.fastBreakBuffer < 3) + // Add one to the buffer. + data.fastBreakBuffer++; + + // Reduce the violation level, the player was nice with blocks. + data.fastBreakVL *= 0.9D; + } + + // Remember the block breaking time. + data.fastBreakBreakTime = System.currentTimeMillis(); + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockBreakData.getData(player).fastBreakVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKBREAK_FASTBREAK) + && BlockBreakConfig.getConfig(player).fastBreakCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreakCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreakCheck.java deleted file mode 100644 index fa2c98c9..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreakCheck.java +++ /dev/null @@ -1,95 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockbreak; - -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * A check used to verify if the player isn't placing his blocks too quickly - * - */ -public class FastBreakCheck extends BlockBreakCheck { - - public class FastBreakCheckEvent extends BlockBreakEvent { - - public FastBreakCheckEvent(final FastBreakCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public FastBreakCheck() { - super("fastbreak"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final BlockBreakConfig cc = getConfig(player); - final BlockBreakData data = getData(player); - - // Get the minimum break time for the player's game mode - int breakTime = cc.fastBreakIntervalSurvival; - if (player.getBukkitPlayer().getGameMode() == GameMode.CREATIVE) - breakTime = cc.fastBreakIntervalCreative; - - // Elapsed time since the previous block was broken - final long elapsedTime = System.currentTimeMillis() - data.lastBreakTime; - - boolean cancel = false; - - // Has the player broken the blocks too quickly - if (data.lastBreakTime != 0 && elapsedTime < breakTime) { - if (!NoCheatPlus.skipCheck()) { - if (data.previousRefused) { - // He failed, increase vl and statistics - data.fastBreakVL += breakTime - elapsedTime; - incrementStatistics(player, Id.BB_FASTBREAK, breakTime - elapsedTime); - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.fastBreakActions, data.fastBreakVL); - } - data.previousRefused = true; - } - } else { - // Reward with lowering of the violation level - data.fastBreakVL *= 0.90D; - data.previousRefused = false; - } - - data.lastBreakTime = System.currentTimeMillis(); - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final FastBreakCheckEvent event = new FastBreakCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).fastBreakVL)); - else if (wildcard == ParameterName.BLOCK_TYPE) { - final SimpleLocation location = getData(player).lastDamagedBlock; - if (location.isSet()) - return new Location(player.getWorld(), location.x, location.y, location.z).getBlock().getType().name() - .toLowerCase().replace("_", " "); - else - return "UNKNOWN"; - } else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/NoSwing.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/NoSwing.java new file mode 100644 index 00000000..eaa30784 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/NoSwing.java @@ -0,0 +1,96 @@ +package fr.neatmonster.nocheatplus.checks.blockbreak; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * M"""""""`YM MP""""""`MM oo + * M mmmm. M M mmmmm..M + * M MMMMM M .d8888b. M. `YM dP dP dP dP 88d888b. .d8888b. + * M MMMMM M 88' `88 MMMMMMM. M 88 88 88 88 88' `88 88' `88 + * M MMMMM M 88. .88 M. .MMM' M 88.88b.88' 88 88 88 88. .88 + * M MMMMM M `88888P' Mb. .dM 8888P Y8P dP dP dP `8888P88 + * MMMMMMMMMMM MMMMMMMMMMM .88 + * d8888P + */ +/** + * We require that the player moves his arm between block breaks, this is what gets checked here. + */ +public class NoSwing extends Check { + + /** + * The event triggered by this check. + */ + public class NoSwingEvent extends CheckEvent { + + /** + * Instantiates a new no swing event. + * + * @param player + * the player + */ + public NoSwingEvent(final Player player) { + super(player); + } + } + + /** + * Checks a player. + * + * @param player + * the player + * @return true, if successful + */ + public boolean check(final Player player) { + final BlockBreakConfig cc = BlockBreakConfig.getConfig(player); + final BlockBreakData data = BlockBreakData.getData(player); + + boolean cancel = false; + + // Did he swing his arm before? + if (data.noSwingArmSwung) { + // "Consume" the flag. + data.noSwingArmSwung = false; + // Reward with lowering of the violation level. + data.noSwingVL *= 0.9D; + } else { + // He failed, increase violation level. + data.noSwingVL += 1D; + + // Dispatch a no swing event (API). + final NoSwingEvent e = new NoSwingEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + cancel = !e.isCancelled() && executeActions(player, cc.noSwingActions, data.noSwingVL); + } + + return cancel; + + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockBreakData.getData(player).noSwingVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKBREAK_NOSWING) && BlockBreakConfig.getConfig(player).noSwingCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/NoswingCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/NoswingCheck.java deleted file mode 100644 index 9a7d8c02..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/NoswingCheck.java +++ /dev/null @@ -1,72 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockbreak; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * We require that the player moves his arm between blockbreaks, this is - * what gets checked here. - * - */ -public class NoswingCheck extends BlockBreakCheck { - - public class NoswingCheckEvent extends BlockBreakEvent { - - public NoswingCheckEvent(final NoswingCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public NoswingCheck() { - super("noswing"); - } - - @Override - public boolean check(final fr.neatmonster.nocheatplus.players.NCPPlayer player, final Object... args) { - final BlockBreakConfig cc = getConfig(player); - final BlockBreakData data = getData(player); - - boolean cancel = false; - - // did he swing his arm before - if (data.armswung) { - // "consume" the flag - data.armswung = false; - // reward with lowering of the violation level - data.noswingVL *= 0.90D; - } else { - // he failed, increase vl and statistics - data.noswingVL += 1; - incrementStatistics(player, Id.BB_NOSWING, 1); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.noswingActions, data.noswingVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final NoswingCheckEvent event = new NoswingCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).noswingVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/Reach.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/Reach.java new file mode 100644 index 00000000..d43e786c --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockbreak/Reach.java @@ -0,0 +1,105 @@ +package fr.neatmonster.nocheatplus.checks.blockbreak; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.CheckUtils; + +/* + * MM"""""""`MM dP + * MM mmmm, M 88 + * M' .M .d8888b. .d8888b. .d8888b. 88d888b. + * MM MMMb. "M 88ooood8 88' `88 88' `"" 88' `88 + * MM MMMMM M 88. ... 88. .88 88. ... 88 88 + * MM MMMMM M `88888P' `88888P8 `88888P' dP dP + * MMMMMMMMMMMM + */ +/** + * The Reach check will find out if a player interacts with something that's too far away. + */ +public class Reach extends Check { + + /** + * The event triggered by this check. + */ + public class ReachEvent extends CheckEvent { + + /** + * Instantiates a new reach event. + * + * @param player + * the player + */ + public ReachEvent(final Player player) { + super(player); + } + } + + /** The maximum distance allowed to interact with a block. */ + public final double DISTANCE = 5D; + + /** + * Checks a player. + * + * @param player + * the player + * @param location + * the location + * @return true, if successful + */ + public boolean check(final Player player, final Location location) { + final BlockBreakConfig cc = BlockBreakConfig.getConfig(player); + final BlockBreakData data = BlockBreakData.getData(player); + + boolean cancel = false; + // Distance is calculated from eye location to center of targeted block. If the player is further away from his + // target than allowed, the difference will be assigned to "distance". + final double distance = Math.max(CheckUtils.distance(player, location) - DISTANCE, 0D); + + if (distance > 0) { + // He failed, increment violation level. + data.reachVL += distance; + + // Dispatch a reach event (API). + final ReachEvent e = new ReachEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Remember how much further than allowed he tried to reach for logging, if necessary. + data.reachDistance = distance + DISTANCE; + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + cancel = !e.isCancelled() && executeActions(player, cc.reachActions, data.reachVL); + } else + // Player passed the check, reward him. + data.reachVL *= 0.9D; + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockBreakData.getData(player).reachVL)); + else if (wildcard == ParameterName.REACHDISTANCE) + return String.valueOf(Math.round(BlockBreakData.getData(player).reachDistance)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKBREAK_REACH) && BlockBreakConfig.getConfig(player).reachCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockbreak/ReachCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockbreak/ReachCheck.java deleted file mode 100644 index 50d810cf..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockbreak/ReachCheck.java +++ /dev/null @@ -1,86 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockbreak; - -import org.bukkit.Bukkit; -import org.bukkit.GameMode; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * The reach check will find out if a player interacts with something that's - * too far away - * - */ -public class ReachCheck extends BlockBreakCheck { - - public class ReachCheckEvent extends BlockBreakEvent { - - public ReachCheckEvent(final ReachCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public ReachCheck() { - super("reach"); - } - - @Override - public boolean check(final fr.neatmonster.nocheatplus.players.NCPPlayer player, final Object... args) { - final BlockBreakConfig cc = getConfig(player); - final BlockBreakData data = getData(player); - - boolean cancel = false; - - final SimpleLocation brokenBlock = data.brokenBlockLocation; - - // Distance is calculated from eye location to center of targeted block - // If the player is further away from his target than allowed, the - // difference will be assigned to "distance" - final double distance = CheckUtils.reachCheck(player, brokenBlock.x + 0.5D, brokenBlock.y + 0.5D, - brokenBlock.z + 0.5D, - player.getBukkitPlayer().getGameMode() == GameMode.CREATIVE ? cc.reachDistance + 2 : cc.reachDistance); - - if (distance <= 0D) - // Player passed the check, reward him - data.reachVL *= 0.9D; - else { - // He failed, increment violation level and statistics - data.reachVL += distance; - incrementStatistics(player, Id.BB_REACH, distance); - - // Remember how much further than allowed he tried to reach for - // logging, if necessary - data.reachDistance = distance; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.reachActions, data.reachVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final ReachCheckEvent event = new ReachCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).reachVL)); - else if (wildcard == ParameterName.REACHDISTANCE) - return String.valueOf(Math.round(getData(player).reachDistance)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceCheck.java deleted file mode 100644 index a7cc4f75..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceCheck.java +++ /dev/null @@ -1,51 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockplace; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * Abstract base class for BlockPlace checks, provides some convenience - * methods for access to data and config that's relevant to this checktype - */ -public abstract class BlockPlaceCheck extends Check { - - public BlockPlaceCheck(final String name) { - super("blockplace." + name, BlockPlaceConfig.class, BlockPlaceData.class); - } - - public abstract boolean check(final NCPPlayer player, final Object... args); - - public BlockPlaceConfig getConfig(final NCPPlayer player) { - return (BlockPlaceConfig) player.getConfig(this); - } - - public BlockPlaceData getData(final NCPPlayer player) { - return (BlockPlaceData) player.getData(this); - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - if (wildcard == ParameterName.PLACE_LOCATION) { - final SimpleLocation l = getData(player).blockPlaced; - if (l.isSet()) - return String.valueOf(Math.round(l.x)) + " " + String.valueOf(Math.round(l.y)) + " " - + String.valueOf(Math.round(l.z)); - else - return "null"; - } - - else if (wildcard == ParameterName.PLACE_AGAINST) { - final SimpleLocation l = getData(player).blockPlacedAgainst; - if (l.isSet()) - return String.valueOf(Math.round(l.x)) + " " + String.valueOf(Math.round(l.y)) + " " - + String.valueOf(Math.round(l.z)); - else - return "null"; - } - - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceConfig.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceConfig.java index 733feccc..6d873e6b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceConfig.java @@ -1,62 +1,99 @@ package fr.neatmonster.nocheatplus.checks.blockplace; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.entity.Player; import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckConfig; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; -import fr.neatmonster.nocheatplus.players.informations.Permissions; +import fr.neatmonster.nocheatplus.config.ConfigManager; +import fr.neatmonster.nocheatplus.players.Permissions; -/** - * Configurations specific for the "BlockPlace" checks - * Every world gets one of these assigned to it, or if a world doesn't get - * it's own, it will use the "global" version +/* + * M#"""""""'M dP dP MM"""""""`YM dP + * ## mmmm. `M 88 88 MM mmmmm M 88 + * #' .M 88 .d8888b. .d8888b. 88 .dP M' .M 88 .d8888b. .d8888b. .d8888b. + * M# MMMb.'YM 88 88' `88 88' `"" 88888" MM MMMMMMMM 88 88' `88 88' `"" 88ooood8 + * M# MMMM' M 88 88. .88 88. ... 88 `8b. MM MMMMMMMM 88 88. .88 88. ... 88. ... + * M# .;M dP `88888P' `88888P' dP `YP MM MMMMMMMM dP `88888P8 `88888P' `88888P' + * M#########M MMMMMMMMMMMM * + * MM'""""'YMM .8888b oo + * M' .mmm. `M 88 " + * M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. + * M MMMMMMMM 88' `88 88' `88 88 88 88' `88 + * M. `MMM' .M 88. .88 88 88 88 88 88. .88 + * MM. .dM `88888P' dP dP dP dP `8888P88 + * MMMMMMMMMMM .88 + * d8888P */ -public class BlockPlaceConfig extends CheckConfig { +/** + * Configurations specific for the block place checks. Every world gets one of these assigned to it, or if a world + * doesn't get it's own, it will use the "global" version. + */ +public class BlockPlaceConfig { - public final boolean fastPlaceCheck; - public final int fastPlaceInterval; - public final ActionList fastPlaceActions; + /** The map containing the configurations per world. */ + private static Map worldsMap = new HashMap(); - public final boolean reachCheck; - public final double reachDistance; - public final ActionList reachActions; + /** + * Clear all the configurations. + */ + public static void clear() { + worldsMap.clear(); + } - public final boolean directionCheck; - public final ActionList directionActions; - public final long directionPenaltyTime; - public final double directionPrecision; + /** + * Gets the configuration for a specified player. + * + * @param player + * the player + * @return the configuration + */ + public static BlockPlaceConfig getConfig(final Player player) { + if (!worldsMap.containsKey(player.getWorld().getName())) + worldsMap.put(player.getWorld().getName(), + new BlockPlaceConfig(ConfigManager.getConfigFile(player.getWorld().getName()))); + return worldsMap.get(player.getWorld().getName()); + } - public final boolean projectileCheck; - public final int projectileInterval; - public final ActionList projectileActions; + public final boolean directionCheck; + public final ActionList directionActions; - public final List fastSignExclusions = new ArrayList(); + public final boolean fastPlaceCheck; + public final boolean fastPlaceExperimental; + public final long fastPlaceInterval; + public final ActionList fastPlaceActions; + public final boolean reachCheck; + public final ActionList reachActions; + + public final boolean speedCheck; + public final long speedInterval; + public final ActionList speedActions; + + /** + * Instantiates a new block place configuration. + * + * @param data + * the data + */ public BlockPlaceConfig(final ConfigFile data) { + directionCheck = data.getBoolean(ConfPaths.BLOCKPLACE_DIRECTION_CHECK); + directionActions = data.getActionList(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, Permissions.BLOCKPLACE_DIRECTION); fastPlaceCheck = data.getBoolean(ConfPaths.BLOCKPLACE_FASTPLACE_CHECK); - fastPlaceInterval = data.getInt(ConfPaths.BLOCKPLACE_FASTPLACE_INTERVAL); + fastPlaceExperimental = data.getBoolean(ConfPaths.BLOCKPLACE_FASTPLACE_EXPERIMENTAL); + fastPlaceInterval = data.getLong(ConfPaths.BLOCKPLACE_FASTPLACE_INTERVAL); fastPlaceActions = data.getActionList(ConfPaths.BLOCKPLACE_FASTPLACE_ACTIONS, Permissions.BLOCKPLACE_FASTPLACE); reachCheck = data.getBoolean(ConfPaths.BLOCKPLACE_REACH_CHECK); - reachDistance = 535D / 100D; reachActions = data.getActionList(ConfPaths.BLOCKPLACE_REACH_ACTIONS, Permissions.BLOCKPLACE_REACH); - directionCheck = data.getBoolean(ConfPaths.BLOCKPLACE_DIRECTION_CHECK); - directionPenaltyTime = data.getInt(ConfPaths.BLOCKPLACE_DIRECTION_PENALTYTIME); - directionPrecision = data.getInt(ConfPaths.BLOCKPLACE_DIRECTION_PRECISION) / 100D; - directionActions = data.getActionList(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, Permissions.BLOCKPLACE_DIRECTION); - - projectileCheck = data.getBoolean(ConfPaths.BLOCKPLACE_PROJECTILE_CHECK); - projectileInterval = data.getInt(ConfPaths.BLOCKPLACE_PROJECTILE_INTERVAL); - projectileActions = data.getActionList(ConfPaths.BLOCKPLACE_PROJECTILE_ACTIONS, - Permissions.BLOCKPLACE_PROJECTILE); - - for (final String exclusion : data.getStringList(ConfPaths.BLOCKPLACE_FASTSIGN_EXCLUSIONS)) - data.getStringList(ConfPaths.BLOCKPLACE_FASTSIGN_EXCLUSIONS).add(exclusion.toLowerCase()); + speedCheck = data.getBoolean(ConfPaths.BLOCKPLACE_SPEED_CHECK); + speedInterval = data.getLong(ConfPaths.BLOCKPLACE_SPEED_INTERVAL); + speedActions = data.getActionList(ConfPaths.BLOCKPLACE_SPEED_ACTIONS, Permissions.BLOCKPLACE_SPEED); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceData.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceData.java index 680855c9..7db2d3bd 100644 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceData.java +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceData.java @@ -1,45 +1,62 @@ package fr.neatmonster.nocheatplus.checks.blockplace; -import fr.neatmonster.nocheatplus.checks.CheckData; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; +import java.util.HashMap; +import java.util.Map; -/** - * Player specific data for the blockbreak checks +import org.bukkit.entity.Player; + +/* + * M#"""""""'M dP dP MM"""""""`YM dP + * ## mmmm. `M 88 88 MM mmmmm M 88 + * #' .M 88 .d8888b. .d8888b. 88 .dP M' .M 88 .d8888b. .d8888b. .d8888b. + * M# MMMb.'YM 88 88' `88 88' `"" 88888" MM MMMMMMMM 88 88' `88 88' `"" 88ooood8 + * M# MMMM' M 88 88. .88 88. ... 88 `8b. MM MMMMMMMM 88 88. .88 88. ... 88. ... + * M# .;M dP `88888P' `88888P' dP `YP MM MMMMMMMM dP `88888P8 `88888P' `88888P' + * M#########M MMMMMMMMMMMM * + * M""""""'YMM dP + * M mmmm. `M 88 + * M MMMMM M .d8888b. d8888P .d8888b. + * M MMMMM M 88' `88 88 88' `88 + * M MMMM' .M 88. .88 88 88. .88 + * M .MM `88888P8 dP `88888P8 + * MMMMMMMMMMM */ -public class BlockPlaceData extends CheckData { +/** + * Player specific data for the block place checks. + */ +public class BlockPlaceData { - // Keep track of violation levels for the two checks - public double fastPlaceVL = 0.0D; - public double reachVL = 0.0D; - public double directionVL = 0.0D; - public double projectileVL = 0.0D; + /** The map containing the data per players. */ + private static Map playersMap = new HashMap(); - // Used to know when the player has placed his previous block - public long lastPlaceTime = 0; + /** + * Gets the data of a specified player. + * + * @param player + * the player + * @return the data + */ + public static BlockPlaceData getData(final Player player) { + if (!playersMap.containsKey(player.getName())) + playersMap.put(player.getName(), new BlockPlaceData()); + return playersMap.get(player.getName()); + } - // Used to know if the previous event was refused - public boolean previousRefused = false; + // Violation levels. + public double directionVL; + public double fastPlaceVL; + public double reachVL; + public double speedVL; - // Used for the penalty time feature of the direction check - public long directionLastViolationTime = 0; + // Data of the fast place check. + public long fastPlaceLastTime; + public boolean fastPlaceLastRefused; - // Have a nicer/simpler way to work with block locations instead of - // Bukkits own "Location" class - public final SimpleLocation blockPlacedAgainst = new SimpleLocation(); - public final SimpleLocation blockPlaced = new SimpleLocation(); + // Data of the reach check. + public double reachDistance; - // For logging, remember the reachDistance that was calculated in the - // reach check - public double reachdistance; - - // Store the two previous signs' text - public String[] lastSignText = new String[] {"", "", "", ""}; - public String[] lastLastSignText = new String[] {"", "", "", ""}; - - // Used to store the last time a projectile was thrown - public long lastProjectileTime = 0; - - // Used to know if the previous projectile-thrown-event was refused - public boolean previousProjectileRefused = false; + // Data of the speed check; + public boolean speedLastRefused; + public long speedLastTime; } diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceEvent.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceEvent.java deleted file mode 100644 index dbd730fa..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockplace; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckEvent; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public class BlockPlaceEvent extends CheckEvent { - - public BlockPlaceEvent(final BlockPlaceCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - - @Override - public BlockPlaceCheck getCheck() { - return (BlockPlaceCheck) super.getCheck(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java index a5ed9f4f..8fa62b78 100644 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/BlockPlaceListener.java @@ -1,109 +1,132 @@ package fr.neatmonster.nocheatplus.checks.blockplace; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.block.SignChangeEvent; import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.player.PlayerInteractEvent; -import fr.neatmonster.nocheatplus.checks.CheckListener; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Central location to listen to Block-related events and dispatching them to - * checks +/* + * M#"""""""'M dP dP MM"""""""`YM dP + * ## mmmm. `M 88 88 MM mmmmm M 88 + * #' .M 88 .d8888b. .d8888b. 88 .dP M' .M 88 .d8888b. .d8888b. .d8888b. + * M# MMMb.'YM 88 88' `88 88' `"" 88888" MM MMMMMMMM 88 88' `88 88' `"" 88ooood8 + * M# MMMM' M 88 88. .88 88. ... 88 `8b. MM MMMMMMMM 88 88. .88 88. ... 88. ... + * M# .;M dP `88888P' `88888P' dP `YP MM MMMMMMMM dP `88888P8 `88888P' `88888P' + * M#########M MMMMMMMMMMMM * + * M""MMMMMMMM oo dP + * M MMMMMMMM 88 + * M MMMMMMMM dP .d8888b. d8888P .d8888b. 88d888b. .d8888b. 88d888b. + * M MMMMMMMM 88 Y8ooooo. 88 88ooood8 88' `88 88ooood8 88' `88 + * M MMMMMMMM 88 88 88 88. ... 88 88 88. ... 88 + * M M dP `88888P' dP `88888P' dP dP `88888P' dP + * MMMMMMMMMMM */ -public class BlockPlaceListener extends CheckListener { - - private final FastPlaceCheck fastPlaceCheck; - private final ReachCheck reachCheck; - private final DirectionCheck directionCheck; - private final ProjectileCheck projectileCheck; - - public BlockPlaceListener() { - super("blockplace"); - - fastPlaceCheck = new FastPlaceCheck(); - reachCheck = new ReachCheck(); - directionCheck = new DirectionCheck(); - projectileCheck = new ProjectileCheck(); - } +/** + * Central location to listen to events that are relevant for the block place checks. + * + * @see BlockPlaceEvent + */ +public class BlockPlaceListener implements Listener { + private final Direction direction = new Direction(); + private final FastPlace fastPlace = new FastPlace(); + private final Reach reach = new Reach(); + private final Speed speed = new Speed(); /** - * We listen to BlockPlace events for obvious reasons + * We listen to BlockPlace events for obvious reasons. * * @param event - * the BlockPlace event + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.LOWEST) - protected void handleBlockPlaceEvent(final BlockPlaceEvent event) { - + protected void onBlockPlace(final BlockPlaceEvent event) { + /* + * ____ _ _ ____ _ + * | __ )| | ___ ___| | __ | _ \| | __ _ ___ ___ + * | _ \| |/ _ \ / __| |/ / | |_) | |/ _` |/ __/ _ \ + * | |_) | | (_) | (__| < | __/| | (_| | (_| __/ + * |____/|_|\___/ \___|_|\_\ |_| |_|\__,_|\___\___| + */ + // We don't care about null blocks. if (event.getBlock() == null || event.getBlockAgainst() == null) return; - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final BlockPlaceConfig cc = (BlockPlaceConfig) getConfig(player); - final BlockPlaceData data = (BlockPlaceData) getData(player); + final Player player = event.getPlayer(); + final Block block = event.getBlock(); boolean cancelled = false; - // Remember these locations and put them in a simpler "format" - data.blockPlaced.set(event.getBlock()); - data.blockPlacedAgainst.set(event.getBlockAgainst()); + // First, the fast place check. + if (fastPlace.isEnabled(player)) + cancelled = fastPlace.check(player, block); - // Now do the actual checks + // Second, the reach check. + if (!cancelled && reach.isEnabled(player)) + cancelled = reach.check(player, block.getLocation()); - // First the fastplace check - if (cc.fastPlaceCheck && !player.hasPermission(Permissions.BLOCKPLACE_FASTPLACE)) - cancelled = fastPlaceCheck.check(player); + // Third, the direction check. + if (!cancelled && direction.isEnabled(player)) + cancelled = direction.check(player, block.getLocation()); - // Second the reach check - if (!cancelled && cc.reachCheck && !player.hasPermission(Permissions.BLOCKPLACE_REACH)) - cancelled = reachCheck.check(player); - - // Third the direction check - if (!cancelled && cc.directionCheck && !player.hasPermission(Permissions.BLOCKPLACE_DIRECTION)) - cancelled = directionCheck.check(player); - - // If one of the checks requested to cancel the event, do so + // If one of the checks requested to cancel the event, do so. if (cancelled) event.setCancelled(cancelled); } + /** + * We listener to PlayerInteract events to prevent players from spamming the server with monster eggs. + */ @EventHandler( ignoreCancelled = true, priority = EventPriority.LOWEST) - public void monsterEgg(final PlayerInteractEvent event) { - - // We are only interested by monster eggs + public void onPlayerInteract(final PlayerInteractEvent event) { + /* + * ____ _ ___ _ _ + * | _ \| | __ _ _ _ ___ _ __ |_ _|_ __ | |_ ___ _ __ __ _ ___| |_ + * | |_) | |/ _` | | | |/ _ \ '__| | || '_ \| __/ _ \ '__/ _` |/ __| __| + * | __/| | (_| | |_| | __/ | | || | | | || __/ | | (_| | (__| |_ + * |_| |_|\__,_|\__, |\___|_| |___|_| |_|\__\___|_| \__,_|\___|\__| + * |___/ + */ + // We are only interested by monster eggs. if (event.getAction() != Action.RIGHT_CLICK_BLOCK || event.getPlayer().getItemInHand() == null || event.getPlayer().getItemInHand().getType() != Material.MONSTER_EGG) return; - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final BlockPlaceConfig cc = (BlockPlaceConfig) getConfig(player); + final Player player = event.getPlayer(); - // Do the actual check - if (cc.projectileCheck && !player.hasPermission(Permissions.BLOCKPLACE_PROJECTILE) - && projectileCheck.check(player)) - // If the check is positive, cancel the event + // Do the actual check... + if (speed.isEnabled(player) && speed.check(player)) + // If the check was positive, cancel the event. event.setCancelled(true); } + /** + * We listen to ProjectileLaunch events to prevent players from launching projectiles too quickly. + */ @EventHandler( ignoreCancelled = true, priority = EventPriority.LOWEST) - public void otherProjectiles(final ProjectileLaunchEvent event) { - - // We are only interested by enderpears, endersignals, eggs, snowballs and expbottles - // of course thrown by a player + public void onProjectileLaunch(final ProjectileLaunchEvent event) { + /* + * ____ _ _ _ _ _ _ + * | _ \ _ __ ___ (_) ___ ___| |_(_) | ___ | | __ _ _ _ _ __ ___| |__ + * | |_) | '__/ _ \| |/ _ \/ __| __| | |/ _ \ | | / _` | | | | '_ \ / __| '_ \ + * | __/| | | (_) | | __/ (__| |_| | | __/ | |__| (_| | |_| | | | | (__| | | | + * |_| |_| \___// |\___|\___|\__|_|_|\___| |_____\__,_|\__,_|_| |_|\___|_| |_| + * |__/ + */ + // The shooter needs to be a player. if (!(event.getEntity().getShooter() instanceof Player)) return; + + // And the projectile must be one the following: switch (event.getEntityType()) { case ENDER_PEARL: break; @@ -119,56 +142,11 @@ public class BlockPlaceListener extends CheckListener { return; } - final NCPPlayer player = NCPPlayer.getPlayer((Player) event.getEntity().getShooter()); - final BlockPlaceConfig cc = (BlockPlaceConfig) getConfig(player); + final Player player = (Player) event.getEntity().getShooter(); - // Do the actual check - if (cc.projectileCheck && !player.hasPermission(Permissions.BLOCKPLACE_PROJECTILE) - && projectileCheck.check(player)) - // If the check is positive, cancel the event + // Do the actual check... + if (speed.isEnabled(player) && speed.check(player)) + // If the check was positive, cancel the event. event.setCancelled(true); } - - /** - * If the player places three times the same sign, - * the sign will be destroyed and looted - * - * @param event - * the SignChange event - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void sign(final SignChangeEvent event) { - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final BlockPlaceConfig cc = (BlockPlaceConfig) getConfig(player); - final BlockPlaceData data = (BlockPlaceData) getData(player); - - // Check if the sign's content is empty - // if is the first line is whitelisted - if (event.getLine(0).length() + event.getLine(1).length() + event.getLine(2).length() - + event.getLine(3).length() == 0 - || cc.fastSignExclusions.contains(event.getLine(0).toLowerCase())) - return; - - // Check if the text is the same - if (!player.hasPermission(Permissions.BLOCKPLACE_AUTOSIGN) && event.getLine(0).equals(data.lastSignText[0]) - && event.getLine(1).equals(data.lastSignText[1]) && event.getLine(2).equals(data.lastSignText[2]) - && event.getLine(3).equals(data.lastSignText[3]) - && data.lastSignText[0].equals(data.lastLastSignText[0]) - && data.lastSignText[1].equals(data.lastLastSignText[1]) - && data.lastSignText[2].equals(data.lastLastSignText[2]) - && data.lastSignText[3].equals(data.lastLastSignText[3])) - event.getBlock().breakNaturally(); - - // Save the text - data.lastLastSignText[3] = data.lastSignText[3]; - data.lastLastSignText[2] = data.lastSignText[2]; - data.lastLastSignText[1] = data.lastSignText[1]; - data.lastLastSignText[0] = data.lastSignText[0]; - data.lastSignText[3] = event.getLine(3); - data.lastSignText[2] = event.getLine(2); - data.lastSignText[1] = event.getLine(1); - data.lastSignText[0] = event.getLine(0); - } } diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/Direction.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/Direction.java new file mode 100644 index 00000000..bab02fa3 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/Direction.java @@ -0,0 +1,104 @@ +package fr.neatmonster.nocheatplus.checks.blockplace; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.CheckUtils; + +/* + * M""""""'YMM oo dP oo + * M mmmm. `M 88 + * M MMMMM M dP 88d888b. .d8888b. .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMM M 88 88' `88 88ooood8 88' `"" 88 88 88' `88 88' `88 + * M MMMM' .M 88 88 88. ... 88. ... 88 88 88. .88 88 88 + * M .MM dP dP `88888P' `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMM + */ +/** + * The Direction check will find out if a player tried to interact with something that's not in his field of view. + */ +public class Direction extends Check { + + /** + * The event triggered by this check. + */ + public class DirectionEvent extends CheckEvent { + + /** + * Instantiates a new direction event. + * + * @param player + * the player + */ + public DirectionEvent(final Player player) { + super(player); + } + } + + private final double OFFSET = 0.5D; + + /** + * Checks a player. + * + * @param player + * the player + * @param location + * the location + * @return true, if successful + */ + public boolean check(final Player player, final Location location) { + final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); + final BlockPlaceData data = BlockPlaceData.getData(player); + + boolean cancel = false; + + if (!CheckUtils.intersects(player, location, OFFSET)) { + // Player failed the check. Let's try to guess how far he was from looking directly to the block... + final Vector direction = player.getEyeLocation().getDirection(); + final Vector blockEyes = location.add(0.5D, 0.5D, 0.5D).subtract(player.getEyeLocation()).toVector(); + final double distance = blockEyes.crossProduct(direction).length() / direction.length(); + + // Add the overall violation level of the check. + data.directionVL += distance; + + // Dispatch a direction event (API). + final DirectionEvent e = new DirectionEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + if (!e.isCancelled() && executeActions(player, cc.directionActions, data.directionVL)) + cancel = true; + } else + // Player did likely nothing wrong, reduce violation counter to reward him. + data.directionVL *= 0.9D; + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockPlaceData.getData(player).directionVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKPLACE_DIRECTION) + && BlockPlaceConfig.getConfig(player).directionCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/DirectionCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/DirectionCheck.java deleted file mode 100644 index e7c361ff..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/DirectionCheck.java +++ /dev/null @@ -1,124 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockplace; - -import org.bukkit.Bukkit; -import org.bukkit.Location; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * The DirectionCheck will find out if a player tried to interact with something - * that's not in his field of view. - * - */ -public class DirectionCheck extends BlockPlaceCheck { - - public class DirectionCheckEvent extends BlockPlaceEvent { - - public DirectionCheckEvent(final DirectionCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public DirectionCheck() { - super("direction"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final BlockPlaceConfig cc = getConfig(player); - final BlockPlaceData data = getData(player); - - boolean cancel = false; - - final SimpleLocation blockPlaced = data.blockPlaced; - final SimpleLocation blockPlacedAgainst = data.blockPlacedAgainst; - - // How far "off" is the player with his aim. We calculate from the - // players eye location and view direction to the center of the target - // block. If the line of sight is more too far off, "off" will be - // bigger than 0 - double off = CheckUtils.directionCheck(player, blockPlacedAgainst.x + 0.5D, blockPlacedAgainst.y + 0.5D, - blockPlacedAgainst.z + 0.5D, 1D, 1D, cc.directionPrecision); - - // now check if the player is looking at the block from the correct side - double off2 = 0.0D; - - // Find out against which face the player tried to build, and if he - // stood on the correct side of it - final Location eyes = player.getBukkitPlayer().getEyeLocation(); - if (blockPlaced.x > blockPlacedAgainst.x) - off2 = blockPlacedAgainst.x + 0.5D - eyes.getX(); - else if (blockPlaced.x < blockPlacedAgainst.x) - off2 = -(blockPlacedAgainst.x + 0.5D - eyes.getX()); - else if (blockPlaced.y > blockPlacedAgainst.y) - off2 = blockPlacedAgainst.y + 0.5D - eyes.getY(); - else if (blockPlaced.y < blockPlacedAgainst.y) - off2 = -(blockPlacedAgainst.y + 0.5D - eyes.getY()); - else if (blockPlaced.z > blockPlacedAgainst.z) - off2 = blockPlacedAgainst.z + 0.5D - eyes.getZ(); - else if (blockPlaced.z < blockPlacedAgainst.z) - off2 = -(blockPlacedAgainst.z + 0.5D - eyes.getZ()); - - // If he wasn't on the correct side, add that to the "off" value - if (off2 > 0.0D) - off += off2; - - final long time = System.currentTimeMillis(); - - if (off < 0.1D) - // Player did nothing wrong - // reduce violation counter to reward him - data.directionVL *= 0.9D; - else { - // Player failed the check - // Increment violation counter and statistics - data.directionVL += off; - incrementStatistics(player, Id.BP_DIRECTION, off); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.directionActions, data.directionVL); - - if (cancel) - // if we should cancel, remember the current time too - data.directionLastViolationTime = time; - } - - // If the player is still in penalty time, cancel the event anyway - if (data.directionLastViolationTime + cc.directionPenaltyTime > time) { - // A safeguard to avoid people getting stuck in penalty time - // indefinitely in case the system time of the server gets changed - if (data.directionLastViolationTime > time) - data.directionLastViolationTime = 0; - - // He is in penalty time, therefore request cancelling of the event - return true; - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final DirectionCheckEvent event = new DirectionCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).directionVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlace.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlace.java new file mode 100644 index 00000000..97e3a8ce --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlace.java @@ -0,0 +1,106 @@ +package fr.neatmonster.nocheatplus.checks.blockplace; + +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.LagMeasureTask; + +/* + * MM""""""""`M dP MM"""""""`YM dP + * MM mmmmmmmM 88 MM mmmmm M 88 + * M' MMMM .d8888b. .d8888b. d8888P M' .M 88 .d8888b. .d8888b. .d8888b. + * MM MMMMMMMM 88' `88 Y8ooooo. 88 MM MMMMMMMM 88 88' `88 88' `"" 88ooood8 + * MM MMMMMMMM 88. .88 88 88 MM MMMMMMMM 88 88. .88 88. ... 88. ... + * MM MMMMMMMM `88888P8 `88888P' dP MM MMMMMMMM dP `88888P8 `88888P' `88888P' + * MMMMMMMMMMMM MMMMMMMMMMMM + */ +/** + * A check used to verify if the player isn't placing blocks too quickly. + */ +public class FastPlace extends Check { + + /** + * The event triggered by this check. + */ + public class FastPlaceEvent extends CheckEvent { + + /** + * Instantiates a new fast place event. + * + * @param player + * the player + */ + public FastPlaceEvent(final Player player) { + super(player); + } + } + + /** + * Checks a player. + * + * @param player + * the player + * @param block + * the block + * @return true, if successful + */ + public boolean check(final Player player, final Block block) { + final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); + final BlockPlaceData data = BlockPlaceData.getData(player); + + boolean cancel = false; + + // Has the player placed blocks too quickly? + if (data.fastPlaceLastTime != 0 && System.currentTimeMillis() - data.fastPlaceLastTime < cc.fastPlaceInterval) { + if (!LagMeasureTask.skipCheck()) { + if (data.fastPlaceLastRefused) { + // He failed, increase his violation level. + data.fastPlaceVL += cc.fastPlaceInterval - System.currentTimeMillis() + data.fastPlaceLastTime; + + // Distance a fast place event (API). + final FastPlaceEvent e = new FastPlaceEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if + // we should cancel the event. + cancel = !e.isCancelled() && executeActions(player, cc.fastPlaceActions, data.fastPlaceVL); + } + data.fastPlaceLastRefused = true; + } + } else { + // Reward him by lowering his violation level. + data.fastPlaceVL *= 0.9D; + + data.fastPlaceLastRefused = false; + } + + data.fastPlaceLastTime = System.currentTimeMillis(); + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockPlaceData.getData(player).fastPlaceVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKPLACE_FASTPLACE) + && BlockPlaceConfig.getConfig(player).fastPlaceCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlaceCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlaceCheck.java deleted file mode 100644 index 1dc284e8..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlaceCheck.java +++ /dev/null @@ -1,79 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockplace; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * A check used to verify if the player isn't breaking his blocks too quickly - * - */ -public class FastPlaceCheck extends BlockPlaceCheck { - - public class FastPlaceCheckEvent extends BlockPlaceEvent { - - public FastPlaceCheckEvent(final FastPlaceCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public FastPlaceCheck() { - super("fastplace"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final BlockPlaceConfig cc = getConfig(player); - final BlockPlaceData data = getData(player); - - boolean cancel = false; - - // Has the player placed blocks too quickly - if (data.lastPlaceTime != 0 && System.currentTimeMillis() - data.lastPlaceTime < cc.fastPlaceInterval) { - if (!NoCheatPlus.skipCheck()) { - if (data.previousRefused) { - // He failed, increase vl and statistics - data.fastPlaceVL += cc.fastPlaceInterval - System.currentTimeMillis() + data.lastPlaceTime; - incrementStatistics(player, Id.BP_FASTPLACE, cc.fastPlaceInterval - System.currentTimeMillis() - + data.lastPlaceTime); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.fastPlaceActions, data.fastPlaceVL); - } - data.previousRefused = true; - } - } else { - // Reward with lowering of the violation level - data.fastPlaceVL *= 0.90D; - data.previousRefused = false; - } - - data.lastPlaceTime = System.currentTimeMillis(); - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final FastPlaceCheckEvent event = new FastPlaceCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).fastPlaceVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/ProjectileCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/ProjectileCheck.java deleted file mode 100644 index 4fde9b21..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/ProjectileCheck.java +++ /dev/null @@ -1,78 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockplace; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * A check used to verify if the player isn't throwing projectiles too quickly - * - */ -public class ProjectileCheck extends BlockPlaceCheck { - - public class ProjectileCheckEvent extends BlockPlaceEvent { - - public ProjectileCheckEvent(final ProjectileCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public ProjectileCheck() { - super("projectile"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final BlockPlaceConfig cc = getConfig(player); - final BlockPlaceData data = getData(player); - - boolean cancel = false; - - // Has the player thrown the projectiles too quickly - if (data.lastProjectileTime != 0 - && System.currentTimeMillis() - data.lastProjectileTime < cc.projectileInterval) { - if (data.previousProjectileRefused) { - // He failed, increase vl and statistics - data.projectileVL += cc.projectileInterval - System.currentTimeMillis() + data.lastProjectileTime; - incrementStatistics(player, Id.BP_PROJECTILE, cc.projectileInterval - System.currentTimeMillis() - + data.lastProjectileTime); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.projectileActions, data.projectileVL); - } - data.previousProjectileRefused = true; - } else { - // Reward with lowering of the violation level - data.projectileVL *= 0.90D; - data.previousProjectileRefused = false; - } - - data.lastProjectileTime = System.currentTimeMillis(); - - return cancel; - - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final ProjectileCheckEvent event = new ProjectileCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).projectileVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/Reach.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/Reach.java new file mode 100644 index 00000000..b5643b35 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/Reach.java @@ -0,0 +1,105 @@ +package fr.neatmonster.nocheatplus.checks.blockplace; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.CheckUtils; + +/* + * MM"""""""`MM dP + * MM mmmm, M 88 + * M' .M .d8888b. .d8888b. .d8888b. 88d888b. + * MM MMMb. "M 88ooood8 88' `88 88' `"" 88' `88 + * MM MMMMM M 88. ... 88. .88 88. ... 88 88 + * MM MMMMM M `88888P' `88888P8 `88888P' dP dP + * MMMMMMMMMMMM + */ +/** + * The Reach check will find out if a player interacts with something that's too far away. + */ +public class Reach extends Check { + + /** + * The event triggered by this check. + */ + public class ReachEvent extends CheckEvent { + + /** + * Instantiates a new reach event. + * + * @param player + * the player + */ + public ReachEvent(final Player player) { + super(player); + } + } + + /** The maximum distance allowed to interact with a block. */ + public final double DISTANCE = 5D; + + /** + * Checks a player. + * + * @param player + * the player + * @param location + * the location + * @return true, if successful + */ + public boolean check(final Player player, final Location location) { + final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); + final BlockPlaceData data = BlockPlaceData.getData(player); + + boolean cancel = false; + // Distance is calculated from eye location to center of targeted block. If the player is further away from his + // target than allowed, the difference will be assigned to "distance". + final double distance = Math.max(CheckUtils.distance(player, location) - DISTANCE, 0D); + + if (distance > 0) { + // He failed, increment violation level. + data.reachVL += distance; + + // Dispatch a reach event (API). + final ReachEvent e = new ReachEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Remember how much further than allowed he tried to reach for logging, if necessary. + data.reachDistance = distance + DISTANCE; + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + cancel = !e.isCancelled() && executeActions(player, cc.reachActions, data.reachVL); + } else + // Player passed the check, reward him. + data.reachVL *= 0.9D; + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockPlaceData.getData(player).reachVL)); + else if (wildcard == ParameterName.REACHDISTANCE) + return String.valueOf(Math.round(BlockPlaceData.getData(player).reachDistance)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKPLACE_REACH) && BlockPlaceConfig.getConfig(player).reachCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/ReachCheck.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/ReachCheck.java deleted file mode 100644 index a0b0d033..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/blockplace/ReachCheck.java +++ /dev/null @@ -1,86 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.blockplace; - -import org.bukkit.Bukkit; -import org.bukkit.GameMode; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * The reach check will find out if a player interacts with something that's - * too far away - * - */ -public class ReachCheck extends BlockPlaceCheck { - - public class ReachCheckEvent extends BlockPlaceEvent { - - public ReachCheckEvent(final ReachCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public ReachCheck() { - super("reach"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final BlockPlaceConfig cc = getConfig(player); - final BlockPlaceData data = getData(player); - - boolean cancel = false; - - final SimpleLocation placedAgainstBlock = data.blockPlacedAgainst; - - // Distance is calculated from eye location to center of targeted block - // If the player is further away from his target than allowed, the - // difference will be assigned to "distance" - final double distance = CheckUtils.reachCheck(player, placedAgainstBlock.x + 0.5D, placedAgainstBlock.y + 0.5D, - placedAgainstBlock.z + 0.5D, - player.getBukkitPlayer().getGameMode() == GameMode.CREATIVE ? cc.reachDistance + 2 : cc.reachDistance); - - if (distance <= 0D) - // Player passed the check, reward him - data.reachVL *= 0.9D; - else { - // He failed, increment violation level and statistics - data.reachVL += distance; - incrementStatistics(player, Id.BP_REACH, distance); - - // Remember how much further than allowed he tried to reach for - // logging, if necessary - data.reachdistance = distance; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.reachActions, data.reachVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final ReachCheckEvent event = new ReachCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).reachVL)); - else if (wildcard == ParameterName.REACHDISTANCE) - return String.valueOf(Math.round(getData(player).reachdistance)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/blockplace/Speed.java b/src/fr/neatmonster/nocheatplus/checks/blockplace/Speed.java new file mode 100644 index 00000000..c041e52a --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/blockplace/Speed.java @@ -0,0 +1,101 @@ +package fr.neatmonster.nocheatplus.checks.blockplace; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * MP""""""`MM dP + * M mmmmm..M 88 + * M. `YM 88d888b. .d8888b. .d8888b. .d888b88 + * MMMMMMM. M 88' `88 88ooood8 88ooood8 88' `88 + * M. .MMM' M 88. .88 88. ... 88. ... 88. .88 + * Mb. .dM 88Y888P' `88888P' `88888P' `88888P8 + * MMMMMMMMMMM 88 + * dP + */ +/** + * This check verifies if the player isn't throwing items too quickly, like eggs or arrows. + */ +public class Speed extends Check { + + /** + * The event triggered by this check. + */ + public class SpeedEvent extends CheckEvent { + + /** + * Instantiates a new speed event. + * + * @param player + * the player + */ + public SpeedEvent(final Player player) { + super(player); + } + } + + /** + * Checks a player. + * + * @param player + * the player + * @return true, if successful + */ + public boolean check(final Player player) { + final BlockPlaceConfig cc = BlockPlaceConfig.getConfig(player); + final BlockPlaceData data = BlockPlaceData.getData(player); + + boolean cancel = false; + + // Has the player thrown items too quickly? + if (data.speedLastTime != 0 && System.currentTimeMillis() - data.speedLastTime < cc.speedInterval) { + if (data.speedLastRefused) { + // He failed, increase this violation level. + data.speedVL += cc.speedInterval - System.currentTimeMillis() + data.speedLastTime; + + // Dispatch a speed event (API). + final SpeedEvent e = new SpeedEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we + // should cancel the event. + cancel = !e.isCancelled() && executeActions(player, cc.speedActions, data.speedVL); + } + + data.speedLastRefused = true; + } else { + // Reward him by lowering his violation level. + data.speedVL *= 0.9D; + + data.speedLastRefused = false; + } + + data.speedLastTime = System.currentTimeMillis(); + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(BlockPlaceData.getData(player).speedVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.BLOCKPLACE_SPEED) && BlockPlaceConfig.getConfig(player).speedCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/Arrivals.java b/src/fr/neatmonster/nocheatplus/checks/chat/Arrivals.java new file mode 100644 index 00000000..50168fae --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/chat/Arrivals.java @@ -0,0 +1,103 @@ +package fr.neatmonster.nocheatplus.checks.chat; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * MMP"""""""MM oo dP + * M' .mmmm MM 88 + * M `M 88d888b. 88d888b. dP dP .dP .d8888b. 88 .d8888b. + * M MMMMM MM 88' `88 88' `88 88 88 d8' 88' `88 88 Y8ooooo. + * M MMMMM MM 88 88 88 88 .88' 88. .88 88 88 + * M MMMMM MM dP dP dP 8888P' `88888P8 dP `88888P' + * MMMMMMMMMMMM + */ +/** + * The Arrivals check is used to limit the number of new players allowed to join in a specified time frame. + */ +public class Arrivals extends Check { + + /** + * The event triggered by this check. + */ + public class ArrivalsEvent extends CheckEvent { + + /** + * Instantiates a new arrivals event. + * + * @param player + * the player + */ + public ArrivalsEvent(final Player player) { + super(player); + } + } + + /** The map containing the time and the name of the player, every time that one of them joins. */ + private final Map joins = new HashMap(); + + /** + * Checks player. + * + * @param player + * the player + * @return true, if successful + */ + public boolean check(final Player player) { + final ChatConfig cc = ChatConfig.getConfig(player); + + boolean cancel = false; + + // Remove the old data from the map holding the joins. + final List toRemove = new ArrayList(); + for (final long time : joins.keySet()) + // If the data is too old or belong the checked player. + if (System.currentTimeMillis() - time > cc.arrivalsTimeLimit && joins.get(time).equals(player.getName())) + toRemove.add(time); + for (final long time : toRemove) + joins.remove(time); + + // Add the new data. + joins.put(System.currentTimeMillis(), player.getName()); + + if (joins.size() > cc.arrivalsJoinsLimit) { + // Dispatch an arrivals event (API). + final ArrivalsEvent e = new ArrivalsEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Find out if we should cancel the event or not. + cancel = !e.isCancelled() && executeActions(player, cc.arrivalsActions, 0); + } + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return "0"; + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.CHAT_ARRIVALS) && ChatConfig.getConfig(player).arrivalsCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ArrivalsLimitCheck.java b/src/fr/neatmonster/nocheatplus/checks/chat/ArrivalsLimitCheck.java deleted file mode 100644 index 3cf80d4b..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ArrivalsLimitCheck.java +++ /dev/null @@ -1,91 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.chat; - -import java.util.Arrays; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * A check used to limit the number of new players allowed to join in a specified time frame - * - */ -public class ArrivalsLimitCheck extends ChatCheck { - - public class ArrivalsLimitCheckEvent extends ChatEvent { - - public ArrivalsLimitCheckEvent(final ArrivalsLimitCheck check, final NCPPlayer player, - final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - // Used to know if the cooldown is enabled and since when - private boolean cooldown = false; - - private long cooldownStartTime = 0L; - - // Used to remember the latest joins; - private long[] joinsTimes = null; - - private String[] joinsPlayers = null; - - public ArrivalsLimitCheck() { - super("arrivalslimit"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final ChatConfig cc = getConfig(player); - - // Initialize the joins array - if (joinsTimes == null) - joinsTimes = new long[cc.arrivalsLimitPlayersLimit]; - if (joinsPlayers == null) - joinsPlayers = new String[cc.arrivalsLimitPlayersLimit]; - - boolean cancel = false; - - // If the new players cooldown is over - if (cooldown && System.currentTimeMillis() - cooldownStartTime > cc.arrivalsLimitCooldownDelay) { - // Stop the new players cooldown - cooldown = false; - cooldownStartTime = 0L; - } - - // If the new players cooldown is active... - else if (cooldown) - // Kick the player who joined - cancel = executeActions(player, cc.arrivalsLimitActions, 0); - else if (System.currentTimeMillis() - joinsTimes[0] < cc.arrivalsLimitTimeframe) { - // ...if more than limit new players have joined in less than limit time - // Enable the new players cooldown - cooldown = true; - cooldownStartTime = System.currentTimeMillis(); - // Kick the player who joined - cancel = executeActions(player, cc.arrivalsLimitActions, 0); - } - - // Fill the joining times array - if (!Arrays.asList(joinsPlayers).contains(player.getName())) { - for (int i = 0; i < cc.arrivalsLimitPlayersLimit - 1; i++) { - joinsTimes[i] = joinsTimes[i + 1]; - joinsPlayers[i] = joinsPlayers[i + 1]; - } - joinsTimes[cc.arrivalsLimitPlayersLimit - 1] = System.currentTimeMillis(); - joinsPlayers[cc.arrivalsLimitPlayersLimit - 1] = player.getName(); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final ArrivalsLimitCheckEvent event = new ArrivalsLimitCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatCheck.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatCheck.java deleted file mode 100644 index 436d7cc4..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatCheck.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.chat; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * Abstract base class for Chat checks, provides some convenience - * methods for access to data and config that's relevant to this checktype - */ -public abstract class ChatCheck extends Check { - - public ChatCheck(final String name) { - super("chat." + name, ChatConfig.class, ChatData.class); - } - - public abstract boolean check(final NCPPlayer player, final Object... args); - - public ChatConfig getConfig(final NCPPlayer player) { - return (ChatConfig) player.getConfig(this); - } - - public ChatData getData(final NCPPlayer player) { - return (ChatData) player.getData(this); - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.TEXT) - // Filter colors from the players message when logging - return getData(player).message.replaceAll("\302\247.", "").replaceAll("\247.", ""); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java index d605d3a6..2c5e196b 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/ChatConfig.java @@ -1,147 +1,179 @@ package fr.neatmonster.nocheatplus.checks.chat; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.entity.Player; + import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckConfig; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; -import fr.neatmonster.nocheatplus.players.informations.Permissions; +import fr.neatmonster.nocheatplus.config.ConfigManager; +import fr.neatmonster.nocheatplus.players.Permissions; -/** - * Configurations specific for the "Chat" checks - * Every world gets one of these assigned to it, or if a world doesn't get - * it's own, it will use the "global" version - * +/* + * MM'""""'YMM dP dP MM'""""'YMM .8888b oo + * M' .mmm. `M 88 88 M' .mmm. `M 88 " + * M MMMMMooM 88d888b. .d8888b. d8888P M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. + * M MMMMMMMM 88' `88 88' `88 88 M MMMMMMMM 88' `88 88' `88 88 88 88' `88 + * M. `MMM' .M 88 88 88. .88 88 M. `MMM' .M 88. .88 88 88 88 88 88. .88 + * MM. .dM dP dP `88888P8 dP MM. .dM `88888P' dP dP dP dP `8888P88 + * MMMMMMMMMMM MMMMMMMMMMM .88 + * d8888P */ -public class ChatConfig extends CheckConfig { +/** + * Configurations specific for the "chat" checks. Every world gets one of these assigned to it, or if a world doesn't + * get it's own, it will use the "global" version. + */ +public class ChatConfig { - public final boolean opByConsoleOnly; - public final boolean protectPlugins; + /** The map containing the configurations per world. */ + private static Map worldsMap = new HashMap(); - public final boolean noPwnageCheck; - public final boolean noPwnageWarnPlayers; - public final boolean noPwnageWarnOthers; - public final int noPwnageWarnLevel; - public final long noPwnageWarnTimeout; - public final int noPwnageBanLevel; - public final ActionList noPwnageActions; + /** + * Clear all the configurations. + */ + public static void clear() { + worldsMap.clear(); + } - public final boolean noPwnageMoveCheck; - public final int noPwnageMoveWeightBonus; - public final int noPwnageMoveWeightMalus; - public final long noPwnageMoveTimeout; + /** + * Gets the configuration for a specified player. + * + * @param player + * the player + * @return the configuration + */ + public static ChatConfig getConfig(final Player player) { + if (!worldsMap.containsKey(player.getWorld().getName())) + worldsMap.put(player.getWorld().getName(), + new ChatConfig(ConfigManager.getConfigFile(player.getWorld().getName()))); + return worldsMap.get(player.getWorld().getName()); + } - public final boolean noPwnageSpeedCheck; - public final int noPwnageSpeedWeight; - public final long noPwnageSpeedTimeout; - - public final boolean noPwnageFirstCheck; - public final int noPwnageFirstWeight; - public final long noPwnageFirstTimeout; - - public final boolean noPwnageRepeatCheck; - public final int noPwnageRepeatWeight; - public final long noPwnageRepeatTimeout; - - public final boolean noPwnageGlobalCheck; - public final int noPwnageGlobalWeight; - public final long noPwnageGlobalTimeout; - - public final boolean noPwnageBannedCheck; - public final int noPwnageBannedWeight; - public final long noPwnageBannedTimeout; - - public final boolean noPwnageRelogCheck; - public final long noPwnageRelogTime; - public final int noPwnageRelogWarnings; - public final long noPwnageRelogTimeout; - - public final boolean noPwnageCaptchaCheck; - public final int noPwnageCaptchaLength; - public final String noPwnageCaptchaCharacters; - public final int noPwnageCaptchaTries; - - public final String noPwnageMessagesKick; - public final String noPwnageMessagesCaptchaQuestion; - public final String noPwnageMessagesCaptchaSuccess; - public final String noPwnageMessagesWarnPlayer; - public final String noPwnageMessagesWarnOthers; - public final String noPwnageMessagesWarnRelog; - - public final boolean arrivalsLimitCheck; - public final int arrivalsLimitPlayersLimit; - public final long arrivalsLimitTimeframe; - public final long arrivalsLimitCooldownDelay; - public final long arrivalsLimitNewTime; - public final String arrivalsLimitKickMessage; - public final ActionList arrivalsLimitActions; + public final boolean arrivalsCheck; + public final int arrivalsJoinsLimit; + public final String arrivalsMessage; + public final long arrivalsTimeLimit; + public final ActionList arrivalsActions; public final boolean colorCheck; public final ActionList colorActions; + public final boolean noPwnageCheck; + public final int noPwnageLevel; + + public final boolean noPwnageBannedCheck; + public final long noPwnageBannedTimeout; + public final int noPwnageBannedWeight; + + public final boolean noPwnageCaptchaCheck; + public final String noPwnageCaptchaCharacters; + public final int noPwnageCaptchaLength; + public final String noPwnageCaptchaQuestion; + public final String noPwnageCaptchaSuccess; + public final int noPwnageCaptchaTries; + + public final boolean noPwnageFirstCheck; + public final long noPwnageFirstTimeout; + public final int noPwnageFirstWeight; + + public final boolean noPwnageGlobalCheck; + public final long noPwnageGlobalTimeout; + public final int noPwnageGlobalWeight; + + public final boolean noPwnageMoveCheck; + public final long noPwnageMoveTimeout; + public final int noPwnageMoveWeightBonus; + public final int noPwnageMoveWeightMalus; + + public final boolean noPwnageReloginCheck; + public final long noPwnageReloginTimeout; + public final String noPwnageReloginWarningMessage; + public final int noPwnageReloginWarningNumber; + public final long noPwnageReloginWarningTimeout; + + public final boolean noPwnageRepeatCheck; + public final long noPwnageRepeatTimeout; + public final int noPwnageRepeatWeight; + + public final boolean noPwnageSpeedCheck; + public final long noPwnageSpeedTimeout; + public final int noPwnageSpeedWeight; + + public final int noPwnageWarnLevel; + public final long noPwnageWarnTimeout; + public final boolean noPwnageWarnOthersCheck; + public final String noPwnageWarnOthersMessage; + public final boolean noPwnageWarnPlayerCheck; + public final String noPwnageWarnPlayerMessage; + + public final ActionList noPwnageActions; + + /** + * Instantiates a new chat configuration. + * + * @param data + * the data + */ public ChatConfig(final ConfigFile data) { - - opByConsoleOnly = data.getBoolean(ConfPaths.MISCELLANEOUS_OPBYCONSOLEONLY); - protectPlugins = data.getBoolean(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS); - - noPwnageCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_CHECK); - noPwnageWarnPlayers = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_WARNPLAYERS); - noPwnageWarnOthers = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_WARNOTHERS); - noPwnageWarnLevel = data.getInt(ConfPaths.CHAT_NOPWNAGE_WARNLEVEL); - noPwnageWarnTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_WARNTIMEOUT); - noPwnageBanLevel = data.getInt(ConfPaths.CHAT_NOPWNAGE_BANLEVEL); - noPwnageActions = data.getActionList(ConfPaths.CHAT_NOPWNAGE_ACTIONS, Permissions.CHAT_NOPWNAGE); - - noPwnageMoveCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_MOVE_CHECK); - noPwnageMoveWeightBonus = data.getInt(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHTBONUS); - noPwnageMoveWeightMalus = data.getInt(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHTMALUS); - noPwnageMoveTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_MOVE_TIMEOUT); - - noPwnageSpeedCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_SPEED_CHECK); - noPwnageSpeedWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_SPEED_WEIGHT); - noPwnageSpeedTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_SPEED_TIMEOUT); - - noPwnageFirstCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_FIRST_CHECK); - noPwnageFirstWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_FIRST_WEIGHT); - noPwnageFirstTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_FIRST_TIMEOUT); - - noPwnageRepeatCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_REPEAT_CHECK); - noPwnageRepeatWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_REPEAT_WEIGHT); - noPwnageRepeatTimeout = data.getInt(ConfPaths.CHAT_NOPWNAGE_REPEAT_TIMEOUT); - - noPwnageGlobalCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_GLOBAL_CHECK); - noPwnageGlobalWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_GLOBAL_WEIGHT); - noPwnageGlobalTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_GLOBAL_TIMEOUT); - - noPwnageBannedCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_BANNED_CHECK); - noPwnageBannedWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_BANNED_WEIGHT); - noPwnageBannedTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_BANNED_TIMEOUT); - - noPwnageRelogCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_RELOG_CHECK); - noPwnageRelogTime = data.getLong(ConfPaths.CHAT_NOPWNAGE_RELOG_TIME); - noPwnageRelogWarnings = data.getInt(ConfPaths.CHAT_NOPWNAGE_RELOG_WARNINGS); - noPwnageRelogTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_RELOG_TIMEOUT); - - noPwnageCaptchaCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHECK); - noPwnageCaptchaLength = data.getInt(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_LENGTH); - noPwnageCaptchaCharacters = data.getString(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHARACTERS); - noPwnageCaptchaTries = data.getInt(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_TRIES); - - noPwnageMessagesKick = data.getString(ConfPaths.CHAT_NOPWNAGE_MESSAGES_KICK); - noPwnageMessagesCaptchaQuestion = data.getString(ConfPaths.CHAT_NOPWNAGE_MESSAGES_CAPTCHAQUESTION); - noPwnageMessagesCaptchaSuccess = data.getString(ConfPaths.CHAT_NOPWNAGE_MESSAGES_CAPTCHASUCCESS); - noPwnageMessagesWarnPlayer = data.getString(ConfPaths.CHAT_NOPWNAGE_MESSAGES_WARNPLAYER); - noPwnageMessagesWarnOthers = data.getString(ConfPaths.CHAT_NOPWNAGE_MESSAGES_WARNOTHERS); - noPwnageMessagesWarnRelog = data.getString(ConfPaths.CHAT_NOPWNAGE_MESSAGES_WARNRELOG); - - arrivalsLimitCheck = data.getBoolean(ConfPaths.CHAT_ARRIVALSLIMIT_CHECK); - arrivalsLimitPlayersLimit = data.getInt(ConfPaths.CHAT_ARRIVALSLIMIT_PLAYERSLIMIT); - arrivalsLimitTimeframe = data.getLong(ConfPaths.CHAT_ARRIVALSLIMIT_TIMEFRAME); - arrivalsLimitCooldownDelay = data.getLong(ConfPaths.CHAT_ARRIVALSLIMIT_COOLDOWNDELAY); - arrivalsLimitNewTime = data.getLong(ConfPaths.CHAT_ARRIVALSLIMIT_NEWTIME); - arrivalsLimitKickMessage = data.getString(ConfPaths.CHAT_ARRIVALSLIMIT_KICKMESSAGE); - arrivalsLimitActions = data.getActionList(ConfPaths.CHAT_ARRIVALSLIMIT_ACTIONS, Permissions.CHAT_ARRIVALSLIMIT); + arrivalsCheck = data.getBoolean(ConfPaths.CHAT_ARRIVALS_CHECK); + arrivalsJoinsLimit = data.getInt(ConfPaths.CHAT_ARRIVALS_JOINSLIMIT); + arrivalsMessage = data.getString(ConfPaths.CHAT_ARRIVALS_MESSAGE); + arrivalsTimeLimit = data.getLong(ConfPaths.CHAT_ARRIVALS_TIMELIMIT); + arrivalsActions = data.getActionList(ConfPaths.CHAT_ARRIVALS_ACTIONS, Permissions.CHAT_ARRIVALS); colorCheck = data.getBoolean(ConfPaths.CHAT_COLOR_CHECK); colorActions = data.getActionList(ConfPaths.CHAT_COLOR_ACTIONS, Permissions.CHAT_COLOR); + + noPwnageCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_CHECK); + noPwnageLevel = data.getInt(ConfPaths.CHAT_NOPWNAGE_LEVEL); + + noPwnageBannedCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_BANNED_CHECK); + noPwnageBannedTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_BANNED_TIMEOUT); + noPwnageBannedWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_BANNED_WEIGHT); + + noPwnageCaptchaCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHECK); + noPwnageCaptchaCharacters = data.getString(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHARACTERS); + noPwnageCaptchaLength = data.getInt(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_LENGTH); + noPwnageCaptchaQuestion = data.getString(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_QUESTION); + noPwnageCaptchaSuccess = data.getString(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_SUCCESS); + noPwnageCaptchaTries = data.getInt(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_TRIES); + + noPwnageFirstCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_FIRST_CHECK); + noPwnageFirstTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_FIRST_TIMEOUT); + noPwnageFirstWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_FIRST_WEIGHT); + + noPwnageGlobalCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_GLOBAL_CHECK); + noPwnageGlobalTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_GLOBAL_TIMEOUT); + noPwnageGlobalWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_GLOBAL_WEIGHT); + + noPwnageMoveCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_MOVE_CHECK); + noPwnageMoveTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_MOVE_TIMEOUT); + noPwnageMoveWeightBonus = data.getInt(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHT_BONUS); + noPwnageMoveWeightMalus = data.getInt(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHT_MALUS); + + noPwnageReloginCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_RELOGIN_CHECK); + noPwnageReloginTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_RELOGIN_TIMEOUT); + noPwnageReloginWarningMessage = data.getString(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_MESSAGE); + noPwnageReloginWarningNumber = data.getInt(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_NUMBER); + noPwnageReloginWarningTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_TIMEOUT); + + noPwnageRepeatCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_REPEAT_CHECK); + noPwnageRepeatTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_REPEAT_TIMEOUT); + noPwnageRepeatWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_REPEAT_WEIGHT); + + noPwnageSpeedCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_SPEED_CHECK); + noPwnageSpeedTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_SPEED_TIMEOUT); + noPwnageSpeedWeight = data.getInt(ConfPaths.CHAT_NOPWNAGE_SPEED_WEIGHT); + + noPwnageWarnLevel = data.getInt(ConfPaths.CHAT_NOPWNAGE_WARN_LEVEL); + noPwnageWarnTimeout = data.getLong(ConfPaths.CHAT_NOPWNAGE_WARN_TIMEOUT); + noPwnageWarnOthersCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_WARN_OTHERS_CHECK); + noPwnageWarnOthersMessage = data.getString(ConfPaths.CHAT_NOPWNAGE_WARN_OTHERS_MESSAGE); + noPwnageWarnPlayerCheck = data.getBoolean(ConfPaths.CHAT_NOPWNAGE_WARN_PLAYER_CHECK); + noPwnageWarnPlayerMessage = data.getString(ConfPaths.CHAT_NOPWNAGE_WARN_PLAYER_MESSAGE); + + noPwnageActions = data.getActionList(ConfPaths.CHAT_NOPWNAGE_ACTIONS, Permissions.CHAT_NOPWNAGE); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java index 1591826b..634da0f1 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/ChatData.java @@ -1,70 +1,67 @@ package fr.neatmonster.nocheatplus.checks.chat; -import fr.neatmonster.nocheatplus.checks.CheckData; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; +import java.util.HashMap; +import java.util.Map; -/** - * Player specific data for the chat checks - * +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/* + * MM'""""'YMM dP dP M""""""'YMM dP + * M' .mmm. `M 88 88 M mmmm. `M 88 + * * M MMMMMooM 88d888b. .d8888b. d8888P M MMMMM M .d8888b. d8888P .d8888b. + * M MMMMMMMM 88' `88 88' `88 88 M MMMMM M 88' `88 88 88' `88 + * M. `MMM' .M 88 88 88. .88 88 M MMMM' .M 88. .88 88 88. .88 + * MM. .dM dP dP `88888P8 dP M .MM `88888P8 dP `88888P8 + * MMMMMMMMMMM MMMMMMMMMMM */ -public class ChatData extends CheckData { +/** + * Player specific data for the chat checks. + */ +public class ChatData { - // Keep track of the violation levels for the check - public int colorVL; + /** The map containing the data per players. */ + private static Map playersMap = new HashMap(); - // Remember the player's location - public final SimpleLocation location = new SimpleLocation(); - - // Remember the last chat message or command for logging purposes - public String message = ""; - public String lastMessage = ""; - public long lastMessageTime; - - // Remember if the message is a command or not - public boolean isCommand = false; - - // Remember some other time informations about the player - public long joinTime; - public long leaveTime; - public long lastWarningTime; - public long lastRelogWarningTime; - public long lastMovedTime; - - // Remember how many time the player has repeated the same message - public int messageRepeated; - - // Remember some warning levels - public int relogWarnings; - public int speedRepeated; - - // Remember some data about captcha - public String captchaAnswer = ""; - public String captchaQuestion = ""; - public boolean captchaStarted = false; - public int captchaTries; - - // Remember if commands have been run by the player - public boolean commandsHaveBeenRun = false; - - // Remember reason and player's IP - public String reason = ""; - public String ip = ""; - - public void clear() { - location.reset(); - lastMessage = captchaAnswer = captchaQuestion = ""; - lastMessageTime = joinTime = leaveTime = lastWarningTime = lastRelogWarningTime = lastMovedTime = 0L; - messageRepeated = relogWarnings = speedRepeated = captchaTries = 0; - captchaStarted = false; + /** + * Gets the data of a specified player. + * + * @param player + * the player + * @return the data + */ + public static ChatData getData(final Player player) { + if (!playersMap.containsKey(player.getName())) + playersMap.put(player.getName(), new ChatData()); + return playersMap.get(player.getName()); } - public boolean compareLocation(final SimpleLocation l) { - return location != null && location.x == l.x && location.y == l.y && location.z == l.z; - } + // Violation levels. + public double colorVL; + public double noPwnageVL; - public void setLocation(final SimpleLocation l) { - location.x = l.x; - location.y = l.y; - location.z = l.z; + // Data of the no pwnage check. + public int noPwnageCaptchTries; + public String noPwnageGeneratedCaptcha; + public boolean noPwnageHasFilledCaptcha; + public boolean noPwnageHasStartedCaptcha; + public long noPwnageJoinTime; + public Location noPwnageLastLocation; + public String noPwnageLastMessage; + public long noPwnageLastMessageTime; + public long noPwnageLastMovedTime; + public long noPwnageLastWarningTime; + public long noPwnageLeaveTime; + public int noPwnageReloginWarnings; + public long noPwnageReloginWarningTime; + + /** + * Clear the data of the no pwnage check. + */ + public void clearNoPwnageData() { + noPwnageCaptchTries = noPwnageReloginWarnings = 0; + noPwnageJoinTime = noPwnageLastMessageTime = noPwnageLastMovedTime = noPwnageLastWarningTime = noPwnageLeaveTime = noPwnageReloginWarningTime = 0L; + noPwnageGeneratedCaptcha = noPwnageLastMessage = ""; + noPwnageLastLocation = null; } } diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatEvent.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatEvent.java deleted file mode 100644 index 658c5706..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.chat; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckEvent; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public class ChatEvent extends CheckEvent { - - public ChatEvent(final ChatCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - - @Override - public ChatCheck getCheck() { - return (ChatCheck) super.getCheck(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java b/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java index 738418a5..eadc5924 100644 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/chat/ChatListener.java @@ -1,159 +1,19 @@ package fr.neatmonster.nocheatplus.checks.chat; -import java.lang.management.ManagementFactory; +import org.bukkit.event.Listener; -import org.bukkit.ChatColor; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.player.PlayerChatEvent; -import org.bukkit.event.player.PlayerCommandPreprocessEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerLoginEvent.Result; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.checks.CheckListener; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Central location to listen to events that are - * relevant for the chat checks - * +/* + * MM'""""'YMM dP dP M""MMMMMMMM oo dP + * M' .mmm. `M 88 88 M MMMMMMMM 88 + * M MMMMMooM 88d888b. .d8888b. d8888P M MMMMMMMM dP .d8888b. d8888P .d8888b. 88d888b. .d8888b. 88d888b. + * M MMMMMMMM 88' `88 88' `88 88 M MMMMMMMM 88 Y8ooooo. 88 88ooood8 88' `88 88ooood8 88' `88 + * M. `MMM' .M 88 88 88. .88 88 M MMMMMMMM 88 88 88 88. ... 88 88 88. ... 88 + * MM. .dM dP dP `88888P8 dP M M dP `88888P' dP `88888P' dP dP `88888P' dP + * MMMMMMMMMMM MMMMMMMMMMM */ -public class ChatListener extends CheckListener { +/** + * Central location to listen to events that are relevant for the chat checks. + */ +public class ChatListener implements Listener { - private final NoPwnageCheck noPwnageCheck; - private final ArrivalsLimitCheck arrivalsLimitCheck; - private final ColorCheck colorCheck; - - public ChatListener() { - super("chat"); - - noPwnageCheck = new NoPwnageCheck(); - arrivalsLimitCheck = new ArrivalsLimitCheck(); - colorCheck = new ColorCheck(); - - } - - /** - * We listen to PlayerChat events for obvious reasons - * - * @param event - * The PlayerChat event - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void chat(final PlayerChatEvent event) { - - boolean cancelled = false; - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final ChatConfig cc = (ChatConfig) getConfig(player); - final ChatData data = (ChatData) getData(player); - - // Remember the original message - data.message = event.getMessage(); - - // Remember if it is a command or not - if (event instanceof PlayerCommandPreprocessEvent) - data.isCommand = true; - else - data.isCommand = false; - - // Now do the actual checks - - // First the nopwnage check - if (cc.noPwnageCheck && !player.hasPermission(Permissions.CHAT_NOPWNAGE)) - if (noPwnageCheck.check(player, event)) { - player.getBukkitPlayer().kickPlayer(Check.removeColors(cc.noPwnageMessagesKick)); - return; - } else - cancelled = event.isCancelled(); - - // Second the color check - if (!cancelled && cc.colorCheck && !player.hasPermission(Permissions.CHAT_COLOR)) - cancelled = colorCheck.check(player); - - // If one of the checks requested the event to be cancelled, do it - if (cancelled) - event.setCancelled(cancelled); - else - // In case one of the events modified the message, make sure that - // the new message gets used - event.setMessage(data.message); - } - - /** - * We listen to PlayerCommandPreprocess events because commands can be - * used for spamming too. - * - * @param event - * The PlayerCommandPreprocess Event - */ - @EventHandler( - priority = EventPriority.LOWEST) - public void commandPreprocess(final PlayerCommandPreprocessEvent event) { - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final ChatConfig cc = (ChatConfig) getConfig(player); - - final String command = event.getMessage().split(" ")[0].substring(1).toLowerCase(); - - // Protect the /plugins, /pl, /? commands to prevent players for seeing which plugins are installed - if (cc.protectPlugins && (command.equals("plugins") || command.equals("pl") || command.equals("?")) - && !player.hasPermission(Permissions.ADMIN_PLUGINS)) { - event.getPlayer().sendMessage( - ChatColor.RED + "I'm sorry, but you do not have permission to perform this command. " - + "Please contact the server administrators if you believe that this is in error."); - event.setCancelled(true); - return; - } - - // If OP by console only is enabled, prevent the op/deop commands - // to be used by a player who is OP or has the required permissions - if (cc.opByConsoleOnly - && (command.equals("op") - && (event.getPlayer().isOp() || player.hasPermission("bukkit.command.op.give")) || command - .equals("deop") && (event.getPlayer().isOp() || player.hasPermission("bukkit.command.op.take")))) { - event.getPlayer().sendMessage(ChatColor.RED + "This command can only be executed from the console!"); - event.setCancelled(true); - return; - } - - // This type of event is derived from PlayerChatEvent, therefore - // just treat it like that - chat(event); - } - - /** - * We listen to PlayerLogin events for the arrivalslimit check - * - * @param event - * The PlayerLogin Event - */ - @EventHandler( - priority = EventPriority.LOWEST) - public void login(final PlayerLoginEvent event) { - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final ChatConfig cc = (ChatConfig) getConfig(player); - final ChatData data = (ChatData) getData(player); - - /*** NOPWNAGE CHECK ***/ - // Check if the join is legit - if (cc.noPwnageCheck && !player.hasPermission(Permissions.CHAT_NOPWNAGE)) - if (noPwnageCheck.handleJoin(player, data, cc)) - event.disallow(Result.KICK_OTHER, Check.removeColors(cc.noPwnageMessagesKick)); - - /*** ARRIVALSLIMIT CHECK ***/ - // Do not check the players if the event is already cancelled, - // if the server has just restarted or if it is a regular player - if (event.getResult() == Result.KICK_OTHER - || System.currentTimeMillis() - ManagementFactory.getRuntimeMXBean().getStartTime() < 120000L - || System.currentTimeMillis() - event.getPlayer().getFirstPlayed() > cc.arrivalsLimitNewTime) - return; - - if (cc.arrivalsLimitCheck && arrivalsLimitCheck.check(player, data, cc)) - // If the player failed the check, disallow the login - event.disallow(Result.KICK_OTHER, cc.arrivalsLimitKickMessage); - } } diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/Color.java b/src/fr/neatmonster/nocheatplus/checks/chat/Color.java new file mode 100644 index 00000000..af724c2d --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/chat/Color.java @@ -0,0 +1,90 @@ +package fr.neatmonster.nocheatplus.checks.chat; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * MM'""""'YMM dP + * M' .mmm. `M 88 + * M MMMMMooM .d8888b. 88 .d8888b. 88d888b. + * M MMMMMMMM 88' `88 88 88' `88 88' `88 + * M. `MMM' .M 88. .88 88 88. .88 88 + * MM. .dM `88888P' dP `88888P' dP + * MMMMMMMMMMM + */ +/** + * The Color check verifies that no color codes are sent in players' messages. + */ +public class Color extends Check { + + /** + * The event triggered by this check. + */ + public class ColorEvent extends CheckEvent { + + /** + * Instantiates a new color event. + * + * @param player + * the player + */ + public ColorEvent(final Player player) { + super(player); + } + } + + /** + * Checks a player. + * + * @param player + * the player + * @param message + * the message + * @return the string + */ + public String check(final Player player, final String message) { + final ChatConfig cc = ChatConfig.getConfig(player); + final ChatData data = ChatData.getData(player); + + // If the message contains colors... + if (message.contains("\247")) { + // Increment the violation level of the player. + data.colorVL++; + + // Dispatch a color event (API). + final ColorEvent e = new ColorEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Find out if we need to remove the colors or not. + if (!e.isCancelled() && executeActions(player, cc.colorActions, data.colorVL)) + // Remove color codes. + message.replaceAll("\302\247.", "").replaceAll("\247.", ""); + } + + return message; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(ChatData.getData(player).colorVL)); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.CHAT_COLOR) && ChatConfig.getConfig(player).colorCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/ColorCheck.java b/src/fr/neatmonster/nocheatplus/checks/chat/ColorCheck.java deleted file mode 100644 index 72a18855..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/chat/ColorCheck.java +++ /dev/null @@ -1,60 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.chat; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -public class ColorCheck extends ChatCheck { - - public class ColorCheckEvent extends ChatEvent { - - public ColorCheckEvent(final ColorCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public ColorCheck() { - super("color"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final ChatConfig cc = getConfig(player); - final ChatData data = getData(player); - - if (data.message.contains("\247")) { - - data.colorVL += 1; - incrementStatistics(player, Id.CHAT_COLOR, 1); - - final boolean filter = executeActions(player, cc.colorActions, data.colorVL); - - if (filter) - // Remove color codes - data.message = data.message.replaceAll("\302\247.", "").replaceAll("\247.", ""); - } - - return false; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final ColorCheckEvent event = new ColorCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).colorVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java b/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java new file mode 100644 index 00000000..d3b3d601 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java @@ -0,0 +1,276 @@ +package fr.neatmonster.nocheatplus.checks.chat; + +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerChatEvent; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.CheckUtils; + +/* + * M"""""""`YM MM"""""""`YM + * M mmmm. M MM mmmmm M + * M MMMMM M .d8888b. M' .M dP dP dP 88d888b. .d8888b. .d8888b. .d8888b. + * M MMMMM M 88' `88 MM MMMMMMMM 88 88 88 88' `88 88' `88 88' `88 88ooood8 + * M MMMMM M 88. .88 MM MMMMMMMM 88.88b.88' 88 88 88. .88 88. .88 88. ... + * M MMMMM M `88888P' MM MMMMMMMM 8888P Y8P dP dP `88888P8 `8888P88 `88888P' + * MMMMMMMMMMM MMMMMMMMMMMM .88 + * d8888P + */ +/** + * The NoPwnage check will try to detect "spambots" (like the ones created by the PWN4G3 software). + */ +public class NoPwnage extends Check { + + /** + * The event triggered by this check. + */ + public class NoPwnageEvent extends CheckEvent { + + /** + * Instantiates a new no pwnage event. + * + * @param player + * the player + */ + public NoPwnageEvent(final Player player) { + super(player); + } + } + + /** The last message which caused ban said. */ + private String lastBanCausingMessage; + + /** The time it was when the last message which caused ban was said. */ + private long lastBanCausingMessageTime; + + /** The last message said. */ + private String lastGlobalMessage; + + /** The time it was when the last message was said. */ + private long lastGlobalMessageTime; + + private final Random random = new Random(); + + /** + * Instantiates a new no pwnage check. + */ + public NoPwnage() { + for (final Player player : Bukkit.getOnlinePlayers()) + ChatData.getData(player).noPwnageLastLocation = player.getLocation(); + } + + /** + * Checks a player (join). + * + * @param player + * the player + * @return true, if successful + */ + public boolean check(final Player player) { + final ChatConfig cc = ChatConfig.getConfig(player); + final ChatData data = ChatData.getData(player); + + boolean cancel = false; + + final long now = System.currentTimeMillis(); + + // NoPwnage will remember the time when a player leaves the server. If he returns within "time" milliseconds, he + // will get warned. If he has been warned "warnings" times already, the "commands" will be executed for him. + // Warnings get removed if the time of the last warning was more than "timeout" milliseconds ago. + if (cc.noPwnageReloginCheck && now - data.noPwnageLeaveTime < cc.noPwnageReloginTimeout) { + if (now - data.noPwnageReloginWarningTime > cc.noPwnageReloginWarningTimeout) + data.noPwnageReloginWarnings = 0; + if (data.noPwnageReloginWarnings < cc.noPwnageReloginWarningNumber) { + player.sendMessage(replaceColors(cc.noPwnageReloginWarningMessage)); + data.noPwnageReloginWarningTime = now; + data.noPwnageReloginWarnings++; + } else if (now - data.noPwnageReloginWarningTime < cc.noPwnageReloginWarningTimeout) { + // Dispatch a no pwnage event (API). + final NoPwnageEvent e = new NoPwnageEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Find out if we need to ban the player or not. + if (!e.isCancelled()) + cancel = executeActions(player, cc.noPwnageActions, data.noPwnageVL); + } + } + + // Store his location and some other data. + data.noPwnageLastLocation = player.getLocation(); + data.noPwnageJoinTime = now; + + return cancel; + } + + /** + * Checks a player (chat). + * + * @param player + * the player + * @param event + * the event + * @return true, if successful + */ + public boolean check(final Player player, final PlayerChatEvent event) { + final ChatConfig cc = ChatConfig.getConfig(player); + final ChatData data = ChatData.getData(player); + data.noPwnageVL = 0D; + + boolean cancel = false; + + if (!data.noPwnageHasFilledCaptcha) { + final String message = event.getMessage(); + final boolean isCommand = message.startsWith("/"); + final long now = System.currentTimeMillis(); + + if (cc.noPwnageCaptchaCheck && data.noPwnageHasStartedCaptcha) { + // Correct answer to the captcha? + if (message.equals(data.noPwnageGeneratedCaptcha)) { + // Yes, clear his data and do not worry anymore about him. + data.clearNoPwnageData(); + data.noPwnageHasFilledCaptcha = true; + player.sendMessage(replaceColors(cc.noPwnageCaptchaSuccess)); + } else { + // Does he failed too much times? + if (data.noPwnageCaptchTries > cc.noPwnageCaptchaTries) { + + // Dispatch a no pwnage event (API). + final NoPwnageEvent e = new NoPwnageEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Find out if we need to ban the player or not. + if (!e.isCancelled()) + cancel = executeActions(player, cc.noPwnageActions, data.noPwnageVL); + } + + // Increment his tries number counter. + data.noPwnageCaptchTries++; + + // Display the question again. + player.sendMessage(replaceColors(cc.noPwnageCaptchaQuestion.replace("[captcha]", + data.noPwnageGeneratedCaptcha))); + } + + // Cancel the event and return. + event.setCancelled(true); + return cancel; + } + + if (data.noPwnageLastLocation == null) + data.noPwnageLastLocation = player.getLocation(); + else if (!data.noPwnageLastLocation.equals(player.getLocation())) { + data.noPwnageLastLocation = player.getLocation(); + data.noPwnageLastMovedTime = now; + } + + // NoPwnage will remember the last message that caused someone to get banned. If a player repeats that + // message within "timeout" milliseconds, the suspicion will be increased by "weight". + if (!isCommand && cc.noPwnageBannedCheck && now - lastBanCausingMessageTime < cc.noPwnageBannedTimeout + && CheckUtils.isSimilar(message, lastBanCausingMessage, 0.8f)) + data.noPwnageVL += cc.noPwnageBannedWeight; + + // NoPwnage will check if a player sends his first message within "timeout" milliseconds after his login. If + // he does, increase suspicion by "weight". + if (cc.noPwnageFirstCheck && now - data.noPwnageJoinTime < cc.noPwnageFirstTimeout) + data.noPwnageVL += cc.noPwnageFirstWeight; + + // NoPwnage will check if a player repeats a message that has been sent by another player just before, + // within "timeout". If he does, suspicion will be increased by "weight". + if (!isCommand && cc.noPwnageGlobalCheck && now - lastGlobalMessageTime < cc.noPwnageGlobalTimeout + && CheckUtils.isSimilar(message, lastGlobalMessage, 0.8f)) + data.noPwnageVL += cc.noPwnageGlobalWeight; + + // NoPwnage will check if a player sends messages too fast. If a message is sent within "timeout" + // milliseconds after the previous message, increase suspicion by "weight". + if (cc.noPwnageSpeedCheck && now - data.noPwnageLastMessageTime < cc.noPwnageSpeedTimeout) + data.noPwnageVL += cc.noPwnageSpeedWeight; + + // NoPwnage will check if a player repeats his messages within the "timeout" timeframe. Even if the message + // is a bit different, it will be counted as being a repetition. The suspicion is increased by "weight". + if (!isCommand && cc.noPwnageRepeatCheck && now - data.noPwnageLastMessageTime < cc.noPwnageRepeatTimeout + && CheckUtils.isSimilar(message, data.noPwnageLastMessage, 0.8f)) + data.noPwnageVL += cc.noPwnageRepeatWeight; + + // NoPwnage will check if a player moved within the "timeout" timeframe. If he did move, the suspicion will + // be reduced by the "weightbonus" value. If he did not move, the suspicion will be increased by + // "weightmalus" value. + if (cc.noPwnageMoveCheck && now - data.noPwnageLastMovedTime < cc.noPwnageMoveTimeout) + data.noPwnageVL -= cc.noPwnageMoveWeightBonus; + else + data.noPwnageVL += cc.noPwnageMoveWeightMalus; + + // Should a player that reaches the "warnLevel" get a text message telling him that he is under suspicion of + // being a bot. + boolean warned = false; + if (cc.noPwnageWarnPlayerCheck && now - data.noPwnageLastWarningTime < cc.noPwnageWarnTimeout) { + data.noPwnageVL += 100; + warned = true; + } + + if (cc.noPwnageWarnPlayerCheck && data.noPwnageVL > cc.noPwnageWarnLevel && !warned) { + player.sendMessage(replaceColors(cc.noPwnageWarnPlayerMessage)); + data.noPwnageLastWarningTime = now; + } else if (data.noPwnageVL > cc.noPwnageLevel) + if (cc.noPwnageCaptchaCheck && !data.noPwnageHasStartedCaptcha) { + // Display a captcha to the player. + for (int i = 0; i < cc.noPwnageCaptchaLength; i++) + data.noPwnageGeneratedCaptcha += cc.noPwnageCaptchaCharacters.charAt(random + .nextInt(cc.noPwnageCaptchaCharacters.length())); + player.sendMessage(replaceColors(cc.noPwnageCaptchaQuestion.replace("[captcha]", + data.noPwnageGeneratedCaptcha))); + data.noPwnageHasStartedCaptcha = true; + event.setCancelled(true); + } else { + lastBanCausingMessage = message; + data.noPwnageLastWarningTime = lastBanCausingMessageTime = now; + if (cc.noPwnageWarnOthersCheck) + Bukkit.broadcastMessage(replaceColors(cc.noPwnageWarnOthersMessage.replace("[player]", + player.getName()))); + event.setCancelled(true); + + // Dispatch a no pwnage event (API). + final NoPwnageEvent e = new NoPwnageEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Find out if we need to ban the player or not. + if (!e.isCancelled()) + cancel = executeActions(player, cc.noPwnageActions, data.noPwnageVL); + } + + // Store the message and some other data. + data.noPwnageLastMessage = message; + data.noPwnageLastMessageTime = now; + lastGlobalMessage = message; + lastGlobalMessageTime = now; + } + + return cancel; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(ChatData.getData(player).noPwnageVL)); + else if (wildcard == ParameterName.IP) + return player.getAddress().toString().substring(1).split(":")[0]; + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.CHAT_NOPWNAGE) && ChatConfig.getConfig(player).noPwnageCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnageCheck.java b/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnageCheck.java deleted file mode 100644 index ed914193..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/chat/NoPwnageCheck.java +++ /dev/null @@ -1,359 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.chat; - -import java.util.Random; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerChatEvent; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.config.ConfPaths; -import fr.neatmonster.nocheatplus.config.ConfigManager; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.utilities.locations.SimpleLocation; - -/** - * A check used to verify if players aren't spam bots - * - */ -public class NoPwnageCheck extends ChatCheck { - public class NoPwnageCheckEvent extends ChatEvent { - - public NoPwnageCheckEvent(final NoPwnageCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - private String lastBanCausingMessage; - private long lastBanCausingMessageTime; - private String lastGlobalMessage; - private long lastGlobalMessageTime; - - private int globalRepeated; - - private final Random random = new Random(); - - public NoPwnageCheck() { - super("nopwnage"); - - // Store the players' location - for (final Player player : Bukkit.getOnlinePlayers()) { - final ChatData data = getData(NCPPlayer.getPlayer(player)); - data.location.setLocation(player.getLocation()); - } - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final ChatConfig cc = getConfig(player); - final ChatData data = getData(player); - final PlayerChatEvent event = (PlayerChatEvent) args[0]; - - boolean cancel = false; - - // If the player has filled out the captcha, return - if (data.commandsHaveBeenRun || !player.getBukkitPlayer().isOnline()) - return cancel; - - if (cc.noPwnageCaptchaCheck && data.captchaStarted) { - // Correct answer? - if (data.message.equals(data.captchaAnswer)) { - // His reply was valid, he isn't a spambot - data.clear(); - player.sendMessage(replaceColors(cc.noPwnageMessagesCaptchaSuccess)); - } else { - // Display the question again - player.sendMessage(data.captchaQuestion); - - // He failed too much times - if (data.captchaTries > cc.noPwnageCaptchaTries) - if (player.getBukkitPlayer().isOnline()) { - // Execute the commands, it's a spambot - data.reason = "failed captcha"; - cancel = executeActions(player, cc.noPwnageActions, 0); - } - - // Increment the number of times he replied - data.captchaTries++; - } - event.setCancelled(true); - return cancel; - } - - // Do some pre-testing for the next check - final long now = System.currentTimeMillis(); - final SimpleLocation location = new SimpleLocation(); - location.setLocation(player.getLocation()); - - double suspicion = 0; - - if (data.location == null) - data.setLocation(location); - else if (!data.compareLocation(location)) { - data.setLocation(location); - data.lastMovedTime = now; - } - - // Banned check (cf. documentation) - if (!data.isCommand && cc.noPwnageBannedCheck && now - lastBanCausingMessageTime < cc.noPwnageBannedTimeout - && similar(data.message, lastBanCausingMessage)) - suspicion += cc.noPwnageBannedWeight; - - // First check (cf. documentation) - if (cc.noPwnageFirstCheck && now - data.joinTime <= cc.noPwnageFirstTimeout) - suspicion += cc.noPwnageFirstWeight; - - // Global check (cf. documentation) - if (!data.isCommand && cc.noPwnageGlobalCheck && now - lastGlobalMessageTime < cc.noPwnageGlobalTimeout - && similar(data.message, lastGlobalMessage)) { - final int added = (globalRepeated + 2) * cc.noPwnageGlobalWeight / 2; - globalRepeated++; - suspicion += added; - } else - globalRepeated = 0; - - // Speed check (cf. documentation) - if (cc.noPwnageSpeedCheck && now - data.lastMessageTime <= cc.noPwnageSpeedTimeout) { - int added = (data.speedRepeated + 2) * cc.noPwnageSpeedWeight / 2; - data.speedRepeated++; - if (data.isCommand) - added /= 4; - suspicion += added; - } else - data.speedRepeated = 0; - - // Repeat check (cf. documentation) - if (!data.isCommand && cc.noPwnageRepeatCheck && now - data.lastMessageTime <= cc.noPwnageRepeatTimeout - && similar(data.message, data.lastMessage)) { - - final int added = (data.messageRepeated + 2) * cc.noPwnageRepeatWeight / 2; - data.messageRepeated++; - suspicion += added; - } else - data.messageRepeated = 0; - - boolean warned = false; - if (cc.noPwnageWarnPlayers && now - data.lastWarningTime <= cc.noPwnageWarnTimeout) { - suspicion += 100; - warned = true; - } - - // Move checks (cf. documentation) - if (cc.noPwnageMoveCheck && now - data.lastMovedTime <= cc.noPwnageMoveTimeout) - suspicion -= cc.noPwnageMoveWeightBonus; - else - suspicion += cc.noPwnageMoveWeightMalus; - - // Warn player - if (cc.noPwnageWarnPlayers && suspicion >= cc.noPwnageWarnLevel && !warned) { - data.lastWarningTime = now; - warnPlayer(player); - } else if (suspicion >= cc.noPwnageBanLevel) - if (cc.noPwnageCaptchaCheck && !data.captchaStarted) { - // Display the captcha to the player - data.captchaStarted = true; - final String captcha = generateCaptcha(cc); - data.captchaAnswer = captcha; - data.captchaQuestion = replaceColors(cc.noPwnageMessagesCaptchaQuestion).replace("[captcha]", captcha); - event.setCancelled(true); - player.sendMessage(data.captchaQuestion); - } else if (player.getBukkitPlayer().isOnline()) { - // Execute the commands, it's a spambot - lastBanCausingMessage = data.message; - lastBanCausingMessageTime = now; - data.lastWarningTime = now; - if (cc.noPwnageWarnOthers) - warnOthers(player); - data.reason = "spambotlike behaviour"; - event.setCancelled(true); - return executeActions(player, cc.noPwnageActions, 0); - } - - // Remember his message and some other data - data.lastMessage = data.message; - data.lastMessageTime = now; - - lastGlobalMessage = data.message; - lastGlobalMessageTime = now; - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - getData(player).ip = player.getBukkitPlayer().getAddress().toString().substring(1).split(":")[0]; - getData(player).commandsHaveBeenRun = true; - - final NoPwnageCheckEvent event = new NoPwnageCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - /** - * This function is used to generate a captcha - * - * @param cc - * The ChatConfig - * @return - * The captcha generated - */ - private String generateCaptcha(final ChatConfig cc) { - - final StringBuilder b = new StringBuilder(); - - for (int i = 0; i < cc.noPwnageCaptchaLength; i++) - b.append(cc.noPwnageCaptchaCharacters.charAt(random.nextInt(cc.noPwnageCaptchaCharacters.length()))); - - return b.toString(); - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.REASON) - return getData(player).reason; - else if (wildcard == ParameterName.IP) - return getData(player).ip; - else - return super.getParameter(wildcard, player); - } - - public boolean handleJoin(final NCPPlayer player, final ChatData data, final ChatConfig cc) { - boolean cancel = false; - final long now = System.currentTimeMillis(); - - // Re-login check (cf. documentation) - if (cc.noPwnageRelogCheck && now - data.leaveTime <= cc.noPwnageRelogTime) { - if (now - data.lastRelogWarningTime >= cc.noPwnageRelogTimeout) - data.relogWarnings = 0; - - if (data.relogWarnings < cc.noPwnageRelogWarnings) { - player.sendMessage(replaceColors(ConfigManager.getConfigFile().getString(ConfPaths.LOGGING_PREFIX) - + cc.noPwnageMessagesWarnRelog)); - data.lastRelogWarningTime = now; - data.relogWarnings++; - } else if (now - data.lastRelogWarningTime < cc.noPwnageRelogTimeout) { - // Run the commands, it's a spambot - data.reason = "relogged too fast"; - cancel = executeActions(player, cc.noPwnageActions, 0); - } - } - - // Remember his location - final SimpleLocation location = new SimpleLocation(); - location.setLocation(player.getLocation()); - data.setLocation(location); - data.joinTime = now; - - data.commandsHaveBeenRun = false; - - return cancel; - } - - /** - * This function return the minimum between the 3 Integers - * - * @param a - * The first Integer - * @param b - * The second Integer - * @param c - * The third Integer - * @return - * The minimum - */ - private int minimum(final int a, final int b, final int c) { - int mi; - - mi = a; - if (b < mi) - mi = b; - if (c < mi) - mi = c; - return mi; - } - - /** - * This function is used to know if two messages are similar - * - * @param message1 - * The first message - * @param message2 - * The second message - * @return - * true if the messages are similar, false otherwise - */ - private boolean similar(final String message1, final String message2) { - return message1 != null && message2 != null - && stringDifference(message1, message2) < 1 + message1.length() / 10; - } - - private int stringDifference(final String s, final String t) { - int d[][]; - int n; - int m; - int i; - int j; - char s_i; - char t_j; - int cost; - - n = s.length(); - m = t.length(); - if (n == 0) - return m; - if (m == 0) - return n; - d = new int[n + 1][m + 1]; - for (i = 0; i <= n; i++) - d[i][0] = i; - - for (j = 0; j <= m; j++) - d[0][j] = j; - for (i = 1; i <= n; i++) { - - s_i = s.charAt(i - 1); - - for (j = 1; j <= m; j++) { - - t_j = t.charAt(j - 1); - - if (s_i == t_j) - cost = 0; - else - cost = 1; - - d[i][j] = minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); - - } - - } - return d[n][m]; - } - - /** - * This function is used to warn the other player - * - * @param player - * The Player - */ - private void warnOthers(final NCPPlayer player) { - Bukkit.getServer().broadcastMessage( - replaceColors(getConfig(player).noPwnageMessagesWarnOthers).replace("[player]", player.getName())); - } - - /** - * This function is used to warn the player - * - * @param player - * The Player - */ - private void warnPlayer(final NCPPlayer player) { - player.sendMessage(replaceColors(ConfigManager.getConfigFile().getString(ConfPaths.LOGGING_PREFIX) - + getConfig(player).noPwnageMessagesWarnPlayer)); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/AngleCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/AngleCheck.java deleted file mode 100644 index c70915da..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/AngleCheck.java +++ /dev/null @@ -1,206 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.Location; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * A check used to verify if the player isn't using a forcefield in order to attack multiple entities at the same time - * - * Thanks asofold for the original idea! - */ -public class AngleCheck extends FightCheck { - - public class AngleCheckEvent extends FightEvent { - - public AngleCheckEvent(final AngleCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public class AngleData implements Comparable { - public final long time; - public final double x; - public final double y; - public final double z; - public final float yaw; - - public AngleData(final Location location) { - time = System.currentTimeMillis(); - x = location.getX(); - y = location.getY(); - z = location.getZ(); - yaw = location.getYaw(); - } - - @Override - public int compareTo(final AngleData otherData) { - if (otherData.time < time) - return 1; - else if (otherData.time == time) - return 0; - else - return -1; - } - - public boolean shouldBeRemoved() { - return System.currentTimeMillis() - time > 1000L; - } - } - - public AngleCheck() { - super("angle", Permissions.FIGHT_ANGLE); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - // Add the current attack to the list - data.attacks.add(new AngleData(player.getLocation())); - - // Sort the list of the attacks for the oldest to the newest - Collections.sort(data.attacks, Collections.reverseOrder()); - - // Declare 3 list which will contain the times, yaws and pitches - final List dTime = new ArrayList(); - final List dYaw = new ArrayList(); - final List dMove = new ArrayList(); - - AngleData previousAngleData = null; - for (final AngleData angleData : new ArrayList(data.attacks)) - // If the data is older than a second... - if (angleData.shouldBeRemoved()) - // ...remove it from the list - data.attacks.remove(angleData); - else { - // If we have a previous data (to calculate deltas)... - if (previousAngleData != null) { - // ...calculate the time delta... - dTime.add(Math.abs(previousAngleData.time - angleData.time)); - // ...the yaw delta... - dYaw.add(Math.abs(previousAngleData.yaw - angleData.yaw) % 360F); - // ...the move delta - dMove.add(Math.sqrt(Math.pow(previousAngleData.x - angleData.x, 2) - + Math.pow(previousAngleData.y - angleData.y, 2) - + Math.pow(previousAngleData.z - angleData.z, 2))); - } - // Remember this data to calculate the next deltas - previousAngleData = angleData; - } - - /** - * TIME - **/ - // First we calculate the average time between each attack - double mTime = 0D; - for (final long time : dTime) - mTime += time; - if (dTime.size() != 0D) - mTime /= dTime.size(); - - // Then if the time is superior to 150 ms, we set the violation to 0... - if (mTime == 0D || mTime > 150D) - mTime = 0D; - - // ...but otherwise we calculate a percentage of violation - else - mTime = 100D * (150D - mTime) / 150D; - - /** - * YAW - **/ - // First we calculate the average yaw change between each attack - double mYaw = 0D; - for (final double yaw : dYaw) - mYaw += yaw; - if (dYaw.size() != 0D) - mYaw /= dYaw.size(); - - // Then if the yaw is inferior to 50°, we set the violation to 0... - if (mYaw == 0D || mYaw < 50D) - mYaw = 0D; - - // ...but otherwise we calculate a percentage of violation - else - mYaw = 100D * (360D - mYaw) / 360D; - - /** - * MOVE - **/ - // First we calculate the average move between each attack - double mMove = 0D; - for (final double move : dMove) - mMove += move; - if (dMove.size() != 0) - mMove /= dMove.size(); - - // Then, if the move is bigger than 0.2 block(s), we set the violation to 0... - if (mMove == 0D || mMove > 0.2D) - mMove = 0D; - - // ...but otherwise we calculate a percentage of violation - else - mMove = 100D * (0.2D - mMove) / 0.2D; - - // Now we are ready to make the average of the three "checks" violation level - // Each "check" has his coefficient: 5 for the time, 3 for the yaw, 2 for the move - final double mTotal = (5D * mTime + 3D * mYaw + 2D * mMove) / 10D; - - // If the total is superior the value defined in the configuration file... - if (mTotal > cc.angleThreshold) { - // If there was lag, don't count it towards statistics and vl... - if (!NoCheatPlus.skipCheck()) { - // ...otherwise increment the violation level... - data.angleVL += mTotal; - // ...and the statistics - incrementStatistics(player, Id.FI_ANGLE, mTotal); - } - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.angleActions, data.angleVL); - - } else - // Otherwise reward the player by lowering his violation level - data.angleVL *= 0.98; - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final AngleCheckEvent event = new AngleCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).angleVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.angleCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/CriticalCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/CriticalCheck.java deleted file mode 100644 index f0ce83a8..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/CriticalCheck.java +++ /dev/null @@ -1,112 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.MobEffectList; - -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.craftbukkit.entity.CraftPlayer; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -public class CriticalCheck extends FightCheck { - - public class CriticalCheckEvent extends FightEvent { - - public CriticalCheckEvent(final CriticalCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public CriticalCheck() { - super("critical", Permissions.FIGHT_CRITICAL); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - // We'll need the entity to do all the important stuff - final EntityPlayer entity = ((CraftPlayer) data.damager).getHandle(); - - // First we're going to check if the entity is on ladder - // Get the type of the block the entity is currently on - final int type = data.damager.getWorld().getBlockTypeIdAt((int) Math.floor(entity.locX), - (int) Math.floor(entity.locY), (int) Math.floor(entity.locZ)); - // Check if this block if a ladder/vine or not - final boolean isOnLadder = type == Material.LADDER.getId() || type == Material.VINE.getId(); - - // Then we're going to check if the entity is in water - // Get the entity's precise location - final PreciseLocation location = new PreciseLocation(); - location.x = entity.locX; - location.y = entity.locY; - location.z = entity.locZ; - // Check if the entity is in water - final boolean isInWater = CheckUtils.isLiquid(CheckUtils.evaluateLocation(data.damager.getWorld(), location)); - - // Check the hit was a critical hit or not (fallDistance > 0, entity in - // the air, not on ladder, not in water and no blindness effect) - if (entity.fallDistance > 0.0F && !entity.onGround && !isOnLadder && !isInWater - && !entity.hasEffect(MobEffectList.BLINDNESS)) - // That was a critical hit, now check if the player has jumped and not - // just a sent a packet to mislead the server - if (data.damager.getFallDistance() < cc.criticalFallDistance - || Math.abs(data.damager.getVelocity().getY()) < cc.criticalVelocity) { - - final double deltaFallDistance = cc.criticalFallDistance - data.damager.getFallDistance() - / cc.criticalFallDistance; - final double deltaVelocity = cc.criticalVelocity - Math.abs(data.damager.getVelocity().getY()) - / cc.criticalVelocity; - final double delta = deltaFallDistance > 0D ? deltaFallDistance - : 0D + deltaVelocity > 0D ? deltaVelocity : 0D; - // Player failed the check, but this is influenced by lag, - // so don't do it if there was lag - if (!NoCheatPlus.skipCheck()) { - // Increment the violation level - data.criticalVL += delta; - // Increment the statisctics of the player - incrementStatistics(player, Id.FI_CRITICAL, delta); - } - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.criticalActions, data.criticalVL); - } - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final CriticalCheckEvent event = new CriticalCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).criticalVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.criticalCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/DirectionCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/DirectionCheck.java deleted file mode 100644 index 57ecba90..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/DirectionCheck.java +++ /dev/null @@ -1,125 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import net.minecraft.server.Entity; -import net.minecraft.server.EntityComplex; -import net.minecraft.server.EntityComplexPart; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The DirectionCheck will find out if a player tried to interact with something - * that's not in his field of view. - * - */ -public class DirectionCheck extends FightCheck { - - public class DirectionCheckEvent extends FightEvent { - - public DirectionCheckEvent(final DirectionCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public DirectionCheck() { - super("direction", Permissions.FIGHT_DIRECTION); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - final long time = System.currentTimeMillis(); - - // Get the damagee (entity that got hit) - final Entity entity = data.damagee; - - // Safeguard, if entity is complex, this check will fail - // due to giant and hard to define hitboxes - if (entity instanceof EntityComplex || entity instanceof EntityComplexPart) - return false; - - // Find out how wide the entity is - final float width = entity.length > entity.width ? entity.length : entity.width; - // entity.height is broken and will always be 0, therefore - // calculate height instead based on boundingBox - final double height = entity.boundingBox.e - entity.boundingBox.b; - - // How far "off" is the player with his aim. We calculate from the - // players eye location and view direction to the center of the target - // entity. If the line of sight is more too far off, "off" will be - // bigger than 0 - final double off = CheckUtils.directionCheck(player, entity.locX, entity.locY + height / 2D, entity.locZ, - width, height, cc.directionPrecision); - - if (off < 0.1D) - // Player did probably nothing wrong - // reduce violation counter to reward him - data.directionVL *= 0.80D; - else { - // Player failed the check - // Increment violation counter and statistics, but only if there - // wasn't serious lag - if (!NoCheatPlus.skipCheck()) { - final double sqrt = Math.sqrt(off); - data.directionVL += sqrt; - incrementStatistics(player, Id.FI_DIRECTION, sqrt); - } - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.directionActions, data.directionVL); - - if (cancel) - // if we should cancel, remember the current time too - data.directionLastViolationTime = time; - } - - // If the player is still in penalty time, cancel the event anyway - if (data.directionLastViolationTime + cc.directionPenaltyTime > time) { - // A safeguard to avoid people getting stuck in penalty time - // indefinitely in case the system time of the server gets changed - if (data.directionLastViolationTime > time) - data.directionLastViolationTime = 0; - - // He is in penalty time, therefore request cancelling of the event - return true; - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final DirectionCheckEvent event = new DirectionCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).directionVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.directionCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightCheck.java deleted file mode 100644 index 589680ea..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightCheck.java +++ /dev/null @@ -1,31 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * Abstract base class for Fight checks, provides some convenience - * methods for access to data and config that's relevant to this checktype - */ -public abstract class FightCheck extends Check { - - public final String permission; - - public FightCheck(final String name, final String permission) { - super("fight." + name, FightConfig.class, FightData.class); - - this.permission = permission; - } - - public abstract boolean check(final NCPPlayer player, final Object... args); - - public FightConfig getConfig(final NCPPlayer player) { - return (FightConfig) player.getConfig(this); - } - - public FightData getData(final NCPPlayer player) { - return (FightData) player.getData(this); - } - - public abstract boolean isEnabled(final FightConfig cc); -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java deleted file mode 100644 index 7673799f..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightConfig.java +++ /dev/null @@ -1,91 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckConfig; -import fr.neatmonster.nocheatplus.config.ConfPaths; -import fr.neatmonster.nocheatplus.config.ConfigFile; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Configurations specific for the "Fight" checks - * Every world gets one of these assigned to it, or if a world doesn't get - * it's own, it will use the "global" version - * - */ -public class FightConfig extends CheckConfig { - - public final boolean directionCheck; - public final double directionPrecision; - public final ActionList directionActions; - public final long directionPenaltyTime; - - public final boolean noswingCheck; - public final ActionList noswingActions; - - public final boolean reachCheck; - public final double reachLimit; - public final long reachPenaltyTime; - public final ActionList reachActions; - - public final int speedAttackLimit; - public final ActionList speedActions; - public final boolean speedCheck; - - public final boolean godmodeCheck; - public final ActionList godmodeActions; - - public final boolean instanthealCheck; - public final ActionList instanthealActions; - - public final boolean knockbackCheck; - public final long knockbackInterval; - public final ActionList knockbackActions; - - public final boolean criticalCheck; - public final double criticalFallDistance; - public final double criticalVelocity; - public final ActionList criticalActions; - - public final boolean angleCheck; - public final double angleThreshold; - public final ActionList angleActions; - - public FightConfig(final ConfigFile data) { - - directionCheck = data.getBoolean(ConfPaths.FIGHT_DIRECTION_CHECK); - directionPrecision = data.getInt(ConfPaths.FIGHT_DIRECTION_PRECISION) / 100D; - directionPenaltyTime = data.getInt(ConfPaths.FIGHT_DIRECTION_PENALTYTIME); - directionActions = data.getActionList(ConfPaths.FIGHT_DIRECTION_ACTIONS, Permissions.FIGHT_DIRECTION); - - noswingCheck = data.getBoolean(ConfPaths.FIGHT_NOSWING_CHECK); - noswingActions = data.getActionList(ConfPaths.FIGHT_NOSWING_ACTIONS, Permissions.FIGHT_NOSWING); - - reachCheck = data.getBoolean(ConfPaths.FIGHT_REACH_CHECK); - reachLimit = data.getInt(ConfPaths.FIGHT_REACH_LIMIT) / 100D; - reachPenaltyTime = data.getInt(ConfPaths.FIGHT_REACH_PENALTYTIME); - reachActions = data.getActionList(ConfPaths.FIGHT_REACH_ACTIONS, Permissions.FIGHT_REACH); - - speedCheck = data.getBoolean(ConfPaths.FIGHT_SPEED_CHECK); - speedActions = data.getActionList(ConfPaths.FIGHT_SPEED_ACTIONS, Permissions.FIGHT_SPEED); - speedAttackLimit = data.getInt(ConfPaths.FIGHT_SPEED_ATTACKLIMIT); - - godmodeCheck = data.getBoolean(ConfPaths.FIGHT_GODMODE_CHECK); - godmodeActions = data.getActionList(ConfPaths.FIGHT_GODMODE_ACTIONS, Permissions.FIGHT_GODMODE); - - instanthealCheck = data.getBoolean(ConfPaths.FIGHT_INSTANTHEAL_CHECK); - instanthealActions = data.getActionList(ConfPaths.FIGHT_INSTANTHEAL_ACTIONS, Permissions.FIGHT_INSTANTHEAL); - - knockbackCheck = data.getBoolean(ConfPaths.FIGHT_KNOCKBACK_CHECK); - knockbackInterval = data.getLong(ConfPaths.FIGHT_KNOCKBACK_INTERVAL); - knockbackActions = data.getActionList(ConfPaths.FIGHT_KNOCKBACK_ACTIONS, Permissions.FIGHT_KNOCKBACK); - - criticalCheck = data.getBoolean(ConfPaths.FIGHT_CRITICAL_CHECK); - criticalFallDistance = data.getDouble(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE); - criticalVelocity = data.getDouble(ConfPaths.FIGHT_CRITICAL_VELOCITY); - criticalActions = data.getActionList(ConfPaths.FIGHT_CRITICAL_ACTIONS, Permissions.FIGHT_CRITICAL); - - angleCheck = data.getBoolean(ConfPaths.FIGHT_ANGLE_CHECK); - angleThreshold = data.getDouble(ConfPaths.FIGHT_ANGLE_THRESHOLD); - angleActions = data.getActionList(ConfPaths.FIGHT_ANGLE_ACTIONS, Permissions.FIGHT_ANGLE); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java deleted file mode 100644 index eb2dc8e2..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightData.java +++ /dev/null @@ -1,66 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import java.util.ArrayList; -import java.util.List; - -import net.minecraft.server.Entity; - -import org.bukkit.entity.Player; - -import fr.neatmonster.nocheatplus.checks.CheckData; -import fr.neatmonster.nocheatplus.checks.fight.AngleCheck.AngleData; - -/** - * Player specific data for the fight checks - * - */ -public class FightData extends CheckData { - - // Keep track of the violation levels of the checks - public double directionVL; - public double noswingVL; - public double reachVL; - public int speedVL; - public double godmodeVL; - public double instanthealVL; - public double knockbackVL; - public double criticalVL; - public double angleVL; - - // For checks that have penalty time - public long directionLastViolationTime; - public long reachLastViolationTime; - - // Godmode check needs to know these - public long godmodeLastDamageTime; - public int godmodeLastAge; - public int godmodeBuffer = 40; - - // Last time player regenerated health by satiation - public long instanthealLastRegenTime; - - // Three seconds buffer to smooth out lag - public long instanthealBuffer = 3000; - - // While handling an event, use this to keep the attacked entity - public Entity damagee; - - // Remember the player who attacked the entity - public Player damager; - - // The player swung his arm - public boolean armswung = true; - - // For some reason the next event should be ignored - public boolean skipNext = false; - - // Keep track of time and amount of attacks - public long speedTime; - public int speedAttackCount; - - // Remember when the player has toggled his sprint mode - public long sprint = 0L; - - // Store the player's attacks - public final List attacks = new ArrayList(); -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightEvent.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightEvent.java deleted file mode 100644 index 0ff12fd5..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckEvent; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public class FightEvent extends CheckEvent { - - public FightEvent(final FightCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - - @Override - public FightCheck getCheck() { - return (FightCheck) super.getCheck(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java b/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java deleted file mode 100644 index 4909dff7..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/FightListener.java +++ /dev/null @@ -1,258 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.craftbukkit.entity.CraftEntity; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityDamageEvent.DamageCause; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent; -import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason; -import org.bukkit.event.player.PlayerAnimationEvent; -import org.bukkit.event.player.PlayerToggleSprintEvent; - -import fr.neatmonster.nocheatplus.checks.CheckListener; -import fr.neatmonster.nocheatplus.config.ConfPaths; -import fr.neatmonster.nocheatplus.config.ConfigManager; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Central location to listen to events that are - * relevant for the fight checks - * - */ -public class FightListener extends CheckListener { - - private final List checks = new ArrayList(5); - - private final GodmodeCheck godmodeCheck; - private final InstanthealCheck instanthealCheck; - - public FightListener() { - super("fight"); - - // Keep these in a list, because they can be executed in a bundle - checks.add(new SpeedCheck()); - checks.add(new NoswingCheck()); - checks.add(new DirectionCheck()); - checks.add(new ReachCheck()); - checks.add(new KnockbackCheck()); - checks.add(new CriticalCheck()); - checks.add(new AngleCheck()); - - godmodeCheck = new GodmodeCheck(); - instanthealCheck = new InstanthealCheck(); - } - - /** - * We listen to PlayerAnimationEvent because it is used for arm swinging - * - * @param event - * The PlayerAnimationEvent - */ - @EventHandler( - priority = EventPriority.MONITOR) - protected void armSwing(final PlayerAnimationEvent event) { - // Set a flag telling us that the arm has been swung - ((FightData) getData(NCPPlayer.getPlayer(event.getPlayer()))).armswung = true; - } - - /** - * There is an unofficial agreement that if a plugin wants an attack to - * not get checked by NoCheatPlus, it either has to use a Damage type different - * from ENTITY_ATTACK or fire an event with damage type CUSTOM and damage - * 0 directly before the to-be-ignored event. - * - * @param event - * The EntityDamageByEntityEvent - */ - private void customDamage(final EntityDamageByEntityEvent event) { - - final NCPPlayer player = NCPPlayer.getPlayer((Player) event.getDamager()); - final FightData data = (FightData) getData(player); - - // Skip the next damage event, because it is with high probability - // something from the Heroes plugin - data.skipNext = true; - } - - /** - * We listen to death events to prevent a very specific method of doing - * godmode. - * - * @param event - * The EntityDeathEvent - */ - @EventHandler( - priority = EventPriority.MONITOR) - protected void death(final EntityDeathEvent event) { - // Only interested in dying players - if (!(event.getEntity() instanceof CraftPlayer)) - return; - - godmodeCheck.death((CraftPlayer) event.getEntity()); - } - - /** - * We listen to EntityDamage events for obvious reasons - * - * @param event - * The EntityDamage Event - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void entityDamage(final EntityDamageEvent event) { - - // Filter some unwanted events right now - if (!(event instanceof EntityDamageByEntityEvent)) - return; - - final EntityDamageByEntityEvent e = (EntityDamageByEntityEvent) event; - if (!(e.getDamager() instanceof Player)) - return; - - if (e.getCause() == DamageCause.ENTITY_ATTACK) - normalDamage(e); - else if (e.getCause() == DamageCause.CUSTOM) - customDamage(e); - } - - /** - * We listen to EntityDamage events (again) for obvious reasons - * - * @param event - * The EntityDamage Event - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOW) - public void entityDamageForGodmodeCheck(final EntityDamageEvent event) { - - // Filter unwanted events right here - final Entity entity = event.getEntity(); - if (!(entity instanceof Player) || entity.isDead()) - return; - - final NCPPlayer player = NCPPlayer.getPlayer((Player) entity); - final FightConfig cc = (FightConfig) getConfig(player); - - if (!godmodeCheck.isEnabled(cc) || player.hasPermission(godmodeCheck.permission)) - return; - - // Run the godmode check on the attacked player - final boolean cancelled = godmodeCheck.check(NCPPlayer.getPlayer((Player) entity)); - - // It requested to "cancel" the players invulnerability, so set his - // noDamageTicks to 0 - if (cancelled) - // Remove the invulnerability from the player - player.getBukkitPlayer().setNoDamageTicks(0); - } - - /** - * A player attacked something with DamageCause ENTITY_ATTACK. That's most - * likely what we want to really check. - * - * @param event - * The EntityDamageByEntityEvent - */ - private void normalDamage(final EntityDamageByEntityEvent event) { - - final Player damager = (Player) event.getDamager(); - final NCPPlayer player = NCPPlayer.getPlayer(damager); - final FightConfig cc = (FightConfig) getConfig(player); - final FightData data = (FightData) getData(player); - - // For some reason we decided to skip this event anyway - if (data.skipNext) { - data.skipNext = false; - return; - } - - boolean cancelled = false; - - // Get the attacked entity and remember it - data.damagee = ((CraftEntity) event.getEntity()).getHandle(); - - // Remember the attacker - data.damager = damager; - - // Run through the four main checks - for (final FightCheck check : checks) - // If it should be executed, do it - if (!cancelled && check.isEnabled(cc) && !player.hasPermission(check.permission)) - cancelled = check.check(player); - - final boolean blockingCheck = !ConfigManager.getConfFile(player.getWorld().getName()).getBoolean( - ConfPaths.MOVING_RUNFLY_ALLOWFASTBLOCKING); - if (!cancelled && blockingCheck && player.getBukkitPlayer().isBlocking()) - cancelled = true; - - // Forget the attacked entity (to allow garbage collecting, etc.) - data.damagee = null; - - // Forget the attacker (to allow garbage collecting, etc.) - data.damager = null; - - // One of the checks requested the event to be cancelled, so do it - if (cancelled) - event.setCancelled(cancelled); - } - - /** - * We listen to EntityRegainHealth events of type "Satiated" - * for instantheal check - * - * @param event - * The EntityRegainHealth Event - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void satiatedRegen(final EntityRegainHealthEvent event) { - - if (!(event.getEntity() instanceof Player) || event.getRegainReason() != RegainReason.SATIATED) - return; - - boolean cancelled = false; - - final NCPPlayer player = NCPPlayer.getPlayer((Player) event.getEntity()); - final FightConfig config = (FightConfig) getConfig(player); - - if (!instanthealCheck.isEnabled(config) || player.hasPermission(instanthealCheck.permission)) - return; - - cancelled = instanthealCheck.check(player); - - if (cancelled) - event.setCancelled(true); - } - - /** - * We listen to the PlayerToggleSprint event for the - * knockback check - * - * @param event - * The PlayerToggleSprintEvent - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void sprint(final PlayerToggleSprintEvent event) { - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final FightConfig cc = (FightConfig) getConfig(player); - - if (!cc.knockbackCheck || player.hasPermission(Permissions.FIGHT_KNOCKBACK)) - return; - - // Store when the player has started sprinting - final FightData data = (FightData) getData(player); - data.sprint = System.currentTimeMillis(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/GodmodeCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/GodmodeCheck.java deleted file mode 100644 index 32481bea..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/GodmodeCheck.java +++ /dev/null @@ -1,144 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import net.minecraft.server.EntityPlayer; - -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.entity.CraftPlayer; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics; - -/** - * The Godmode Check will find out if a player tried to stay invulnerable after - * being hit or after dying - * - */ -public class GodmodeCheck extends FightCheck { - - public class GodmodeCheckEvent extends FightEvent { - - public GodmodeCheckEvent(final GodmodeCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public GodmodeCheck() { - super("godmode", Permissions.FIGHT_GODMODE); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancelled = false; - - final long time = System.currentTimeMillis(); - - // Check at most once a second - if (data.godmodeLastDamageTime + 1000L < time) { - data.godmodeLastDamageTime = time; - - // How old is the player now? - final int age = player.getBukkitPlayer().getTicksLived(); - // How much older did he get? - final int ageDiff = Math.max(0, age - data.godmodeLastAge); - // Is he invulnerable? - final int nodamageTicks = player.getBukkitPlayer().getNoDamageTicks(); - - if (nodamageTicks > 0 && ageDiff < 15) { - // He is invulnerable and didn't age fast enough, that costs - // some points - data.godmodeBuffer -= 15 - ageDiff; - - // Still points left? - if (data.godmodeBuffer <= 0) { - // No, that means VL and statistics increased - data.godmodeVL -= data.godmodeBuffer; - incrementStatistics(player, Statistics.Id.FI_GODMODE, -data.godmodeBuffer); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancelled = executeActions(player, cc.godmodeActions, data.godmodeVL); - } - } else { - // Give some new points, once a second - data.godmodeBuffer += 15; - data.godmodeVL *= 0.95; - } - - if (data.godmodeBuffer < 0) - // Can't have less than 0 - data.godmodeBuffer = 0; - else if (data.godmodeBuffer > 30) - // And 30 is enough for simple lag situations - data.godmodeBuffer = 30; - - // Start age counting from a new time - data.godmodeLastAge = age; - } - - return cancelled; - } - - /** - * If a player apparently died, make sure he really dies after some time - * if he didn't already, by setting up a Bukkit task - * - * @param player - * The player - */ - public void death(final CraftPlayer player) { - // First check if the player is really dead (e.g. another plugin could - // have just fired an artificial event) - if (player.getHealth() <= 0 && player.isDead()) - try { - final EntityPlayer entity = player.getHandle(); - - // Schedule a task to be executed in roughly 1.5 seconds - Bukkit.getScheduler().scheduleSyncDelayedTask(NoCheatPlus.instance, new Runnable() { - - @Override - public void run() { - try { - // Check again if the player should be dead, and - // if the game didn't mark him as dead - if (entity.getHealth() <= 0 && !entity.dead) { - // Artificially "kill" him - entity.deathTicks = 19; - entity.a(true); - } - } catch (final Exception e) {} - } - }, 30); - } catch (final Exception e) {} - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final GodmodeCheckEvent event = new GodmodeCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round((int) getData(player).godmodeVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.godmodeCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/InstanthealCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/InstanthealCheck.java deleted file mode 100644 index f3092d13..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/InstanthealCheck.java +++ /dev/null @@ -1,97 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics; - -/** - * The instantheal Check should find out if a player tried to artificially - * accellerate the health regeneration by food - * - */ -public class InstanthealCheck extends FightCheck { - - public class InstanthealCheckEvent extends FightEvent { - - public InstanthealCheckEvent(final InstanthealCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public InstanthealCheck() { - super("instantheal", Permissions.FIGHT_INSTANTHEAL); - } - - @Override - public boolean check(final NCPPlayer player, final Object... check) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancelled = false; - - final long time = System.currentTimeMillis(); - - // security check if system time ran backwards - if (data.instanthealLastRegenTime > time) { - data.instanthealLastRegenTime = 0; - return false; - } - - final long difference = time - (data.instanthealLastRegenTime + 3500L); - - data.instanthealBuffer += difference; - - if (data.instanthealBuffer < 0) { - // Buffer has been fully consumed - // Increase vl and statistics - final double vl = data.instanthealVL -= data.instanthealBuffer / 1000; - incrementStatistics(player, Statistics.Id.FI_INSTANTHEAL, vl); - - data.instanthealBuffer = 0; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancelled = executeActions(player, cc.instanthealActions, data.instanthealVL); - } else - // vl gets decreased - data.instanthealVL *= 0.9; - - // max 2 seconds buffer - if (data.instanthealBuffer > 2000L) - data.instanthealBuffer = 2000L; - - if (!cancelled) - // New reference time - data.instanthealLastRegenTime = time; - - return cancelled; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final InstanthealCheckEvent event = new InstanthealCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).instanthealVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.instanthealCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/KnockbackCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/KnockbackCheck.java deleted file mode 100644 index 3c8d6701..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/KnockbackCheck.java +++ /dev/null @@ -1,81 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * A check used to verify if players aren't knockbacking other players when it's not technically possible - * - */ -public class KnockbackCheck extends FightCheck { - - public class KnockbackCheckEvent extends FightEvent { - - public KnockbackCheckEvent(final KnockbackCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public KnockbackCheck() { - super("knockback", Permissions.FIGHT_KNOCKBACK); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - // Check how long ago has the player started sprinting - if (data.sprint > 0L && System.currentTimeMillis() - data.sprint < cc.knockbackInterval) { - - // Player failed the check, but this is influenced by lag, - // so don't do it if there was lag - if (!NoCheatPlus.skipCheck()) { - // The violation level if the difference between the regular and the elapsed time - final long delta = cc.knockbackInterval - System.currentTimeMillis() + data.sprint; - // Increment the violation level - data.knockbackVL += delta; - // Increment the statisctics of the player - incrementStatistics(player, Id.FI_KNOCKBACK, delta); - } - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.knockbackActions, data.knockbackVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final KnockbackCheckEvent event = new KnockbackCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).knockbackVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.knockbackCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/NoswingCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/NoswingCheck.java deleted file mode 100644 index 6c41f520..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/NoswingCheck.java +++ /dev/null @@ -1,77 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * We require that the player moves his arm between attacks, this is - * what gets checked here. - * - */ -public class NoswingCheck extends FightCheck { - - public class NoswingCheckEvent extends FightEvent { - - public NoswingCheckEvent(final NoswingCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public NoswingCheck() { - super("noswing", Permissions.FIGHT_NOSWING); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - // did he swing his arm before? - if (data.armswung) { - // Yes, reward him with reduction of his vl - data.armswung = false; - data.noswingVL *= 0.90D; - } else { - // No, increase vl and statistics - data.noswingVL += 1; - incrementStatistics(player, Id.FI_NOSWING, 1); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.noswingActions, data.noswingVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final NoswingCheckEvent event = new NoswingCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).noswingVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.noswingCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/ReachCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/ReachCheck.java deleted file mode 100644 index 9861160e..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/ReachCheck.java +++ /dev/null @@ -1,116 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import net.minecraft.server.Entity; -import net.minecraft.server.EntityComplex; -import net.minecraft.server.EntityComplexPart; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The reach check will find out if a player interacts with something that's - * too far away - * - */ -public class ReachCheck extends FightCheck { - - public class ReachCheckEvent extends FightEvent { - - public ReachCheckEvent(final ReachCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public ReachCheck() { - super("reach", Permissions.FIGHT_REACH); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - final long time = System.currentTimeMillis(); - - // Get the width of the damagee - final Entity entity = data.damagee; - - // Safeguard, if entity is Giant or Ender Dragon, this check will fail - // due to giant and hard to define hitboxes - if (entity instanceof EntityComplex || entity instanceof EntityComplexPart) - return false; - - // Distance is calculated from eye location to center of targeted - // If the player is further away from his target than allowed, the - // difference will be assigned to "distance" - final double off = CheckUtils.reachCheck(player, entity.locX, entity.locY + 1.0D, entity.locZ, cc.reachLimit); - - if (off < 0.1D) - // Player did probably nothing wrong - // reduce violation counter to reward him - data.reachVL *= 0.80D; - else { - // Player failed the check - // Increment violation counter and statistics - // This is influenced by lag, so don't do it if there was lag - if (!NoCheatPlus.skipCheck()) { - final double sqrt = Math.sqrt(off); - data.reachVL += sqrt; - incrementStatistics(player, Id.FI_REACH, sqrt); - } - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.reachActions, data.reachVL); - - if (cancel) - // if we should cancel, remember the current time too - data.reachLastViolationTime = time; - } - - // If the player is still in penalty time, cancel the event anyway - if (data.reachLastViolationTime + cc.reachPenaltyTime > time) { - // A safeguard to avoid people getting stuck in penalty time - // indefinitely in case the system time of the server gets changed - if (data.reachLastViolationTime > time) - data.reachLastViolationTime = 0; - - // He is in penalty time, therefore request cancelling of the event - return true; - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final ReachCheckEvent event = new ReachCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).reachVL)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.reachCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/fight/SpeedCheck.java b/src/fr/neatmonster/nocheatplus/checks/fight/SpeedCheck.java deleted file mode 100644 index 1db2e8ac..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/fight/SpeedCheck.java +++ /dev/null @@ -1,89 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.fight; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The speed check will find out if a player interacts with something that's - * too far away - * - */ -public class SpeedCheck extends FightCheck { - - public class SpeedCheckEvent extends FightEvent { - - public SpeedCheckEvent(final SpeedCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public SpeedCheck() { - super("speed", Permissions.FIGHT_SPEED); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final FightConfig cc = getConfig(player); - final FightData data = getData(player); - - boolean cancel = false; - - final long time = System.currentTimeMillis(); - - // Check if one second has passed and reset counters and vl in that case - if (data.speedTime + 1000L <= time) { - data.speedTime = time; - data.speedAttackCount = 0; - data.speedVL = 0; - } - - // count the attack - data.speedAttackCount++; - - // too many attacks - if (data.speedAttackCount > cc.speedAttackLimit) { - // if there was lag, don't count it towards statistics and vl - if (!NoCheatPlus.skipCheck()) { - data.speedVL += 1; - incrementStatistics(player, Id.FI_SPEED, 1); - } - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.speedActions, data.speedVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final SpeedCheckEvent event = new SpeedCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).speedVL)); - else if (wildcard == ParameterName.LIMIT) - return String.valueOf(Math.round(getConfig(player).speedAttackLimit)); - else - return super.getParameter(wildcard, player); - } - - @Override - public boolean isEnabled(final FightConfig cc) { - return cc.speedCheck; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/DropCheck.java b/src/fr/neatmonster/nocheatplus/checks/inventory/DropCheck.java deleted file mode 100644 index 733ad0ab..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/DropCheck.java +++ /dev/null @@ -1,80 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The DropCheck will find out if a player drops too many items within a short - * amount of time - * - */ -public class DropCheck extends InventoryCheck { - - public class DropCheckEvent extends InventoryEvent { - - public DropCheckEvent(final DropCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - public DropCheck() { - super("drop"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final InventoryConfig cc = getConfig(player); - final InventoryData data = getData(player); - - boolean cancel = false; - - final long time = System.currentTimeMillis(); - - // Has the configured time passed? If so, reset the counter - if (data.dropLastTime + cc.dropTimeFrame <= time) { - data.dropLastTime = time; - data.dropCount = 0; - data.dropVL = 0; - } - // Security check, if the system time changes - else if (data.dropLastTime > time) - data.dropLastTime = Integer.MIN_VALUE; - - data.dropCount++; - - // The player dropped more than he should - if (data.dropCount > cc.dropLimit) { - // Set vl and increment statistics - data.dropVL = data.dropCount - cc.dropLimit; - incrementStatistics(player, Id.INV_DROP, 1); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.dropActions, data.dropVL); - } - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final DropCheckEvent event = new DropCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).dropVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InstantBowCheck.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InstantBowCheck.java deleted file mode 100644 index f9f02301..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InstantBowCheck.java +++ /dev/null @@ -1,82 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.Bukkit; -import org.bukkit.event.entity.EntityShootBowEvent; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The InstantBowCheck will find out if a player pulled the string of his bow - * too fast - */ -public class InstantBowCheck extends InventoryCheck { - - public class InstantBowCheckEvent extends InventoryEvent { - - public InstantBowCheckEvent(final InstantBowCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public InstantBowCheck() { - super("instantbow"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final InventoryConfig cc = getConfig(player); - final InventoryData data = getData(player); - final EntityShootBowEvent event = (EntityShootBowEvent) args[0]; - - boolean cancelled = false; - - final long time = System.currentTimeMillis(); - - // How fast will the arrow be? - final float bowForce = event.getForce(); - - // Rough estimation of how long pulling the string should've taken - final long expectedTimeWhenStringDrawn = data.lastBowInteractTime + (int) (bowForce * bowForce * 700F); - - if (expectedTimeWhenStringDrawn < time) - // The player was slow enough, reward him by lowering the vl - data.instantBowVL *= 0.90D; - else if (data.lastBowInteractTime > time) - // Security check if time ran backwards, reset - data.lastBowInteractTime = 0; - else { - // Player was too fast, increase violation level and statistics - final int vl = (int) (expectedTimeWhenStringDrawn - time) / 100; - data.instantBowVL += vl; - incrementStatistics(player, Id.INV_BOW, vl); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancelled = executeActions(player, cc.bowActions, data.instantBowVL); - } - - return cancelled; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final InstantBowCheckEvent event = new InstantBowCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).instantBowVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InstantEatCheck.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InstantEatCheck.java deleted file mode 100644 index 3af77c38..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InstantEatCheck.java +++ /dev/null @@ -1,84 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.Bukkit; -import org.bukkit.event.entity.FoodLevelChangeEvent; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The InstantEatCheck will find out if a player eats his food too fast - */ -public class InstantEatCheck extends InventoryCheck { - - public class InstantEatCheckEvent extends InventoryEvent { - - public InstantEatCheckEvent(final InstantEatCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public InstantEatCheck() { - super("instanteat"); - } - - @Override - public boolean check(final NCPPlayer player, final Object... args) { - final InventoryConfig cc = getConfig(player); - final InventoryData data = getData(player); - final FoodLevelChangeEvent event = (FoodLevelChangeEvent) args[0]; - - // Hunger level change seems to not be the result of eating - if (data.foodMaterial == null || event.getFoodLevel() <= player.getBukkitPlayer().getFoodLevel()) - return false; - - boolean cancelled = false; - - final long time = System.currentTimeMillis(); - // rough estimation about how long it should take to eat - final long expectedTimeWhenEatingFinished = data.lastEatInteractTime + 700; - - if (expectedTimeWhenEatingFinished < time) - // Acceptable, reduce VL to reward the player - data.instantEatVL *= 0.60D; - else if (data.lastEatInteractTime > time) - // Security test, if time ran backwards, reset - data.lastEatInteractTime = 0; - else { - // Player was too fast, increase violation level and statistics - final int vl = (int) (expectedTimeWhenEatingFinished - time) / 100; - data.instantEatVL += vl; - incrementStatistics(player, Id.INV_EAT, vl); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancelled = executeActions(player, cc.eatActions, data.instantEatVL); - } - - return cancelled; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final InstantEatCheckEvent event = new InstantEatCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).instantEatVL)); - else if (wildcard == ParameterName.FOOD) - return getData(player).foodMaterial.toString(); - else - return super.getParameter(wildcard, player); - } - -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryCheck.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryCheck.java deleted file mode 100644 index 45c713af..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryCheck.java +++ /dev/null @@ -1,25 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -/** - * Abstract base class for Inventory checks, provides some convenience - * methods for access to data and config that's relevant to this checktype - */ -public abstract class InventoryCheck extends Check { - - public InventoryCheck(final String name) { - super("inventory." + name, InventoryConfig.class, InventoryData.class); - } - - public abstract boolean check(final NCPPlayer player, final Object... args); - - public InventoryConfig getConfig(final NCPPlayer player) { - return (InventoryConfig) player.getConfig(this); - } - - public InventoryData getData(final NCPPlayer player) { - return (InventoryData) player.getData(this); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryConfig.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryConfig.java deleted file mode 100644 index 8c24b650..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckConfig; -import fr.neatmonster.nocheatplus.config.ConfPaths; -import fr.neatmonster.nocheatplus.config.ConfigFile; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Configurations specific for the "Inventory" checks - * Every world gets one of these assigned to it, or if a world doesn't get - * it's own, it will use the "global" version - * - */ -public class InventoryConfig extends CheckConfig { - - public final boolean dropCheck; - public final long dropTimeFrame; - public final int dropLimit; - public final ActionList dropActions; - - public final boolean bowCheck; - public final ActionList bowActions; - - public final boolean eatCheck; - public final ActionList eatActions; - - public InventoryConfig(final ConfigFile data) { - - dropCheck = data.getBoolean(ConfPaths.INVENTORY_DROP_CHECK); - dropTimeFrame = data.getInt(ConfPaths.INVENTORY_DROP_TIMEFRAME) * 1000; - dropLimit = data.getInt(ConfPaths.INVENTORY_DROP_LIMIT); - dropActions = data.getActionList(ConfPaths.INVENTORY_DROP_ACTIONS, Permissions.INVENTORY_DROP); - - bowCheck = data.getBoolean(ConfPaths.INVENTORY_INSTANTBOW_CHECK); - bowActions = data.getActionList(ConfPaths.INVENTORY_INSTANTBOW_ACTIONS, Permissions.INVENTORY_INSTANTBOW); - - eatCheck = data.getBoolean(ConfPaths.INVENTORY_INSTANTEAT_CHECK); - eatActions = data.getActionList(ConfPaths.INVENTORY_INSTANTEAT_ACTIONS, Permissions.INVENTORY_INSTANTEAT); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryData.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryData.java deleted file mode 100644 index fdc26ca2..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryData.java +++ /dev/null @@ -1,28 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.Material; - -import fr.neatmonster.nocheatplus.checks.CheckData; - -/** - * Player specific data for the inventory checks - * - */ -public class InventoryData extends CheckData { - - // Keep track of the violation levels of the three checks - public int dropVL; - public int instantBowVL; - public double instantEatVL; - - // Time and amount of dropped items - public long dropLastTime; - public int dropCount; - - // Times when bow shooting and eating started - public long lastBowInteractTime; - public long lastEatInteractTime; - - // What the player is eating - public Material foodMaterial; -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryEvent.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryEvent.java deleted file mode 100644 index b82e273f..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckEvent; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public class InventoryEvent extends CheckEvent { - - public InventoryEvent(final InventoryCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - - @Override - public InventoryCheck getCheck() { - return (InventoryCheck) super.getCheck(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryListener.java b/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryListener.java deleted file mode 100644 index 61045b9b..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/inventory/InventoryListener.java +++ /dev/null @@ -1,159 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.inventory; - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.Action; -import org.bukkit.event.entity.EntityShootBowEvent; -import org.bukkit.event.entity.FoodLevelChangeEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; - -import fr.neatmonster.nocheatplus.checks.CheckListener; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; - -/** - * Central location to listen to events that are - * relevant for the inventory checks - * - */ -public class InventoryListener extends CheckListener { - - private final DropCheck dropCheck; - private final InstantBowCheck instantBowCheck; - private final InstantEatCheck instantEatCheck; - - public InventoryListener() { - super("inventory"); - - dropCheck = new DropCheck(); - instantBowCheck = new InstantBowCheck(); - instantEatCheck = new InstantEatCheck(); - } - - /** - * We listen to EntityShootBowEvent for the instantbow check - * - * @param event - * The EntityShootBowEvent - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void bowfired(final EntityShootBowEvent event) { - // Only if a player shot the arrow - if (event.getEntity() instanceof Player) { - final NCPPlayer player = NCPPlayer.getPlayer((Player) event.getEntity()); - final InventoryConfig cc = (InventoryConfig) getConfig(player); - - // Only if he should get checked - if (cc.bowCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTBOW)) { - getData(player); - final boolean cancelled = instantBowCheck.check(player, event); - - // The check requested the bowshooting turo get cancelled - event.setCancelled(cancelled); - } - } - } - - /** - * We listen to FoodLevelChange Event because Bukkit doesn't provide a - * PlayerFoodEating Event (or whatever it would be called). - * - * @param event - * The FoodLevelChangeEvent - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void foodchanged(final FoodLevelChangeEvent event) { - // Only if a player ate food - if (event.getEntity() instanceof Player) { - final NCPPlayer player = NCPPlayer.getPlayer((Player) event.getEntity()); - final InventoryConfig cc = (InventoryConfig) getConfig(player); - final InventoryData data = (InventoryData) getData(player); - - // Only if he should get checked - if (cc.eatCheck && !player.hasPermission(Permissions.INVENTORY_INSTANTEAT)) { - - final boolean cancelled = instantEatCheck.check(player, event); - - // The check requested the foodlevelchange to get cancelled - event.setCancelled(cancelled); - } - - // Forget the food material, as the info is no longer needed - data.foodMaterial = null; - } - } - - /** - * We listen to DropItem Event for the dropCheck - * - * @param event - * The PlayerDropItem Event - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - protected void handlePlayerDropItemEvent(final PlayerDropItemEvent event) { - - if (event.getPlayer().isDead()) - return; - - boolean cancelled = false; - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final InventoryConfig cc = (InventoryConfig) getConfig(player); - getData(player); - - // If it should be executed, do it - if (cc.dropCheck && !player.hasPermission(Permissions.INVENTORY_DROP)) - cancelled = dropCheck.check(player); - - if (cancelled) { - // Cancelling drop events is not save (in certain circumstances - // items will disappear completely). So don't do it and kick - // players instead by default - - // event.setCancelled(true); - } - } - - /** - * We listen to PlayerInteractEvent for the instantEat and instantBow - * checks - * - * @param event - * The PlayerInteractEvent - */ - @EventHandler( - priority = EventPriority.LOWEST) - public void interact(final PlayerInteractEvent event) { - - // Only interested in right-clicks while holding an item - if (!event.hasItem() - || !(event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) - return; - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final InventoryData data = (InventoryData) getData(player); - - if (event.getItem().getType() == Material.BOW) - // It was a bow, the player starts to pull the string - // Remember this time - data.lastBowInteractTime = System.currentTimeMillis(); - else if (CheckUtils.isFood(event.getItem())) { - // It was food, the player starts to eat some food - // Remember this time and the type of food - data.foodMaterial = event.getItem().getType(); - data.lastEatInteractTime = System.currentTimeMillis(); - } else { - // Nothing that we are interested in, reset data - data.lastBowInteractTime = 0; - data.lastEatInteractTime = 0; - data.foodMaterial = null; - } - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/BedFlyingCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/BedFlyingCheck.java deleted file mode 100644 index fa20682e..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/BedFlyingCheck.java +++ /dev/null @@ -1,67 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * A check preventing players from flying by sending bed leaving packets - */ -public class BedFlyingCheck extends MovingCheck { - - public class BedFlyingCheckEvent extends MovingEvent { - - public BedFlyingCheckEvent(final BedFlyingCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public BedFlyingCheck() { - super("bedflying"); - } - - public boolean check(final NCPPlayer player, final Object... args) { - final MovingData data = getData(player); - - // If the player wasn't sleeping but is only sending packets, he is cheating! - if (!data.wasSleeping) { - final MovingConfig cc = getConfig(player); - - // Increment violation counter - data.bedFlyVL++; - - // Increment player's statistics - incrementStatistics(player, Id.MOV_BEDFLYING, 1); - - // Execute the actions - return executeActions(player, cc.bedFlyActions, data.bedFlyVL); - } - - // Otherwise reward the player for his legit bed leave - else - data.bedFlyVL = Math.max(0D, data.bedFlyVL - 1); - - return false; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final BedFlyingCheckEvent event = new BedFlyingCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).bedFlyVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java b/src/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java new file mode 100644 index 00000000..44daf74d --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java @@ -0,0 +1,188 @@ +package fr.neatmonster.nocheatplus.checks.moving; + +import java.util.Locale; + +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.MobEffectList; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.PlayerLocation; + +/* + * MM'""""'YMM dP oo MM""""""""`M dP + * M' .mmm. `M 88 MM mmmmmmmM 88 + * M MMMMMooM 88d888b. .d8888b. .d8888b. d8888P dP dP .dP .d8888b. M' MMMM 88 dP dP + * M MMMMMMMM 88' `88 88ooood8 88' `88 88 88 88 d8' 88ooood8 MM MMMMMMMM 88 88 88 + * M. `MMM' .M 88 88. ... 88. .88 88 88 88 .88' 88. ... MM MMMMMMMM 88 88. .88 + * MM. .dM dP `88888P' `88888P8 dP dP 8888P' `88888P' MM MMMMMMMM dP `8888P88 + * MMMMMMMMMMM MMMMMMMMMMMM .88 + * d8888P + */ +/** + * A check designed for people that are allowed to fly. The complement to the "SurvivalFly", which is for people that + * aren't allowed to fly, and therefore have tighter rules to obey. + */ +public class CreativeFly extends Check { + /** + * The event triggered by this check. + */ + public class CreativeFlyEvent extends CheckEvent { + + /** + * Instantiates a new creative fly event. + * + * @param player + * the player + */ + public CreativeFlyEvent(final Player player) { + super(player); + } + } + + /** The horizontal speed in creative mode. */ + private static final double HORIZONTAL_SPEED = 0.6D; + + /** The vertical speed in creative mode. */ + private static final double VERTICAL_SPEED = 1D; + + /** + * Checks a player. + * + * @param player + * the player + * @param from + * the from + * @param to + * the to + * @return the location + */ + public Location check(final Player player, final PlayerLocation from, final PlayerLocation to) { + final MovingConfig cc = MovingConfig.getConfig(player); + final MovingData data = MovingData.getData(player); + + // If we have no setback, define one now. + data.setBack = data.setBack == null ? from.getLocation() : data.setBack; + + // Before doing anything, do a basic height check to determine if players are flying too high. + final int maximumHeight = cc.creativeFlyMaxHeight + player.getWorld().getMaxHeight(); + if (to.getY() - data.verticalFreedom > maximumHeight) + return new Location(player.getWorld(), data.setBack.getX(), maximumHeight - 10D, data.setBack.getZ(), + to.getYaw(), to.getPitch()); + + // Calculate some distances. + final double xDistance = to.getX() - from.getX(); + final double yDistance = to.getY() - from.getY(); + final double zDistance = to.getZ() - from.getZ(); + + // How far did the player move horizontally? + final double hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); + + // If the player is affected by potion of swiftness. + final EntityPlayer entity = ((CraftPlayer) player).getHandle(); + final double limitH = cc.creativeFlyHorizontalSpeed + / 100D + * HORIZONTAL_SPEED + * (entity.hasEffect(MobEffectList.FASTER_MOVEMENT) ? 1D + 0.2D * (entity.getEffect( + MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1D) : 1D); + + // Finally, determine how far the player went beyond the set limits. + double resultH = Math.max(0.0D, hDistance - data.horizontalFreedom - limitH); + + final boolean sprinting = player.isSprinting() && player.getFoodLevel() > 5; + + data.bunnyhopDelay--; + + if (resultH > 0 && sprinting) + // Try to treat it as a the "bunnyhop" problem. The bunnyhop problem is that landing and immediately jumping + // again leads to a player moving almost twice as far in that step. + if (data.bunnyhopDelay <= 0 && resultH < 0.4D) { + data.bunnyhopDelay = 9; + resultH = 0D; + } + + resultH *= 100D; + + // Is the player affected by the "jumping" potion. This is really just a very, very crude estimation and far + // from reality. + double jumpAmplifier = 1D; + if (entity.hasEffect(MobEffectList.JUMP)) { + final int amplifier = entity.getEffect(MobEffectList.JUMP).getAmplifier(); + if (amplifier > 20) + jumpAmplifier = 1.5D * (entity.getEffect(MobEffectList.JUMP).getAmplifier() + 1D); + else + jumpAmplifier = 1.2D * (entity.getEffect(MobEffectList.JUMP).getAmplifier() + 1D); + } + if (jumpAmplifier > data.jumpAmplifier) + data.jumpAmplifier = jumpAmplifier; + + final double limitV = cc.creativeFlyVerticalSpeed / 100D * VERTICAL_SPEED * data.jumpAmplifier; + + if (from.getY() >= to.getY() && data.jumpAmplifier > 0D) + data.jumpAmplifier--; + + // Super simple, just check distance compared to max distance vertical. + final double resultV = Math.max(0D, yDistance - data.verticalFreedom - limitV) * 100D; + + final double result = resultH + resultV; + + // The player went to far, either horizontal or vertical. + if (result > 0D) { + // Increment violation level. + data.creativeFlyVL += result; + + // Dispatch a creative fly event (API). + final CreativeFlyEvent e = new CreativeFlyEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + if (!e.isCancelled() && executeActions(player, cc.creativeFlyActions, data.creativeFlyVL)) + // Compose a new location based on coordinates of "newTo" and viewing direction of "event.getTo()" to + // allow the player to look somewhere else despite getting pulled back by NoCheatPlus. + return new Location(player.getWorld(), data.setBack.getX(), data.setBack.getY(), data.setBack.getZ(), + to.getYaw(), to.getPitch()); + } + + // Slowly reduce the violation level with each event. + data.creativeFlyVL *= 0.97D; + + // If the event did not get cancelled, define a new setback point. + data.setBack = to.getLocation(); + return null; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, + * org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + final MovingData data = MovingData.getData(player); + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(data.creativeFlyVL)); + else if (wildcard == ParameterName.LOCATION_FROM) + return String.format(Locale.US, "%.2f, %.2f, %.2f", data.from.getX(), data.from.getY(), data.from.getZ()); + else if (wildcard == ParameterName.LOCATION_TO) + return String.format(Locale.US, "%.2f, %.2f, %.2f", data.to.getX(), data.to.getY(), data.to.getZ()); + else if (wildcard == ParameterName.DISTANCE) + return String.format(Locale.US, "%.2f", data.to.subtract(data.from).lengthSquared()); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.MOVING_CREATIVEFLY) && MovingConfig.getConfig(player).creativeFlyCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/FlyingCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/FlyingCheck.java deleted file mode 100644 index b5f1e4d4..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/FlyingCheck.java +++ /dev/null @@ -1,165 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * A check designed for people that are allowed to fly. The complement to - * the "RunningCheck", which is for people that aren't allowed to fly, and - * therefore have tighter rules to obey. - * - */ -public class FlyingCheck extends MovingCheck { - - public class FlyingCheckEvent extends MovingEvent { - - public FlyingCheckEvent(final FlyingCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - // Determined by trial and error, the flying movement speed of the creative - // mode - private static final double creativeSpeed = 0.60D; - - public FlyingCheck() { - super("flying"); - } - - public PreciseLocation check(final NCPPlayer player, final Object... args) { - final MovingConfig cc = getConfig(player); - final MovingData data = getData(player); - - // The setBack is the location that players may get teleported to when - // they fail the check - final PreciseLocation setBack = data.runflySetBackPoint; - - final PreciseLocation from = data.from; - final PreciseLocation to = data.to; - - // If we have no setback, define one now - if (!setBack.isSet()) - setBack.set(from); - - // Used to store the location where the player gets teleported to - PreciseLocation newToLocation = null; - - // Before doing anything, do a basic height check to determine if - // players are flying too high - final int maxheight = cc.flyingHeightLimit + player.getWorld().getMaxHeight(); - - if (to.y - data.vertFreedom > maxheight) { - newToLocation = new PreciseLocation(); - newToLocation.set(setBack); - newToLocation.y = maxheight - 10; - return newToLocation; - } - - // Calculate some distances - final double yDistance = to.y - from.y; - final double xDistance = to.x - from.x; - final double zDistance = to.z - from.z; - - // How far did the player move horizontally - final double horizontalDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); - - double resultHoriz = 0; - double resultVert = 0; - double result = 0; - - // In case of creative game mode give at least 0.60 speed limit horizontal - double speedLimitHorizontal = player.canFly() ? Math.max(creativeSpeed, cc.flyingSpeedLimitHorizontal) - : cc.flyingSpeedLimitHorizontal; - - // If the player is affected by potion of swiftness - speedLimitHorizontal *= player.getSpeedAmplifier(); - - // Finally, determine how far the player went beyond the set limits - resultHoriz = Math.max(0.0D, horizontalDistance - data.horizFreedom - speedLimitHorizontal); - - final boolean sprinting = player.getBukkitPlayer().isSprinting(); - - data.bunnyhopdelay--; - - if (resultHoriz > 0 && sprinting) - // Try to treat it as a the "bunnyhop" problem - // The bunnyhop problem is that landing and immediatly jumping - // again leads to a player moving almost twice as far in that step - if (data.bunnyhopdelay <= 0 && resultHoriz < 0.4D) { - data.bunnyhopdelay = 9; - resultHoriz = 0; - } - - resultHoriz *= 100; - - // Is the player affected by the "jumping" potion - // This is really just a very, very crude estimation and far from - // reality - final double jumpAmplifier = player.getJumpAmplifier(); - if (jumpAmplifier > data.lastJumpAmplifier) - data.lastJumpAmplifier = jumpAmplifier; - - final double speedLimitVertical = cc.flyingSpeedLimitVertical * data.lastJumpAmplifier; - - if (data.from.y >= data.to.y && data.lastJumpAmplifier > 0) - data.lastJumpAmplifier--; - - // super simple, just check distance compared to max distance vertical - resultVert = Math.max(0.0D, yDistance - data.vertFreedom - speedLimitVertical) * 100; - - result = resultHoriz + resultVert; - - // The player went to far, either horizontal or vertical - if (result > 0) { - - // Increment violation counter and statistics - data.runflyVL += result; - if (resultHoriz > 0) - incrementStatistics(player, Id.MOV_RUNNING, resultHoriz); - - if (resultVert > 0) - incrementStatistics(player, Id.MOV_FLYING, resultVert); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - final boolean cancel = executeActions(player, cc.flyingActions, data.runflyVL); - - // Was one of the actions a cancel? Then really do it - if (cancel) - newToLocation = setBack; - } - - // Slowly reduce the violation level with each event - data.runflyVL *= 0.97; - - // If the player did not get cancelled, define a new setback point - if (newToLocation == null) - setBack.set(to); - - return newToLocation; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final FlyingCheckEvent event = new FlyingCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).runflyVL)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MorePackets.java b/src/fr/neatmonster/nocheatplus/checks/moving/MorePackets.java new file mode 100644 index 00000000..65801bad --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MorePackets.java @@ -0,0 +1,156 @@ +package fr.neatmonster.nocheatplus.checks.moving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.PlayerLocation; + +/* + * M"""""`'"""`YM MM"""""""`YM dP dP + * M mm. mm. M MM mmmmm M 88 88 + * M MMM MMM M .d8888b. 88d888b. .d8888b. M' .M .d8888b. .d8888b. 88 .dP .d8888b. d8888P .d8888b. + * M MMM MMM M 88' `88 88' `88 88ooood8 MM MMMMMMMM 88' `88 88' `"" 88888" 88ooood8 88 Y8ooooo. + * M MMM MMM M 88. .88 88 88. ... MM MMMMMMMM 88. .88 88. ... 88 `8b. 88. ... 88 88 + * M MMM MMM M `88888P' dP `88888P' MM MMMMMMMM `88888P8 `88888P' dP `YP `88888P' dP `88888P' + * MMMMMMMMMMMMMM MMMMMMMMMMMM + */ +/** + * The MorePackets check (previously called Speedhack check) will try to identify players that send more than the usual + * amount of move-packets to the server to be able to move faster than normal, without getting caught by the other + * checks (flying/running). + * + * It monitors the number of packets sent to the server within 1 second and compares it to the "legal" number of packets + * for that timeframe (22). + */ +public class MorePackets extends Check { + + /** + * The event triggered by this check. + */ + public class MorePacketsEvent extends CheckEvent { + + /** + * Instantiates a new more packets event. + * + * @param player + * the player + */ + public MorePacketsEvent(final Player player) { + super(player); + } + } + + /** + * The usual number of packets per timeframe. + * + * 20 would be for perfect internet connections, 22 is good enough. + */ + private final static int packetsPerTimeframe = 22; + + /** + * Checks a player. + * + * Players get assigned a certain amount of "free" packets as a limit initially. Every move packet reduces that + * limit by 1. If more than 1 second of time passed, the limit gets increased by 22 * time in seconds, up to 50 and + * he gets a new "setback" location. If the player reaches limit = 0 -> teleport him back to "setback". If there was + * a long pause (maybe lag), limit may be up to 100. + * + * @param player + * the player + * @param from + * the from + * @param to + * the to + * @return the location + */ + public Location check(final Player player, final PlayerLocation from, final PlayerLocation to) { + final MovingConfig cc = MovingConfig.getConfig(player); + final MovingData data = MovingData.getData(player); + + Location newTo = null; + + if (data.morePacketsSetback == null) + data.morePacketsSetback = from.getLocation(); + + final long time = System.currentTimeMillis(); + + // Take a packet from the buffer. + data.morePacketsBuffer--; + + // Player used up buffer, he fails the check. + if (data.morePacketsBuffer < 0) { + data.morePacketsPackets = -data.morePacketsBuffer; + + // Increment violation level. + data.morePacketsVL = -data.morePacketsBuffer; + + // Dispatch a more packets event (API). + final MorePacketsEvent e = new MorePacketsEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + if (!e.isCancelled() && executeActions(player, cc.morePacketsActions, data.morePacketsVL)) + newTo = data.teleported = data.morePacketsSetback; + } + + if (data.morePacketsLastTime + 1000 < time) { + // More than 1 second elapsed, but how many? + final double seconds = (time - data.morePacketsLastTime) / 1000D; + + // For each second, fill the buffer. + data.morePacketsBuffer += packetsPerTimeframe * seconds; + + // If there was a long pause (maybe server lag?), allow buffer to grow up to 100. + if (seconds > 2) { + if (data.morePacketsBuffer > 100) + data.morePacketsBuffer = 100; + } else if (data.morePacketsBuffer > 50) + // Only allow growth up to 50. + data.morePacketsBuffer = 50; + + // Set the new "last" time. + data.morePacketsLastTime = time; + + // Set the new "setback" location. + if (newTo == null) + data.morePacketsSetback = from.getLocation(); + } else if (data.morePacketsLastTime > time) + // Security check, maybe system time changed. + data.morePacketsLastTime = time; + + if (newTo == null) + return null; + + // Compose a new location based on coordinates of "newTo" and viewing direction of "event.getTo()" to allow the + // player to look somewhere else despite getting pulled back by NoCheatPlus. + return new Location(player.getWorld(), newTo.getX(), newTo.getY(), newTo.getZ(), to.getYaw(), to.getPitch()); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, + * org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(MovingData.getData(player).morePacketsVL)); + else if (wildcard == ParameterName.PACKETS) + return String.valueOf(MovingData.getData(player).morePacketsPackets); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.MOVING_MOREPACKETS) && MovingConfig.getConfig(player).morePacketsCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsCheck.java deleted file mode 100644 index c92610c9..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsCheck.java +++ /dev/null @@ -1,124 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * The morePacketsCheck (previously called SpeedhackCheck) will try to identify - * players that send more than the usual amount of move-packets to the server to - * be able to move faster than normal, without getting caught by the other - * checks (flying/running). - * - * It monitors the number of packets sent to the server within 1 second and - * compares it to the "legal" number of packets for that timeframe (22). - * - */ -public class MorePacketsCheck extends MovingCheck { - - public class MorePacketsCheckEvent extends MovingEvent { - - public MorePacketsCheckEvent(final MorePacketsCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - // 20 would be for perfect internet connections, 22 is good enough - private final static int packetsPerTimeframe = 22; - - public MorePacketsCheck() { - super("morepackets"); - } - - /** - * 1. Players get assigned a certain amount of "free" packets as a limit initially - * 2. Every move packet reduces that limit by 1 - * 3. If more than 1 second of time passed, the limit gets increased - * by 22 * time in seconds, up to 50 and he gets a new "setback" location - * 4. If the player reaches limit = 0 -> teleport him back to "setback" - * 5. If there was a long pause (maybe lag), limit may be up to 100 - * - */ - public PreciseLocation check(final NCPPlayer player, final Object... args) { - final MovingConfig cc = getConfig(player); - final MovingData data = getData(player); - - PreciseLocation newToLocation = null; - - if (!data.morePacketsSetbackPoint.isSet()) - data.morePacketsSetbackPoint.set(data.from); - - final long time = System.currentTimeMillis(); - - // Take a packet from the buffer - data.morePacketsBuffer--; - - // Player used up buffer, he fails the check - if (data.morePacketsBuffer < 0) { - - data.morePacketsVL = -data.morePacketsBuffer; - incrementStatistics(player, Id.MOV_MOREPACKETS, 1); - - data.packets = -data.morePacketsBuffer; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - final boolean cancel = executeActions(player, cc.morePacketsActions, data.morePacketsVL); - - if (cancel) - newToLocation = data.morePacketsSetbackPoint; - } - - if (data.morePacketsLastTime + 1000 < time) { - // More than 1 second elapsed, but how many? - final double seconds = (time - data.morePacketsLastTime) / 1000D; - - // For each second, fill the buffer - data.morePacketsBuffer += packetsPerTimeframe * seconds; - - // If there was a long pause (maybe server lag?) - // Allow buffer to grow up to 100 - if (seconds > 2) { - if (data.morePacketsBuffer > 100) - data.morePacketsBuffer = 100; - } else if (data.morePacketsBuffer > 50) - data.morePacketsBuffer = 50; - - // Set the new "last" time - data.morePacketsLastTime = time; - - // Set the new "setback" location - if (newToLocation == null) - data.morePacketsSetbackPoint.set(data.from); - } else if (data.morePacketsLastTime > time) - // Security check, maybe system time changed - data.morePacketsLastTime = time; - - return newToLocation; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final MorePacketsCheckEvent event = new MorePacketsCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).morePacketsVL)); - else if (wildcard == ParameterName.PACKETS) - return String.valueOf(Math.round(getData(player).packets)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicle.java b/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicle.java new file mode 100644 index 00000000..33260cf2 --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicle.java @@ -0,0 +1,156 @@ +package fr.neatmonster.nocheatplus.checks.moving; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; + +/* + * M"""""`'"""`YM MM"""""""`YM dP dP + * M mm. mm. M MM mmmmm M 88 88 + * M MMM MMM M .d8888b. 88d888b. .d8888b. M' .M .d8888b. .d8888b. 88 .dP .d8888b. d8888P .d8888b. + * M MMM MMM M 88' `88 88' `88 88ooood8 MM MMMMMMMM 88' `88 88' `"" 88888" 88ooood8 88 Y8ooooo. + * M MMM MMM M 88. .88 88 88. ... MM MMMMMMMM 88. .88 88. ... 88 `8b. 88. ... 88 88 + * M MMM MMM M `88888P' dP `88888P' MM MMMMMMMM `88888P8 `88888P' dP `YP `88888P' dP `88888P' + * MMMMMMMMMMMMMM MMMMMMMMMMMM + * + * M""MMMMM""M dP oo dP + * M MMMMM M 88 88 + * M MMMMP M .d8888b. 88d888b. dP .d8888b. dP dP 88 .d8888b. + * M MMMM' .M 88ooood8 88' `88 88 88' `"" 88 88 88 88ooood8 + * M MMP' .MM 88. ... 88 88 88 88. ... 88. .88 88 88. ... + * M .dMMM `88888P' dP dP dP `88888P' `88888P' dP `88888P' + * MMMMMMMMMMM + */ +/** + * This check does the exact same thing as the MorePacket check but this one works for players inside vehicles. + */ +public class MorePacketsVehicle extends Check { + + /** + * The event triggered by this check. + */ + public class MorePacketsVehicleEvent extends CheckEvent { + + /** + * Instantiates a new more packets vehicle event. + * + * @param player + * the player + */ + public MorePacketsVehicleEvent(final Player player) { + super(player); + } + } + + /** + * The usual number of packets per timeframe. + * + * 20 would be for perfect internet connections, 22 is good enough. + */ + private final static int packetsPerTimeframe = 22; + + /** + * Checks a player. + * + * (More information on the MorePacket class.) + * + * @param player + * the player + * @param from + * the from + * @param to + * the to + * @return the location + */ + public Location check(final Player player, final Location from, final Location to) { + final MovingConfig cc = MovingConfig.getConfig(player); + final MovingData data = MovingData.getData(player); + + Location newTo = null; + + if (data.morePacketsVehicleSetback == null) + data.morePacketsVehicleSetback = from; + + final long time = System.currentTimeMillis(); + + // Take a packet from the buffer. + data.morePacketsVehicleBuffer--; + + // Player used up buffer, he fails the check. + if (data.morePacketsVehicleBuffer < 0) { + data.morePacketsVehiclePackets = -data.morePacketsVehicleBuffer; + + // Increment violation level. + data.morePacketsVehicleVL = -data.morePacketsVehicleBuffer; + + // Dispatch a more packets vehicle event (API). + final MorePacketsVehicleEvent e = new MorePacketsVehicleEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + if (!e.isCancelled() && executeActions(player, cc.morePacketsVehicleActions, data.morePacketsVehicleVL)) + newTo = data.morePacketsVehicleSetback; + } + + if (data.morePacketsVehicleLastTime + 1000 < time) { + // More than 1 second elapsed, but how many? + final double seconds = (time - data.morePacketsVehicleLastTime) / 1000D; + + // For each second, fill the buffer. + data.morePacketsVehicleBuffer += packetsPerTimeframe * seconds; + + // If there was a long pause (maybe server lag?), allow buffer to grow up to 100. + if (seconds > 2) { + if (data.morePacketsVehicleBuffer > 100) + data.morePacketsVehicleBuffer = 100; + } else if (data.morePacketsVehicleBuffer > 50) + // Only allow growth up to 50. + data.morePacketsVehicleBuffer = 50; + + // Set the new "last" time. + data.morePacketsVehicleLastTime = time; + + // Set the new "setback" location. + if (newTo == null) + data.morePacketsVehicleSetback = from; + } else if (data.morePacketsVehicleLastTime > time) + // Security check, maybe system time changed. + data.morePacketsVehicleLastTime = time; + + if (newTo == null) + return null; + + // Compose a new location based on coordinates of "newTo" and viewing direction of "event.getTo()" to allow the + // player to look somewhere else despite getting pulled back by NoCheatPlus. + return new Location(player.getWorld(), newTo.getX(), newTo.getY(), newTo.getZ(), to.getYaw(), to.getPitch()); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, + * org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(MovingData.getData(player).morePacketsVehicleVL)); + else if (wildcard == ParameterName.PACKETS) + return String.valueOf(MovingData.getData(player).morePacketsVehiclePackets); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.MOVING_MOREPACKETSVEHICLE) + && MovingConfig.getConfig(player).morePacketsVehicleCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicleCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicleCheck.java deleted file mode 100644 index f507b8e9..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MorePacketsVehicleCheck.java +++ /dev/null @@ -1,113 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * The morePacketsVehiculeCheck will try to identify players that send more than - * the usual amount of vehicule-move-packets to the server to be able to move - * faster than normal, without getting caught by the other checks (flying/running). - * - * It monitors the number of packets sent to the server within 1 second and - * compares it to the "legal" number of packets for that timeframe (22). - * - */ -public class MorePacketsVehicleCheck extends MovingCheck { - - public class MorePacketsVehicleCheckEvent extends MovingEvent { - - public MorePacketsVehicleCheckEvent(final MorePacketsVehicleCheck check, final NCPPlayer player, - final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - } - - // 20 would be for perfect internet connections, 22 is good enough - private final static int packetsPerTimeframe = 22; - - public MorePacketsVehicleCheck() { - super("morepacketsvehicle"); - } - - /** - * 1. Players get assigned a certain amount of "free" packets as a limit initially - * 2. Every move packet reduces that limit by 1 - * 3. If more than 1 second of time passed, the limit gets increased - * by 22 * time in seconds, up to 50 and he gets a new "setback" location - * 4. If the player reaches limit = 0 -> teleport him back to "setback" - * 5. If there was a long pause (maybe lag), limit may be up to 100 - * - */ - public boolean check(final NCPPlayer player, final Object... args) { - final MovingConfig cc = getConfig(player); - final MovingData data = getData(player); - - boolean cancel = false; - - final long time = System.currentTimeMillis(); - - // Take a packet from the buffer - data.morePacketsVehicleBuffer--; - - // Player used up buffer, he fails the check - if (data.morePacketsVehicleBuffer < 0) { - - data.morePacketsVehicleVL = -data.morePacketsVehicleBuffer; - incrementStatistics(player, Id.MOV_MOREPACKETSVEHICLE, 1); - - data.packetsVehicle = -data.morePacketsVehicleBuffer; - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - cancel = executeActions(player, cc.morePacketsVehicleActions, data.morePacketsVehicleVL); - } - - if (data.morePacketsVehicleLastTime + 1000 < time) { - // More than 1 second elapsed, but how many? - final double seconds = (time - data.morePacketsVehicleLastTime) / 1000D; - - // For each second, fill the buffer - data.morePacketsVehicleBuffer += packetsPerTimeframe * seconds; - - // If there was a long pause (maybe server lag?) - // Allow buffer to grow up to 100 - if (seconds > 2) { - if (data.morePacketsVehicleBuffer > 100) - data.morePacketsVehicleBuffer = 100; - } else if (data.morePacketsVehicleBuffer > 50) - data.morePacketsVehicleBuffer = 50; - - // Set the new "last" time - data.morePacketsVehicleLastTime = time; - } else if (data.morePacketsVehicleLastTime > time) - // Security check, maybe system time changed - data.morePacketsVehicleLastTime = time; - - return cancel; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final MorePacketsVehicleCheckEvent event = new MorePacketsVehicleCheckEvent(this, player, actionList, - violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).morePacketsVehicleVL)); - else if (wildcard == ParameterName.PACKETS) - return String.valueOf(Math.round(getData(player).packetsVehicle)); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingCheck.java deleted file mode 100644 index f4a19d89..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingCheck.java +++ /dev/null @@ -1,44 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import java.util.Locale; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * Abstract base class for Moving checks, provides some convenience - * methods for access to data and config that's relevant to this checktype - */ -public abstract class MovingCheck extends Check { - - public MovingCheck(final String name) { - super("moving." + name, MovingConfig.class, MovingData.class); - } - - public MovingConfig getConfig(final NCPPlayer player) { - return (MovingConfig) player.getConfig(this); - } - - public MovingData getData(final NCPPlayer player) { - return (MovingData) player.getData(this); - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.LOCATION) { - final PreciseLocation from = getData(player).from; - return String.format(Locale.US, "%.2f,%.2f,%.2f", from.x, from.y, from.z); - } else if (wildcard == ParameterName.MOVEDISTANCE) { - final PreciseLocation from = getData(player).from; - final PreciseLocation to = getData(player).to; - return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x - from.x, to.y - from.y, to.z - from.z); - } else if (wildcard == ParameterName.LOCATION_TO) { - final PreciseLocation to = getData(player).to; - return String.format(Locale.US, "%.2f,%.2f,%.2f", to.x, to.y, to.z); - } else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java index 1db7be37..d0b5cc6e 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingConfig.java @@ -1,46 +1,60 @@ package fr.neatmonster.nocheatplus.checks.moving; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.entity.Player; + import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckConfig; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigFile; -import fr.neatmonster.nocheatplus.players.informations.Permissions; +import fr.neatmonster.nocheatplus.config.ConfigManager; +import fr.neatmonster.nocheatplus.players.Permissions; -/** - * Configurations specific for the Move Checks. Every world gets one of these - * assigned to it. - * +/* + * M"""""`'"""`YM oo MM'""""'YMM .8888b oo + * M mm. mm. M M' .mmm. `M 88 " + * M MMM MMM M .d8888b. dP .dP dP 88d888b. .d8888b. M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. + * M MMM MMM M 88' `88 88 d8' 88 88' `88 88' `88 M MMMMMMMM 88' `88 88' `88 88 88 88' `88 + * M MMM MMM M 88. .88 88 .88' 88 88 88 88. .88 M. `MMM' .M 88. .88 88 88 88 88 88. .88 + * M MMM MMM M `88888P' 8888P' dP dP dP `8888P88 MM. .dM `88888P' dP dP dP dP `8888P88 + * MMMMMMMMMMMMMM .88 MMMMMMMMMMM .88 + * d8888P d8888P */ -public class MovingConfig extends CheckConfig { +/** + * Configurations specific for the moving checks. Every world gets one of these assigned to it. + */ +public class MovingConfig { - public final boolean runflyCheck; - public final double jumpheight; - public final boolean identifyCreativeMode; - public final double walkingSpeedLimit; - public final double sprintingSpeedLimit; - public final double swimmingSpeedLimit; - public final double verticalSwimmingSpeedLimit; - public final boolean sneakingCheck; - public final double sneakingSpeedLimit; - public final boolean blockingCheck; - public final double blockingSpeedLimit; - public final double cobWebHoriSpeedLimit; - public final double cobWebVertSpeedLimit; + /** The map containing the configurations per world. */ + private static Map worldsMap = new HashMap(); - public final ActionList actions; + /** + * Clear all the configurations. + */ + public static void clear() { + worldsMap.clear(); + } - public final boolean allowFlying; - public final double flyingSpeedLimitVertical; - public final double flyingSpeedLimitHorizontal; - public final ActionList flyingActions; + /** + * Gets the configuration for a specified player. + * + * @param player + * the player + * @return the configuration + */ + public static MovingConfig getConfig(final Player player) { + if (!worldsMap.containsKey(player.getWorld().getName())) + worldsMap.put(player.getWorld().getName(), + new MovingConfig(ConfigManager.getConfigFile(player.getWorld().getName()))); + return worldsMap.get(player.getWorld().getName()); + } - public final boolean bedFlyCheck; - public final ActionList bedFlyActions; - - public final boolean nofallCheck; - public final boolean nofallAggressive; - public final float nofallMultiplier; - public final ActionList nofallActions; + public final boolean creativeFlyCheck; + public final int creativeFlyHorizontalSpeed; + public final int creativeFlyMaxHeight; + public final int creativeFlyVerticalSpeed; + public final ActionList creativeFlyActions; public final boolean morePacketsCheck; public final ActionList morePacketsActions; @@ -48,51 +62,36 @@ public class MovingConfig extends CheckConfig { public final boolean morePacketsVehicleCheck; public final ActionList morePacketsVehicleActions; - public final boolean waterWalkCheck; - public final ActionList waterWalkActions; + public final boolean noFallCheck; + public final boolean noFallAggressive; + public final ActionList noFallActions; - public final int flyingHeightLimit; + public final boolean survivalFlyCheck; + public final boolean survivalFlyAllowFastBlocking; + public final boolean survivalFlyAllowFastSneaking; + public final int survivalFlyBlockingSpeed; + public final int survivalFlyCobWebSpeed; + public final int survivalFlyLadderSpeed; + public final int survivalFlyLavaSpeed; + public final int survivalFlyMoveSpeed; + public final int survivalFlySneakingSpeed; + public final int survivalFlySoulSandSpeed; + public final int survivalFlySprintingSpeed; + public final int survivalFlyWaterSpeed; + public final ActionList survivalFlyActions; + /** + * Instantiates a new moving configuration. + * + * @param data + * the data + */ public MovingConfig(final ConfigFile data) { - - identifyCreativeMode = data.getBoolean(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWINCREATIVE); - - runflyCheck = data.getBoolean(ConfPaths.MOVING_RUNFLY_CHECK); - - final int walkspeed = data.getInt(ConfPaths.MOVING_RUNFLY_WALKSPEED, 100); - final int sprintspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SPRINTSPEED, 100); - final int swimspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SWIMSPEED, 100); - final int vertSwimSpeed = data.getInt(ConfPaths.MOVING_RUNFLY_VERTICALSWIMSPEED, 100); - final int sneakspeed = data.getInt(ConfPaths.MOVING_RUNFLY_SNEAKSPEED, 100); - final int blockspeed = data.getInt(ConfPaths.MOVING_RUNFLY_BLOCKSPEED, 100); - final int cobWebSpeed = data.getInt(ConfPaths.MOVING_RUNFLY_COBWEBSPEED, 100); - walkingSpeedLimit = 0.22 * walkspeed / 100D; - sprintingSpeedLimit = 0.35 * sprintspeed / 100D; - swimmingSpeedLimit = 0.18 * swimspeed / 100D; - verticalSwimmingSpeedLimit = 0.43 * vertSwimSpeed / 100D; - sneakingSpeedLimit = 0.14 * sneakspeed / 100D; - blockingSpeedLimit = 0.16 * blockspeed / 100D; - cobWebHoriSpeedLimit = 0.08 * cobWebSpeed / 100D; - cobWebVertSpeedLimit = 0.07 * cobWebSpeed / 100D; - jumpheight = 135 / 100D; - - sneakingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING); - blockingCheck = !data.getBoolean(ConfPaths.MOVING_RUNFLY_ALLOWFASTBLOCKING); - actions = data.getActionList(ConfPaths.MOVING_RUNFLY_ACTIONS, Permissions.MOVING_RUNFLY); - - allowFlying = data.getBoolean(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWALWAYS); - flyingSpeedLimitVertical = data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL) / 100D; - flyingSpeedLimitHorizontal = data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL) / 100D; - flyingHeightLimit = data.getInt(ConfPaths.MOVING_RUNFLY_FLYING_HEIGHTLIMIT); - flyingActions = data.getActionList(ConfPaths.MOVING_RUNFLY_FLYING_ACTIONS, Permissions.MOVING_FLYING); - - bedFlyCheck = data.getBoolean(ConfPaths.MOVING_RUNFLY_BEDFLYING_CHECK); - bedFlyActions = data.getActionList(ConfPaths.MOVING_RUNFLY_BEDFLYING_ACTIONS, Permissions.MOVING_BEDFLYING); - - nofallCheck = data.getBoolean(ConfPaths.MOVING_RUNFLY_NOFALL_CHECK); - nofallMultiplier = 200 / 100F; - nofallAggressive = data.getBoolean(ConfPaths.MOVING_RUNFLY_NOFALL_AGGRESSIVE); - nofallActions = data.getActionList(ConfPaths.MOVING_RUNFLY_NOFALL_ACTIONS, Permissions.MOVING_NOFALL); + creativeFlyCheck = data.getBoolean(ConfPaths.MOVING_CREATIVEFLY_CHECK); + creativeFlyHorizontalSpeed = data.getInt(ConfPaths.MOVING_CREATIVEFLY_HORIZONTALSPEED); + creativeFlyMaxHeight = data.getInt(ConfPaths.MOVING_CREATIVEFLY_MAXHEIGHT); + creativeFlyVerticalSpeed = data.getInt(ConfPaths.MOVING_CREATIVEFLY_VERTICALSPEED); + creativeFlyActions = data.getActionList(ConfPaths.MOVING_CREATIVEFLY_ACTIONS, Permissions.MOVING_CREATIVEFLY); morePacketsCheck = data.getBoolean(ConfPaths.MOVING_MOREPACKETS_CHECK); morePacketsActions = data.getActionList(ConfPaths.MOVING_MOREPACKETS_ACTIONS, Permissions.MOVING_MOREPACKETS); @@ -101,7 +100,23 @@ public class MovingConfig extends CheckConfig { morePacketsVehicleActions = data.getActionList(ConfPaths.MOVING_MOREPACKETSVEHICLE_ACTIONS, Permissions.MOVING_MOREPACKETS); - waterWalkCheck = data.getBoolean(ConfPaths.MOVING_WATERWALK_CHECK); - waterWalkActions = data.getActionList(ConfPaths.MOVING_WATERWALK_ACTIONS, Permissions.MOVING_WATERWALK); + noFallCheck = data.getBoolean(ConfPaths.MOVING_NOFALL_CHECK); + noFallAggressive = data.getBoolean(ConfPaths.MOVING_NOFALL_AGGRESSIVE); + noFallActions = data.getActionList(ConfPaths.MOVING_NOFALL_ACTIONS, Permissions.MOVING_NOFALL); + + survivalFlyCheck = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_CHECK); + survivalFlyAllowFastBlocking = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_ALLOWFASTBLOCKING); + survivalFlyAllowFastSneaking = data.getBoolean(ConfPaths.MOVING_SURVIVALFLY_ALLOWFASTSNEAKING); + // Default values are specified here because this settings aren't showed by default into the configuration file. + survivalFlyBlockingSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_BLOCKINGSPEED, 100); + survivalFlyCobWebSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_COBWEBSPEED, 100); + survivalFlyLadderSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_LADDERSPEED, 100); + survivalFlyLavaSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_LAVASPEED, 100); + survivalFlyMoveSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_MOVESPEED, 100); + survivalFlySneakingSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_SNEAKINGSPEED, 100); + survivalFlySoulSandSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_SOULSANDSPEED, 100); + survivalFlySprintingSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_SPRINTINGSPEED, 100); + survivalFlyWaterSpeed = data.getInt(ConfPaths.MOVING_SURVIVALFLY_WATERSPEED, 100); + survivalFlyActions = data.getActionList(ConfPaths.MOVING_SURVIVALFLY_ACTIONS, Permissions.MOVING_SURVIVALFLY); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java index c12f7260..565c1d70 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingData.java @@ -1,97 +1,106 @@ package fr.neatmonster.nocheatplus.checks.moving; +import java.util.HashMap; +import java.util.Map; + import org.bukkit.Location; +import org.bukkit.entity.Player; -import fr.neatmonster.nocheatplus.checks.CheckData; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * Player specific data for the moving check group +/* + * M"""""`'"""`YM oo M""""""'YMM dP + * M mm. mm. M M mmmm. `M 88 + * M MMM MMM M .d8888b. dP .dP dP 88d888b. .d8888b. M MMMMM M .d8888b. d8888P .d8888b. + * M MMM MMM M 88' `88 88 d8' 88 88' `88 88' `88 M MMMMM M 88' `88 88 88' `88 + * M MMM MMM M 88. .88 88 .88' 88 88 88 88. .88 M MMMM' .M 88. .88 88 88. .88 + * M MMM MMM M `88888P' 8888P' dP dP dP `8888P88 M .MM `88888P8 dP `88888P8 + * MMMMMMMMMMMMMM .88 MMMMMMMMMMM + * d8888P */ -public class MovingData extends CheckData { +/** + * Player specific data for the moving checks. + */ +public class MovingData { - // Keep track of the violation levels of the checks - public double runflyVL; - public double nofallVL; - public double morePacketsVL; - public double morePacketsVehicleVL; - public double waterWalkVL; - public double bedFlyVL; + /** The map containing the data per players. */ + private static Map playersMap = new HashMap(); - // Count how long a player is in the air - public int jumpPhase; - - // Remember how big the players last JumpAmplifier (potion effect) was - public double lastJumpAmplifier; - - // Remember for a short time that the player was on ice and therefore - // should be allowed to move a bit faster - public int onIce; - - // Where should a player be teleported back to when failing the check - public final PreciseLocation runflySetBackPoint = new PreciseLocation(); - - // Some values for estimating movement freedom - public double vertFreedom; - public double vertVelocity; - public int vertVelocityCounter; - public double horizFreedom; - public int horizVelocityCounter; - public double horizontalBuffer; - public int bunnyhopdelay; - - // Keep track of estimated fall distance to compare to real fall distance - public float fallDistance; - public float lastAddedFallDistance; - - // Keep in mind the player's last safe position - public Location[] lastSafeLocations = new Location[] {null, null}; - - // Keep track of when "morePackets" last time checked and how much packets - // a player sent and may send before failing the check - public long morePacketsLastTime; - public int packets; - public int morePacketsBuffer = 50; - - // Where to teleport the player that fails the "morepackets" check - public final PreciseLocation morePacketsSetbackPoint = new PreciseLocation(); - - // Keep track of when "morePacketsVehicle" last time checked an how much - // packets a vehicle sent and may send before failing the check - public long morePacketsVehicleLastTime; - public int packetsVehicle; - public int morePacketsVehicleBuffer = 50; - - // When NoCheatPlus does teleport the player, remember the target location to - // be able to distinguish "our" teleports from teleports of others - public final PreciseLocation teleportTo = new PreciseLocation(); - - // For logging and convenience, make copies of the events locations - public final PreciseLocation from = new PreciseLocation(); - public final PreciseLocation fromVehicle = new PreciseLocation(); - public final PreciseLocation to = new PreciseLocation(); - public final PreciseLocation toVehicle = new PreciseLocation(); - - // For convenience, remember if the locations are considered "on ground" - // by NoCheatPlus - public boolean fromOnOrInGround; - public boolean toOnOrInGround; - - // Remember if the player was previously sleeping - public boolean wasSleeping = false; - - public Id statisticCategory = Id.MOV_RUNNING; - - public void clearMorePacketsData() { - morePacketsSetbackPoint.reset(); + /** + * Gets the data of a specified player. + * + * @param player + * the player + * @return the data + */ + public static MovingData getData(final Player player) { + if (!playersMap.containsKey(player.getName())) + playersMap.put(player.getName(), new MovingData()); + return playersMap.get(player.getName()); } - public void clearRunFlyData() { - runflySetBackPoint.reset(); - jumpPhase = 0; - fallDistance = 0; - lastAddedFallDistance = 0; - bunnyhopdelay = 0; + // Violation levels. + public double creativeFlyVL = 0D; + public double morePacketsVL = 0D; + public double morePacketsVehicleVL = 0D; + public double noFallVL = 0D; + public double survivalFlyVL = 0D; + + // Data shared between the fly checks. + public int bunnyhopDelay; + public double horizontalBuffer; + public double horizontalFreedom; + public double horizontalVelocityCounter; + public double jumpAmplifier; + public double verticalFreedom; + public double verticalVelocity; + public int verticalVelocityCounter; + + public Location[] lastSafeLocations = new Location[] {null, null}; + + // Data of the more packets check. + public int morePacketsBuffer = 50; + public long morePacketsLastTime; + public int morePacketsPackets; + public Location morePacketsSetback; + + // Data of the more packets vehicle check. + public int morePacketsVehicleBuffer = 50; + public long morePacketsVehicleLastTime; + public int morePacketsVehiclePackets; + public Location morePacketsVehicleSetback; + + // Data of the no fall check. + public float noFallDistance; + public float noFallLastAddedDistance; + + // Data of the survival fly check. + public int survivalFlyJumpPhase; + public int survivalFlyOnIce; + public long survivalInLavaSince; + public long survivalInWaterSince; + public long survivalOnLadderSince; + + // Locations shared between all checks. + public Location from; + public Location to; + public Location setBack; + public Location teleported; + + /** + * Clear the data of the fly checks. + */ + public void clearFlyData() { + bunnyhopDelay = 0; + setBack = null; + noFallDistance = 0F; + noFallLastAddedDistance = 0F; + survivalFlyJumpPhase = 0; + } + + /** + * Clear the data of the more packets checks. + */ + public void clearMorePacketsData() { + morePacketsSetback = null; + morePacketsVehicleSetback = null; } } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingEvent.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingEvent.java deleted file mode 100644 index 4e6f1985..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckEvent; -import fr.neatmonster.nocheatplus.players.NCPPlayer; - -public class MovingEvent extends CheckEvent { - - public MovingEvent(final MovingCheck check, final NCPPlayer player, final ActionList actions, final double vL) { - super(check, player, actions, vL); - } - - @Override - public MovingCheck getCheck() { - return (MovingCheck) super.getCheck(); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java index 6cadf376..766cb539 100644 --- a/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java +++ b/src/fr/neatmonster/nocheatplus/checks/moving/MovingListener.java @@ -1,485 +1,465 @@ package fr.neatmonster.nocheatplus.checks.moving; +import net.minecraft.server.Block; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.entity.Boat; -import org.bukkit.entity.Minecart; import org.bukkit.entity.Player; +import org.bukkit.entity.Vehicle; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.player.PlayerBedEnterEvent; -import org.bukkit.event.player.PlayerBedLeaveEvent; import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerPortalEvent; -import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerVelocityEvent; import org.bukkit.event.vehicle.VehicleMoveEvent; -import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; -import fr.neatmonster.nocheatplus.checks.CheckListener; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; +import fr.neatmonster.nocheatplus.NoCheatPlus; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.PlayerLocation; -/** - * Central location to listen to events that are - * relevant for the moving checks - * +/* + * M"""""`'"""`YM oo + * M mm. mm. M + * M MMM MMM M .d8888b. dP .dP dP 88d888b. .d8888b. + * M MMM MMM M 88' `88 88 d8' 88 88' `88 88' `88 + * M MMM MMM M 88. .88 88 .88' 88 88 88 88. .88 + * M MMM MMM M `88888P' 8888P' dP dP dP `8888P88 + * MMMMMMMMMMMMMM .88 + * d8888P + * + * M""MMMMMMMM oo dP + * M MMMMMMMM 88 + * M MMMMMMMM dP .d8888b. d8888P .d8888b. 88d888b. .d8888b. 88d888b. + * M MMMMMMMM 88 Y8ooooo. 88 88ooood8 88' `88 88ooood8 88' `88 + * M MMMMMMMM 88 88 88 88. ... 88 88 88. ... 88 + * M M dP `88888P' dP `88888P' dP dP `88888P' dP + * MMMMMMMMMMM */ -public class MovingListener extends CheckListener { +/** + * Central location to listen to events that are relevant for the moving checks. + * + * @see MovingEvent + */ +public class MovingListener implements Listener { - private final MorePacketsCheck morePacketsCheck; - private final MorePacketsVehicleCheck morePacketsVehicleCheck; - private final FlyingCheck flyingCheck; - private final BedFlyingCheck bedFlyingCheck; - private final RunningCheck runningCheck; - private final WaterWalkCheck waterWalkCheck; + /** The plugin. */ + private final NoCheatPlus plugin = (NoCheatPlus) Bukkit.getPluginManager().getPlugin( + "NoCheatPlus"); + /** The creative fly check. */ + private final CreativeFly creativeFly = new CreativeFly(); - public MovingListener() { - super("moving"); + /** The more packets check. */ + private final MorePackets morePackets = new MorePackets(); - flyingCheck = new FlyingCheck(); - bedFlyingCheck = new BedFlyingCheck(); - runningCheck = new RunningCheck(); - morePacketsCheck = new MorePacketsCheck(); - morePacketsVehicleCheck = new MorePacketsVehicleCheck(); - waterWalkCheck = new WaterWalkCheck(); - } + /** The more packets vehicle check. */ + private final MorePacketsVehicle morePacketsVehicle = new MorePacketsVehicle(); + + /** The survival fly check. */ + private final SurvivalFly survivalFly = new SurvivalFly(); /** - * We listen to this event to prevent player from flying by sending - * bed leaving packets. - * - * @param event + * Checks if a material is liquid. * + * @param material + * the material + * @return true, if the material is liquid */ - @EventHandler( - priority = EventPriority.MONITOR) - public void bedEntering(final PlayerBedEnterEvent event) { - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final MovingConfig cc = (MovingConfig) getConfig(player); - - if (cc.bedFlyCheck && !player.hasPermission(Permissions.MOVING_BEDFLYING)) { - final MovingData data = (MovingData) getData(player); - data.wasSleeping = true; - } + private boolean isLiquid(final Material material) { + return material == Material.LAVA || material == Material.STATIONARY_LAVA + || material == Material.STATIONARY_WATER || material == Material.WATER; } /** - * We listen to this event to prevent player from flying by sending - * bed leaving packets. + * A workaround for players placing blocks below them getting pushed off the block by NoCheatPlus. + * + * It essentially moves the "setbackpoint" to the top of the newly placed block, therefore tricking NoCheatPlus into + * thinking the player was already on top of that block and should be allowed to stay there. + * + * It also prevent players from placing a block on a liquid (which is impossible without a modified version of + * Minecraft). * * @param event - * - */ - @EventHandler( - priority = EventPriority.MONITOR) - public void bedLeaving(final PlayerBedLeaveEvent event) { - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final MovingConfig cc = (MovingConfig) getConfig(player); - - if (cc.bedFlyCheck && !player.hasPermission(Permissions.MOVING_BEDFLYING)) { - final MovingData data = (MovingData) getData(player); - - if (bedFlyingCheck.check(player)) - // To cancel the event, simply teleport him to his last safe location - event.getPlayer().teleport(data.lastSafeLocations[1]); - - data.wasSleeping = false; - } - } - - /** - * A workaround for players placing blocks below them getting pushed - * off the block by NoCheatPlus. - * - * It essentially moves the "setbackpoint" to the top of the newly - * placed block, therefore tricking NoCheatPlus into thinking the player - * was already on top of that block and should be allowed to stay - * there - * - * @param event - * The BlockPlaceEvent + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.MONITOR) - public void blockPlace(final BlockPlaceEvent event) { + public void onBlockPlace(final BlockPlaceEvent event) { + /* + * ____ _ _ ____ _ + * | __ )| | ___ ___| | __ | _ \| | __ _ ___ ___ + * | _ \| |/ _ \ / __| |/ / | |_) | |/ _` |/ __/ _ \ + * | |_) | | (_) | (__| < | __/| | (_| | (_| __/ + * |____/|_|\___/ \___|_|\_\ |_| |_|\__,_|\___\___| + */ + final Player player = event.getPlayer(); - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final MovingConfig config = (MovingConfig) getConfig(player); - - // If the player is allowed to fly anyway, the workaround is not needed - // It's kind of expensive (looking up block types) therefore it makes - // sense to avoid it - if (config.allowFlying || !config.runflyCheck || player.hasPermission(Permissions.MOVING_FLYING) - || player.hasPermission(Permissions.MOVING_RUNFLY)) + // Ignore players inside a vehicle. + if (player.isInsideVehicle()) return; - // Get the player-specific stored data that applies here - final MovingData data = (MovingData) getData(player); + final MovingData data = MovingData.getData(player); - final Block block = event.getBlockPlaced(); - - if (block == null || !data.runflySetBackPoint.isSet()) - return; - - // Keep some results of "expensive calls - final Location l = player.getLocation(); - final int playerX = l.getBlockX(); - final int playerY = l.getBlockY(); - final int playerZ = l.getBlockZ(); - final int blockY = block.getY(); - - // Was the block below the player? - if (Math.abs(playerX - block.getX()) <= 1 && Math.abs(playerZ - block.getZ()) <= 1 && playerY - blockY >= 0 - && playerY - blockY <= 2) { - // yes - final int type = CheckUtils.getType(block.getTypeId()); - if (CheckUtils.isSolid(type) || CheckUtils.isLiquid(type)) - if (blockY + 1 >= data.runflySetBackPoint.y) { - data.runflySetBackPoint.y = blockY + 1; - data.jumpPhase = 0; - } + final int blockY = event.getBlock().getY(); + if (isLiquid(event.getBlockAgainst().getType())) + // The block was placed against a liquid block, cancel its placement. + event.setCancelled(true); + else if ((creativeFly.isEnabled(player) || survivalFly.isEnabled(player)) && event.getBlock() != null + && data.setBack != null && blockY + 1D >= data.setBack.getY() + && Math.abs(player.getLocation().getX() - event.getBlock().getX()) <= 1D + && Math.abs(player.getLocation().getZ() - event.getBlock().getZ()) <= 1D + && player.getLocation().getY() - blockY > 0D && player.getLocation().getY() - blockY < 2D + && (Block.i(event.getBlock().getTypeId()) || isLiquid(event.getBlock().getType()))) { + // The creative fly and/or survival fly check is enabled, the block was placed below the player and is + // solid, so do what we have to do. + data.setBack.setY(blockY + 1D); + data.survivalFlyJumpPhase = 0; } } /** - * If a player tries to place a boat on the ground, the event - * will be cancelled. + * Just for security, if a player switches between worlds, reset the fly and more packets checks data, because it is + * definitely invalid now. * * @param event - * The PlayerInteractEvent + * the event + */ + @EventHandler( + priority = EventPriority.MONITOR) + public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) { + /* + * ____ _ ____ _ _ __ __ _ _ + * | _ \| | __ _ _ _ ___ _ __ / ___| |__ __ _ _ __ __ _ ___ __| | \ \ / /__ _ __| | __| | + * | |_) | |/ _` | | | |/ _ \ '__| | | | '_ \ / _` | '_ \ / _` |/ _ \/ _` | \ \ /\ / / _ \| '__| |/ _` | + * | __/| | (_| | |_| | __/ | | |___| | | | (_| | | | | (_| | __/ (_| | \ V V / (_) | | | | (_| | + * |_| |_|\__,_|\__, |\___|_| \____|_| |_|\__,_|_| |_|\__, |\___|\__,_| \_/\_/ \___/|_| |_|\__,_| + * |___/ |___/ + */ + // Maybe this helps with people teleporting through Multiverse portals having problems? + final MovingData data = MovingData.getData(event.getPlayer()); + data.teleported = null; + data.clearFlyData(); + data.clearMorePacketsData(); + } + + /** + * We listen to this event to cancel the placement of boat the ground. Boats are made to float on water, right? + * + * @param event + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.LOWEST) - public void boat(final PlayerInteractEvent event) { - if (!NCPPlayer.hasPermission(event.getPlayer(), Permissions.MOVING_BOATONGROUND) + public void onPlayerInteract(final PlayerInteractEvent event) { + /* + * ____ _ ___ _ _ + * | _ \| | __ _ _ _ ___ _ __ |_ _|_ __ | |_ ___ _ __ __ _ ___| |_ + * | |_) | |/ _` | | | |/ _ \ '__| | || '_ \| __/ _ \ '__/ _` |/ __| __| + * | __/| | (_| | |_| | __/ | | || | | | || __/ | | (_| | (__| |_ + * |_| |_|\__,_|\__, |\___|_| |___|_| |_|\__\___|_| \__,_|\___|\__| + * |___/ + */ + if (!event.getPlayer().hasPermission(Permissions.MOVING_BOATSANYWHERE) && event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getPlayer().getItemInHand().getType() == Material.BOAT && event.getClickedBlock().getType() != Material.WATER && event.getClickedBlock().getType() != Material.STATIONARY_WATER && event.getClickedBlock().getRelative(event.getBlockFace()).getType() != Material.WATER && event.getClickedBlock().getRelative(event.getBlockFace()).getType() != Material.STATIONARY_WATER) + // If the player right clicked on a non-liquid block with a boat in his hands, cancel the event. event.setCancelled(true); } /** - * This event handler is used to prevent the player from quickly - * disconnecting/reconnecting in order to cancel his fall damages. + * We listen to this event to prevent players from leaving while falling, so from avoiding fall damages. * * @param event - * The PlayerJoinEvent + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.MONITOR) - public void join(final PlayerJoinEvent event) { - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final MovingData data = (MovingData) getData(player); + public void onPlayerJoin(final PlayerJoinEvent event) { + /* + * ____ _ _ _ + * | _ \| | __ _ _ _ ___ _ __ | | ___ (_)_ __ + * | |_) | |/ _` | | | |/ _ \ '__| _ | |/ _ \| | '_ \ + * | __/| | (_| | |_| | __/ | | |_| | (_) | | | | | + * |_| |_|\__,_|\__, |\___|_| \___/ \___/|_|_| |_| + * |___/ + */ + final Player player = event.getPlayer(); + final MovingData data = MovingData.getData(player); // If the player has joined in the air and a safe location is defined... - if (player.getLocation().add(0, -1, 0).getBlock().getType() == Material.AIR - && data.lastSafeLocations[0] != null) - // ...then teleport him to this location - event.getPlayer().teleport(data.lastSafeLocations[0]); + if (player.getLocation().add(0D, -1D, 0D).getBlock().getType() == Material.AIR + && MovingData.getData(player).lastSafeLocations[0] != null) + // ...teleport him to this location. + player.teleport(data.lastSafeLocations[0]); } /** - * When a player moves, he will be checked for various - * suspicious behaviour. + * When a player moves, he will be checked for various suspicious behaviors. * * @param event - * The PlayerMoveEvent + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.LOWEST) - public void move(final PlayerMoveEvent event) { + public void onPlayerMove(final PlayerMoveEvent event) { + /* + * _____ _ __ __ + * | __ \| | | \/ | + * | |__) | | __ _ _ _ ___ _ __ | \ / | _____ _____ + * | ___/| |/ _` | | | |/ _ \ '__| | |\/| |/ _ \ \ / / _ \ + * | | | | (_| | |_| | __/ | | | | | (_) \ V / __/ + * |_| |_|\__,_|\__, |\___|_| |_| |_|\___/ \_/ \___| + * __/ | + * |___/ + */ + final Player player = event.getPlayer(); - // Don't care for vehicles - if (event.getPlayer().isInsideVehicle()) - return; - - // Don't care for movements that are very high distance or to another - // world (such that it is very likely the event data was modified by - // another plugin before we got it) + // Don't care for movements that are very high distance, to another world (such that it is very likely the event + // data was modified by another plugin before we got it) or if the player is inside a vehicle. if (!event.getFrom().getWorld().equals(event.getTo().getWorld()) - || event.getFrom().distanceSquared(event.getTo()) > 400) + || event.getFrom().distanceSquared(event.getTo()) > 400D || player.isInsideVehicle()) return; - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final MovingConfig cc = (MovingConfig) getConfig(player); - final MovingData data = (MovingData) getData(player); + final MovingData data = MovingData.getData(player); - // Advance various counters and values that change per movement - // tick. They are needed to decide on how fast a player may - // move. - tickVelocities(data); + // Just try to estimate velocities over time. Not very precise, but works good enough most of the time. Do + // general data modifications one for each event. + if (data.horizontalVelocityCounter > 0D) + data.horizontalVelocityCounter--; + else if (data.horizontalFreedom > 0.001D) + data.horizontalFreedom *= 0.90D; - // Remember locations - data.from.set(event.getFrom()); - final Location to = event.getTo(); - data.to.set(to); + if (data.verticalVelocity <= 0.1D) + data.verticalVelocityCounter--; + if (data.verticalVelocityCounter > 0D) { + data.verticalFreedom += data.verticalVelocity; + data.verticalVelocity *= 0.90D; + } else if (data.verticalFreedom > 0.001D) + // Counter has run out, now reduce the vertical freedom over time. + data.verticalFreedom *= 0.93D; - // Remember safe locations + // Remember the location if it's safe. if (Math.abs(event.getPlayer().getVelocity().getY()) < 0.0785D) { data.lastSafeLocations[0] = data.lastSafeLocations[1]; data.lastSafeLocations[1] = event.getFrom(); } - PreciseLocation newTo = null; + final PlayerLocation from = new PlayerLocation(event.getFrom(), player); + data.from = from.getLocation(); + final PlayerLocation to = new PlayerLocation(event.getTo(), player); + data.to = to.getLocation(); - /** RUNFLY CHECK SECTION **/ - // If the player isn't handled by runfly checks - if (!cc.runflyCheck || player.hasPermission(Permissions.MOVING_RUNFLY)) - // Just because he is allowed now, doesn't mean he will always - // be. So forget data about the player related to moving - data.clearRunFlyData(); - else if (cc.allowFlying || player.canFly() && cc.identifyCreativeMode - || player.hasPermission(Permissions.MOVING_FLYING)) - // Only do the limited flying check - newTo = flyingCheck.check(player); + Location newTo = null; + + if ((player.getGameMode() == GameMode.CREATIVE || player.getAllowFlight()) && creativeFly.isEnabled(player)) + // If the player is handled by the creative fly check, execute it. + newTo = creativeFly.check(player, from, to); + else if (survivalFly.isEnabled(player)) + // If he is handled by the survival fly check, execute it. + newTo = survivalFly.check(player, from, to); else - // Go for the full treatment - newTo = runningCheck.check(player); + // He isn't handled by any fly check, clear his data. + data.clearFlyData(); - /** WATERWALK CHECK SECTION **/ - if (newTo == null && cc.waterWalkCheck && !cc.allowFlying && (!player.canFly() || !cc.identifyCreativeMode) - && (!cc.runflyCheck || !player.hasPermission(Permissions.MOVING_FLYING)) - && !player.hasPermission(Permissions.MOVING_WATERWALK)) - newTo = waterWalkCheck.check(player); - - /** MOREPACKETS CHECK SECTION **/ - if (!cc.morePacketsCheck || player.hasPermission(Permissions.MOVING_MOREPACKETS)) + if (newTo == null && morePackets.isEnabled(player)) + // If he hasn't been stopped by any other check and is handled by the more packets check, execute it. + newTo = morePackets.check(player, from, to); + else + // Otherwise we need to clear his data. data.clearMorePacketsData(); - else if (newTo == null) - newTo = morePacketsCheck.check(player); - // Did one of the check(s) decide we need a new "to"-location? + // Did one of the checks decide we need a new "to"-location? if (newTo != null) { - // Compose a new location based on coordinates of "newTo" and - // viewing direction of "event.getTo()" to allow the player to - // look somewhere else despite getting pulled back by NoCheatPlus - event.setTo(new Location(player.getWorld(), newTo.x, newTo.y, newTo.z, to.getYaw(), to.getPitch())); - - // remember where we send the player to - data.teleportTo.set(newTo); + // Yes, so set it. + event.setTo(newTo); + // Remember where we send the player to. + data.teleported = newTo; } } /** - * When a player uses a portal, all information related to the - * moving checks becomes invalid. + * When a player uses a portal, all information related to the moving checks becomes invalid. * * @param event - */ - @EventHandler( - priority = EventPriority.MONITOR) - public void portal(final PlayerPortalEvent event) { - final MovingData data = (MovingData) getData(NCPPlayer.getPlayer(event.getPlayer())); - data.clearMorePacketsData(); - data.clearRunFlyData(); - } - - /** - * This events listener fixes the exploitation of the safe - * respawn location (usually exploited with gravel or sand). - * - * @param event - */ - @EventHandler - public void quit(final PlayerQuitEvent event) { - - // If the player has buried himself, remove the blocks to prevent - // him from respawning at the surface - if (!NCPPlayer.hasPermission(event.getPlayer(), Permissions.MOVING_RESPAWNTRICK) - && (event.getPlayer().getLocation().getBlock().getType() == Material.GRAVEL || event.getPlayer() - .getLocation().getBlock().getType() == Material.SAND)) { - event.getPlayer().getLocation().getBlock().setType(Material.AIR); - event.getPlayer().getLocation().add(0, 1, 0).getBlock().setType(Material.AIR); - } - } - - /** - * When a player respawns, all information related to the - * moving checks becomes invalid. - * - * @param event - */ - @EventHandler( - priority = EventPriority.MONITOR) - public void respawn(final PlayerRespawnEvent event) { - final MovingData data = (MovingData) getData(NCPPlayer.getPlayer(event.getPlayer())); - data.clearMorePacketsData(); - data.clearRunFlyData(); - } - - /** - * If a player gets teleported, it may have two reasons. Either - * it was NoCheatPlus or another plugin. If it was NoCheatPlus, the target - * location should match the "data.teleportTo" value. - * - * On teleports, reset some movement related data that gets invalid - * - * @param event - * The PlayerTeleportEvent - */ - @EventHandler( - priority = EventPriority.HIGHEST) - public void teleport(final PlayerTeleportEvent event) { - - final NCPPlayer player = NCPPlayer.getPlayer(event.getPlayer()); - final MovingData data = (MovingData) getData(player); - - // If it was a teleport initialized by NoCheatPlus, do it anyway - // even if another plugin said "no" - if (data.teleportTo.isSet() && data.teleportTo.equals(event.getTo())) - event.setCancelled(false); - else - // Only if it wasn't NoCheatPlus, drop data from morepackets check. - // If it was NoCheatPlus, we don't want players to exploit the - // runfly check teleporting to get rid of the "morepackets" - // data. - data.clearMorePacketsData(); - - // Always drop data from runfly check, as it always loses its validity - // after teleports. Always! - data.teleportTo.reset(); - data.clearRunFlyData(); - } - - /** - * Just try to estimate velocities over time - * Not very precise, but works good enough most - * of the time. - * - * @param data - */ - private void tickVelocities(final MovingData data) { - - /******** DO GENERAL DATA MODIFICATIONS ONCE FOR EACH EVENT *****/ - if (data.horizVelocityCounter > 0) - data.horizVelocityCounter--; - else if (data.horizFreedom > 0.001) - data.horizFreedom *= 0.90; - - if (data.vertVelocity <= 0.1) - data.vertVelocityCounter--; - if (data.vertVelocityCounter > 0) { - data.vertFreedom += data.vertVelocity; - data.vertVelocity *= 0.90; - } else if (data.vertFreedom > 0.001) - // Counter has run out, now reduce the vert freedom over time - data.vertFreedom *= 0.93; - } - - /** - * When an vehicle moves, it will be checked for various - * suspicious behaviour. - * - * @param event - * The VehicleMoveEvent - */ - @EventHandler( - ignoreCancelled = true, priority = EventPriority.LOWEST) - public void vehicleMove(final VehicleMoveEvent event) { - - // Don't care for vehicles without a player as passenger - if (event.getVehicle().getPassenger() == null || !(event.getVehicle().getPassenger() instanceof Player)) - return; - - // Don't care for movements that are very high distance or to another - // world (such that it is very likely the event data was modified by - // another plugin before we got it) - if (!event.getFrom().getWorld().equals(event.getTo().getWorld()) - || event.getFrom().distanceSquared(event.getTo()) > 400) - return; - - final NCPPlayer player = NCPPlayer.getPlayer((Player) event.getVehicle().getPassenger()); - - final MovingConfig cc = (MovingConfig) getConfig(player); - final MovingData data = (MovingData) getData(player); - - // Remember locations - data.fromVehicle.set(event.getFrom()); - final Location to = event.getTo(); - data.toVehicle.set(to); - - if (cc.morePacketsVehicleCheck && !player.hasPermission(Permissions.MOVING_MOREPACKETSVEHICLE) - && morePacketsVehicleCheck.check(player)) { - // Drop the usual items (depending on the vehicle) - if (event.getVehicle() instanceof Minecart) - event.getVehicle().getWorld() - .dropItemNaturally(event.getVehicle().getLocation(), new ItemStack(Material.MINECART, 1)); - else if (event.getVehicle() instanceof Boat) { - event.getVehicle().getWorld() - .dropItemNaturally(event.getVehicle().getLocation(), new ItemStack(Material.WOOD, 3)); - event.getVehicle().getWorld() - .dropItemNaturally(event.getVehicle().getLocation(), new ItemStack(Material.STICK, 2)); - } - // Remove the passenger - if (event.getVehicle().getPassenger() != null) - event.getVehicle().setPassenger(null); - // Destroy the vehicle - event.getVehicle().remove(); - } - } - - /** - * Player got a velocity packet. The server can't keep track - * of actual velocity values (by design), so we have to try - * and do that ourselves. Very rough estimates. - * - * @param event - * The PlayerVelocityEvent + * the event */ @EventHandler( ignoreCancelled = true, priority = EventPriority.MONITOR) - public void velocity(final PlayerVelocityEvent event) { + public void onPlayerPortal(final PlayerPortalEvent event) { + /* + * ____ _ ____ _ _ + * | _ \| | __ _ _ _ ___ _ __ | _ \ ___ _ __| |_ __ _| | + * | |_) | |/ _` | | | |/ _ \ '__| | |_) / _ \| '__| __/ _` | | + * | __/| | (_| | |_| | __/ | | __/ (_) | | | || (_| | | + * |_| |_|\__,_|\__, |\___|_| |_| \___/|_| \__\__,_|_| + * |___/ + */ + final MovingData data = MovingData.getData(event.getPlayer()); + data.clearFlyData(); + data.clearMorePacketsData(); + } - final MovingData data = (MovingData) getData(NCPPlayer.getPlayer(event.getPlayer())); + /** + * When a player respawns, all information related to the moving checks becomes invalid. + * + * @param event + * the event + */ + @EventHandler( + priority = EventPriority.MONITOR) + public void onPlayerRespawn(final PlayerRespawnEvent event) { + /* + * ____ _ ____ + * | _ \| | __ _ _ _ ___ _ __ | _ \ ___ ___ _ __ __ ___ ___ __ + * | |_) | |/ _` | | | |/ _ \ '__| | |_) / _ \/ __| '_ \ / _` \ \ /\ / / '_ \ + * | __/| | (_| | |_| | __/ | | _ < __/\__ \ |_) | (_| |\ V V /| | | | + * |_| |_|\__,_|\__, |\___|_| |_| \_\___||___/ .__/ \__,_| \_/\_/ |_| |_| + * |___/ |_| + */ + final MovingData data = MovingData.getData(event.getPlayer()); + data.clearFlyData(); + data.clearMorePacketsData(); + } - final Vector v = event.getVelocity(); + /** + * If a player gets teleported, it may have two reasons. Either it was NoCheat or another plugin. If it was + * NoCheatPlus, the target location should match the "data.teleportedTo" value. + * + * On teleports, reset some movement related data that gets invalid. + * + * @param event + * the event + */ + @EventHandler( + priority = EventPriority.HIGHEST) + public void onPlayerTeleport(final PlayerTeleportEvent event) { + /* + * ____ _ _____ _ _ + * | _ \| | __ _ _ _ ___ _ __ |_ _|__| | ___ _ __ ___ _ __| |_ + * | |_) | |/ _` | | | |/ _ \ '__| | |/ _ \ |/ _ \ '_ \ / _ \| '__| __| + * | __/| | (_| | |_| | __/ | | | __/ | __/ |_) | (_) | | | |_ + * |_| |_|\__,_|\__, |\___|_| |_|\___|_|\___| .__/ \___/|_| \__| + * |___/ |_| + */ + final Player player = event.getPlayer(); + final MovingData data = MovingData.getData(player); - double newVal = v.getY(); - if (newVal >= 0.0D) { - data.vertVelocity += newVal; - data.vertFreedom += data.vertVelocity; + // If it was a teleport initialized by NoCheatPlus, do it anyway even if another plugin said "no". + if (data.teleported != null && data.teleported.equals(event.getTo())) + event.setCancelled(false); + else + // Only if it wasn't NoCheatPlus, drop data from more packets check. If it was NoCheatPlus, we don't want + // players to exploit the fly check teleporting to get rid of the "morepackets" data. + data.clearMorePacketsData(); + + // Always drop data from fly checks, as it always loses its validity after teleports. Always! + data.teleported = null; + data.clearFlyData(); + } + + /** + * Player got a velocity packet. The server can't keep track of actual velocity values (by design), so we have to + * try and do that ourselves. Very rough estimates. + * + * @param event + * the event + */ + @EventHandler( + ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerVelocity(final PlayerVelocityEvent event) { + /* + * ____ _ __ __ _ _ _ + * | _ \| | __ _ _ _ ___ _ __ \ \ / /__| | ___ ___(_) |_ _ _ + * | |_) | |/ _` | | | |/ _ \ '__| \ \ / / _ \ |/ _ \ / __| | __| | | | + * | __/| | (_| | |_| | __/ | \ V / __/ | (_) | (__| | |_| |_| | + * |_| |_|\__,_|\__, |\___|_| \_/ \___|_|\___/ \___|_|\__|\__, | + * |___/ |___/ + */ + final MovingData data = MovingData.getData(event.getPlayer()); + + final Vector velocity = event.getVelocity(); + + double newVal = velocity.getY(); + if (newVal >= 0D) { + data.verticalVelocity += newVal; + data.verticalFreedom += data.verticalVelocity; } - data.vertVelocityCounter = 50; + data.verticalVelocityCounter = 50; - newVal = Math.sqrt(Math.pow(v.getX(), 2) + Math.pow(v.getZ(), 2)); - if (newVal > 0.0D) { - data.horizFreedom += newVal; - data.horizVelocityCounter = 30; + newVal = Math.sqrt(velocity.getX() * velocity.getX() + velocity.getZ() * velocity.getZ()); + if (newVal > 0D) { + data.horizontalFreedom += newVal; + data.horizontalVelocityCounter = 30; } } /** - * Just for security, if a player switches between worlds, reset the - * runfly and morepackets checks data, because it is definitely invalid - * now + * When a vehicle moves, its player will be checked for various suspicious behaviors. * * @param event - * The PlayerChangedWorldEvent + * the event */ @EventHandler( - priority = EventPriority.MONITOR) - public void worldChange(final PlayerChangedWorldEvent event) { - // Maybe this helps with people teleporting through multiverse portals having problems? - final MovingData data = (MovingData) getData(NCPPlayer.getPlayer(event.getPlayer())); - data.teleportTo.reset(); - data.clearRunFlyData(); - data.clearMorePacketsData(); + ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onVehicleMove(final VehicleMoveEvent event) { + /* + * __ __ _ _ _ __ __ + * \ \ / /__| |__ (_) ___| | ___ | \/ | _____ _____ + * \ \ / / _ \ '_ \| |/ __| |/ _ \ | |\/| |/ _ \ \ / / _ \ + * \ V / __/ | | | | (__| | __/ | | | | (_) \ V / __/ + * \_/ \___|_| |_|_|\___|_|\___| |_| |_|\___/ \_/ \___| + */ + // Don't care if a player isn't inside the vehicle, for movements that are very high distance or to another + // world (such that it is very likely the event data was modified by another plugin before we got it). + if (event.getVehicle().getPassenger() == null || !(event.getVehicle().getPassenger() instanceof Player) + || !event.getFrom().getWorld().equals(event.getTo().getWorld()) + || event.getFrom().distanceSquared(event.getTo()) > 400D) + return; + + final Player player = (Player) event.getVehicle().getPassenger(); + + Location newTo = null; + + if (morePacketsVehicle.isEnabled(player)) + // If the player is handled by the more packets vehicle check, execute it. + newTo = morePacketsVehicle.check(player, event.getFrom(), event.getTo()); + else + // Otherwise we need to clear his data. + MovingData.getData(player).clearMorePacketsData(); + + // Did one of the checks decide we need a new "to"-location? + if (newTo != null) + // Yes, so schedule a delayed task to teleport back the vehicle (this event isn't cancellable and we can't + // teleport the vehicle within the event). + Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() { + private Vehicle vehicle; + private Location location; + + @Override + public void run() { + vehicle.teleport(location); + } + + public Runnable set(final Vehicle vehicle, final Location location) { + this.vehicle = vehicle; + this.location = location; + return this; + } + }.set(event.getVehicle(), newTo), 1L); } } diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java b/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java new file mode 100644 index 00000000..3c846efe --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java @@ -0,0 +1,167 @@ +package fr.neatmonster.nocheatplus.checks.moving; + +import java.util.Locale; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.PlayerLocation; + +/* + * M"""""""`YM MM""""""""`M dP dP + * M mmmm. M MM mmmmmmmM 88 88 + * M MMMMM M .d8888b. M' MMMM .d8888b. 88 88 + * M MMMMM M 88' `88 MM MMMMMMMM 88' `88 88 88 + * M MMMMM M 88. .88 MM MMMMMMMM 88. .88 88 88 + * M MMMMM M `88888P' MM MMMMMMMM `88888P8 dP dP + * MMMMMMMMMMM MMMMMMMMMMMM + */ +/** + * A check to see if people cheat by tricking the server to not deal them fall damage. + */ +public class NoFall extends Check { + + /** + * The event triggered by this check. + */ + public class NoFallEvent extends CheckEvent { + + /** + * Instantiates a new no fall event. + * + * @param player + * the player + */ + public NoFallEvent(final Player player) { + super(player); + } + } + + /** + * Checks a player. + * + * @param player + * the player + * @param from + * the from + * @param to + * the to + */ + public void check(final Player player, final PlayerLocation from, final PlayerLocation to) { + final MovingConfig cc = MovingConfig.getConfig(player); + final MovingData data = MovingData.getData(player); + + // If the player is server-side in creative mode, we have to stop here to avoid hurting him when he switches + // back to "normal" mode. + if (player.getGameMode() == GameMode.CREATIVE || player.getAllowFlight()) { + data.noFallDistance = 0F; + data.noFallLastAddedDistance = 0F; + return; + } + + // This check is pretty much always a step behind for technical reasons. + if (from.isInLiquid() || to.isInLiquid() || from.isOnGround() || to.isOnGround() || from.isOnLadder() + || to.isOnLadder()) + // Start with zero fall distance. + data.noFallDistance = 0F; + + if (cc.noFallAggressive && (from.isInLiquid() || from.isOnGround() || from.isOnLadder()) + && (to.isInLiquid() || to.isOnGround() || to.isOnLadder()) && from.getY() <= to.getY() + && player.getFallDistance() > 3F) { + Bukkit.broadcastMessage(ChatColor.RED + "Problem with the no fall check!"); // TODO + + data.noFallDistance = player.getFallDistance(); + + // Increment violation level. + data.noFallVL += player.getFallDistance(); + + // Dispatch a no fall event (API). + final NoFallEvent e = new NoFallEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. + if (!e.isCancelled() && executeActions(player, cc.noFallActions, data.noFallVL)) + // Deal fall damages to the player. + ((CraftPlayer) player).getHandle().b(0D, true); + data.noFallDistance = 0F; + } + + // If we increased fall height before for no good reason, reduce now by the same amount. + if (player.getFallDistance() > data.noFallLastAddedDistance) + player.setFallDistance(player.getFallDistance() - data.noFallLastAddedDistance); + + data.noFallLastAddedDistance = 0F; + + final float difference = data.noFallDistance - player.getFallDistance(); + + // We want to know if the fallDistance recorded by the game is smaller than the fall distance recorded by the + // plugin. + if (difference > 1F && (to.isInWater() || to.isOnGround() || to.isOnLadder()) && data.noFallDistance > 2F) { + Bukkit.broadcastMessage(ChatColor.RED + "Problem with the no fall check!"); // TODO + + // Increment violation level. + data.noFallVL += difference; + + // Dispatch a no fall event (API). + final NoFallEvent e = new NoFallEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // Execute whatever actions are associated with this check and the violation level and find out if we should + // cancel the event. If "cancelled", the fall damage gets dealt in a way that's visible to other plugins. + if (!e.isCancelled() && executeActions(player, cc.noFallActions, data.noFallVL)) + // Increase the fall distance a bit. :) + player.setFallDistance(data.noFallDistance + difference); + data.noFallDistance = 0F; + } + + // Increase the fall distance that is recorded by the plugin, AND set the fall distance of the player to + // whatever he would get with this move event. This modifies Minecrafts fall damage calculation slightly, but + // that's still better than ignoring players that try to use "teleports" or "stepdown" to avoid falldamage. It + // is only added for big height differences anyway, as to avoid to much deviation from the original Minecraft + // feeling. + if (from.getY() > to.getY()) { + final float deltaY = (float) (from.getY() - to.getY()); + data.noFallDistance += deltaY; + + if (deltaY > 1F) { + data.noFallLastAddedDistance = deltaY; + player.setFallDistance(player.getFallDistance() + deltaY); + } else + data.noFallLastAddedDistance = 0F; + } else + data.noFallLastAddedDistance = 0F; + + // Reduce violation level. + data.noFallVL *= 0.95D; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, + * org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(MovingData.getData(player).noFallVL)); + else if (wildcard == ParameterName.FALLDISTANCE) + return String.format(Locale.US, "%.2f", MovingData.getData(player).noFallDistance); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.MOVING_NOFALL) && MovingConfig.getConfig(player).noFallCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/NoFallCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/NoFallCheck.java deleted file mode 100644 index b842ab9c..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/NoFallCheck.java +++ /dev/null @@ -1,159 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import java.util.Locale; - -import org.bukkit.Bukkit; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; - -/** - * A check to see if people cheat by tricking the server to not deal them - * fall damage. - * - */ -public class NoFallCheck extends MovingCheck { - - public class NoFallCheckEvent extends MovingEvent { - - public NoFallCheckEvent(final NoFallCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public NoFallCheck() { - super("nofall"); - } - - /** - * Calculate if and how much the player "failed" this check. - * - */ - public void check(final NCPPlayer player, final Object... args) { - final MovingConfig cc = getConfig(player); - final MovingData data = getData(player); - - // If the player is serverside in creative mode, we have to stop here to - // avoid hurting him when he switches back to "normal" mode - if (player.canFly()) { - data.fallDistance = 0F; - data.lastAddedFallDistance = 0F; - return; - } - - // If the player is in ladder or unclimbable vines, do not do the check - if (CheckUtils.isLadder(CheckUtils.evaluateLocation(player.getWorld(), data.from)) - || CheckUtils.isLadder(CheckUtils.evaluateLocation(player.getWorld(), data.to)) - || CheckUtils.isVine(CheckUtils.evaluateLocation(player.getWorld(), data.from)) - || CheckUtils.isVine(CheckUtils.evaluateLocation(player.getWorld(), data.to))) { - data.fallDistance = 0F; - data.lastAddedFallDistance = 0F; - return; - } - - // This check is pretty much always a step behind for technical reasons. - if (data.fromOnOrInGround) - // Start with zero fall distance - data.fallDistance = 0F; - - if (cc.nofallAggressive && data.fromOnOrInGround && data.toOnOrInGround && data.from.y <= data.to.y - && player.getBukkitPlayer().getFallDistance() > 3.0F) { - data.fallDistance = player.getBukkitPlayer().getFallDistance(); - data.nofallVL += data.fallDistance; - incrementStatistics(player, Id.MOV_NOFALL, data.fallDistance); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - final boolean cancel = executeActions(player, cc.nofallActions, data.nofallVL); - if (cancel) - player.dealFallDamage(); - data.fallDistance = 0F; - } - - // If we increased fall height before for no good reason, reduce now by - // the same amount - if (player.getBukkitPlayer().getFallDistance() > data.lastAddedFallDistance) - player.getBukkitPlayer().setFallDistance( - player.getBukkitPlayer().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 - final float difference = data.fallDistance - player.getBukkitPlayer().getFallDistance(); - - if (difference > 1.0F && data.toOnOrInGround && data.fallDistance > 2.0F) { - data.nofallVL += difference; - incrementStatistics(player, Id.MOV_NOFALL, difference); - - // Execute whatever actions are associated with this check and the - // violation level and find out if we should cancel the event - final boolean cancel = executeActions(player, cc.nofallActions, data.nofallVL); - - // If "cancelled", the fall damage gets dealt in a way that's - // visible to other plugins - if (cancel) { - // Increase the fall distance a bit :) - final float totalDistance = data.fallDistance + difference * (cc.nofallMultiplier - 1.0F); - - player.getBukkitPlayer().setFallDistance(totalDistance); - } - - data.fallDistance = 0F; - } - - // Increase the fall distance that is recorded by the plugin, AND set - // the fall distance of the player - // to whatever he would get with this move event. This modifies - // Minecrafts fall damage calculation - // slightly, but that's still better than ignoring players that try to - // use "teleports" or "stepdown" - // to avoid falldamage. It is only added for big height differences - // anyway, as to avoid to much deviation - // from the original Minecraft feeling. - - final double oldY = data.from.y; - final double newY = data.to.y; - - if (oldY > newY) { - final float dist = (float) (oldY - newY); - data.fallDistance += dist; - - if (dist > 1.0F) { - data.lastAddedFallDistance = dist; - player.getBukkitPlayer().setFallDistance(player.getBukkitPlayer().getFallDistance() + dist); - } else - data.lastAddedFallDistance = 0.0F; - } else - data.lastAddedFallDistance = 0.0F; - - // Reduce falldamage violation level - data.nofallVL *= 0.95D; - - return; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final NoFallCheckEvent event = new NoFallCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).nofallVL)); - else if (wildcard == ParameterName.FALLDISTANCE) - return String.format(Locale.US, "%.2f", getData(player).fallDistance); - else - return super.getParameter(wildcard, player); - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/RunningCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/RunningCheck.java deleted file mode 100644 index 9d7ccc9e..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/RunningCheck.java +++ /dev/null @@ -1,334 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import net.minecraft.server.AxisAlignedBB; -import net.minecraft.server.EntityPlayer; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.craftbukkit.entity.CraftPlayer; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Permissions; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * The counterpart to the FlyingCheck. People that are not allowed to fly - * get checked by this. It will try to identify when they are jumping, check if - * they aren't jumping too high or far, check if they aren't moving too fast on - * normal ground, while sprinting, sneaking or swimming. - * - */ -public class RunningCheck extends MovingCheck { - - public class RunningCheckEvent extends MovingEvent { - - public RunningCheckEvent(final RunningCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - 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 NoFallCheck noFallCheck; - - public RunningCheck() { - super("running"); - - noFallCheck = new NoFallCheck(); - } - - public PreciseLocation check(final NCPPlayer player, final Object... args) { - final MovingConfig cc = getConfig(player); - final MovingData data = getData(player); - - // Some shortcuts: - final PreciseLocation setBack = data.runflySetBackPoint; - final PreciseLocation to = data.to; - final PreciseLocation from = data.from; - - // Calculate some distances - final double xDistance = data.to.x - from.x; - final double zDistance = to.z - from.z; - final double horizontalDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); - - if (!setBack.isSet()) - setBack.set(from); - - // To know if a player "is on ground" is useful - final int fromType = CheckUtils.evaluateLocation(player.getWorld(), from); - final int toType = CheckUtils.evaluateLocation(player.getWorld(), to); - - final boolean fromOnGround = CheckUtils.isOnGround(fromType); - final boolean fromInGround = CheckUtils.isInGround(fromType); - final boolean toOnGround = CheckUtils.isOnGround(toType); - final boolean toInGround = CheckUtils.isInGround(toType); - - PreciseLocation newToLocation = null; - - final double resultHoriz = Math.max( - 0.0D, - checkHorizontal(player, data, CheckUtils.isLiquid(fromType) && CheckUtils.isLiquid(toType), - horizontalDistance, cc)); - final double resultVert = Math.max( - 0.0D, - checkVertical(player, data, fromOnGround, toOnGround, - CheckUtils.isLiquid(fromType) && CheckUtils.isLiquid(toType), cc)); - - final double result = (resultHoriz + resultVert) * 100; - - data.jumpPhase++; - - // Slowly reduce the level with each event - data.runflyVL *= 0.95; - - // Did the player move in unexpected ways? - if (result > 0) { - // Increment violation counter - data.runflyVL += result; - - incrementStatistics(player, data.statisticCategory, result); - - final boolean cancel = executeActions(player, cc.actions, data.runflyVL); - - // Was one of the actions a cancel? Then do it - if (cancel) - newToLocation = setBack; - else if (toOnGround || toInGround) { - // In case it only gets logged, not stopped by NoCheatPlus - // Update the setback location at least a bit - setBack.set(to); - data.jumpPhase = 0; - - } - } else if (toInGround && from.y >= to.y || CheckUtils.isLiquid(toType)) { - // Yes, if the player moved down "into" the ground or into liquid - setBack.set(to); - setBack.y = Math.ceil(setBack.y); - data.jumpPhase = 0; - } else if (toOnGround && (from.y >= to.y || setBack.y <= Math.floor(to.y))) { - // Yes, if the player moved down "onto" the ground and the new - // setback point is higher up than the old or at least at the - // same height - setBack.set(to); - setBack.y = Math.floor(setBack.y); - data.jumpPhase = 0; - } else if (fromOnGround || fromInGround || toOnGround || toInGround) - // The player at least touched the ground somehow - data.jumpPhase = 0; - - /********* EXECUTE THE NOFALL CHECK ********************/ - final boolean checkNoFall = cc.nofallCheck && !player.hasPermission(Permissions.MOVING_NOFALL); - - if (checkNoFall && newToLocation == null) { - data.fromOnOrInGround = fromOnGround || fromInGround; - data.toOnOrInGround = toOnGround || toInGround; - noFallCheck.check(player, data, cc); - } - - return newToLocation; - } - - /** - * Calculate how much the player failed this check - * - */ - private double checkHorizontal(final NCPPlayer player, final MovingData data, final boolean isSwimming, - final double totalDistance, final MovingConfig cc) { - - // How much further did the player move than expected?? - double distanceAboveLimit = 0.0D; - - // A player is considered sprinting if the flag is set and if he has - // enough food level (configurable) - final boolean sprinting = player.getBukkitPlayer().isSprinting() && player.getBukkitPlayer().getFoodLevel() > 5; - - double limit = 0.0D; - - Id statisticsCategory = null; - - // Player on ice? Give him higher max speed - final Block b = player.getLocation().getBlock(); - if (b.getType() == Material.ICE || b.getRelative(0, -1, 0).getType() == Material.ICE) - data.onIce = 20; - else if (data.onIce > 0) - data.onIce--; - - if (cc.blockingCheck && player.getBukkitPlayer().isBlocking() - && !player.hasPermission(Permissions.MOVING_BLOCKING)) { - limit = cc.blockingSpeedLimit; - statisticsCategory = Id.MOV_BLOCKING; - if (cc.sneakingCheck && player.getBukkitPlayer().isSneaking() - && !player.hasPermission(Permissions.MOVING_SNEAKING)) - limit = Math.min(cc.sneakingSpeedLimit, cc.blockingSpeedLimit); - } else if (cc.sneakingCheck && player.getBukkitPlayer().isSneaking() - && !player.hasPermission(Permissions.MOVING_SNEAKING)) { - limit = cc.sneakingSpeedLimit; - statisticsCategory = Id.MOV_SNEAKING; - } else if (isSwimming && !player.hasPermission(Permissions.MOVING_SWIMMING)) { - limit = cc.swimmingSpeedLimit; - statisticsCategory = Id.MOV_SWIMMING; - } else if (!sprinting) { - limit = cc.walkingSpeedLimit; - statisticsCategory = Id.MOV_RUNNING; - } else { - limit = cc.sprintingSpeedLimit; - statisticsCategory = Id.MOV_RUNNING; - } - - if (data.onIce > 0) - limit *= 2.5D; - - // If the player is in web, we need a fixed limit - final World world = player.getWorld(); - if (CheckUtils.isWeb(CheckUtils.evaluateLocation(world, data.from)) - && CheckUtils.isWeb(CheckUtils.evaluateLocation(world, data.to)) - && !player.hasPermission(Permissions.MOVING_COBWEB)) { - limit = cc.cobWebHoriSpeedLimit; - statisticsCategory = Id.MOV_COBWEB; - } - - // Taken directly from Minecraft code, should work - limit *= player.getSpeedAmplifier(); - - distanceAboveLimit = totalDistance - limit - data.horizFreedom; - - data.bunnyhopdelay--; - - // Did he go too far? - if (distanceAboveLimit > 0 && sprinting) - // Try to treat it as a the "bunnyhop" problem - if (data.bunnyhopdelay <= 0 && distanceAboveLimit > 0.05D && distanceAboveLimit < 0.4D) { - data.bunnyhopdelay = 9; - distanceAboveLimit = 0; - } - - if (distanceAboveLimit > 0) { - // Try to consume the "buffer" - distanceAboveLimit -= data.horizontalBuffer; - data.horizontalBuffer = 0; - - // Put back the "overconsumed" buffer - if (distanceAboveLimit < 0) - data.horizontalBuffer = -distanceAboveLimit; - } else - data.horizontalBuffer = Math.min(maxBonus, data.horizontalBuffer - distanceAboveLimit); - - if (distanceAboveLimit > 0) - data.statisticCategory = statisticsCategory; - - return distanceAboveLimit; - } - - /** - * Calculate if and how much the player "failed" this check. - * - */ - private double checkVertical(final NCPPlayer player, final MovingData data, final boolean fromOnGround, - final boolean toOnGround, final boolean isSwimming, final MovingConfig cc) { - - // How much higher did the player move than expected?? - double distanceAboveLimit = 0.0D; - - // Potion effect "Jump" - final double jumpAmplifier = player.getJumpAmplifier(); - if (jumpAmplifier > data.lastJumpAmplifier) - data.lastJumpAmplifier = jumpAmplifier; - - double limit = data.vertFreedom + cc.jumpheight; - - limit *= data.lastJumpAmplifier; - - if (data.jumpPhase > jumpingLimit + data.lastJumpAmplifier) - limit -= (data.jumpPhase - jumpingLimit) * 0.15D; - - // Handle the calculation differently if the player is in water - if (isSwimming && data.to.y - data.from.y > 0D) { - // We need to make sure the player isn't a special block - // We get the bounding box of the player - final EntityPlayer entity = ((CraftPlayer) player.getBukkitPlayer()).getHandle(); - final AxisAlignedBB aabb = entity.boundingBox.clone(); - // Grow it of the minimum value (to collide with blocks) - aabb.grow(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); - final double xValue = (aabb.d - aabb.a) / 2D; - final double zValue = (aabb.f - aabb.c) / 2D; - if (!isSpecial(player.getWorld(), data.to.x - xValue, data.to.y, data.to.z - zValue) - && !isSpecial(player.getWorld(), data.to.x + xValue, data.to.y, data.to.z - zValue) - && !isSpecial(player.getWorld(), data.to.x - xValue, data.to.y, data.to.z + zValue) - && !isSpecial(player.getWorld(), data.to.x + xValue, data.to.y, data.to.z + zValue)) - distanceAboveLimit = data.to.y - data.from.y - cc.verticalSwimmingSpeedLimit; - } - - // Handle the calculation differently if the player is in cobweb - if (distanceAboveLimit <= 0D - && new Location(player.getWorld(), data.to.x, data.to.y, data.to.z).getBlock().getType() == Material.WEB) - distanceAboveLimit = Math.abs(data.to.y - data.from.y) - cc.cobWebVertSpeedLimit; - - if (distanceAboveLimit <= 0D) - distanceAboveLimit = data.to.y - data.runflySetBackPoint.y - limit; - - if (distanceAboveLimit > 0D) - data.statisticCategory = Id.MOV_FLYING; - - if (toOnGround || fromOnGround) - data.lastJumpAmplifier = 0; - - // Bukkit.broadcastMessage("d = " + distanceAboveLimit); - - return distanceAboveLimit; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final RunningCheckEvent event = new RunningCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - - if (wildcard == ParameterName.CHECK) - // Workaround for something until I find a better way to do it - return getData(player).statisticCategory.toString(); - else if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).runflyVL)); - else - return super.getParameter(wildcard, player); - } - - /** - * Checks if a block special (checks if the block is stairs/fence or not) - * - * @param world - * @param x - * @param y - * @param z - * @param above - * @return is the block special? - */ - private boolean isSpecial(final World world, final double x, final double y, final double z) { - Material material = new Location(world, x, y, z).getBlock().getType(); - if (material == Material.BRICK_STAIRS || material == Material.COBBLESTONE_STAIRS - || material == Material.NETHER_BRICK_STAIRS || material == Material.SMOOTH_STAIRS - || material == Material.STEP || material == Material.WOOD_STAIRS) - return true; - material = new Location(world, x, y - 1, z).getBlock().getType(); - if (material == Material.FENCE || material == Material.IRON_FENCE || material == Material.NETHER_FENCE) - return true; - return false; - } -} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java new file mode 100644 index 00000000..d399fe0e --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java @@ -0,0 +1,359 @@ +package fr.neatmonster.nocheatplus.checks.moving; + +import java.util.Locale; + +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.MobEffectList; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import fr.neatmonster.nocheatplus.actions.ParameterName; +import fr.neatmonster.nocheatplus.checks.Check; +import fr.neatmonster.nocheatplus.checks.CheckEvent; +import fr.neatmonster.nocheatplus.players.Permissions; +import fr.neatmonster.nocheatplus.utilities.PlayerLocation; + +/* + * MP""""""`MM oo dP MM""""""""`M dP + * M mmmmm..M 88 MM mmmmmmmM 88 + * M. `YM dP dP 88d888b. dP .dP dP dP .dP .d8888b. 88 M' MMMM 88 dP dP + * MMMMMMM. M 88 88 88' `88 88 d8' 88 88 d8' 88' `88 88 MM MMMMMMMM 88 88 88 + * M. .MMM' M 88. .88 88 88 .88' 88 88 .88' 88. .88 88 MM MMMMMMMM 88 88. .88 + * Mb. .dM `88888P' dP 8888P' dP 8888P' `88888P8 dP MM MMMMMMMM dP `8888P88 + * MMMMMMMMMMM MMMMMMMMMMMM .88 + * d8888P + */ +/** + * The counterpart to the CreativeFly check. People that are not allowed to fly get checked by this. It will try to + * identify when they are jumping, check if they aren't jumping too high or far, check if they aren't moving too fast on + * normal ground, while sprinting, sneaking, swimming, etc. + */ +public class SurvivalFly extends Check { + + /** + * The event triggered by this check. + */ + public class SurvivalFlyEvent extends CheckEvent { + + /** + * Instantiates a new survival fly event. + * + * @param player + * the player + */ + public SurvivalFlyEvent(final Player player) { + super(player); + } + } + + /** The common margin of error for some speeds. */ + private static final double MARGIN = 0.001D; + + /** The horizontal speed limit when blocking. */ + private static final double BLOCKING_MOVE = 0.16D; + + /** The vertical speed limit when ascending into web. */ + private static final double COBWEB_ASCEND = 0.02D + MARGIN; + + /** The vertical speed limit when descending into web. */ + private static final double COBWEB_DESCEND = 0.062D + MARGIN; + + /** The horizontal speed limit when moving into web. */ + private static final double COBWEB_MOVE = 0.08D; + + /** The horizontal speed amplifier when being on ice. */ + private static final double ICE_AMPLIFIER = 2.5D; + + /** The number of events contained in a jump phase. */ + private static final int JUMP_PHASE = 7; + + /** The distance removed after each jumping event. */ + private static final double JUMP_STEP = 0.15D; + + /** The vertical speed limit when ascending on a ladder. */ + private static final double LADDER_ASCEND = 0.225D + MARGIN; + + /** The vertical speed limit when descending on a ladder. */ + private static final double LADDER_DESCEND = 0.15D + MARGIN; + + /** The vertical speed limit when ascending into lava. */ + private static final double LAVA_ASCEND = 0.08D + MARGIN; + + /** The vertical speed limit when descending into lava. */ + private static final double LAVA_DESCEND = 0.085D + MARGIN; + + /** The horizontal speed limit when moving into lava. */ + private static final double LAVA_MOVE = 0.12D; + + /** The horizontal and usual speed limit when moving. */ + private static final double MOVE = 0.22D; + + /** The horizontal speed limit when sneaking. */ + private static final double SNEAKING_MOVE = 0.14D; + + /** The horizontal speed limit when moving on soul sand. */ + private static final double SOULSAND_MOVE = 0.11D; + + /** The horizontal speed limit when sprinting on soul sand. */ + private static final double SOULSAND_SPRINTING_MOVE = 0.14D; + + /** The horizontal speed limit when sprinting. */ + private static final double SPRINTING_MOVE = 0.37D; + + /** The vertical speed limit when ascending into water. */ + private static final double WATER_ASCEND = 0.13D + MARGIN; + + /** The vertical speed limit when descending into water. */ + private static final double WATER_DESCEND = 0.17D + MARGIN; + + /** The horizontal speed limit when moving into water. */ + private static final double WATER_MOVE = 0.18D; + + /** The no fall check. */ + private final NoFall noFall = new NoFall(); + + /** + * Checks a player. + * + * @param player + * the player + * @param from + * the from + * @param to + * the to + * @return the location + */ + public Location check(final Player player, final PlayerLocation from, final PlayerLocation to) { + final MovingConfig cc = MovingConfig.getConfig(player); + final MovingData data = MovingData.getData(player); + + data.setBack = data.setBack == null ? from.getLocation() : data.setBack; + + // Player on ice? Give him higher max speed. + if (from.isOnIce() || to.isOnIce()) + data.survivalFlyOnIce = 20; + else if (data.survivalFlyOnIce > 0) + data.survivalFlyOnIce--; + + // A player is considered sprinting if the flag is set and if he has enough food level. + final boolean sprinting = player.isSprinting() && player.getFoodLevel() > 5; + + boolean useBuffer = true; + + // Handle all the special cases. + double hAllowedDistance = cc.survivalFlyMoveSpeed / 100D * MOVE; + if (from.isInWeb() && to.isInWeb()) { + hAllowedDistance = cc.survivalFlyCobWebSpeed / 100D * COBWEB_MOVE; + useBuffer = false; + } else if (from.isOnSoulSand() && to.isOnSoulSand() && !sprinting) { + hAllowedDistance = cc.survivalFlySoulSandSpeed / 100D * SOULSAND_MOVE; + useBuffer = false; + } else if (from.isInLava() && to.isInLava()) + hAllowedDistance = cc.survivalFlyLavaSpeed / 100D * LAVA_MOVE; + else if (from.isOnSoulSand() && to.isOnSoulSand() && sprinting) { + hAllowedDistance = cc.survivalFlySoulSandSpeed / 100D * SOULSAND_SPRINTING_MOVE; + useBuffer = false; + } else if (player.isSneaking()) + hAllowedDistance = cc.survivalFlySneakingSpeed / 100D * SNEAKING_MOVE; + else if (player.isBlocking()) + hAllowedDistance = cc.survivalFlyBlockingSpeed / 100D * BLOCKING_MOVE; + else if (from.isInWater() && to.isInWater()) + hAllowedDistance = cc.survivalFlyWaterSpeed / 100D * WATER_MOVE; + else if (player.isSprinting() && player.getFoodLevel() > 5) + hAllowedDistance = cc.survivalFlySprintingSpeed / 100D * SPRINTING_MOVE; + + if (data.survivalFlyOnIce > 0) + hAllowedDistance *= ICE_AMPLIFIER; + + // Taken directly from Minecraft code, should work. + final EntityPlayer entity = ((CraftPlayer) player).getHandle(); + if (entity.hasEffect(MobEffectList.FASTER_MOVEMENT)) + hAllowedDistance *= 1.0D + 0.2D * (entity.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1); + + // Calculate some distances. + final double xDistance = to.getX() - from.getX(); + final double zDistance = to.getZ() - from.getZ(); + final double hDistance = Math.sqrt(xDistance * xDistance + zDistance * zDistance); + + double hDistanceAboveLimit = hDistance - hAllowedDistance - data.horizontalFreedom; + + data.bunnyhopDelay--; + + if (useBuffer) { + // Did he go too far? + if (hDistanceAboveLimit > 0D && sprinting) + // Try to treat it as a the "bunnyhop" problem. + if (data.bunnyhopDelay <= 0 && hDistanceAboveLimit > 0.05D && hDistanceAboveLimit < 0.4D) { + data.bunnyhopDelay = 9; + hDistanceAboveLimit = 0D; + } + + if (hDistanceAboveLimit > 0D) { + // Try to consume the "buffer". + hDistanceAboveLimit -= data.horizontalBuffer; + data.horizontalBuffer = 0D; + + // Put back the "overconsumed" buffer. + if (hDistanceAboveLimit < 0D) + data.horizontalBuffer = -hDistanceAboveLimit; + } else + // He was within limits, give the difference as buffer. + data.horizontalBuffer = Math.min(1D, data.horizontalBuffer - hDistanceAboveLimit); + } + + hDistanceAboveLimit = Math.max(0D, hDistanceAboveLimit); + + // Potion effect "Jump". + double jumpAmplifier = 1D; + if (entity.hasEffect(MobEffectList.JUMP)) { + final int amplifier = entity.getEffect(MobEffectList.JUMP).getAmplifier(); + if (amplifier > 20) + jumpAmplifier = 1.5D * (entity.getEffect(MobEffectList.JUMP).getAmplifier() + 1D); + else + jumpAmplifier = 1.2D * (entity.getEffect(MobEffectList.JUMP).getAmplifier() + 1D); + } + if (jumpAmplifier > data.jumpAmplifier) + data.jumpAmplifier = jumpAmplifier; + + // Remember since when the player is in lava/in water/on ladder. + if (from.isInLava() && !to.isInLava()) + data.survivalInLavaSince = 0L; + else if (!from.isInLava() && to.isInLava()) + data.survivalInLavaSince = System.currentTimeMillis(); + if (from.isInWater() && !to.isInWater()) + data.survivalInWaterSince = 0L; + else if (!from.isInWater() && to.isInWater()) + data.survivalInWaterSince = System.currentTimeMillis(); + if (from.isOnLadder() && !to.isOnLadder()) + data.survivalOnLadderSince = 0L; + else if (!from.isOnLadder() && to.isOnLadder()) + data.survivalOnLadderSince = System.currentTimeMillis(); + + double vDistance = to.getY() - from.getY(); + + // Handle all the special cases. + double vDistanceAboveLimit = 0D; + if (from.isInLava() && to.isInLava() && data.survivalInLavaSince > 0L + && System.currentTimeMillis() - data.survivalInLavaSince > 1000L) { + if (vDistance > cc.survivalFlyLavaSpeed / 100D * LAVA_ASCEND) + vDistanceAboveLimit = vDistance - cc.survivalFlyLavaSpeed / 100D * LAVA_ASCEND; + else if (vDistance < cc.survivalFlyLavaSpeed / 100D * -LAVA_DESCEND) + vDistanceAboveLimit = cc.survivalFlyLavaSpeed / 100D * -LAVA_DESCEND - vDistance; + } else if (from.isInWater() && to.isInWater() && data.survivalInWaterSince > 0L + && System.currentTimeMillis() - data.survivalInWaterSince > 1000L) { + if (vDistance > cc.survivalFlyWaterSpeed / 100D * WATER_ASCEND) + vDistanceAboveLimit = vDistance - cc.survivalFlyWaterSpeed / 100D * WATER_ASCEND; + else if (vDistance < cc.survivalFlyWaterSpeed / 100D * -WATER_DESCEND) + vDistanceAboveLimit = cc.survivalFlyWaterSpeed / 100D * -WATER_DESCEND - vDistance; + } else if (from.isInWeb() && to.isInWeb()) { + if (vDistance > cc.survivalFlyCobWebSpeed / 100D * COBWEB_ASCEND) + vDistanceAboveLimit = vDistance - cc.survivalFlyCobWebSpeed / 100D * COBWEB_ASCEND; + else if (vDistance < cc.survivalFlyCobWebSpeed / 100D * -COBWEB_DESCEND) + vDistanceAboveLimit = cc.survivalFlyCobWebSpeed / 100D * -COBWEB_DESCEND - vDistance; + } else if (from.isOnLadder(true) && to.isOnLadder(true) && data.survivalOnLadderSince > 0L + && System.currentTimeMillis() - data.survivalOnLadderSince > 1000L) { + if (vDistance > cc.survivalFlyLadderSpeed / 100D * LADDER_ASCEND) + vDistanceAboveLimit = vDistance - cc.survivalFlyLadderSpeed / 100D * LADDER_ASCEND; + else if (vDistance < cc.survivalFlyLadderSpeed / 100D * -LADDER_DESCEND) + vDistanceAboveLimit = cc.survivalFlyLadderSpeed / 100D * -LADDER_DESCEND - vDistance; + } else { + vDistance = to.getY() - data.setBack.getY(); + + double vAllowedDistance = (data.verticalFreedom + 1.35D) * data.jumpAmplifier; + if (data.survivalFlyJumpPhase > JUMP_PHASE + data.jumpAmplifier) + vAllowedDistance -= (data.survivalFlyJumpPhase - JUMP_PHASE) * JUMP_STEP; + + vDistanceAboveLimit = Math.max(0D, vDistance - vAllowedDistance); + } + + if (from.isOnGround() || to.isOnGround()) + data.jumpAmplifier = 0D; + + final double result = (hDistanceAboveLimit + vDistanceAboveLimit) * 100D; + + data.survivalFlyJumpPhase++; + + // Slowly reduce the level with each event. + data.survivalFlyVL *= 0.95D; + + // Did the player move in unexpected ways? + if (result > 0D) { + Bukkit.broadcastMessage(ChatColor.RED + player.getName() + ": problem with the survival fly check!"); // TODO + + // Increment violation counter. + data.survivalFlyVL += result; + + // Dispatch a survival fly event (API). + final SurvivalFlyEvent e = new SurvivalFlyEvent(player); + Bukkit.getPluginManager().callEvent(e); + + // If the other plugins haven't decided to cancel the execution of the actions, then do it. If one of the + // actions was a cancel, cancel it. + if (!e.isCancelled() && executeActions(player, cc.survivalFlyActions, data.survivalFlyVL)) + // Compose a new location based on coordinates of "newTo" and viewing direction of "event.getTo()" to + // allow the player to look somewhere else despite getting pulled back by NoCheatPlus. + return new Location(player.getWorld(), data.setBack.getX(), data.setBack.getY(), data.setBack.getZ(), + to.getYaw(), to.getPitch()); + else if (to.isInLiquid() || to.isInWeb() || to.isOnGround() || to.isOnLadder()) { + // In case it only gets logged, not stopped by NoCheatPlus, update the setback location at least a bit. + data.setBack = to.getLocation(); + data.survivalFlyJumpPhase = 0; + } + } + + // Decide if we should create a new setBack point. These are the result of a lot of bug reports, experience and + // trial and error. + else if (to.isInLiquid()) { + // If the player moved into liquid. + data.setBack = to.getLocation(); + data.setBack.setY(Math.ceil(data.setBack.getY())); + data.survivalFlyJumpPhase = 0; + } else if (to.isInWeb() || to.isOnLadder() || to.isOnGround() + && (from.getY() >= to.getY() || data.setBack.getY() <= Math.floor(to.getY()))) { + // If the player moved down "onto" the ground and the new setback point is higher up than the old or at + // least at the same height, or if the player is in web or on a ladder. + data.setBack = to.getLocation(); + data.survivalFlyJumpPhase = 0; + } else if (from.isInLiquid() || to.isInLiquid() || from.isInWeb() || to.isInWeb() || from.isOnGround() + || to.isOnGround() || from.isOnLadder() || to.isOnLadder()) + // The player at least touched the ground somehow. + data.survivalFlyJumpPhase = 0; + + if (noFall.isEnabled(player)) + // Execute the NoFall check. + noFall.check(player, from, to); + + return null; + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#getParameter(fr.neatmonster.nocheatplus.actions.ParameterName, + * org.bukkit.entity.Player) + */ + @Override + public String getParameter(final ParameterName wildcard, final Player player) { + final MovingData data = MovingData.getData(player); + if (wildcard == ParameterName.VIOLATIONS) + return String.valueOf(Math.round(data.survivalFlyVL)); + else if (wildcard == ParameterName.LOCATION_FROM) + return String.format(Locale.US, "%.2f, %.2f, %.2f", data.from.getX(), data.from.getY(), data.from.getZ()); + else if (wildcard == ParameterName.LOCATION_TO) + return String.format(Locale.US, "%.2f, %.2f, %.2f", data.to.getX(), data.to.getY(), data.to.getZ()); + else if (wildcard == ParameterName.DISTANCE) + return String.format(Locale.US, "%.2f", data.to.subtract(data.from).lengthSquared()); + else + return super.getParameter(wildcard, player); + } + + /* (non-Javadoc) + * @see fr.neatmonster.nocheatplus.checks.Check#isEnabled(org.bukkit.entity.Player) + */ + @Override + protected boolean isEnabled(final Player player) { + return !player.hasPermission(Permissions.MOVING_SURVIVALFLY) && MovingConfig.getConfig(player).survivalFlyCheck; + } +} diff --git a/src/fr/neatmonster/nocheatplus/checks/moving/WaterWalkCheck.java b/src/fr/neatmonster/nocheatplus/checks/moving/WaterWalkCheck.java deleted file mode 100644 index aaa305ff..00000000 --- a/src/fr/neatmonster/nocheatplus/checks/moving/WaterWalkCheck.java +++ /dev/null @@ -1,164 +0,0 @@ -package fr.neatmonster.nocheatplus.checks.moving; - -import net.minecraft.server.AxisAlignedBB; -import net.minecraft.server.EntityPlayer; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.craftbukkit.entity.CraftPlayer; - -import fr.neatmonster.nocheatplus.actions.ParameterName; -import fr.neatmonster.nocheatplus.actions.types.ActionList; -import fr.neatmonster.nocheatplus.checks.CheckUtils; -import fr.neatmonster.nocheatplus.players.NCPPlayer; -import fr.neatmonster.nocheatplus.players.informations.Statistics.Id; -import fr.neatmonster.nocheatplus.utilities.locations.PreciseLocation; - -/** - * This check is used to verify that players aren't walking on water - * - */ -public class WaterWalkCheck extends MovingCheck { - - public class WaterWalkCheckEvent extends MovingEvent { - - public WaterWalkCheckEvent(final WaterWalkCheck check, final NCPPlayer player, final ActionList actions, - final double vL) { - super(check, player, actions, vL); - } - } - - public WaterWalkCheck() { - super("waterwalk"); - } - - public PreciseLocation check(final NCPPlayer player, final Object... args) { - // Get the configuration and data of the player - final MovingConfig cc = getConfig(player); - final MovingData data = getData(player); - - // Check if the player comes from a liquid - final PreciseLocation from = data.from; - final int fromType = CheckUtils.evaluateLocation(player.getWorld(), from); - final boolean fromLiquid = CheckUtils.isLiquid(fromType); - - // If he is not, return - if (!fromLiquid) - return null; - - // Check if the player is going into a liquid - final PreciseLocation to = data.to; - final int toType = CheckUtils.evaluateLocation(player.getWorld(), to); - final boolean toLiquid = CheckUtils.isLiquid(toType); - - boolean upLiquid = false; - // If he is, check if the block containing his head is liquid too - if (toLiquid) { - final PreciseLocation upFrom = new PreciseLocation(); - upFrom.set(from); - upFrom.y++; - final int upFromType = CheckUtils.evaluateLocation(player.getWorld(), upFrom); - final PreciseLocation upTo = new PreciseLocation(); - upTo.set(to); - upTo.y++; - final int upToType = CheckUtils.evaluateLocation(player.getWorld(), upTo); - upLiquid = CheckUtils.isLiquid(upFromType) || CheckUtils.isLiquid(upToType); - } - - // Here is the interesting part, we get the bounding box of the player - final EntityPlayer entity = ((CraftPlayer) player.getBukkitPlayer()).getHandle(); - final AxisAlignedBB aabb = entity.boundingBox.clone(); - // Grow it of the minimum value (to collide with blocks) - aabb.grow(Double.MIN_VALUE, Double.MIN_VALUE, Double.MIN_VALUE); - // Now check if the player is forced to walk horizontally - // If he has a block above his head or if he his walking on stairs - final boolean isForced = isSpecial(player.getWorld(), aabb.a, aabb.e, aabb.c, true) - || isSpecial(player.getWorld(), aabb.d, aabb.e, aabb.c, true) - || isSpecial(player.getWorld(), aabb.a, aabb.e, aabb.f, true) - || isSpecial(player.getWorld(), aabb.d, aabb.e, aabb.f, true) - || isSpecial(player.getWorld(), aabb.a, aabb.b, aabb.c, false) - || isSpecial(player.getWorld(), aabb.d, aabb.b, aabb.c, false) - || isSpecial(player.getWorld(), aabb.a, aabb.b, aabb.f, false) - || isSpecial(player.getWorld(), aabb.d, aabb.b, aabb.f, false); - - // Calculate the delta with the surface - final double dSurface = Math.abs(to.y - Math.ceil(to.y)) + (to.y - Math.ceil(to.y) == 0 ? 1 : 0); - // Calculate the velocity of the player - final double velocity = player.getBukkitPlayer().getVelocity().lengthSquared(); - - // If the player his walking straight (and not force to do so) - if (fromLiquid && toLiquid && !upLiquid && !isForced && to.y == from.y && dSurface < 0.8D) { - // Increment the violation counter - data.waterWalkVL += 100D * dSurface; - // Increment the statistics - incrementStatistics(player, Id.MOV_WATERWALK, 100D * dSurface); - // Execute the actions - if (executeActions(player, cc.actions, data.waterWalkVL)) - // Cancel the move if required - return from; - } - - // If the player is trying to jump above the water - else if (fromLiquid && !toLiquid && !isForced && velocity > 0.09D) { - // Increment the violation counter - data.waterWalkVL += 100D * (velocity - 0.09D); - // Increment the statistics - incrementStatistics(player, Id.MOV_WATERWALK, 100D * (velocity - 0.09D)); - // Execute the actions - if (executeActions(player, cc.actions, data.waterWalkVL)) - // Cancel the move if required - return from; - } - - // Slowly reduce the level with each event to reward the player - data.waterWalkVL *= 0.95; - - return null; - } - - @Override - protected boolean executeActions(final NCPPlayer player, final ActionList actionList, final double violationLevel) { - final WaterWalkCheckEvent event = new WaterWalkCheckEvent(this, player, actionList, violationLevel); - Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled()) - return super.executeActions(player, event.getActions(), event.getVL()); - return false; - } - - @Override - public String getParameter(final ParameterName wildcard, final NCPPlayer player) { - if (wildcard == ParameterName.VIOLATIONS) - return String.valueOf(Math.round(getData(player).waterWalkVL)); - else - return super.getParameter(wildcard, player); - } - - /** - * Checks if a block special (if above is true, it checks if the block's type isn't air, otherwise it checks if the - * block is stairs/fence or not) - * - * @param world - * @param x - * @param y - * @param z - * @param above - * @return is the block special? - */ - private boolean isSpecial(final World world, final double x, final double y, final double z, final boolean above) { - Material material = new Location(world, x, y, z).getBlock().getType(); - if (above) - return material != Material.AIR; - else { - if (material == Material.BRICK_STAIRS || material == Material.COBBLESTONE_STAIRS - || material == Material.NETHER_BRICK_STAIRS || material == Material.SMOOTH_STAIRS - || material == Material.STEP || material == Material.WOOD_STAIRS) - return true; - material = new Location(world, x, y - 1, z).getBlock().getType(); - if (material == Material.FENCE || material == Material.IRON_FENCE || material == Material.NETHER_FENCE) - return true; - return false; - } - } -} diff --git a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java index 0dcf73d0..88d43657 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfPaths.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfPaths.java @@ -1,264 +1,243 @@ package fr.neatmonster.nocheatplus.config; +/* + * MM'""""'YMM .8888b MM"""""""`YM dP dP + * M' .mmm. `M 88 " MM mmmmm M 88 88 + * M MMMMMooM .d8888b. 88d888b. 88aaa M' .M .d8888b. d8888P 88d888b. .d8888b. + * M MMMMMMMM 88' `88 88' `88 88 MM MMMMMMMM 88' `88 88 88' `88 Y8ooooo. + * M. `MMM' .M 88. .88 88 88 88 MM MMMMMMMM 88. .88 88 88 88 88 + * MM. .dM `88888P' dP dP dP MM MMMMMMMM `88888P8 dP dP dP `88888P' + * MMMMMMMMMMM MMMMMMMMMMMM + */ /** - * Paths for the configuration options - * Making everything final static prevents accidentially modifying any - * of these - * + * Paths for the configuration options. Making everything final static prevents accidentally modifying any of these. */ public abstract class ConfPaths { - private static final String LOGGING = "logging."; - public static final String LOGGING_ACTIVE = LOGGING + "active"; - public static final String LOGGING_PREFIX = LOGGING + "prefix"; - public static final String LOGGING_FILENAME = LOGGING + "filename"; - public static final String LOGGING_LOGTOFILE = LOGGING + "file"; - public static final String LOGGING_LOGTOCONSOLE = LOGGING + "console"; - public static final String LOGGING_LOGTOINGAMECHAT = LOGGING + "ingamechat"; - public static final String LOGGING_DEBUGMESSAGES = LOGGING + "debugmessages"; + /* + * 888 ,e, + * 888 e88 88e e88 888 e88 888 " 888 8e e88 888 + * 888 d888 888b d888 888 d888 888 888 888 88b d888 888 + * 888 ,d Y888 888P Y888 888 Y888 888 888 888 888 Y888 888 + * 888,d88 "88 88" "88 888 "88 888 888 888 888 "88 888 + * , 88P , 88P , 88P + * "8",P" "8",P" "8",P" + */ + private static final String LOGGING = "logging."; + public static final String LOGGING_ACTIVE = LOGGING + "active"; + public static final String LOGGING_LOGTOFILE = LOGGING + "file"; + public static final String LOGGING_LOGTOCONSOLE = LOGGING + "console"; + public static final String LOGGING_LOGTOINGAMECHAT = LOGGING + "ingamechat"; + public static final String LOGGING_DEBUGMESSAGES = LOGGING + "debugmessages"; - private static final String MISCELLANEOUS = "miscellaneous."; - public static final String MISCELLANEOUS_ALLOWCLIENTMODS = MISCELLANEOUS + "allowclientmods"; - public static final String MISCELLANEOUS_OPBYCONSOLEONLY = MISCELLANEOUS + "opbyconsoleonly"; - public static final String MISCELLANEOUS_PROTECTPLUGINS = MISCELLANEOUS + "protectplugins"; + /* + * e e ,e, 888 888 + * d8b d8b " dP"Y e88'888 ,e e, 888 888 ,"Y88b 888 8e ,e e, e88 88e 8888 8888 dP"Y + * e Y8b Y8b 888 C88b d888 '8 d88 88b 888 888 "8" 888 888 88b d88 88b d888 888b 8888 8888 C88b + * d8b Y8b Y8b 888 Y88D Y888 , 888 , 888 888 ,ee 888 888 888 888 , Y888 888P Y888 888P Y88D + * d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP + */ + private static final String MISCELLANEOUS = "miscellaneous."; + public static final String MISCELLANEOUS_ALLOWCLIENTMODS = MISCELLANEOUS + "allowclientmods"; + public static final String MISCELLANEOUS_PROTECTPLUGINS = MISCELLANEOUS + "protectplugins"; - private static final String CHECKS = "checks."; + private static final String CHECKS = "checks."; - private static final String BLOCKBREAK = CHECKS + "blockbreak."; + /* + * 888 88b, 888 888 888 88b, 888 + * 888 88P' 888 e88 88e e88'888 888 ee 888 88P' 888,8, ,e e, ,"Y88b 888 ee + * 888 8K 888 d888 888b d888 '8 888 P 888 8K 888 " d88 88b "8" 888 888 P + * 888 88b, 888 Y888 888P Y888 , 888 b 888 88b, 888 888 , ,ee 888 888 b + * 888 88P' 888 "88 88" "88,e8' 888 8b 888 88P' 888 "YeeP" "88 888 888 8b + */ + private static final String BLOCKBREAK = CHECKS + "blockbreak."; - private static final String BLOCKBREAK_FASTBREAK = BLOCKBREAK + "fastbreak."; - public static final String BLOCKBREAK_FASTBREAK_CHECK = BLOCKBREAK_FASTBREAK + "active"; - public static final String BLOCKBREAK_FASTBREAK_INTERVALSURVIVAL = BLOCKBREAK_FASTBREAK + "intervalsurvival"; - public static final String BLOCKBREAK_FASTBREAK_INTERVALCREATIVE = BLOCKBREAK_FASTBREAK + "intervalcreative"; - public static final String BLOCKBREAK_FASTBREAK_ACTIONS = BLOCKBREAK_FASTBREAK + "actions"; + private static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + "direction."; + public static final String BLOCKBREAK_DIRECTION_CHECK = BLOCKBREAK_DIRECTION + "active"; + public static final String BLOCKBREAK_DIRECTION_ACTIONS = BLOCKBREAK_DIRECTION + "actions"; - private static final String BLOCKBREAK_REACH = BLOCKBREAK + "reach."; - public static final String BLOCKBREAK_REACH_CHECK = BLOCKBREAK_REACH + "active"; - public static final String BLOCKBREAK_REACH_ACTIONS = BLOCKBREAK_REACH + "actions"; + private static final String BLOCKBREAK_FASTBREAK = BLOCKBREAK + "fastbreak."; + public static final String BLOCKBREAK_FASTBREAK_CHECK = BLOCKBREAK_FASTBREAK + "active"; + public static final String BLOCKBREAK_FASTBREAK_EXPERIMENTAL = BLOCKBREAK_FASTBREAK + "experimental"; + public static final String BLOCKBREAK_FASTBREAK_INTERVAL = BLOCKBREAK_FASTBREAK + "interval"; + public static final String BLOCKBREAK_FASTBREAK_ACTIONS = BLOCKBREAK_FASTBREAK + "actions"; - private static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + "direction."; - public static final String BLOCKBREAK_DIRECTION_CHECK = BLOCKBREAK_DIRECTION + "active"; - public static final String BLOCKBREAK_DIRECTION_PRECISION = BLOCKBREAK_DIRECTION + "precision"; - public static final String BLOCKBREAK_DIRECTION_PENALTYTIME = BLOCKBREAK_DIRECTION + "penaltytime"; - public static final String BLOCKBREAK_DIRECTION_ACTIONS = BLOCKBREAK_DIRECTION + "actions"; + private static final String BLOCKBREAK_NOSWING = BLOCKBREAK + "noswing."; + public static final String BLOCKBREAK_NOSWING_CHECK = BLOCKBREAK_NOSWING + "active"; + public static final String BLOCKBREAK_NOSWING_ACTIONS = BLOCKBREAK_NOSWING + "actions"; - private static final String BLOCKBREAK_NOSWING = BLOCKBREAK + "noswing."; - public static final String BLOCKBREAK_NOSWING_CHECK = BLOCKBREAK_NOSWING + "active"; - public static final String BLOCKBREAK_NOSWING_ACTIONS = BLOCKBREAK_NOSWING + "actions"; + private static final String BLOCKBREAK_REACH = BLOCKBREAK + "reach."; + public static final String BLOCKBREAK_REACH_CHECK = BLOCKBREAK_REACH + "active"; + public static final String BLOCKBREAK_REACH_ACTIONS = BLOCKBREAK_REACH + "actions"; - private static final String BLOCKPLACE = CHECKS + "blockplace."; + /* + * 888 88b, 888 888 888 88e 888 + * 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e, + * 888 8K 888 d888 888b d888 '8 888 P 888 88" 888 "8" 888 d888 '8 d88 88b + * 888 88b, 888 Y888 888P Y888 , 888 b 888 888 ,ee 888 Y888 , 888 , + * 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 "88 888 "88,e8' "YeeP" + */ + private static final String BLOCKPLACE = CHECKS + "blockplace."; - private static final String BLOCKPLACE_FASTPLACE = BLOCKPLACE + "fastplace."; - public static final String BLOCKPLACE_FASTPLACE_CHECK = BLOCKPLACE_FASTPLACE + "active"; - public static final String BLOCKPLACE_FASTPLACE_INTERVAL = BLOCKPLACE_FASTPLACE + "interval"; - public static final String BLOCKPLACE_FASTPLACE_ACTIONS = BLOCKPLACE_FASTPLACE + "actions"; + private static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + "direction."; + public static final String BLOCKPLACE_DIRECTION_CHECK = BLOCKPLACE_DIRECTION + "active"; + public static final String BLOCKPLACE_DIRECTION_ACTIONS = BLOCKPLACE_DIRECTION + "actions"; - private static final String BLOCKPLACE_REACH = BLOCKPLACE + "reach."; - public static final String BLOCKPLACE_REACH_CHECK = BLOCKPLACE_REACH + "active"; - public static final String BLOCKPLACE_REACH_ACTIONS = BLOCKPLACE_REACH + "actions"; + private static final String BLOCKPLACE_FASTPLACE = BLOCKPLACE + "fastplace."; + public static final String BLOCKPLACE_FASTPLACE_CHECK = BLOCKPLACE_FASTPLACE + "active"; + public static final String BLOCKPLACE_FASTPLACE_EXPERIMENTAL = BLOCKPLACE_FASTPLACE + "experimental"; + public static final String BLOCKPLACE_FASTPLACE_INTERVAL = BLOCKPLACE_FASTPLACE + "interval"; + public static final String BLOCKPLACE_FASTPLACE_ACTIONS = BLOCKPLACE_FASTPLACE + "actions"; - private static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + "direction."; - public static final String BLOCKPLACE_DIRECTION_CHECK = BLOCKPLACE_DIRECTION + "active"; - public static final String BLOCKPLACE_DIRECTION_PRECISION = BLOCKPLACE_DIRECTION + "precision"; - public static final String BLOCKPLACE_DIRECTION_PENALTYTIME = BLOCKPLACE_DIRECTION + "penaltytime"; - public static final String BLOCKPLACE_DIRECTION_ACTIONS = BLOCKPLACE_DIRECTION + "actions"; + private static final String BLOCKPLACE_REACH = BLOCKPLACE + "reach."; + public static final String BLOCKPLACE_REACH_CHECK = BLOCKPLACE_REACH + "active"; + public static final String BLOCKPLACE_REACH_ACTIONS = BLOCKPLACE_REACH + "actions"; - private static final String BLOCKPLACE_PROJECTILE = BLOCKPLACE + "projectile."; - public static final String BLOCKPLACE_PROJECTILE_CHECK = BLOCKPLACE_PROJECTILE + "active"; - public static final String BLOCKPLACE_PROJECTILE_INTERVAL = BLOCKPLACE_PROJECTILE + "interval"; - public static final String BLOCKPLACE_PROJECTILE_ACTIONS = BLOCKPLACE_PROJECTILE + "actions"; + private static final String BLOCKPLACE_SPEED = BLOCKPLACE + "speed."; + public static final String BLOCKPLACE_SPEED_CHECK = BLOCKPLACE_SPEED + "active"; + public static final String BLOCKPLACE_SPEED_INTERVAL = BLOCKPLACE_SPEED + "interval"; + public static final String BLOCKPLACE_SPEED_ACTIONS = BLOCKPLACE_SPEED + "actions"; - private static final String BLOCKPLACE_FASTSIGN = BLOCKPLACE + "fastsign."; - public static final String BLOCKPLACE_FASTSIGN_CHECK = BLOCKPLACE_FASTSIGN + "active"; - public static final String BLOCKPLACE_FASTSIGN_EXCLUSIONS = BLOCKPLACE_FASTSIGN + "exclusions"; + /* + * e88'Y88 888 d8 + * d888 'Y 888 ee ,"Y88b d88 + * C8888 888 88b "8" 888 d88888 + * Y888 ,d 888 888 ,ee 888 888 + * "88,d88 888 888 "88 888 888 + */ + private static final String CHAT = CHECKS + "chat."; - private static final String CHAT = CHECKS + "chat."; + private static final String CHAT_ARRIVALS = CHAT + "arrivals."; + public static final String CHAT_ARRIVALS_CHECK = CHAT_ARRIVALS + "active"; + public static final String CHAT_ARRIVALS_JOINSLIMIT = CHAT_ARRIVALS + "joinslimit"; + public static final String CHAT_ARRIVALS_MESSAGE = CHAT_ARRIVALS + "message"; + public static final String CHAT_ARRIVALS_TIMELIMIT = CHAT_ARRIVALS + "timelimit"; + public static final String CHAT_ARRIVALS_ACTIONS = CHAT_ARRIVALS + "actions"; - private static final String CHAT_NOPWNAGE = CHAT + "nopwnage."; - public static final String CHAT_NOPWNAGE_CHECK = CHAT_NOPWNAGE + "active"; - public static final String CHAT_NOPWNAGE_WARNPLAYERS = CHAT_NOPWNAGE + "warnplayers"; - public static final String CHAT_NOPWNAGE_WARNOTHERS = CHAT_NOPWNAGE + "warnothers"; - public static final String CHAT_NOPWNAGE_WARNLEVEL = CHAT_NOPWNAGE + "warnlevel"; - public static final String CHAT_NOPWNAGE_WARNTIMEOUT = CHAT_NOPWNAGE + "warntimeout"; - public static final String CHAT_NOPWNAGE_BANLEVEL = CHAT_NOPWNAGE + "banlevel"; - public static final String CHAT_NOPWNAGE_ACTIONS = CHAT_NOPWNAGE + "otheractions"; + private static final String CHAT_COLOR = CHAT + "color."; + public static final String CHAT_COLOR_CHECK = CHAT_COLOR + "active"; + public static final String CHAT_COLOR_ACTIONS = CHAT_COLOR + "actions"; - private static final String CHAT_NOPWNAGE_MOVE = CHAT_NOPWNAGE + "move."; - public static final String CHAT_NOPWNAGE_MOVE_CHECK = CHAT_NOPWNAGE_MOVE + "active"; - public static final String CHAT_NOPWNAGE_MOVE_WEIGHTBONUS = CHAT_NOPWNAGE_MOVE + "weightbonus"; - public static final String CHAT_NOPWNAGE_MOVE_WEIGHTMALUS = CHAT_NOPWNAGE_MOVE + "weightmalus"; - public static final String CHAT_NOPWNAGE_MOVE_TIMEOUT = CHAT_NOPWNAGE_MOVE + "timeout"; + private static final String CHAT_NOPWNAGE = CHAT + "nopwnage."; + public static final String CHAT_NOPWNAGE_CHECK = CHAT_NOPWNAGE + "active"; + public static final String CHAT_NOPWNAGE_LEVEL = CHAT_NOPWNAGE + "level"; - private static final String CHAT_NOPWNAGE_REPEAT = CHAT_NOPWNAGE + "repeat."; - public static final String CHAT_NOPWNAGE_REPEAT_CHECK = CHAT_NOPWNAGE_REPEAT + "active"; - public static final String CHAT_NOPWNAGE_REPEAT_WEIGHT = CHAT_NOPWNAGE_REPEAT + "weight"; - public static final String CHAT_NOPWNAGE_REPEAT_TIMEOUT = CHAT_NOPWNAGE_REPEAT + "timeout"; + private static final String CHAT_NOPWNAGE_BANNED = CHAT_NOPWNAGE + "banned."; + public static final String CHAT_NOPWNAGE_BANNED_CHECK = CHAT_NOPWNAGE_BANNED + "active"; + public static final String CHAT_NOPWNAGE_BANNED_TIMEOUT = CHAT_NOPWNAGE_BANNED + "timeout"; + public static final String CHAT_NOPWNAGE_BANNED_WEIGHT = CHAT_NOPWNAGE_BANNED + "weight"; - private static final String CHAT_NOPWNAGE_SPEED = CHAT_NOPWNAGE + "speed."; - public static final String CHAT_NOPWNAGE_SPEED_CHECK = CHAT_NOPWNAGE_SPEED + "active"; - public static final String CHAT_NOPWNAGE_SPEED_WEIGHT = CHAT_NOPWNAGE_SPEED + "weight"; - public static final String CHAT_NOPWNAGE_SPEED_TIMEOUT = CHAT_NOPWNAGE_SPEED + "timeout"; + private static final String CHAT_NOPWNAGE_CAPTCHA = CHAT_NOPWNAGE + "captcha."; + public static final String CHAT_NOPWNAGE_CAPTCHA_CHECK = CHAT_NOPWNAGE_CAPTCHA + "active"; + public static final String CHAT_NOPWNAGE_CAPTCHA_CHARACTERS = CHAT_NOPWNAGE_CAPTCHA + "characters"; + public static final String CHAT_NOPWNAGE_CAPTCHA_LENGTH = CHAT_NOPWNAGE_CAPTCHA + "length"; + public static final String CHAT_NOPWNAGE_CAPTCHA_QUESTION = CHAT_NOPWNAGE_CAPTCHA + "question"; + public static final String CHAT_NOPWNAGE_CAPTCHA_SUCCESS = CHAT_NOPWNAGE_CAPTCHA + "success"; + public static final String CHAT_NOPWNAGE_CAPTCHA_TRIES = CHAT_NOPWNAGE_CAPTCHA + "tries"; - private static final String CHAT_NOPWNAGE_FIRST = CHAT_NOPWNAGE + "first."; - public static final String CHAT_NOPWNAGE_FIRST_CHECK = CHAT_NOPWNAGE_FIRST + "active"; - public static final String CHAT_NOPWNAGE_FIRST_WEIGHT = CHAT_NOPWNAGE_FIRST + "weight"; - public static final String CHAT_NOPWNAGE_FIRST_TIMEOUT = CHAT_NOPWNAGE_FIRST + "timeout"; + private static final String CHAT_NOPWNAGE_FIRST = CHAT_NOPWNAGE + "first."; + public static final String CHAT_NOPWNAGE_FIRST_CHECK = CHAT_NOPWNAGE_FIRST + "active"; + public static final String CHAT_NOPWNAGE_FIRST_TIMEOUT = CHAT_NOPWNAGE_FIRST + "timeout"; + public static final String CHAT_NOPWNAGE_FIRST_WEIGHT = CHAT_NOPWNAGE_FIRST + "weight"; - private static final String CHAT_NOPWNAGE_GLOBAL = CHAT_NOPWNAGE + "global."; - public static final String CHAT_NOPWNAGE_GLOBAL_CHECK = CHAT_NOPWNAGE_GLOBAL + "active"; - public static final String CHAT_NOPWNAGE_GLOBAL_WEIGHT = CHAT_NOPWNAGE_GLOBAL + "weight"; - public static final String CHAT_NOPWNAGE_GLOBAL_TIMEOUT = CHAT_NOPWNAGE_GLOBAL + "timeout"; + private static final String CHAT_NOPWNAGE_GLOBAL = CHAT_NOPWNAGE + "global."; + public static final String CHAT_NOPWNAGE_GLOBAL_CHECK = CHAT_NOPWNAGE_GLOBAL + "active"; + public static final String CHAT_NOPWNAGE_GLOBAL_TIMEOUT = CHAT_NOPWNAGE_GLOBAL + "timeout"; + public static final String CHAT_NOPWNAGE_GLOBAL_WEIGHT = CHAT_NOPWNAGE_GLOBAL + "weight"; - private static final String CHAT_NOPWNAGE_BANNED = CHAT_NOPWNAGE + "banned."; - public static final String CHAT_NOPWNAGE_BANNED_CHECK = CHAT_NOPWNAGE_BANNED + "active"; - public static final String CHAT_NOPWNAGE_BANNED_WEIGHT = CHAT_NOPWNAGE_BANNED + "weight"; - public static final String CHAT_NOPWNAGE_BANNED_TIMEOUT = CHAT_NOPWNAGE_BANNED + "timeout"; + private static final String CHAT_NOPWNAGE_MOVE = CHAT_NOPWNAGE + "move."; + public static final String CHAT_NOPWNAGE_MOVE_CHECK = CHAT_NOPWNAGE_MOVE + "active"; + public static final String CHAT_NOPWNAGE_MOVE_TIMEOUT = CHAT_NOPWNAGE_MOVE + "timeout"; + public static final String CHAT_NOPWNAGE_MOVE_WEIGHT_BONUS = CHAT_NOPWNAGE_MOVE + "weightbonus"; + public static final String CHAT_NOPWNAGE_MOVE_WEIGHT_MALUS = CHAT_NOPWNAGE_MOVE + "weightmalus"; - private static final String CHAT_NOPWNAGE_RELOG = CHAT_NOPWNAGE + "relog."; - public static final String CHAT_NOPWNAGE_RELOG_CHECK = CHAT_NOPWNAGE_RELOG + "active"; - public static final String CHAT_NOPWNAGE_RELOG_TIME = CHAT_NOPWNAGE_RELOG + "time"; - public static final String CHAT_NOPWNAGE_RELOG_WARNINGS = CHAT_NOPWNAGE_RELOG + "warnings"; - public static final String CHAT_NOPWNAGE_RELOG_TIMEOUT = CHAT_NOPWNAGE_RELOG + "timeout"; + private static final String CHAT_NOPWNAGE_RELOGIN = CHAT_NOPWNAGE + "relogin."; + public static final String CHAT_NOPWNAGE_RELOGIN_CHECK = CHAT_NOPWNAGE_RELOGIN + "active"; + public static final String CHAT_NOPWNAGE_RELOGIN_TIMEOUT = CHAT_NOPWNAGE_RELOGIN + "timeout"; - private static final String CHAT_NOPWNAGE_CAPTCHA = CHAT_NOPWNAGE + "captcha."; - public static final String CHAT_NOPWNAGE_CAPTCHA_CHECK = CHAT_NOPWNAGE_CAPTCHA + "active"; - public static final String CHAT_NOPWNAGE_CAPTCHA_TRIES = CHAT_NOPWNAGE_CAPTCHA + "tries"; - public static final String CHAT_NOPWNAGE_CAPTCHA_LENGTH = CHAT_NOPWNAGE_CAPTCHA + "length"; - public static final String CHAT_NOPWNAGE_CAPTCHA_CHARACTERS = CHAT_NOPWNAGE_CAPTCHA + "characters"; + private static final String CHAT_NOPWNAGE_RELOGIN_WARNING = CHAT_NOPWNAGE_RELOGIN + "warning."; + public static final String CHAT_NOPWNAGE_RELOGIN_WARNING_MESSAGE = CHAT_NOPWNAGE_RELOGIN_WARNING + "message"; + public static final String CHAT_NOPWNAGE_RELOGIN_WARNING_NUMBER = CHAT_NOPWNAGE_RELOGIN_WARNING + "number"; + public static final String CHAT_NOPWNAGE_RELOGIN_WARNING_TIMEOUT = CHAT_NOPWNAGE_RELOGIN_WARNING + "timeout"; - private static final String CHAT_NOPWNAGE_MESSAGES = CHAT_NOPWNAGE + "messages."; - public static final String CHAT_NOPWNAGE_MESSAGES_KICK = CHAT_NOPWNAGE_MESSAGES + "kick"; - public static final String CHAT_NOPWNAGE_MESSAGES_CAPTCHAQUESTION = CHAT_NOPWNAGE_MESSAGES + "captchaquestion"; - public static final String CHAT_NOPWNAGE_MESSAGES_CAPTCHASUCCESS = CHAT_NOPWNAGE_MESSAGES + "captchasuccess"; - public static final String CHAT_NOPWNAGE_MESSAGES_WARNPLAYER = CHAT_NOPWNAGE_MESSAGES + "warnplayer"; - public static final String CHAT_NOPWNAGE_MESSAGES_WARNOTHERS = CHAT_NOPWNAGE_MESSAGES + "warnothers"; - public static final String CHAT_NOPWNAGE_MESSAGES_WARNRELOG = CHAT_NOPWNAGE_MESSAGES + "warnrelog"; + private static final String CHAT_NOPWNAGE_REPEAT = CHAT_NOPWNAGE + "repeat."; + public static final String CHAT_NOPWNAGE_REPEAT_CHECK = CHAT_NOPWNAGE_REPEAT + "active"; + public static final String CHAT_NOPWNAGE_REPEAT_TIMEOUT = CHAT_NOPWNAGE_REPEAT + "timeout"; + public static final String CHAT_NOPWNAGE_REPEAT_WEIGHT = CHAT_NOPWNAGE_REPEAT + "weight"; - private static final String CHAT_ARRIVALSLIMIT = CHAT + "arrivalslimit."; - public static final String CHAT_ARRIVALSLIMIT_CHECK = CHAT_ARRIVALSLIMIT + "active"; - public static final String CHAT_ARRIVALSLIMIT_PLAYERSLIMIT = CHAT_ARRIVALSLIMIT + "playerslimit"; - public static final String CHAT_ARRIVALSLIMIT_TIMEFRAME = CHAT_ARRIVALSLIMIT + "timeframe"; - public static final String CHAT_ARRIVALSLIMIT_COOLDOWNDELAY = CHAT_ARRIVALSLIMIT + "cooldowndelay"; - public static final String CHAT_ARRIVALSLIMIT_KICKMESSAGE = CHAT_ARRIVALSLIMIT + "kickmessage"; - public static final String CHAT_ARRIVALSLIMIT_NEWTIME = CHAT_ARRIVALSLIMIT + "newtime"; - public static final String CHAT_ARRIVALSLIMIT_ACTIONS = CHAT_ARRIVALSLIMIT + "actions"; + private static final String CHAT_NOPWNAGE_SPEED = CHAT_NOPWNAGE + "speed."; + public static final String CHAT_NOPWNAGE_SPEED_CHECK = CHAT_NOPWNAGE_SPEED + "active"; + public static final String CHAT_NOPWNAGE_SPEED_TIMEOUT = CHAT_NOPWNAGE_SPEED + "timeout"; + public static final String CHAT_NOPWNAGE_SPEED_WEIGHT = CHAT_NOPWNAGE_SPEED + "weight"; - private static final String CHAT_COLOR = CHAT + "color."; - public static final String CHAT_COLOR_CHECK = CHAT_COLOR + "active"; - public static final String CHAT_COLOR_ACTIONS = CHAT_COLOR + "actions"; + private static final String CHAT_NOPWNAGE_WARN = CHAT_NOPWNAGE + "warn."; + public static final String CHAT_NOPWNAGE_WARN_LEVEL = CHAT_NOPWNAGE_WARN + "level"; + public static final String CHAT_NOPWNAGE_WARN_TIMEOUT = CHAT_NOPWNAGE_WARN + "timeout"; - private static final String FIGHT = CHECKS + "fight."; + private static final String CHAT_NOPWNAGE_WARN_OTHERS = CHAT_NOPWNAGE_WARN + "others."; + public static final String CHAT_NOPWNAGE_WARN_OTHERS_CHECK = CHAT_NOPWNAGE_WARN_OTHERS + "active"; + public static final String CHAT_NOPWNAGE_WARN_OTHERS_MESSAGE = CHAT_NOPWNAGE_WARN_OTHERS + "message"; - private static final String FIGHT_DIRECTION = FIGHT + "direction."; - public static final String FIGHT_DIRECTION_CHECK = FIGHT_DIRECTION + "active"; - public static final String FIGHT_DIRECTION_PRECISION = FIGHT_DIRECTION + "precision"; - public static final String FIGHT_DIRECTION_PENALTYTIME = FIGHT_DIRECTION + "penaltytime"; - public static final String FIGHT_DIRECTION_ACTIONS = FIGHT_DIRECTION + "actions"; + private static final String CHAT_NOPWNAGE_WARN_PLAYER = CHAT_NOPWNAGE_WARN + "player."; + public static final String CHAT_NOPWNAGE_WARN_PLAYER_CHECK = CHAT_NOPWNAGE_WARN_PLAYER + "active"; + public static final String CHAT_NOPWNAGE_WARN_PLAYER_MESSAGE = CHAT_NOPWNAGE_WARN_PLAYER + "message"; - private static final String FIGHT_NOSWING = FIGHT + "noswing."; - public static final String FIGHT_NOSWING_CHECK = FIGHT_NOSWING + "active"; - public static final String FIGHT_NOSWING_ACTIONS = FIGHT_NOSWING + "actions"; + public static final String CHAT_NOPWNAGE_ACTIONS = CHAT_NOPWNAGE + "actions"; - private static final String FIGHT_REACH = FIGHT + "reach."; - public static final String FIGHT_REACH_CHECK = FIGHT_REACH + "active"; - public static final String FIGHT_REACH_LIMIT = FIGHT_REACH + "distance"; - public static final String FIGHT_REACH_PENALTYTIME = FIGHT_REACH + "penaltytime"; - public static final String FIGHT_REACH_ACTIONS = FIGHT_REACH + "actions"; + /* + * e e ,e, + * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 + * e Y8b Y8b d888 888b Y8b Y8P 888 888 88b d888 888 + * d8b Y8b Y8b Y888 888P Y8b " 888 888 888 Y888 888 + * d888b Y8b Y8b "88 88" Y8P 888 888 888 "88 888 + * , 88P + * "8",P" + */ + private static final String MOVING = CHECKS + "moving."; - private static final String FIGHT_SPEED = FIGHT + "speed."; - public static final String FIGHT_SPEED_CHECK = FIGHT_SPEED + "active"; - public static final String FIGHT_SPEED_ATTACKLIMIT = FIGHT_SPEED + "attacklimit"; - public static final String FIGHT_SPEED_ACTIONS = FIGHT_SPEED + "actions"; + private static final String MOVING_CREATIVEFLY = MOVING + "creativefly."; + public static final String MOVING_CREATIVEFLY_CHECK = MOVING_CREATIVEFLY + "active"; + public static final String MOVING_CREATIVEFLY_HORIZONTALSPEED = MOVING_CREATIVEFLY + "horizontalspeed"; + public static final String MOVING_CREATIVEFLY_MAXHEIGHT = MOVING_CREATIVEFLY + "maxheight"; + public static final String MOVING_CREATIVEFLY_VERTICALSPEED = MOVING_CREATIVEFLY + "verticalspeed"; + public static final String MOVING_CREATIVEFLY_ACTIONS = MOVING_CREATIVEFLY + "actions"; - private static final String FIGHT_GODMODE = FIGHT + "godmode."; - public static final String FIGHT_GODMODE_CHECK = FIGHT_GODMODE + "active"; - public static final String FIGHT_GODMODE_ACTIONS = FIGHT_GODMODE + "actions"; + private static final String MOVING_MOREPACKETS = MOVING + "morepackets."; + public static final String MOVING_MOREPACKETS_CHECK = MOVING_MOREPACKETS + "active"; + public static final String MOVING_MOREPACKETS_ACTIONS = MOVING_MOREPACKETS + "actions"; - private static final String FIGHT_INSTANTHEAL = FIGHT + "instantheal."; - public static final String FIGHT_INSTANTHEAL_CHECK = FIGHT_INSTANTHEAL + "active"; - public static final String FIGHT_INSTANTHEAL_ACTIONS = FIGHT_INSTANTHEAL + "actions"; + private static final String MOVING_MOREPACKETSVEHICLE = MOVING + "morepacketsvehicle."; + public static final String MOVING_MOREPACKETSVEHICLE_CHECK = MOVING_MOREPACKETSVEHICLE + "active"; + public static final String MOVING_MOREPACKETSVEHICLE_ACTIONS = MOVING_MOREPACKETSVEHICLE + "actions"; - private static final String FIGHT_KNOCKBACK = FIGHT + "knockback."; - public static final String FIGHT_KNOCKBACK_CHECK = FIGHT_KNOCKBACK + "active"; - public static final String FIGHT_KNOCKBACK_INTERVAL = FIGHT_KNOCKBACK + "interval"; - public static final String FIGHT_KNOCKBACK_ACTIONS = FIGHT_KNOCKBACK + "actions"; + private static final String MOVING_NOFALL = MOVING + "nofall."; + public static final String MOVING_NOFALL_CHECK = MOVING_NOFALL + "active"; + public static final String MOVING_NOFALL_AGGRESSIVE = MOVING_NOFALL + "aggressive"; + public static final String MOVING_NOFALL_ACTIONS = MOVING_NOFALL + "actions"; - private static final String FIGHT_CRITICAL = FIGHT + "critical."; - public static final String FIGHT_CRITICAL_CHECK = FIGHT_CRITICAL + "active"; - public static final String FIGHT_CRITICAL_FALLDISTANCE = FIGHT_CRITICAL + "falldistance"; - public static final String FIGHT_CRITICAL_VELOCITY = FIGHT_CRITICAL + "velocity"; - public static final String FIGHT_CRITICAL_ACTIONS = FIGHT_CRITICAL + "actions"; + private static final String MOVING_SURVIVALFLY = MOVING + "survivalfly."; + public static final String MOVING_SURVIVALFLY_CHECK = MOVING_SURVIVALFLY + "active"; + public static final String MOVING_SURVIVALFLY_ALLOWFASTSNEAKING = MOVING_SURVIVALFLY + "allowfastsneaking"; + public static final String MOVING_SURVIVALFLY_ALLOWFASTBLOCKING = MOVING_SURVIVALFLY + "allowfastblocking"; + public static final String MOVING_SURVIVALFLY_BLOCKINGSPEED = MOVING_SURVIVALFLY + "blockingspeed"; + public static final String MOVING_SURVIVALFLY_COBWEBSPEED = MOVING_SURVIVALFLY + "cobwebspeed"; + public static final String MOVING_SURVIVALFLY_LAVASPEED = MOVING_SURVIVALFLY + "lavaspeed"; + public static final String MOVING_SURVIVALFLY_LADDERSPEED = MOVING_SURVIVALFLY + "ladderspeed"; + public static final String MOVING_SURVIVALFLY_MOVESPEED = MOVING_SURVIVALFLY + "movespeed"; + public static final String MOVING_SURVIVALFLY_SNEAKINGSPEED = MOVING_SURVIVALFLY + "sneakingspeed"; + public static final String MOVING_SURVIVALFLY_SOULSANDSPEED = MOVING_SURVIVALFLY + "soulsandspeed"; + public static final String MOVING_SURVIVALFLY_SPRINTINGSPEED = MOVING_SURVIVALFLY + "sprintingspeed"; + public static final String MOVING_SURVIVALFLY_WATERSPEED = MOVING_SURVIVALFLY + "waterspeed"; + public static final String MOVING_SURVIVALFLY_ACTIONS = MOVING_SURVIVALFLY + "actions"; - private static final String FIGHT_ANGLE = FIGHT + "angle."; - public static final String FIGHT_ANGLE_CHECK = FIGHT_ANGLE + "active"; - public static final String FIGHT_ANGLE_THRESHOLD = FIGHT_ANGLE + "threshold"; - public static final String FIGHT_ANGLE_ACTIONS = FIGHT_ANGLE + "actions"; - - private static final String INVENTORY = CHECKS + "inventory."; - - private static final String INVENTORY_DROP = INVENTORY + "drop."; - public static final String INVENTORY_DROP_CHECK = INVENTORY_DROP + "active"; - public static final String INVENTORY_DROP_TIMEFRAME = INVENTORY_DROP + "time"; - public static final String INVENTORY_DROP_LIMIT = INVENTORY_DROP + "limit"; - public static final String INVENTORY_DROP_ACTIONS = INVENTORY_DROP + "actions"; - - private static final String INVENTORY_INSTANTBOW = INVENTORY + "instantbow."; - public static final String INVENTORY_INSTANTBOW_CHECK = INVENTORY_INSTANTBOW + "active"; - public static final String INVENTORY_INSTANTBOW_ACTIONS = INVENTORY_INSTANTBOW + "actions"; - - private static final String INVENTORY_INSTANTEAT = INVENTORY + "instanteat."; - public static final String INVENTORY_INSTANTEAT_CHECK = INVENTORY_INSTANTEAT + "active"; - public static final String INVENTORY_INSTANTEAT_ACTIONS = INVENTORY_INSTANTEAT + "actions"; - - private static final String MOVING = CHECKS + "moving."; - - private static final String MOVING_RUNFLY = MOVING + "runfly."; - public static final String MOVING_RUNFLY_CHECK = MOVING_RUNFLY + "active"; - - // These seventh aren't automatically shown in the config - public static final String MOVING_RUNFLY_WALKSPEED = MOVING_RUNFLY + "walkspeed"; - public static final String MOVING_RUNFLY_SNEAKSPEED = MOVING_RUNFLY + "sneakspeed"; - public static final String MOVING_RUNFLY_BLOCKSPEED = MOVING_RUNFLY + "blockspeed"; - public static final String MOVING_RUNFLY_SWIMSPEED = MOVING_RUNFLY + "swimspeed"; - public static final String MOVING_RUNFLY_VERTICALSWIMSPEED = MOVING_RUNFLY + "vertswimspeed"; - public static final String MOVING_RUNFLY_SPRINTSPEED = MOVING_RUNFLY + "sprintspeed"; - public static final String MOVING_RUNFLY_COBWEBSPEED = MOVING_RUNFLY + "cobwebspeed"; - - public static final String MOVING_RUNFLY_ALLOWFASTSNEAKING = MOVING_RUNFLY + "allowfastsneaking"; - public static final String MOVING_RUNFLY_ALLOWFASTBLOCKING = MOVING_RUNFLY + "allowfastblocking"; - public static final String MOVING_RUNFLY_ACTIONS = MOVING_RUNFLY + "actions"; - - private static final String MOVING_RUNFLY_NOFALL = MOVING_RUNFLY + "nofall."; - public static final String MOVING_RUNFLY_NOFALL_CHECK = MOVING_RUNFLY_NOFALL + "active"; - public static final String MOVING_RUNFLY_NOFALL_AGGRESSIVE = MOVING_RUNFLY_NOFALL + "aggressivemode"; - public static final String MOVING_RUNFLY_NOFALL_ACTIONS = MOVING_RUNFLY_NOFALL + "actions"; - - private static final String MOVING_RUNFLY_FLYING = MOVING_RUNFLY + "flying."; - public static final String MOVING_RUNFLY_FLYING_ALLOWALWAYS = MOVING_RUNFLY_FLYING + "allowflyingalways"; - public static final String MOVING_RUNFLY_FLYING_ALLOWINCREATIVE = MOVING_RUNFLY_FLYING - + "allowflyingincreative"; - public static final String MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL = MOVING_RUNFLY_FLYING - + "flyingspeedlimitvertical"; - public static final String MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL = MOVING_RUNFLY_FLYING - + "flyingspeedlimithorizontal"; - public static final String MOVING_RUNFLY_FLYING_HEIGHTLIMIT = MOVING_RUNFLY_FLYING + "flyingheightlimit"; - public static final String MOVING_RUNFLY_FLYING_ACTIONS = MOVING_RUNFLY_FLYING + "actions"; - - private static final String MOVING_RUNFLY_BEDFLYING = MOVING_RUNFLY + "bedflying."; - public static final String MOVING_RUNFLY_BEDFLYING_CHECK = MOVING_RUNFLY_BEDFLYING + "active"; - public static final String MOVING_RUNFLY_BEDFLYING_ACTIONS = MOVING_RUNFLY_BEDFLYING + "actions"; - - private static final String MOVING_MOREPACKETS = MOVING + "morepackets."; - public static final String MOVING_MOREPACKETS_CHECK = MOVING_MOREPACKETS + "active"; - public static final String MOVING_MOREPACKETS_ACTIONS = MOVING_MOREPACKETS + "actions"; - - private static final String MOVING_MOREPACKETSVEHICLE = MOVING + "morepacketsvehicle."; - public static final String MOVING_MOREPACKETSVEHICLE_CHECK = MOVING_MOREPACKETSVEHICLE + "active"; - public static final String MOVING_MOREPACKETSVEHICLE_ACTIONS = MOVING_MOREPACKETSVEHICLE + "actions"; - - private static final String MOVING_WATERWALK = MOVING + "waterwalk."; - public static final String MOVING_WATERWALK_CHECK = MOVING_WATERWALK + "active"; - public static final String MOVING_WATERWALK_ACTIONS = MOVING_WATERWALK + "actions"; - - public static final String STRINGS = "strings"; + /* + * dP"8 d8 ,e, + * C8b Y d88 888,8, " 888 8e e88 888 dP"Y + * Y8b d88888 888 " 888 888 88b d888 888 C88b + * b Y8D 888 888 888 888 888 Y888 888 Y88D + * 8edP 888 888 888 888 888 "88 888 d,dP + * , 88P + * "8",P" + */ + public static final String STRINGS = "strings"; } diff --git a/src/fr/neatmonster/nocheatplus/config/ConfigFile.java b/src/fr/neatmonster/nocheatplus/config/ConfigFile.java index d67baace..b0d6e344 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfigFile.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfigFile.java @@ -10,33 +10,50 @@ import fr.neatmonster.nocheatplus.actions.Action; import fr.neatmonster.nocheatplus.actions.ActionFactory; import fr.neatmonster.nocheatplus.actions.types.ActionList; +/* + * MM'""""'YMM .8888b oo MM""""""""`M oo dP + * M' .mmm. `M 88 " MM mmmmmmmM 88 + * M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. M' MMMM dP 88 .d8888b. + * M MMMMMMMM 88' `88 88' `88 88 88 88' `88 MM MMMMMMMM 88 88 88ooood8 + * M. `MMM' .M 88. .88 88 88 88 88 88. .88 MM MMMMMMMM 88 88 88. ... + * MM. .dM `88888P' dP dP dP dP `8888P88 MM MMMMMMMM dP dP `88888P' + * MMMMMMMMMMM .88 MMMMMMMMMMMM + * d8888P + */ +/** + * A special configuration class created to handle the loading/saving of actions lists. + */ public class ConfigFile extends YamlConfiguration { - private ActionFactory factory; /** - * A convenience method to get action lists from the config + * A convenience method to get action lists from the configuration. * * @param path - * @return + * the path + * @param permission + * the permission + * @return the action list */ public ActionList getActionList(final String path, final String permission) { - final String value = this.getString(path); return factory.createActionList(value, permission); } /** - * Do this after reading new data + * Do this after reading new data. */ public void regenerateActionLists() { factory = new ActionFactory(((MemorySection) this.get(ConfPaths.STRINGS)).getValues(false)); } + /* (non-Javadoc) + * @see org.bukkit.configuration.file.YamlConfiguration#saveToString() + */ @Override public String saveToString() { - // Some reflection wizardry to avoid having a lot of - // linebreaks in the yml file, and get a "footer" into the file + // Some reflection wizardly to avoid having a lot of linebreaks in the yaml file, and get a "footer" into the + // file. try { Field op; op = YamlConfiguration.class.getDeclaredField("yamlOptions"); @@ -45,24 +62,24 @@ public class ConfigFile extends YamlConfiguration { options.setWidth(200); } catch (final Exception e) {} - final String result = super.saveToString(); - - return result; + return super.saveToString(); } /** - * Savely store ActionLists back into the yml file + * Safely store ActionLists back into the yml file. * * @param path + * the path * @param list + * the list */ public void set(final String path, final ActionList list) { final StringBuffer string = new StringBuffer(); - for (final int treshold : list.getTresholds()) { - if (treshold > 0) - string.append(" vl>").append(treshold); - for (final Action action : list.getActions(treshold)) + for (final int threshold : list.getThresholds()) { + if (threshold > 0) + string.append(" vl>").append(threshold); + for (final Action action : list.getActions(threshold)) string.append(" ").append(action); } diff --git a/src/fr/neatmonster/nocheatplus/config/ConfigManager.java b/src/fr/neatmonster/nocheatplus/config/ConfigManager.java index 2994424b..3096ebd1 100644 --- a/src/fr/neatmonster/nocheatplus/config/ConfigManager.java +++ b/src/fr/neatmonster/nocheatplus/config/ConfigManager.java @@ -19,19 +19,47 @@ import java.util.logging.Logger; import fr.neatmonster.nocheatplus.NoCheatPlus; import fr.neatmonster.nocheatplus.checks.Check; +/* + * MM'""""'YMM .8888b oo M"""""`'"""`YM + * M' .mmm. `M 88 " M mm. mm. M + * M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. M MMM MMM M .d8888b. 88d888b. .d8888b. .d8888b. .d8888b. 88d888b. + * M MMMMMMMM 88' `88 88' `88 88 88 88' `88 M MMM MMM M 88' `88 88' `88 88' `88 88' `88 88ooood8 88' `88 + * M. `MMM' .M 88. .88 88 88 88 88 88. .88 M MMM MMM M 88. .88 88 88 88. .88 88. .88 88. ... 88 + * MM. .dM `88888P' dP dP dP dP `8888P88 M MMM MMM M `88888P8 dP dP `88888P8 `8888P88 `88888P' dP + * MMMMMMMMMMM .88 MMMMMMMMMMMMMM .88 + * d8888P d8888P + */ +/** + * Central location for everything that's described in the configuration file(s). + */ public class ConfigManager { + + /** + * The formatter that is used to format the log file. + */ private static class LogFileFormatter extends Formatter { + /** + * Create a new instance of the log file formatter. + * + * @return the log file formatter + */ public static LogFileFormatter newInstance() { return new LogFileFormatter(); } private final SimpleDateFormat date; + /** + * Instantiates a new log file formatter. + */ private LogFileFormatter() { date = new SimpleDateFormat("yy.MM.dd HH:mm:ss"); } + /* (non-Javadoc) + * @see java.util.logging.Formatter#format(java.util.logging.LogRecord) + */ @Override public String format(final LogRecord record) { final StringBuilder builder = new StringBuilder(); @@ -54,10 +82,15 @@ public class ConfigManager { } } - private static final Map worldsMap = new HashMap(); + /** The map containing the configuration files per world. */ + private static final Map worldsMap = new HashMap(); - private static FileHandler fileHandler; + /** The file handler. */ + private static FileHandler fileHandler = null; + /** + * Cleanup. + */ public static void cleanup() { fileHandler.flush(); fileHandler.close(); @@ -66,55 +99,64 @@ public class ConfigManager { fileHandler = null; } - public static ConfigFile getConfFile(final String worldName) { - if (worldsMap.containsKey(worldName)) - return worldsMap.get(worldName); - return worldsMap.get(null); - } - + /** + * Gets the configuration file. + * + * @return the configuration file + */ public static ConfigFile getConfigFile() { return worldsMap.get(null); } + /** + * Gets the configuration file. + * + * @param worldName + * the world name + * @return the configuration file + */ public static ConfigFile getConfigFile(final String worldName) { if (worldsMap.containsKey(worldName)) return worldsMap.get(worldName); return getConfigFile(); } - public static void init() { - // First try to obtain and parse the global config file - final File rootFolder = NoCheatPlus.instance.getDataFolder(); - final ConfigFile root = new ConfigFile(); - root.setDefaults(new DefaultConfig()); - root.options().copyDefaults(true); - root.options().copyHeader(true); + /** + * Initializes the configuration manager. + * + * @param plugin + * the instance of NoCheatPlus + */ + public static void init(final NoCheatPlus plugin) { + // First try to obtain and parse the global configuration file. + final File folder = plugin.getDataFolder(); + final File globalFile = new File(folder, "config.yml"); - final File globalConfigFile = new File(rootFolder, "config.yml"); + final ConfigFile global = new ConfigFile(); + global.setDefaults(new DefaultConfig()); + global.options().copyDefaults(true); + global.options().copyHeader(true); - if (globalConfigFile.exists()) + if (globalFile.exists()) try { - root.load(globalConfigFile); + global.load(globalFile); } catch (final Exception e) { e.printStackTrace(); } try { - root.save(globalConfigFile); + global.save(globalFile); } catch (final Exception e) { e.printStackTrace(); } - root.regenerateActionLists(); + global.regenerateActionLists(); - // Create a corresponding ConfigurationByPlayer and - // put the global configuration in the worlds map - worldsMap.put(null, root); + // Put the global configuration file on the configurations map. + worldsMap.put(null, global); - // Setup the file logger used by the plugin final Logger logger = Logger.getAnonymousLogger(); logger.setLevel(Level.INFO); - // Ignore parent's settings logger.setUseParentHandlers(false); for (final Handler h : logger.getHandlers()) logger.removeHandler(h); @@ -125,7 +167,7 @@ public class ConfigManager { fileHandler = null; } - final File logFile = new File(rootFolder, root.getString(ConfPaths.LOGGING_FILENAME)); + final File logFile = new File(folder, "nocheatplus.log"); try { try { logFile.getParentFile().mkdirs(); @@ -143,15 +185,14 @@ public class ConfigManager { Check.setFileLogger(logger); - // Try to find world-specific config files + // Try to find world-specific configuration files. final HashMap worldFiles = new HashMap(); - if (rootFolder.isDirectory()) - for (final File file : rootFolder.listFiles()) + if (folder.isDirectory()) + for (final File file : folder.listFiles()) if (file.isFile()) { final String filename = file.getName(); if (filename.matches(".+_config.yml$")) { - // Get the first part = world name final String worldname = filename.substring(0, filename.length() - 10); worldFiles.put(worldname, file); } @@ -160,15 +201,17 @@ public class ConfigManager { for (final Entry worldEntry : worldFiles.entrySet()) { final File worldConfigFile = worldEntry.getValue(); final ConfigFile world = new ConfigFile(); - world.setDefaults(root); + world.setDefaults(global); try { world.load(worldConfigFile); worldsMap.put(worldEntry.getKey(), world); - // write the config file back to disk immediately + + // Write the configuration file back to disk immediately. world.save(worldConfigFile); } catch (final Exception e) { - System.out.println("NoCheatPlus: Couldn't load world-specific config for " + worldEntry.getKey()); + System.out.println("[NoCheatPlus] Couldn't load world-specific configuration for " + + worldEntry.getKey() + "!"); e.printStackTrace(); } @@ -176,11 +219,16 @@ public class ConfigManager { } } - public static void writeInstructions() { + /** + * Write instructions. + * + * @param plugin + * the instance of NoCheatPlus + */ + public static void writeInstructions(final NoCheatPlus plugin) { try { - final InputStream is = NoCheatPlus.instance.getResource("Instructions.txt"); - final FileOutputStream fos = new FileOutputStream(new File(NoCheatPlus.instance.getDataFolder(), - "Intructions.txt")); + final InputStream is = plugin.getResource("Instructions.txt"); + final FileOutputStream fos = new FileOutputStream(new File(plugin.getDataFolder(), "Intructions.txt")); final byte[] buffer = new byte[64 * 1024]; int length = 0; while ((length = is.read(buffer)) != -1) diff --git a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java index 65dd9294..2d1fe648 100644 --- a/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java +++ b/src/fr/neatmonster/nocheatplus/config/DefaultConfig.java @@ -1,291 +1,242 @@ package fr.neatmonster.nocheatplus.config; -import java.util.Arrays; - +/* + * M""""""'YMM .8888b dP dP MM'""""'YMM .8888b oo + * M mmmm. `M 88 " 88 88 M' .mmm. `M 88 " + * M MMMMM M .d8888b. 88aaa .d8888b. dP dP 88 d8888P M MMMMMooM .d8888b. 88d888b. 88aaa dP .d8888b. + * M MMMMM M 88ooood8 88 88' `88 88 88 88 88 M MMMMMMMM 88' `88 88' `88 88 88 88' `88 + * M MMMM' .M 88. ... 88 88. .88 88. .88 88 88 M. `MMM' .M 88. .88 88 88 88 88 88. .88 + * M .MM `88888P' dP `88888P8 `88888P' dP dP MM. .dM `88888P' dP dP dP dP `8888P88 + * MMMMMMMMMMM MMMMMMMMMMM .88 + * d8888P + */ /** - * These are the default settings for NoCheatPlus. They will be used - * in addition to/in replacement of configurations given in the - * config.yml file - * + * These are the default settings for NoCheatPlus. They will be used in addition to/in replacement of configurations + * given in the config.yml file. */ public class DefaultConfig extends ConfigFile { + /** + * Instantiates a new default configuration. + */ public DefaultConfig() { - super(); - options().header("Main configuration file for NoCheatPlus. Read \"Instructions.txt\""); - - /*** LOGGING ***/ + options().header("Main configuration file for NoCheatPlus. Read \"Instructions.txt\"."); + /* + * 888 ,e, + * 888 e88 88e e88 888 e88 888 " 888 8e e88 888 + * 888 d888 888b d888 888 d888 888 888 888 88b d888 888 + * 888 ,d Y888 888P Y888 888 Y888 888 888 888 888 Y888 888 + * 888,d88 "88 88" "88 888 "88 888 888 888 888 "88 888 + * , 88P , 88P , 88P + * "8",P" "8",P" "8",P" + */ set(ConfPaths.LOGGING_ACTIVE, true); set(ConfPaths.LOGGING_DEBUGMESSAGES, false); - set(ConfPaths.LOGGING_PREFIX, "&4NCP&f: "); - set(ConfPaths.LOGGING_FILENAME, "nocheatplus.log"); set(ConfPaths.LOGGING_LOGTOFILE, true); set(ConfPaths.LOGGING_LOGTOCONSOLE, true); set(ConfPaths.LOGGING_LOGTOINGAMECHAT, true); - /*** MISCELLANEOUS ***/ - + /* + * e e ,e, 888 888 + * d8b d8b " dP"Y e88'888 ,e e, 888 888 ,"Y88b 888 8e ,e e, e88 88e 8888 8888 dP"Y + * e Y8b Y8b 888 C88b d888 '8 d88 88b 888 888 "8" 888 888 88b d88 88b d888 888b 8888 8888 C88b + * d8b Y8b Y8b 888 Y88D Y888 , 888 , 888 888 ,ee 888 888 888 888 , Y888 888P Y888 888P Y88D + * d888b Y8b Y8b 888 d,dP "88,e8' "YeeP" 888 888 "88 888 888 888 "YeeP" "88 88" "88 88" d,dP + */ set(ConfPaths.MISCELLANEOUS_ALLOWCLIENTMODS, false); - set(ConfPaths.MISCELLANEOUS_OPBYCONSOLEONLY, true); set(ConfPaths.MISCELLANEOUS_PROTECTPLUGINS, true); - /*** BLOCKBREAK ***/ + /* + * 888 88b, 888 888 888 88b, 888 + * 888 88P' 888 e88 88e e88'888 888 ee 888 88P' 888,8, ,e e, ,"Y88b 888 ee + * 888 8K 888 d888 888b d888 '8 888 P 888 8K 888 " d88 88b "8" 888 888 P + * 888 88b, 888 Y888 888P Y888 , 888 b 888 88b, 888 888 , ,ee 888 888 b + * 888 88P' 888 "88 88" "88,e8' 888 8b 888 88P' 888 "YeeP" "88 888 888 8b + */ + set(ConfPaths.BLOCKBREAK_DIRECTION_CHECK, true); + set(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, "cancel vl>10 log:bdirection:0:5:if cancel"); set(ConfPaths.BLOCKBREAK_FASTBREAK_CHECK, true); - set(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVALSURVIVAL, 45); - set(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVALCREATIVE, 145); - set(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, - "cancel vl>100 log:bbfastbreak:3:5:cif cancel vl>1000 log:bbfastbreak:3:5:cif cmd:kick cancel"); - - set(ConfPaths.BLOCKBREAK_REACH_CHECK, true); - set(ConfPaths.BLOCKBREAK_REACH_ACTIONS, "cancel vl>5 log:bbreach:0:2:if cancel"); - - set(ConfPaths.BLOCKBREAK_DIRECTION_CHECK, true); - set(ConfPaths.BLOCKBREAK_DIRECTION_PRECISION, 50); - set(ConfPaths.BLOCKBREAK_DIRECTION_PENALTYTIME, 300); - set(ConfPaths.BLOCKBREAK_DIRECTION_ACTIONS, "cancel vl>10 log:bbdirection:0:5:if cancel"); + set(ConfPaths.BLOCKBREAK_FASTBREAK_EXPERIMENTAL, true); + set(ConfPaths.BLOCKBREAK_FASTBREAK_INTERVAL, 100); + set(ConfPaths.BLOCKBREAK_FASTBREAK_ACTIONS, "cancel vl>100 log:bbfastbreak:3:5:cif cancel"); set(ConfPaths.BLOCKBREAK_NOSWING_CHECK, true); set(ConfPaths.BLOCKBREAK_NOSWING_ACTIONS, "log:bbnoswing:3:2:if cancel"); - /*** BLOCKPLACE ***/ + set(ConfPaths.BLOCKBREAK_REACH_CHECK, true); + set(ConfPaths.BLOCKBREAK_REACH_ACTIONS, "cancel vl>5 log:breach:0:2:if cancel"); + + /* + * 888 88b, 888 888 888 88e 888 + * 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e, + * 888 8K 888 d888 888b d888 '8 888 P 888 88" 888 "8" 888 d888 '8 d88 88b + * 888 88b, 888 Y888 888P Y888 , 888 b 888 888 ,ee 888 Y888 , 888 , + * 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 "88 888 "88,e8' "YeeP" + */ + set(ConfPaths.BLOCKPLACE_DIRECTION_CHECK, true); + set(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, "cancel vl>10 log:bdirection:0:3:if cancel"); set(ConfPaths.BLOCKPLACE_FASTPLACE_CHECK, true); - set(ConfPaths.BLOCKPLACE_FASTPLACE_INTERVAL, 95); - set(ConfPaths.BLOCKPLACE_FASTPLACE_ACTIONS, - "cancel vl>100 log:bpfastplace:3:5:cif cancel vl>1000 log:bpfastplace:3:5:cif cmd:kick cancel"); + set(ConfPaths.BLOCKPLACE_FASTPLACE_EXPERIMENTAL, true); + set(ConfPaths.BLOCKPLACE_FASTPLACE_INTERVAL, 95L); + set(ConfPaths.BLOCKPLACE_FASTPLACE_ACTIONS, "cancel vl>100 log:bpfastplace:3:5:cif cancel"); set(ConfPaths.BLOCKPLACE_REACH_CHECK, true); - set(ConfPaths.BLOCKPLACE_REACH_ACTIONS, "cancel vl>5 log:bpreach:0:2:if cancel"); + set(ConfPaths.BLOCKPLACE_REACH_ACTIONS, "cancel vl>5 log:breach:0:2:if cancel"); - set(ConfPaths.BLOCKPLACE_DIRECTION_CHECK, true); - set(ConfPaths.BLOCKPLACE_DIRECTION_PRECISION, 75); - set(ConfPaths.BLOCKPLACE_DIRECTION_PENALTYTIME, 100); - set(ConfPaths.BLOCKPLACE_DIRECTION_ACTIONS, "cancel vl>10 log:bpdirection:0:3:if cancel"); + set(ConfPaths.BLOCKPLACE_SPEED_CHECK, true); + set(ConfPaths.BLOCKPLACE_SPEED_INTERVAL, 45L); + set(ConfPaths.BLOCKPLACE_SPEED_ACTIONS, + "cancel vl>150 log:bpspeed:3:5:if cancel vl>1000 log:bpspeed:3:5:cif cancel"); - set(ConfPaths.BLOCKPLACE_PROJECTILE_CHECK, true); - set(ConfPaths.BLOCKPLACE_PROJECTILE_INTERVAL, 150); - set(ConfPaths.BLOCKPLACE_PROJECTILE_ACTIONS, - "cancel vl>150 log:bpprojectile:3:5:if cancel vl>1000 log:bpprojectile:3:5:cif cancel vl>4000 log:bpprojectile:3:5:cif cancel cmd:kick"); - - set(ConfPaths.BLOCKPLACE_FASTPLACE_CHECK, true); - set(ConfPaths.BLOCKPLACE_FASTSIGN_EXCLUSIONS, - Arrays.asList(new String[] {"[public]", "[private]", "[protection]", "[mail]", "[free]", "[kit]", - "[disposal]", "[heal]", "[time]", "[weather]", "[warp]", "[spawnmob]", "[enchant]", "[trade]", - "[buy]", "[sell]", "[balance]", "[gate]", "[bridge]", "[door]"})); - - /*** CHAT ***/ - - set(ConfPaths.CHAT_NOPWNAGE_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_WARNPLAYERS, false); - set(ConfPaths.CHAT_NOPWNAGE_WARNOTHERS, false); - set(ConfPaths.CHAT_NOPWNAGE_WARNLEVEL, 400); - set(ConfPaths.CHAT_NOPWNAGE_WARNTIMEOUT, 30000); - set(ConfPaths.CHAT_NOPWNAGE_BANLEVEL, 800); - set(ConfPaths.CHAT_NOPWNAGE_ACTIONS, "cancel log:nopwnage:2:5:cf cmd:ban cmd:ban-ip"); - - set(ConfPaths.CHAT_NOPWNAGE_MOVE_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHTBONUS, 200); - set(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHTMALUS, 200); - set(ConfPaths.CHAT_NOPWNAGE_MOVE_TIMEOUT, 30000); - - set(ConfPaths.CHAT_NOPWNAGE_REPEAT_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_REPEAT_WEIGHT, 150); - set(ConfPaths.CHAT_NOPWNAGE_REPEAT_TIMEOUT, 5000); - - set(ConfPaths.CHAT_NOPWNAGE_SPEED_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_SPEED_WEIGHT, 200); - set(ConfPaths.CHAT_NOPWNAGE_SPEED_TIMEOUT, 500); - - set(ConfPaths.CHAT_NOPWNAGE_FIRST_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_FIRST_WEIGHT, 200); - set(ConfPaths.CHAT_NOPWNAGE_FIRST_TIMEOUT, 3000); - - set(ConfPaths.CHAT_NOPWNAGE_GLOBAL_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_GLOBAL_WEIGHT, 100); - set(ConfPaths.CHAT_NOPWNAGE_GLOBAL_TIMEOUT, 5000); - - set(ConfPaths.CHAT_NOPWNAGE_BANNED_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_BANNED_WEIGHT, 200); - set(ConfPaths.CHAT_NOPWNAGE_BANNED_TIMEOUT, 2000); - - set(ConfPaths.CHAT_NOPWNAGE_RELOG_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_RELOG_TIME, 1500); - set(ConfPaths.CHAT_NOPWNAGE_RELOG_WARNINGS, 1); - set(ConfPaths.CHAT_NOPWNAGE_RELOG_TIMEOUT, 60000); - - set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHECK, true); - set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_TRIES, 20); - set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_LENGTH, 4); - set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHARACTERS, - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"); - - set(ConfPaths.CHAT_NOPWNAGE_MESSAGES_KICK, "You're not allowed to spam this server!"); - set(ConfPaths.CHAT_NOPWNAGE_MESSAGES_CAPTCHAQUESTION, - "&cPlease type '&6[captcha]&c' to continue sending messages/commands."); - set(ConfPaths.CHAT_NOPWNAGE_MESSAGES_CAPTCHASUCCESS, "&aOK, it sounds like you're not a spambot."); - set(ConfPaths.CHAT_NOPWNAGE_MESSAGES_WARNPLAYER, - "&cOur system has detected unusual bot activities coming from you. Please be careful with what you say. DON'T repeat what you just said either, unless you want to be banned."); - set(ConfPaths.CHAT_NOPWNAGE_MESSAGES_WARNOTHERS, "&cPlease do not say anything similar to what [player] said!"); - set(ConfPaths.CHAT_NOPWNAGE_MESSAGES_WARNRELOG, - "&cYou relogged really fast! If you keep doing that, you're going to be banned."); - - set(ConfPaths.CHAT_ARRIVALSLIMIT_CHECK, false); - set(ConfPaths.CHAT_ARRIVALSLIMIT_PLAYERSLIMIT, 3); - set(ConfPaths.CHAT_ARRIVALSLIMIT_TIMEFRAME, 5000); - set(ConfPaths.CHAT_ARRIVALSLIMIT_COOLDOWNDELAY, 5000); - set(ConfPaths.CHAT_ARRIVALSLIMIT_NEWTIME, 600000); - set(ConfPaths.CHAT_ARRIVALSLIMIT_KICKMESSAGE, "Please try again later!"); - set(ConfPaths.CHAT_ARRIVALSLIMIT_ACTIONS, "cancel"); + /* + * e88'Y88 888 d8 + * d888 'Y 888 ee ,"Y88b d88 + * C8888 888 88b "8" 888 d88888 + * Y888 ,d 888 888 ,ee 888 888 + * "88,d88 888 888 "88 888 888 + */ + set(ConfPaths.CHAT_ARRIVALS_CHECK, false); + set(ConfPaths.CHAT_ARRIVALS_JOINSLIMIT, 3); + set(ConfPaths.CHAT_ARRIVALS_MESSAGE, "Please try again later!"); + set(ConfPaths.CHAT_ARRIVALS_TIMELIMIT, 5000L); + set(ConfPaths.CHAT_ARRIVALS_ACTIONS, "cancel"); set(ConfPaths.CHAT_COLOR_CHECK, true); set(ConfPaths.CHAT_COLOR_ACTIONS, "log:color:0:1:if cancel"); - /*** FIGHT ***/ + set(ConfPaths.CHAT_NOPWNAGE_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_LEVEL, 800); - set(ConfPaths.FIGHT_DIRECTION_CHECK, true); - set(ConfPaths.FIGHT_DIRECTION_PRECISION, 75); - set(ConfPaths.FIGHT_DIRECTION_PENALTYTIME, 500); - set(ConfPaths.FIGHT_DIRECTION_ACTIONS, - "cancel vl>5 log:fdirection:3:5:f cancel vl>20 log:fdirection:0:5:if cancel vl>50 log:fdirection:0:5:cif cancel"); + set(ConfPaths.CHAT_NOPWNAGE_BANNED_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_BANNED_TIMEOUT, 5000L); + set(ConfPaths.CHAT_NOPWNAGE_BANNED_WEIGHT, 100); - set(ConfPaths.FIGHT_NOSWING_CHECK, true); - set(ConfPaths.FIGHT_NOSWING_ACTIONS, "log:fnoswing:0:5:cif cancel"); + set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_CHARACTERS, + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"); + set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_LENGTH, 4); + set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_QUESTION, + "&cPlease type '&6[captcha]&c' to continue sending messages/commands."); + set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_SUCCESS, "&aOK, it sounds like you're not a spambot."); + set(ConfPaths.CHAT_NOPWNAGE_CAPTCHA_TRIES, 20); - set(ConfPaths.FIGHT_REACH_CHECK, true); - set(ConfPaths.FIGHT_REACH_LIMIT, 400); - set(ConfPaths.FIGHT_REACH_PENALTYTIME, 500); - set(ConfPaths.FIGHT_REACH_ACTIONS, "cancel vl>10 log:freach:2:5:if cancel"); + set(ConfPaths.CHAT_NOPWNAGE_FIRST_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_FIRST_TIMEOUT, 3000L); + set(ConfPaths.CHAT_NOPWNAGE_FIRST_WEIGHT, 200); - set(ConfPaths.FIGHT_SPEED_CHECK, true); - set(ConfPaths.FIGHT_SPEED_ATTACKLIMIT, 15); - set(ConfPaths.FIGHT_SPEED_ACTIONS, "log:fspeed:0:5:if cancel"); + set(ConfPaths.CHAT_NOPWNAGE_GLOBAL_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_GLOBAL_TIMEOUT, 5000L); + set(ConfPaths.CHAT_NOPWNAGE_GLOBAL_WEIGHT, 100); - set(ConfPaths.FIGHT_GODMODE_CHECK, true); - set(ConfPaths.FIGHT_GODMODE_ACTIONS, "log:fgod:2:5:if cancel"); + set(ConfPaths.CHAT_NOPWNAGE_MOVE_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_MOVE_TIMEOUT, 30000L); + set(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHT_BONUS, 200); + set(ConfPaths.CHAT_NOPWNAGE_MOVE_WEIGHT_MALUS, 200); - set(ConfPaths.FIGHT_INSTANTHEAL_CHECK, true); - set(ConfPaths.FIGHT_INSTANTHEAL_ACTIONS, "log:fheal:1:1:if cancel"); + set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_TIMEOUT, 1500L); - set(ConfPaths.FIGHT_KNOCKBACK_CHECK, true); - set(ConfPaths.FIGHT_KNOCKBACK_INTERVAL, 50); - set(ConfPaths.FIGHT_KNOCKBACK_ACTIONS, "cancel vl>50 log:fknock:0:5:cif cancel"); + set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_MESSAGE, + "&cYou relogged really fast! If you keep doing that, you're going to be banned."); + set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_NUMBER, 1); + set(ConfPaths.CHAT_NOPWNAGE_RELOGIN_WARNING_TIMEOUT, 60000L); - set(ConfPaths.FIGHT_CRITICAL_CHECK, true); - set(ConfPaths.FIGHT_CRITICAL_FALLDISTANCE, 0.01D); - set(ConfPaths.FIGHT_CRITICAL_VELOCITY, 0.1D); - set(ConfPaths.FIGHT_CRITICAL_ACTIONS, "cancel vl>50 log:fcritical:0:5:cif cancel"); + set(ConfPaths.CHAT_NOPWNAGE_REPEAT_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_REPEAT_TIMEOUT, 5000L); + set(ConfPaths.CHAT_NOPWNAGE_REPEAT_WEIGHT, 150); - set(ConfPaths.FIGHT_ANGLE_CHECK, true); - set(ConfPaths.FIGHT_ANGLE_THRESHOLD, 50D); - set(ConfPaths.FIGHT_ANGLE_ACTIONS, "cancel vl>100 log:fangle:3:5:f cancel vl>250 log:fangle:0:5:cif cancel"); + set(ConfPaths.CHAT_NOPWNAGE_SPEED_CHECK, true); + set(ConfPaths.CHAT_NOPWNAGE_SPEED_TIMEOUT, 500L); + set(ConfPaths.CHAT_NOPWNAGE_SPEED_WEIGHT, 200); - /*** INVENTORY ***/ + set(ConfPaths.CHAT_NOPWNAGE_WARN_LEVEL, 400); + set(ConfPaths.CHAT_NOPWNAGE_WARN_TIMEOUT, 30000L); - set(ConfPaths.INVENTORY_DROP_CHECK, true); - set(ConfPaths.INVENTORY_DROP_TIMEFRAME, 20); - set(ConfPaths.INVENTORY_DROP_LIMIT, 100); - set(ConfPaths.INVENTORY_DROP_ACTIONS, "log:drop:0:1:cif cmd:kick"); + set(ConfPaths.CHAT_NOPWNAGE_WARN_OTHERS_CHECK, false); + set(ConfPaths.CHAT_NOPWNAGE_WARN_OTHERS_MESSAGE, "&cPlease do not say anything similar to what [player] said!"); - set(ConfPaths.INVENTORY_INSTANTBOW_CHECK, true); - set(ConfPaths.INVENTORY_INSTANTBOW_ACTIONS, "log:ibow:2:5:if cancel"); + set(ConfPaths.CHAT_NOPWNAGE_WARN_PLAYER_CHECK, false); + set(ConfPaths.CHAT_NOPWNAGE_WARN_PLAYER_MESSAGE, + "&cOur system has detected unusual bot activities coming from you. Please be careful with what you say. DON'T repeat what you just said either, unless you want to be banned."); - set(ConfPaths.INVENTORY_INSTANTEAT_CHECK, true); - set(ConfPaths.INVENTORY_INSTANTEAT_ACTIONS, "log:ieat:2:5:if cancel"); + set(ConfPaths.CHAT_NOPWNAGE_ACTIONS, "cancel log:nopwnage:2:5:cf cmd:ban cmd:ban-ip"); - /*** MOVING ***/ - - set(ConfPaths.MOVING_RUNFLY_CHECK, true); - set(ConfPaths.MOVING_RUNFLY_ALLOWFASTSNEAKING, false); - set(ConfPaths.MOVING_RUNFLY_ALLOWFASTBLOCKING, false); - set(ConfPaths.MOVING_RUNFLY_ACTIONS, - "log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel"); - - set(ConfPaths.MOVING_RUNFLY_NOFALL_CHECK, true); - set(ConfPaths.MOVING_RUNFLY_NOFALL_AGGRESSIVE, true); - set(ConfPaths.MOVING_RUNFLY_NOFALL_ACTIONS, "log:nofall:0:5:cif cancel"); - - set(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWALWAYS, false); - set(ConfPaths.MOVING_RUNFLY_FLYING_ALLOWINCREATIVE, true); - set(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITVERTICAL, 100); - set(ConfPaths.MOVING_RUNFLY_FLYING_SPEEDLIMITHORIZONTAL, 60); - set(ConfPaths.MOVING_RUNFLY_FLYING_HEIGHTLIMIT, 128); - set(ConfPaths.MOVING_RUNFLY_FLYING_ACTIONS, - "log:moveshort:3:5:f cancel vl>100 log:moveshort:0:5:if cancel vl>400 log:movelong:0:5:cif cancel"); - - set(ConfPaths.MOVING_RUNFLY_BEDFLYING_CHECK, true); - set(ConfPaths.MOVING_RUNFLY_BEDFLYING_ACTIONS, - "log:bedfly:3:5:f cancel vl>1 log:bedfly:0:5:if cancel vl>4 log:bedfly:0:5:cif cancel"); + /* + * e e ,e, + * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 + * e Y8b Y8b d888 888b Y8b Y8P 888 888 88b d888 888 + * d8b Y8b Y8b Y888 888P Y8b " 888 888 888 Y888 888 + * d888b Y8b Y8b "88 88" Y8P 888 888 888 "88 888 + * , 88P + * "8",P" + */ + set(ConfPaths.MOVING_CREATIVEFLY_CHECK, true); + set(ConfPaths.MOVING_CREATIVEFLY_HORIZONTALSPEED, 100); + set(ConfPaths.MOVING_CREATIVEFLY_MAXHEIGHT, 128); + set(ConfPaths.MOVING_CREATIVEFLY_VERTICALSPEED, 100); + set(ConfPaths.MOVING_CREATIVEFLY_ACTIONS, + "log:flyshort:3:5:f cancel vl>100 log:flyshort:0:5:if cancel vl>400 log:flylong:0:5:cif cancel"); set(ConfPaths.MOVING_MOREPACKETS_CHECK, true); set(ConfPaths.MOVING_MOREPACKETS_ACTIONS, "log:morepackets:3:2:if cancel vl>20 log:morepackets:0:2:if cancel"); set(ConfPaths.MOVING_MOREPACKETSVEHICLE_CHECK, true); - set(ConfPaths.MOVING_MOREPACKETSVEHICLE_ACTIONS, "log:morepackets:0:2:if cancel"); + set(ConfPaths.MOVING_MOREPACKETSVEHICLE_ACTIONS, + "log:morepackets:3:2:if cancel vl>20 log:morepackets:0:2:if cancel"); - set(ConfPaths.MOVING_WATERWALK_CHECK, true); - set(ConfPaths.MOVING_WATERWALK_ACTIONS, - "log:waterwalk:3:5:f vl>100 log:waterwalk:0:5:if cancel vl>400 log:waterwalk:0:5:cif cancel"); + set(ConfPaths.MOVING_NOFALL_CHECK, true); + set(ConfPaths.MOVING_NOFALL_AGGRESSIVE, true); + set(ConfPaths.MOVING_NOFALL_ACTIONS, "log:nofall:0:5:cif cancel"); - /*** STRINGS ***/ + set(ConfPaths.MOVING_SURVIVALFLY_CHECK, true); + set(ConfPaths.MOVING_SURVIVALFLY_ALLOWFASTBLOCKING, false); + set(ConfPaths.MOVING_SURVIVALFLY_ALLOWFASTSNEAKING, false); + // The settings aren't enabled by default. Simply write them yourself in the configuration file. + // set(ConfPaths.MOVING_SURVIVALFLY_BLOCKINGSPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_COBWEBSPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_LADDERSPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_LAVASPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_MOVESPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_SNEAKINGSPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_SOULSANDSPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_SPRINTINGSPEED, 100); + // set(ConfPaths.MOVING_SURVIVALFLY_WATERSPEED, 100); + set(ConfPaths.MOVING_SURVIVALFLY_ACTIONS, + "log:flyshort:3:5:f cancel vl>100 log:flyshort:0:5:if cancel vl>400 log:flylong:0:5:cif cancel"); - set(ConfPaths.STRINGS + ".drop", - "[player] failed [check]: tried to drop more items than allowed. VL [violations]."); - set(ConfPaths.STRINGS + ".moveshort", "[player] failed [check]. VL [violations]."); - set(ConfPaths.STRINGS + ".movelong", - "[player] in [world] at [location] moving to [locationto] over distance [movedistance] failed check [check]. Total violation level so far [violations]."); - set(ConfPaths.STRINGS + ".bedfly", - "[player] failed [check]: tried to fly by sending bed leaving packets. VL [violations]."); - set(ConfPaths.STRINGS + ".nofall", - "[player] failed [check]: tried to avoid fall damage for ~[falldistance] blocks. VL [violations]."); - set(ConfPaths.STRINGS + ".morepackets", - "[player] failed [check]: sent [packets] more packets than expected. Total violation level [violations]."); - set(ConfPaths.STRINGS + ".waterwalk", - "[player] failed [check]: tried to walk on water. Total violation level [violations]."); - set(ConfPaths.STRINGS + ".bbfastbreak", - "[player] failed [check]: tried to break too much [blocktype]. Total violation level [violations]."); - set(ConfPaths.STRINGS + ".bbreach", - "[player] failed [check]: tried to interact with a block over distance [reachdistance]. VL [violations]."); - set(ConfPaths.STRINGS + ".bbdirection", - "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]."); - set(ConfPaths.STRINGS + ".bbnoswing", "[player] failed [check]: Didn't swing arm. VL [violations]."); - set(ConfPaths.STRINGS + ".bpfastplace", - "[player] failed [check]: tried to place too much blocks. Total violation level [violations]."); - set(ConfPaths.STRINGS + ".bpreach", - "[player] failed [check]: tried to interact with a block over distance [reachdistance]. VL [violations]."); - set(ConfPaths.STRINGS + ".bpdirection", - "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]."); - set(ConfPaths.STRINGS + ".bpprojectile", - "[player] failed [check]: tried to throw items too quicly. VL [violations]."); - set(ConfPaths.STRINGS + ".nopwnage", "[player] ([ip]) failed chat.nopwnage: [reason]."); - set(ConfPaths.STRINGS + ".color", - "[player] failed [check]: sent colored chat message '[text]'. VL [violations]."); - set(ConfPaths.STRINGS + ".fdirection", - "[player] failed [check]: tried to interact with a block out of line of sight. VL [violations]."); - set(ConfPaths.STRINGS + ".freach", - "[player] failed [check]: tried to attack entity out of reach. VL [violations]."); - set(ConfPaths.STRINGS + ".fspeed", - "[player] failed [check]: tried to attack more than [limit] times per second. VL [violations]."); - set(ConfPaths.STRINGS + ".fnoswing", "[player] failed [check]: Didn't swing arm. VL [violations]."); - set(ConfPaths.STRINGS + ".fgod", "[player] failed [check]: Avoided taking damage or lagging. VL [violations]."); - set(ConfPaths.STRINGS + ".fheal", - "[player] failed [check]: tried to regenerate health faster than normal. VL [violations]."); - set(ConfPaths.STRINGS + ".fknock", - "[player] failed [check]: tried to do a knockback but wasn't technically sprinting. VL [violations]."); - set(ConfPaths.STRINGS + ".fcritical", - "[player] failed [check]: tried to do a critical hit but wasn't technically jumping. VL [violations]."); - set(ConfPaths.STRINGS + ".fangle", - "[player] failed [check]: tried to fight multiple entities at the same time. VL [violations]."); - set(ConfPaths.STRINGS + ".ibow", "[player] failed [check]: fires bow to fast. VL [violations]."); - set(ConfPaths.STRINGS + ".ieat", "[player] failed [check]: eats food [food] too fast. VL [violations]."); - set(ConfPaths.STRINGS + ".kick", "kick [player]"); + /* + * dP"8 d8 ,e, + * C8b Y d88 888,8, " 888 8e e88 888 dP"Y + * Y8b d88888 888 " 888 888 88b d888 888 C88b + * b Y8D 888 888 888 888 888 Y888 888 Y88D + * 8edP 888 888 888 888 888 "88 888 d,dP + * , 88P + * "8",P" + */ + final String start = "[player] failed [check]: "; + final String end = ". VL [violations]."; set(ConfPaths.STRINGS + ".ban", "ban [player]"); set(ConfPaths.STRINGS + ".ban-ip", "ban-ip [ip]"); + set(ConfPaths.STRINGS + ".bbfastbreak", start + "tried to break too much blocks" + end); + set(ConfPaths.STRINGS + ".bbnoswing", start + "didn't swing arm" + end); + set(ConfPaths.STRINGS + ".bdirection", start + "tried to interact with a block out of his line of sight" + end); + set(ConfPaths.STRINGS + ".bpspeed", start + "tried to throw projectiles too quickly" + end); + set(ConfPaths.STRINGS + ".breach", start + + "tried to interact with a block over distance [reachdistance] block(s)" + end); + set(ConfPaths.STRINGS + ".flyshort", start + "tried to move unexpectedly" + end); + set(ConfPaths.STRINGS + ".flylong", start + + "tried to move from [locationfrom] to [locationto] over a distance of [distance] block(s)" + end); + set(ConfPaths.STRINGS + ".kick", "kick [player]"); + set(ConfPaths.STRINGS + ".morepackets", start + "sent [packets] more packet(s) than expected" + end); + set(ConfPaths.STRINGS + ".nofall", start + "tried to avoid fall damage for ~[falldistance] block(s)" + end); + set(ConfPaths.STRINGS + ".nopwnage", start + "acted like a spambot (IP: [ip])" + end); - // Update internal factory based on all the new entries to the "actions" section + // Update internal factory based on all the new entries to the "actions" section. regenerateActionLists(); } } diff --git a/src/fr/neatmonster/nocheatplus/players/informations/ExecutionHistory.java b/src/fr/neatmonster/nocheatplus/players/ExecutionHistory.java similarity index 51% rename from src/fr/neatmonster/nocheatplus/players/informations/ExecutionHistory.java rename to src/fr/neatmonster/nocheatplus/players/ExecutionHistory.java index c0da5a43..d0244f52 100644 --- a/src/fr/neatmonster/nocheatplus/players/informations/ExecutionHistory.java +++ b/src/fr/neatmonster/nocheatplus/players/ExecutionHistory.java @@ -1,35 +1,70 @@ -package fr.neatmonster.nocheatplus.players.informations; +package fr.neatmonster.nocheatplus.players; import java.util.HashMap; import java.util.Map; import fr.neatmonster.nocheatplus.actions.Action; +/* + * MM""""""""`M dP oo + * MM mmmmmmmM 88 + * M` MMMM dP. .dP .d8888b. .d8888b. dP dP d8888P dP .d8888b. 88d888b. + * MM MMMMMMMM `8bd8' 88ooood8 88' `"" 88 88 88 88 88' `88 88' `88 + * MM MMMMMMMM .d88b. 88. ... 88. ... 88. .88 88 88 88. .88 88 88 + * MM .M dP' `dP `88888P' `88888P' `88888P' dP dP `88888P' dP dP + * MMMMMMMMMMMM + + * M""MMMMM""MM oo dP + * M MMMMM MM 88 + * M `M dP .d8888b. d8888P .d8888b. 88d888b. dP dP + * M MMMMM MM 88 Y8ooooo. 88 88' `88 88' `88 88 88 + * M MMMMM MM 88 88 88 88. .88 88 88. .88 + * M MMMMM MM dP `88888P' dP `88888P' dP `8888P88 + * MMMMMMMMMMMM .88 + * d8888P + */ /** - * Store amount of action executions for last 60 seconds - * for various actions - * + * Store amount of action executions for last 60 seconds for various actions. */ public class ExecutionHistory { + /** + * Represents an entry in the execution history. + */ private static class ExecutionHistoryEntry { + /** The execution times. */ private final int executionTimes[]; + + /** The last execution. */ private long lastExecution = 0; + + /** The total entries. */ private int totalEntries = 0; + + /** The last cleared time. */ private long lastClearedTime = 0; + /** + * Instantiates a new execution history entry. + * + * @param monitoredTimeFrame + * the monitored time frame + */ private ExecutionHistoryEntry(final int monitoredTimeFrame) { executionTimes = new int[monitoredTimeFrame]; } /** - * Remember an execution at the specific time + * Remember an execution at the specific time. + * + * @param time + * the time */ private void addCounter(final long time) { - // clear out now outdated values from the array + // Clear out now outdated values from the array. if (time - lastClearedTime > 0) { - // Clear the next few fields of the array + // Clear the next few fields of the array. clearTimes(lastClearedTime + 1, time - lastClearedTime); lastClearedTime = time + 1; } @@ -39,15 +74,17 @@ public class ExecutionHistory { } /** - * Clean parts of the array + * Clean parts of the array. * * @param start + * the start * @param length + * the length */ private void clearTimes(final long start, long length) { if (length <= 0) - return; // nothing to do (yet) + return; // Nothing to do (yet). if (length > executionTimes.length) length = executionTimes.length; @@ -64,38 +101,56 @@ public class ExecutionHistory { } } + /** + * Gets the counter. + * + * @return the counter + */ public int getCounter() { return totalEntries; } + /** + * Gets the last execution. + * + * @return the last execution + */ public long getLastExecution() { return lastExecution; } + /** + * Sets the last execution. + * + * @param time + * the new last execution + */ public void setLastExecution(final long time) { lastExecution = time; } } - // Store data between Events - // time + action + action-counter + /** Store data between events (time + action + action-counter). **/ private final Map> executionHistories; + /** + * Instantiates a new execution history. + */ public ExecutionHistory() { executionHistories = new HashMap>(); } /** - * 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 and remember - * the result + * 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 and remember the result. * * @param check + * the check * @param action + * the action * @param time * a time IN SECONDS - * @return + * @return true, if successful */ public boolean executeAction(final String check, final Action action, final long time) { @@ -113,7 +168,7 @@ public class ExecutionHistory { executionHistory.put(action, entry); } - // update entry + // Update entry. entry.addCounter(time); if (entry.getCounter() > action.delay) diff --git a/src/fr/neatmonster/nocheatplus/players/NCPPlayer.java b/src/fr/neatmonster/nocheatplus/players/NCPPlayer.java deleted file mode 100644 index 5d75483f..00000000 --- a/src/fr/neatmonster/nocheatplus/players/NCPPlayer.java +++ /dev/null @@ -1,182 +0,0 @@ -package fr.neatmonster.nocheatplus.players; - -import java.util.HashMap; -import java.util.Map; - -import net.minecraft.server.EntityPlayer; -import net.minecraft.server.MobEffectList; - -import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.craftbukkit.entity.CraftPlayer; -import org.bukkit.entity.Player; - -import fr.neatmonster.nocheatplus.NoCheatPlus; -import fr.neatmonster.nocheatplus.checks.Check; -import fr.neatmonster.nocheatplus.checks.CheckConfig; -import fr.neatmonster.nocheatplus.checks.CheckData; -import fr.neatmonster.nocheatplus.players.informations.ExecutionHistory; -import fr.neatmonster.nocheatplus.players.informations.Statistics; - -public class NCPPlayer { - public class ConfigByCheck { - private final String worldName; - - private final Map configMap = new HashMap(); - - public ConfigByCheck(final String worldName) { - this.worldName = worldName; - } - - public CheckConfig getConfig(final String group) { - if (!configMap.containsKey(group)) - configMap.put(group, Check.newConfig(group, worldName)); - return configMap.get(group); - } - } - - private static final Map players = new HashMap(); - - public static NCPPlayer getPlayer(final Player bukkitPlayer) { - if (!players.containsKey(bukkitPlayer.getName())) - players.put(bukkitPlayer.getName(), new NCPPlayer(bukkitPlayer)); - NCPPlayer player = players.get(bukkitPlayer.getName()); - if (player.getBukkitPlayer() != bukkitPlayer) - players.put(bukkitPlayer.getName(), player = new NCPPlayer(bukkitPlayer)); - return player; - } - - public static boolean hasPermission(final CommandSender sender, final String permission) { - String subPermission = ""; - for (final String partOfPermission : permission.split("\\.")) { - subPermission += (subPermission == "" ? "" : ".") + partOfPermission; - if (sender.hasPermission(permission) || sender.hasPermission(permission + ".*")) - return true; - } - return false; - } - - public static void reloadConfig() { - for (final String playerName : players.keySet()) - players.get(playerName).configMap.clear(); - } - - private final String name; - - private Player bukkitPlayer; - private final Map configMap = new HashMap(); - private final Map dataMap = new HashMap(); - private final ExecutionHistory history = new ExecutionHistory(); - - private final Statistics statistics = new Statistics(); - - public NCPPlayer(final Player bukkitPlayer) { - name = bukkitPlayer.getName(); - this.bukkitPlayer = bukkitPlayer; - } - - public boolean canFly() { - return bukkitPlayer.getGameMode() == GameMode.CREATIVE || bukkitPlayer.getAllowFlight(); - } - - public Map collectData() { - final Map map = statistics.get(); - - map.put("nocheatplus.version", NoCheatPlus.instance.getDescription().getVersion()); - - return map; - } - - public void dealFallDamage() { - final EntityPlayer p = ((CraftPlayer) bukkitPlayer).getHandle(); - p.b(0D, true); - } - - public Player getBukkitPlayer() { - return bukkitPlayer; - } - - public CheckConfig getConfig(final Check check) { - return getConfig(check.getGroup()); - } - - public CheckConfig getConfig(final String group) { - final String worldName = getWorld().getName(); - if (!configMap.containsKey(worldName)) - configMap.put(worldName, new ConfigByCheck(worldName)); - return configMap.get(worldName).getConfig(group); - } - - public CheckData getData(final Check check) { - return getData(check.getGroup()); - } - - public CheckData getData(final String group) { - if (!dataMap.containsKey(group)) - dataMap.put(group, Check.newData(group)); - return dataMap.get(group); - } - - public ExecutionHistory getExecutionHistory() { - return history; - } - - public float getJumpAmplifier() { - final EntityPlayer ep = ((CraftPlayer) bukkitPlayer).getHandle(); - if (ep.hasEffect(MobEffectList.JUMP)) { - final int amp = ep.getEffect(MobEffectList.JUMP).getAmplifier(); - // Very rough estimates only - if (amp > 20) - return 1.5F * (ep.getEffect(MobEffectList.JUMP).getAmplifier() + 1); - else - return 1.2F * (ep.getEffect(MobEffectList.JUMP).getAmplifier() + 1); - } else - return 1.0F; - } - - public Location getLocation() { - return bukkitPlayer.getLocation(); - } - - public String getName() { - return name; - } - - public float getSpeedAmplifier() { - final EntityPlayer ep = ((CraftPlayer) bukkitPlayer).getHandle(); - if (ep.hasEffect(MobEffectList.FASTER_MOVEMENT)) - // Taken directly from Minecraft code, should work - return 1.0F + 0.2F * (ep.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1); - else - return 1.0F; - } - - public Statistics getStatistics() { - return statistics; - } - - public World getWorld() { - return bukkitPlayer.getWorld(); - } - - public boolean hasPermission(final String permission) { - String subPermission = ""; - for (final String partOfPermission : permission.split("\\.")) { - subPermission += (subPermission == "" ? "" : ".") + partOfPermission; - if (bukkitPlayer.hasPermission(permission) || bukkitPlayer.hasPermission(permission + ".*")) - return true; - } - return false; - } - - public void refresh() { - bukkitPlayer = Bukkit.getPlayer(name); - } - - public void sendMessage(final String message) { - bukkitPlayer.sendMessage(message); - } -} diff --git a/src/fr/neatmonster/nocheatplus/players/Permissions.java b/src/fr/neatmonster/nocheatplus/players/Permissions.java new file mode 100644 index 00000000..3d1f700c --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/players/Permissions.java @@ -0,0 +1,121 @@ +package fr.neatmonster.nocheatplus.players; + +/* + * MM"""""""`YM oo oo + * MM mmmmm M + * M' .M .d8888b. 88d888b. 88d8b.d8b. dP .d8888b. .d8888b. dP .d8888b. 88d888b. .d8888b. + * MM MMMMMMMM 88ooood8 88' `88 88'`88'`88 88 Y8ooooo. Y8ooooo. 88 88' `88 88' `88 Y8ooooo. + * MM MMMMMMMM 88. ... 88 88 88 88 88 88 88 88 88. .88 88 88 88 + * MM MMMMMMMM `88888P' dP dP dP dP dP `88888P' `88888P' dP `88888P' dP dP `88888P' + * MMMMMMMMMMMM + */ +/** + * The various permission nodes used by NoCheatPlus. + */ +public class Permissions { + private static final String NOCHEATPLUS = "nocheatplus"; + + /* + * e Y8b 888 ,e, ,e, d8 d8 ,e, + * d8b Y8b e88 888 888 888 8e " 888 8e " dP"Y d88 888,8, ,"Y88b d88 " e88 88e 888 8e + * d888b Y8b d888 888 888 888 88b 888 888 88b 888 C88b d88888 888 " "8" 888 d88888 888 d888 888b 888 88b + * d888888888b Y888 888 888 888 888 888 888 888 888 Y88D 888 888 ,ee 888 888 888 Y888 888P 888 888 + * d8888888b Y8b "88 888 888 888 888 888 888 888 888 d,dP 888 888 "88 888 888 888 "88 88" 888 888 + */ + private static final String ADMINISTRATION = NOCHEATPLUS + ".admin"; + public static final String ADMINISTRATION_NOTIFY = ADMINISTRATION + ".notify"; + public static final String ADMINISTRATION_RELOAD = ADMINISTRATION + ".reload"; + + /* + * e e 888 ,e, dP,e, ,e, d8 ,e, + * d8b d8b e88 88e e88 888 " 8b " " e88'888 ,"Y88b d88 " e88 88e 888 8e dP"Y + * e Y8b Y8b d888 888b d888 888 888 888888 888 d888 '8 "8" 888 d88888 888 d888 888b 888 88b C88b + * d8b Y8b Y8b Y888 888P Y888 888 888 888 888 Y888 , ,ee 888 888 888 Y888 888P 888 888 Y88D + * d888b Y8b Y8b "88 88" "88 888 888 888 888 "88,e8' "88 888 888 888 "88 88" 888 888 d,dP + */ + private static final String MODS = NOCHEATPLUS + ".mods"; + + private static final String CJB = MODS + ".cjb"; + public static final String CJB_FLY = CJB + ".fly"; + public static final String CJB_XRAY = CJB + ".xray"; + public static final String CJB_RADAR = CJB + ".radar"; + + private static final String MINECRAFTAUTOMAP = MODS + ".minecraftautomap"; + public static final String MINECRAFTAUTOMAP_ORES = MINECRAFTAUTOMAP + ".ores"; + public static final String MINECRAFTAUTOMAP_CAVE = MINECRAFTAUTOMAP + ".cave"; + public static final String MINECRAFTAUTOMAP_RADAR = MINECRAFTAUTOMAP + ".radar"; + + private static final String REI = MODS + ".rei"; + public static final String REI_CAVE = REI + ".cave"; + public static final String REI_RADAR = REI + ".radar"; + + private static final String SMARTMOVING = MODS + ".smartmoving"; + public static final String SMARTMOVING_CLIMBING = SMARTMOVING + ".climbing"; + public static final String SMARTMOVING_SWIMMING = SMARTMOVING + ".swimming"; + public static final String SMARTMOVING_CRAWLING = SMARTMOVING + ".crawling"; + public static final String SMARTMOVING_SLIDING = SMARTMOVING + ".sliding"; + public static final String SMARTMOVING_JUMPING = SMARTMOVING + ".jumping"; + public static final String SMARTMOVING_FLYING = SMARTMOVING + ".flying"; + + private static final String ZOMBE = MODS + ".zombe"; + public static final String ZOMBE_FLY = ZOMBE + ".fly"; + public static final String ZOMBE_NOCLIP = ZOMBE + ".noclip"; + public static final String ZOMBE_CHEAT = ZOMBE + ".cheat"; + + private static final String CHECKS = NOCHEATPLUS + ".checks"; + + /* + * 888 88b, 888 888 888 88b, 888 + * 888 88P' 888 e88 88e e88'888 888 ee 888 88P' 888,8, ,e e, ,"Y88b 888 ee + * 888 8K 888 d888 888b d888 '8 888 P 888 8K 888 " d88 88b "8" 888 888 P + * 888 88b, 888 Y888 888P Y888 , 888 b 888 88b, 888 888 , ,ee 888 888 b + * 888 88P' 888 "88 88" "88,e8' 888 8b 888 88P' 888 "YeeP" "88 888 888 8b + */ + private static final String BLOCKBREAK = CHECKS + ".blockbreak"; + public static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + ".direction"; + public static final String BLOCKBREAK_FASTBREAK = BLOCKBREAK + ".fastbreak"; + public static final String BLOCKBREAK_NOSWING = BLOCKBREAK + ".noswing"; + public static final String BLOCKBREAK_REACH = BLOCKBREAK + ".reach"; + + /* + * 888 88b, 888 888 888 88e 888 + * 888 88P' 888 e88 88e e88'888 888 ee 888 888D 888 ,"Y88b e88'888 ,e e, + * 888 8K 888 d888 888b d888 '8 888 P 888 88" 888 "8" 888 d888 '8 d88 88b + * 888 88b, 888 Y888 888P Y888 , 888 b 888 888 ,ee 888 Y888 , 888 , + * 888 88P' 888 "88 88" "88,e8' 888 8b 888 888 "88 888 "88,e8' "YeeP" + */ + private static final String BLOCKPLACE = CHECKS + ".blockplace"; + public static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + ".direction"; + public static final String BLOCKPLACE_FASTPLACE = BLOCKPLACE + "fastplace"; + public static final String BLOCKPLACE_REACH = BLOCKPLACE + ".reach"; + public static final String BLOCKPLACE_SPEED = BLOCKPLACE + ".speed"; + + /* + * e88'Y88 888 d8 + * d888 'Y 888 ee ,"Y88b d88 + * C8888 888 88b "8" 888 d88888 + * Y888 ,d 888 888 ,ee 888 888 + * "88,d88 888 888 "88 888 888 + */ + private static final String CHAT = CHECKS + ".chat"; + public static final String CHAT_ARRIVALS = CHAT + ".arrivals"; + public static final String CHAT_COLOR = CHAT + ".color"; + public static final String CHAT_NOPWNAGE = CHAT + ".nopwnage"; + + /* + * e e ,e, + * d8b d8b e88 88e Y8b Y888P " 888 8e e88 888 + * e Y8b Y8b d888 888b Y8b Y8P 888 888 88b d888 888 + * d8b Y8b Y8b Y888 888P Y8b " 888 888 888 Y888 888 + * d888b Y8b Y8b "88 88" Y8P 888 888 888 "88 888 + * , 88P + * "8",P" + */ + private static final String MOVING = CHECKS + ".moving"; + public static final String MOVING_BOATSANYWHERE = MOVING + ".boatsanywhere"; + public static final String MOVING_CREATIVEFLY = MOVING + ".creativefly"; + public static final String MOVING_MOREPACKETS = MOVING + ".morepackets"; + public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle"; + public static final String MOVING_NOFALL = MOVING + ".nofall"; + public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly"; +} diff --git a/src/fr/neatmonster/nocheatplus/players/informations/Permissions.java b/src/fr/neatmonster/nocheatplus/players/informations/Permissions.java deleted file mode 100644 index 40449716..00000000 --- a/src/fr/neatmonster/nocheatplus/players/informations/Permissions.java +++ /dev/null @@ -1,97 +0,0 @@ -package fr.neatmonster.nocheatplus.players.informations; - -/** - * The various permission nodes used by NoCheatPlus - * - */ -public class Permissions { - - private static final String NOCHEATPLUS = "nocheatplus"; - private static final String ADMIN = NOCHEATPLUS + ".admin"; - private static final String CHECKS = NOCHEATPLUS + ".checks"; - private static final String MODS = NOCHEATPLUS + ".mods"; - - /** ADMIN **/ - public static final String ADMIN_CHATLOG = ADMIN + ".chatlog"; - public static final String ADMIN_COMMANDS = ADMIN + ".commands"; - public static final String ADMIN_RELOAD = ADMIN + ".reload"; - public static final String ADMIN_PLUGINS = ADMIN + ".plugins"; - - /** CHECKS **/ - private static final String BLOCKBREAK = CHECKS + ".blockbreak"; - public static final String BLOCKBREAK_FASTBREAK = BLOCKBREAK + ".fastbreak"; - public static final String BLOCKBREAK_REACH = BLOCKBREAK + ".reach"; - public static final String BLOCKBREAK_DIRECTION = BLOCKBREAK + ".direction"; - public static final String BLOCKBREAK_NOSWING = BLOCKBREAK + ".noswing"; - - private static final String BLOCKPLACE = CHECKS + ".blockplace"; - public static final String BLOCKPLACE_FASTPLACE = BLOCKPLACE + ".fastplace"; - public static final String BLOCKPLACE_REACH = BLOCKPLACE + ".reach"; - public static final String BLOCKPLACE_DIRECTION = BLOCKPLACE + ".direction"; - public static final String BLOCKPLACE_PROJECTILE = BLOCKPLACE + ".projectile"; - public static final String BLOCKPLACE_AUTOSIGN = BLOCKPLACE + ".autosign"; - - private static final String CHAT = CHECKS + ".chat"; - public static final String CHAT_NOPWNAGE = CHAT + ".nopwnage"; - public static final String CHAT_ARRIVALSLIMIT = CHAT + ".arrivalslimit"; - public static final String CHAT_COLOR = CHAT + ".color"; - - private static final String FIGHT = CHECKS + ".fight"; - public static final String FIGHT_DIRECTION = FIGHT + ".direction"; - public static final String FIGHT_NOSWING = FIGHT + ".noswing"; - public static final String FIGHT_REACH = FIGHT + ".reach"; - public static final String FIGHT_SPEED = FIGHT + ".speed"; - public static final String FIGHT_GODMODE = FIGHT + ".godmode"; - public static final String FIGHT_INSTANTHEAL = FIGHT + ".instantheal"; - public static final String FIGHT_KNOCKBACK = FIGHT + ".knockback"; - public static final String FIGHT_CRITICAL = FIGHT + ".critical"; - public static final String FIGHT_ANGLE = FIGHT + ".angle"; - - private static final String INVENTORY = CHECKS + ".inventory"; - public static final String INVENTORY_DROP = INVENTORY + ".drop"; - public static final String INVENTORY_INSTANTBOW = INVENTORY + ".instantbow"; - public static final String INVENTORY_INSTANTEAT = INVENTORY + ".instanteat"; - - private static final String MOVING = CHECKS + ".moving"; - public static final String MOVING_RUNFLY = MOVING + ".runfly"; - public static final String MOVING_FLYING = MOVING + ".flying"; - public static final String MOVING_BEDFLYING = MOVING + ".bedflying"; - public static final String MOVING_NOFALL = MOVING + ".nofall"; - public static final String MOVING_SWIMMING = MOVING + ".swimming"; - public static final String MOVING_SNEAKING = MOVING + ".sneaking"; - public static final String MOVING_BLOCKING = MOVING + ".blocking"; - public static final String MOVING_COBWEB = MOVING + ".cobweb"; - public static final String MOVING_MOREPACKETS = MOVING + ".morepackets"; - public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle"; - public static final String MOVING_WATERWALK = MOVING + ".waterwalk"; - public static final String MOVING_RESPAWNTRICK = MOVING + ".respawntrick"; - public static final String MOVING_BOATONGROUND = MOVING + ".boatonground"; - - /** MODS **/ - private static final String CJB = MODS + ".cjb"; - public static final String CJB_FLY = CJB + ".fly"; - public static final String CJB_XRAY = CJB + ".xray"; - public static final String CJB_RADAR = CJB + ".radar"; - - private static final String MINECRAFTAUTOMAP = MODS + ".minecraftautomap"; - public static final String MINECRAFTAUTOMAP_ORES = MINECRAFTAUTOMAP + ".ores"; - public static final String MINECRAFTAUTOMAP_CAVE = MINECRAFTAUTOMAP + ".cave"; - public static final String MINECRAFTAUTOMAP_RADAR = MINECRAFTAUTOMAP + ".radar"; - - private static final String REI = MODS + ".rei"; - public static final String REI_CAVE = REI + ".cave"; - public static final String REI_RADAR = REI + ".radar"; - - private static final String SMARTMOVING = MODS + ".smartmoving"; - public static final String SMARTMOVING_CLIMBING = SMARTMOVING + ".climbing"; - public static final String SMARTMOVING_SWIMMING = SMARTMOVING + ".swimming"; - public static final String SMARTMOVING_CRAWLING = SMARTMOVING + ".crawling"; - public static final String SMARTMOVING_SLIDING = SMARTMOVING + ".sliding"; - public static final String SMARTMOVING_JUMPING = SMARTMOVING + ".jumping"; - public static final String SMARTMOVING_FLYING = SMARTMOVING + ".flying"; - - private static final String ZOMBE = MODS + ".zombe"; - public static final String ZOMBE_FLY = ZOMBE + ".fly"; - public static final String ZOMBE_NOCLIP = ZOMBE + ".noclip"; - public static final String ZOMBE_CHEAT = ZOMBE + ".cheat"; -} diff --git a/src/fr/neatmonster/nocheatplus/players/informations/Statistics.java b/src/fr/neatmonster/nocheatplus/players/informations/Statistics.java deleted file mode 100644 index 9e95bbd8..00000000 --- a/src/fr/neatmonster/nocheatplus/players/informations/Statistics.java +++ /dev/null @@ -1,92 +0,0 @@ -package fr.neatmonster.nocheatplus.players.informations; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.TreeMap; - -public class Statistics { - - public enum Id { - - BB_FASTBREAK("blockbreak.fastbreak"), - BB_DIRECTION("blockbreak.direction"), - BB_NOSWING("blockbreak.noswing"), - BB_REACH("blockbreak.reach"), - BP_FASTPLACE("blockplace.fastplace"), - BP_DIRECTION("blockplace.direction"), - BP_REACH("blockplace.reach"), - BP_PROJECTILE("blockplace.projectile"), - CHAT_COLOR("chat.color"), - FI_DIRECTION("fight.direction"), - FI_NOSWING("fight.noswing"), - FI_REACH("fight.reach"), - FI_SPEED("fight.speed"), - FI_KNOCKBACK("fight.knockback"), - FI_CRITICAL("fight.critical"), - FI_ANGLE("fight.angle"), - INV_DROP("inventory.drop"), - INV_BOW("inventory.instantbow"), - INV_EAT("inventory.instanteat"), - MOV_RUNNING("moving.running"), - MOV_FLYING("moving.flying"), - MOV_BEDFLYING("moving.bedflying"), - MOV_MOREPACKETS("moving.morepackets"), - MOV_MOREPACKETSVEHICLE("moving.morepacketsvehicle"), - MOV_NOFALL("moving.nofall"), - MOV_SNEAKING("moving.sneaking"), - MOV_BLOCKING("moving.blocking"), - MOV_SWIMMING("moving.swimming"), - MOV_COBWEB("moving.cobweb"), - MOV_WATERWALK("moving.waterwalk"), - FI_GODMODE("fight.godmode"), - FI_INSTANTHEAL("fight.instantheal"); - - private final String name; - - private Id(final String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } - - } - - private final Map statisticVLs = new HashMap(Id.values().length); - private final Map statisticFails = new HashMap(Id.values().length); - - public Statistics() { - // Initialize statistic values - for (final Id id : Id.values()) { - statisticVLs.put(id, 0D); - statisticFails.put(id, 0); - } - } - - public Map get() { - final Map map = new TreeMap(); - - for (final Entry entry : statisticVLs.entrySet()) - map.put(entry.getKey().toString() + ".vl", entry.getValue().intValue()); - - for (final Entry entry : statisticFails.entrySet()) - map.put(entry.getKey().toString() + ".failed", entry.getValue()); - - return map; - } - - public void increment(final Id id, final double vl) { - Double stored = statisticVLs.get(id); - if (stored == null) - stored = 0D; - statisticVLs.put(id, stored + vl); - - Integer failed = statisticFails.get(id); - if (failed == null) - failed = 0; - statisticFails.put(id, failed + 1); - } -} diff --git a/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java b/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java new file mode 100644 index 00000000..6ad4f1fa --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/utilities/CheckUtils.java @@ -0,0 +1,207 @@ +package fr.neatmonster.nocheatplus.utilities; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +/** + * The Class CheckUtils. + */ +public class CheckUtils { + + /** + * Calculates the distance between the player and the intersection of the player's line of sight with the targeted + * block. + * + * @param player + * the player + * @param location + * the location + * @return the double + */ + public static double distance(final Player player, final Location location) { + final Location eyes = player.getEyeLocation(); + final Vector directionUnit = eyes.getDirection().normalize(); + final double xMin = (location.getX() - eyes.getX()) / directionUnit.getX(); + final double xMax = (location.getX() + 1D - eyes.getX()) / directionUnit.getX(); + final double yMin = (location.getY() - eyes.getY()) / directionUnit.getY(); + final double yMax = (location.getY() + 1D - eyes.getY()) * directionUnit.getY(); + final double zMin = (location.getZ() - eyes.getZ()) / directionUnit.getZ(); + final double zMax = (location.getZ() + 1D - eyes.getZ()) / directionUnit.getZ(); + final double min = Math.max(Math.max(Math.min(xMin, xMax), Math.min(yMin, yMax)), Math.min(zMin, zMax)); + final double max = Math.min(Math.min(Math.max(xMin, xMax), Math.max(yMin, yMax)), Math.max(zMin, zMax)); + if (max < 0D || min > max) + return max; + else + return min; + } + + /** + * Check if the location is in the line of sight of the player. + * + * @param player + * the player + * @param location + * the location + * @param offset + * the offset + * @return true, if successful + */ + public static boolean intersects(final Player player, final Location location, final double offset) { + final double x1 = location.getX() - offset; + final double y1 = location.getY() - offset; + final double z1 = location.getZ() - offset; + final double xH = location.getX() + 1D + offset; + final double yH = location.getY() + 1D + offset; + final double zH = location.getZ() + 1D + offset; + final double x0 = player.getEyeLocation().getX(); + final double y0 = player.getEyeLocation().getY(); + final double z0 = player.getEyeLocation().getZ(); + final double xD = player.getEyeLocation().getDirection().getX(); + final double yD = player.getEyeLocation().getDirection().getY(); + final double zD = player.getEyeLocation().getDirection().getZ(); + double tNear = Double.NEGATIVE_INFINITY; + double tFar = Double.POSITIVE_INFINITY; + if (xD == 0D) { + if (x0 < x1 || x0 > xH) + return false; + } else { + double t1 = (x1 - x0) / xD; + double t2 = (xH - x0) / xD; + if (t1 > t2) { + final double tTemp = t1; + t1 = t2; + t2 = tTemp; + } + if (t1 > tNear) + tNear = t1; + if (t2 < tFar) + tFar = t2; + if (tNear > tFar) + return false; + if (tFar < 0D) + return false; + } + if (yD == 0D) { + if (y0 < y1 || y0 > yH) + return false; + } else { + double t1 = (y1 - y0) / yD; + double t2 = (yH - y0) / yD; + if (t1 > t2) { + final double tTemp = t1; + t1 = t2; + t2 = tTemp; + } + if (t1 > tNear) + tNear = t1; + if (t2 < tFar) + tFar = t2; + if (tNear > tFar) + return false; + if (tFar < 0D) + return false; + } + if (zD == 0D) { + if (z0 < z1 || z0 > zH) + return false; + } else { + double t1 = (z1 - z0) / zD; + double t2 = (zH - z0) / zD; + if (t1 > t2) { + final double tTemp = t1; + t1 = t2; + t2 = tTemp; + } + if (t1 > tNear) + tNear = t1; + if (t2 < tFar) + tFar = t2; + if (tNear > tFar) + return false; + if (tFar < 0D) + return false; + } + return true; + } + + /** + * Return if the two Strings are similar based on the given threshold. + * + * @param s + * the first String, must not be null + * @param t + * the second String, must not be null + * @param threshold + * the minimum value of the correlation coefficient + * @return result true if the two Strings are similar, false otherwise + */ + public static boolean isSimilar(final String s, final String t, final float threshold) { + return 1.0f - (float) levenshteinDistance(s, t) / Math.max(s.length(), t.length()) > threshold; + } + + /** + * Find the Levenshtein distance between two Strings. + * + * This is the number of changes needed to change one String into another, where each change is a single character + * modification (deletion, insertion or substitution). + * + * @param s + * the first String, must not be null + * @param t + * the second String, must not be null + * @return result distance + * @throws IllegalArgumentException + * if either String input is null + */ + private static int levenshteinDistance(CharSequence s, CharSequence t) { + if (s == null || t == null) + throw new IllegalArgumentException("Strings must not be null"); + + int n = s.length(); + int m = t.length(); + + if (n == 0) + return m; + else if (m == 0) + return n; + + if (n > m) { + final CharSequence tmp = s; + s = t; + t = tmp; + n = m; + m = t.length(); + } + + int p[] = new int[n + 1]; + int d[] = new int[n + 1]; + int _d[]; + + int i; + int j; + + char t_j; + + int cost; + + for (i = 0; i <= n; i++) + p[i] = i; + + for (j = 1; j <= m; j++) { + t_j = t.charAt(j - 1); + d[0] = j; + + for (i = 1; i <= n; i++) { + cost = s.charAt(i - 1) == t_j ? 0 : 1; + d[i] = Math.min(Math.min(d[i - 1] + 1, p[i] + 1), p[i - 1] + cost); + } + + _d = p; + p = d; + d = _d; + } + + return p[n]; + } +} diff --git a/src/fr/neatmonster/nocheatplus/utilities/LagMeasureTask.java b/src/fr/neatmonster/nocheatplus/utilities/LagMeasureTask.java index acb79b11..fca16564 100644 --- a/src/fr/neatmonster/nocheatplus/utilities/LagMeasureTask.java +++ b/src/fr/neatmonster/nocheatplus/utilities/LagMeasureTask.java @@ -6,70 +6,102 @@ import fr.neatmonster.nocheatplus.NoCheatPlus; import fr.neatmonster.nocheatplus.config.ConfPaths; import fr.neatmonster.nocheatplus.config.ConfigManager; +/* + * M""MMMMMMMM M"""""`'"""`YM + * M MMMMMMMM M mm. mm. M + * M MMMMMMMM .d8888b. .d8888b. M MMM MMM M .d8888b. .d8888b. .d8888b. dP dP 88d888b. .d8888b. + * M MMMMMMMM 88' `88 88' `88 M MMM MMM M 88ooood8 88' `88 Y8ooooo. 88 88 88' `88 88ooood8 + * M MMMMMMMM 88. .88 88. .88 M MMM MMM M 88. ... 88. .88 88 88. .88 88 88. ... + * M M `88888P8 `8888P88 M MMM MMM M `88888P' `88888P8 `88888P' `88888P' dP `88888P' + * MMMMMMMMMMM .88 MMMMMMMMMMMMMM + * d8888P + * + * M""""""""M dP + * Mmmm mmmM 88 + * MMMM MMMM .d8888b. .d8888b. 88 .dP + * MMMM MMMM 88' `88 Y8ooooo. 88888" + * MMMM MMMM 88. .88 88 88 `8b. + * MMMM MMMM `88888P8 `88888P' dP `YP + * MMMMMMMMMM + */ /** - * A task running in the background that measures tick time vs. real time - * + * A task running in the background that measures tick time vs. real time. */ public class LagMeasureTask implements Runnable { + private static LagMeasureTask instance = new LagMeasureTask(); - // private int ingameseconds = 1; - private long lastIngamesecondTime = System.currentTimeMillis(); - private long lastIngamesecondDuration = 2000L; - private boolean skipCheck = false; - private int lagMeasureTaskId = -1; - - public void cancel() { - if (lagMeasureTaskId != -1) { + /** + * Cancel the task. + */ + public static void cancel() { + if (instance.lagMeasureTaskId != -1) { try { - Bukkit.getServer().getScheduler().cancelTask(lagMeasureTaskId); + Bukkit.getServer().getScheduler().cancelTask(instance.lagMeasureTaskId); } catch (final Exception e) { - System.out.println("NoCheatPlus: Couldn't cancel LagMeasureTask: " + e.getMessage()); + System.out.println("[NoCheatPlus] Couldn't cancel LagMeasureTask: " + e.getMessage() + "."); } - lagMeasureTaskId = -1; + instance.lagMeasureTaskId = -1; } } + /** + * Returns if checking must be skipped (lag). + * + * @return true, if successful + */ + public static boolean skipCheck() { + return instance.skipCheck; + } + + /** + * Start the task. + * + * @param plugin + * the instance of NoCheatPlus + */ + public static void start(final NoCheatPlus plugin) { + instance.lagMeasureTaskId = Bukkit.getServer().getScheduler() + .scheduleSyncRepeatingTask(plugin, instance, 20, 20); + } + + /** The last in game second time. */ + private long lastInGameSecondTime = System.currentTimeMillis(); + + /** The last in game second duration. */ + private long lastInGameSecondDuration = 2000L; + + /** The skip check. */ + private boolean skipCheck = false; + + /** The lag measure task id. */ + private int lagMeasureTaskId = -1; + + /* (non-Javadoc) + * @see java.lang.Runnable#run() + */ @Override public void run() { - try { final boolean oldStatus = skipCheck; - // If the previous second took to long, skip checks during - // this second - skipCheck = lastIngamesecondDuration > 2000; + // If the previous second took to long, skip checks during this second. + skipCheck = lastInGameSecondDuration > 2000; if (ConfigManager.getConfigFile().getBoolean(ConfPaths.LOGGING_DEBUGMESSAGES)) if (oldStatus != skipCheck && skipCheck) - System.out.println("[NoCheatPlus] detected server lag, some checks will not work."); + System.out.println("[NoCheatPlus] Detected server lag, some checks will not work."); else if (oldStatus != skipCheck && !skipCheck) - System.out.println("[NoCheatPlus] server lag seems to have stopped, reenabling checks."); + System.out.println("[NoCheatPlus] Server lag seems to have stopped, reenabling checks."); final long time = System.currentTimeMillis(); - lastIngamesecondDuration = time - lastIngamesecondTime; - if (lastIngamesecondDuration < 1000) - lastIngamesecondDuration = 1000; - else if (lastIngamesecondDuration > 3600000) - lastIngamesecondDuration = 3600000; // top limit of 1 - // hour per "second" - lastIngamesecondTime = time; - // ingameseconds++; - - // Check if some data is outdated now and let it be removed - // if (ingameseconds % 62 == 0) - // NoCheatPlus.cleanDataMap(); + lastInGameSecondDuration = time - lastInGameSecondTime; + if (lastInGameSecondDuration < 1000) + lastInGameSecondDuration = 1000; + else if (lastInGameSecondDuration > 3600000) + // Top limit of 1 hour per "second". + lastInGameSecondDuration = 3600000; + lastInGameSecondTime = time; } catch (final Exception e) { - // Just prevent this thread from dying for whatever reason + // Just prevent this thread from dying for whatever reason. } - - } - - public boolean skipCheck() { - return skipCheck; - } - - public void start() { - // start measuring with a delay of 10 seconds - lagMeasureTaskId = Bukkit.getServer().getScheduler() - .scheduleSyncRepeatingTask(NoCheatPlus.instance, this, 20, 20); } } diff --git a/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java new file mode 100644 index 00000000..013f482f --- /dev/null +++ b/src/fr/neatmonster/nocheatplus/utilities/PlayerLocation.java @@ -0,0 +1,348 @@ +package fr.neatmonster.nocheatplus.utilities; + +import net.minecraft.server.AxisAlignedBB; +import net.minecraft.server.Block; +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.Material; +import net.minecraft.server.WorldServer; + +import org.bukkit.Location; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +/* + * MM"""""""`YM dP + * MM mmmmm M 88 + * M' .M 88 .d8888b. dP dP .d8888b. 88d888b. + * MM MMMMMMMM 88 88' `88 88 88 88ooood8 88' `88 + * MM MMMMMMMM 88 88. .88 88. .88 88. ... 88 + * MM MMMMMMMM dP `88888P8 `8888P88 `88888P' dP + * MMMMMMMMMMMM .88 + * d8888P + * + * M""MMMMMMMM dP oo + * M MMMMMMMM 88 + * M MMMMMMMM .d8888b. .d8888b. .d8888b. d8888P dP .d8888b. 88d888b. + * M MMMMMMMM 88' `88 88' `"" 88' `88 88 88 88' `88 88' `88 + * M MMMMMMMM 88. .88 88. ... 88. .88 88 88 88. .88 88 88 + * M M `88888P' `88888P' `88888P8 dP dP `88888P' dP dP + * MMMMMMMMMMM + */ +/** + * An utility class used to know a lot of things for a player and a location given. + */ +public class PlayerLocation { + + /** + * Another utility class used to manipulate differently booleans. + */ + private class CustomBoolean { + + /** Is the boolean set? */ + private boolean isSet = false; + + /** What is its value? */ + private boolean value = false; + + /** + * Gets the boolean. + * + * @return the value + */ + public boolean get() { + return value; + } + + /** + * Checks if the boolean is set. + * + * @return true, if the boolean is set + */ + public boolean isSet() { + return isSet; + } + + /** + * Sets the boolean. + * + * @param value + * the value + */ + public void set(final boolean value) { + this.value = value; + isSet = true; + } + } + + /** The original location. */ + private final Location location; + + /** Is the player in lava? */ + private final CustomBoolean inLava = new CustomBoolean(); + + /** Is the player in water? */ + private final CustomBoolean inWater = new CustomBoolean(); + + /** Is the player is web? */ + private final CustomBoolean inWeb = new CustomBoolean(); + + /** Is the player on the ground? */ + private final CustomBoolean onGround = new CustomBoolean(); + + /** Is the player on ice? */ + private final CustomBoolean onIce = new CustomBoolean(); + + /** Is the player on ladder? */ + private final CustomBoolean onLadder = new CustomBoolean(); + + /** Is the player on ladder (ignoring unclimbable vines)? **/ + private final CustomBoolean onLadderBis = new CustomBoolean(); + + /** Is the player on soul sand? */ + private final CustomBoolean onSoulSand = new CustomBoolean(); + + /** The bounding box of the player. */ + private final AxisAlignedBB boundingBox; + + /** The entity player. */ + private final EntityPlayer entity; + + /** The x, y and z coordinates. */ + private final int x, y, z; + + /** The world. */ + private final WorldServer world; + + /** + * Instantiates a new player location. + * + * @param location + * the location + * @param player + * the player + */ + public PlayerLocation(final Location location, final Player player) { + this.location = location; + + entity = ((CraftPlayer) player).getHandle(); + boundingBox = entity.boundingBox.clone().d(location.getX() - entity.locX, location.getY() - entity.locY, + location.getZ() - entity.locZ); + x = (int) Math.floor(location.getX()); + y = (int) Math.floor(boundingBox.b); + z = (int) Math.floor(location.getZ()); + world = ((CraftWorld) location.getWorld()).getHandle(); + } + + /** + * Gets the location. + * + * @return the location + */ + public Location getLocation() { + return location; + } + + /** + * Gets the pitch. + * + * @return the pitch + */ + public float getPitch() { + return location.getPitch(); + } + + /** + * Gets the x. + * + * @return the x + */ + public double getX() { + return location.getX(); + } + + /** + * Gets the y. + * + * @return the y + */ + public double getY() { + return location.getY(); + } + + /** + * Gets the yaw. + * + * @return the yaw + */ + public float getYaw() { + return location.getYaw(); + } + + /** + * Gets the z. + * + * @return the z + */ + public double getZ() { + return location.getZ(); + } + + /** + * Checks if the player is in lava. + * + * @return true, if the player is in lava + */ + public boolean isInLava() { + if (!inLava.isSet()) { + AxisAlignedBB boundingBoxLava = boundingBox.clone(); + boundingBoxLava = boundingBoxLava.grow(-0.10000000149011612D, -0.40000000596046448D, -0.10000000149011612D); + inLava.set(world.a(boundingBoxLava, Material.LAVA)); + } + return inLava.get(); + } + + /** + * Checks if the player is in a liquid. + * + * @return true, if the player is in a liquid + */ + public boolean isInLiquid() { + return isInLava() || isInWater(); + } + + /** + * Checks if the player is in water. + * + * @return true, if the player is in water + */ + public boolean isInWater() { + if (!inWater.isSet()) { + AxisAlignedBB boundingBoxWater = boundingBox.clone(); + boundingBoxWater = boundingBoxWater.grow(0.0D, -0.40000000596046448D, 0.0D); + boundingBoxWater = boundingBoxWater.shrink(0.001D, 0.001D, 0.001D); + inWater.set(world.a(boundingBoxWater, Material.WATER, entity)); + } + return inWater.get(); + } + + /** + * Checks if the player is in web. + * + * @return true, if the player is in web + */ + public boolean isInWeb() { + if (!inWeb.isSet()) { + for (int blockX = (int) Math.floor(boundingBox.a + 0.001D); blockX <= (int) Math + .floor(boundingBox.d - 0.001D); blockX++) + for (int blockY = (int) Math.floor(boundingBox.b + 0.001D); blockY <= (int) Math + .floor(boundingBox.e - 0.001D); blockY++) + for (int blockZ = (int) Math.floor(boundingBox.c + 0.001D); blockZ <= (int) Math + .floor(boundingBox.f - 0.001D); blockZ++) + if (!inWeb.get() && world.getTypeId(blockX, blockY, blockZ) == Block.WEB.id) + inWeb.set(true); + if (!inWeb.isSet()) + inWeb.set(false); + } + return inWeb.get(); + } + + /** + * Checks if the player is on ground. + * + * @return true, if the player is on ground + */ + public boolean isOnGround() { + if (!onGround.isSet()) { + AxisAlignedBB boundingBoxGround = boundingBox.clone(); + boundingBoxGround = boundingBoxGround.d(0D, -0.001D, 0D); + onGround.set(world.getCubes(entity, boundingBoxGround).size() > 0); + } + return onGround.get(); + } + + /** + * Checks if the player is on ice. + * + * @return true, if the player is on ice + */ + public boolean isOnIce() { + if (!onIce.isSet()) + onIce.set(world.getTypeId(x, y - 1, z) == Block.ICE.id); + return onIce.get(); + } + + /** + * Checks if the player is on a ladder. + * + * @return true, if the player is on a ladder + */ + public boolean isOnLadder() { + return isOnLadder(false); + } + + /** + * Checks if the player is on a ladder. + * + * @param ignoreUnclimbableVines + * ignore unclimbable vines or not? + * @return true, if the player is on a ladder + */ + public boolean isOnLadder(final boolean ignoreUnclimbableVines) { + if (ignoreUnclimbableVines) { + if (!onLadderBis.isSet()) + if (world.getTypeId(x, y, z) == Block.LADDER.id) + onLadderBis.set(true); + else if (world.getTypeId(x, y, z) == Block.VINE.id) { + final int data = world.getData(x, y, z); + if ((data & 1) != 0) { + final int id = world.getTypeId(x, y, z + 1); + if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid()) + onLadderBis.set(true); + } + if (!onLadder.isSet() && (data & 2) != 0) { + final int id = world.getTypeId(x - 1, y, z); + if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid()) + onLadderBis.set(true); + } + if (!onLadder.isSet() && (data & 4) != 0) { + final int id = world.getTypeId(x, y, z - 1); + if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid()) + onLadderBis.set(true); + } + if (!onLadder.isSet() && (data & 8) != 0) { + final int id = world.getTypeId(x + 1, y, z); + if (id != 0 && Block.byId[id].c() && Block.byId[id].material.isSolid()) + onLadderBis.set(true); + } + } + return onLadderBis.get(); + } + if (!onLadder.isSet()) + onLadder.set(world.getTypeId(x, y, z) == Block.LADDER.id || world.getTypeId(x, y, z) == Block.VINE.id); + return onLadder.get(); + } + + /** + * Checks if the player is on soul sand. + * + * @return true, if the player is on soul sand + */ + public boolean isOnSoulSand() { + if (!onSoulSand.isSet()) { + AxisAlignedBB boundingBoxGround = boundingBox.clone(); + boundingBoxGround = boundingBoxGround.d(0D, -0.001D, 0D); + for (final Object object : world.getCubes(entity, boundingBoxGround)) { + final AxisAlignedBB aabbCube = (AxisAlignedBB) object; + final int blockX = (int) Math.floor(aabbCube.a); + final int blockY = (int) Math.floor(aabbCube.b); + final int blockZ = (int) Math.floor(aabbCube.c); + if (!onSoulSand.get() && world.getTypeId(blockX, blockY, blockZ) == Block.SOUL_SAND.id) + onSoulSand.set(true); + } + if (!onSoulSand.isSet()) + onSoulSand.set(false); + } + return onSoulSand.get(); + } +} diff --git a/src/fr/neatmonster/nocheatplus/utilities/locations/PreciseLocation.java b/src/fr/neatmonster/nocheatplus/utilities/locations/PreciseLocation.java deleted file mode 100644 index e0537937..00000000 --- a/src/fr/neatmonster/nocheatplus/utilities/locations/PreciseLocation.java +++ /dev/null @@ -1,50 +0,0 @@ -package fr.neatmonster.nocheatplus.utilities.locations; - -import org.bukkit.Location; - -/** - * A class to store x,y,z triple data, instead of using bukkits Location - * objects, which can't be easily recycled - * - */ -public final class PreciseLocation { - - public double x; - public double y; - public double z; - - public PreciseLocation() { - reset(); - } - - public final boolean equals(final Location location) { - return location.getX() == x && location.getY() == y && location.getZ() == z; - } - - public final boolean isSet() { - return x != Double.MAX_VALUE; - } - - public final void reset() { - x = Double.MAX_VALUE; - y = Double.MAX_VALUE; - z = Double.MAX_VALUE; - } - - public final void set(final Location location) { - x = location.getX(); - y = location.getY(); - z = location.getZ(); - } - - public final void set(final PreciseLocation location) { - x = location.x; - y = location.y; - z = location.z; - } - - @Override - public String toString() { - return "PreciseLocation {x=" + x + ", y=" + y + ", z=" + z + "}"; - } -} diff --git a/src/fr/neatmonster/nocheatplus/utilities/locations/SimpleLocation.java b/src/fr/neatmonster/nocheatplus/utilities/locations/SimpleLocation.java deleted file mode 100644 index b415e611..00000000 --- a/src/fr/neatmonster/nocheatplus/utilities/locations/SimpleLocation.java +++ /dev/null @@ -1,68 +0,0 @@ -package fr.neatmonster.nocheatplus.utilities.locations; - -import org.bukkit.Location; -import org.bukkit.block.Block; - -/** - * To avoid constantly creating and referencing "Location" objects, which - * in turn reference a whole lot of other unnecessary stuff, rather use - * our own "Location" object which is easily reusable. - * - */ -public final class SimpleLocation { - - public int x; - public int y; - public int z; - - public SimpleLocation() { - reset(); - } - - @Override - public final boolean equals(final Object object) { - if (!(object instanceof SimpleLocation)) - return false; - - final SimpleLocation simpleLocation = (SimpleLocation) object; - - if (!isSet() && !simpleLocation.isSet()) - return true; - else if (!isSet() || !simpleLocation.isSet()) - return false; - - return simpleLocation.x == x && simpleLocation.y == y && simpleLocation.z == z; - } - - @Override - public final int hashCode() { - return x * 1000000 + y * 1000 + z; - } - - public final boolean isSet() { - return x != Integer.MAX_VALUE; - } - - public final void reset() { - x = Integer.MAX_VALUE; - y = Integer.MAX_VALUE; - z = Integer.MAX_VALUE; - } - - public final void set(final Block block) { - x = block.getX(); - y = block.getY(); - z = block.getZ(); - } - - public final void setLocation(final Location location) { - x = location.getBlockX(); - y = location.getBlockY(); - z = location.getBlockZ(); - } - - @Override - public String toString() { - return "SimpleLocation {x=" + x + ", y=" + y + ", z=" + z + "}"; - } -}