[Development] BlockBreak, BlockPlace, Chat & Moving checks rewritten but

untested. This version is far from being complete.
This commit is contained in:
NeatMonster 2012-08-03 16:48:06 +02:00
parent 2feceae9b0
commit 3d88aed041
113 changed files with 5723 additions and 7891 deletions

3
.gitignore vendored
View File

@ -28,4 +28,5 @@
*.iml
*.ipr
*.iws
.idea/
.idea/
/auth.properties

94
pom.xml
View File

@ -4,7 +4,7 @@
<!-- Informations -->
<name>NoCheatPlus</name>
<version>3.6.1</version>
<version>3.7</version>
<description>Detect and fight the exploitation of various flaws/bugs in Minecraft.</description>
<url>http://dev.bukkit.org/server-mods/nocheatplus</url>
@ -42,7 +42,7 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.2.5-R1.2</version>
<version>1.3.1-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
@ -50,7 +50,7 @@
<!-- Building -->
<build>
<defaultGoal>clean install</defaultGoal>
<defaultGoal>clean package</defaultGoal>
<sourceDirectory>${basedir}/src</sourceDirectory>
<resources>
<resource>
@ -64,35 +64,65 @@
</includes>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>NoCheatPlus</finalName>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<pomPropertiesFile>false</pomPropertiesFile>
<manifest>
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>NoCheatPlus</finalName>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<pomPropertiesFile>false</pomPropertiesFile>
<manifest>
<addDefaultSpecificationEntries>false</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>false</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>deploy-build</id>
<phase>install</phase>
<configuration>
<target>
<property file="auth.properties" prefix="auth" />
<scp todir="${auth.user}:${auth.pass}@${auth.host}:${auth.path}"
file="target/NoCheatPlus.jar" sftp="yes" trust="yes"
failonerror="no" />
<sshexec host="${auth.host}" username="${auth.user}"
password="${auth.pass}" command="${auth.cmd}" trust="yes"
failonerror="no" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-jsch</artifactId>
<version>1.8.4</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<!-- Properties -->

View File

@ -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<Permission> perms;
public CommandHandler() {
// Make a copy to allow sorting
perms = new LinkedList<Permission>(NoCheatPlus.instance.getDescription().getPermissions());
// Sort NoCheats permission by name and parent-child relation with
// a custom sorting method
Collections.sort(perms, new Comparator<Permission>() {
@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<String, Object> map = player == null ? new HashMap<String, Object>() : NCPPlayer.getPlayer(player)
.collectData();
String filter = "";
if (args.length > 2)
filter = args[2];
sender.sendMessage("PlayerInfo for " + args[1]);
for (final Entry<String, Object> 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;
}
}

View File

@ -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<Listener> 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<Listener>();
// 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);
}
}

View File

@ -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;

View File

@ -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<String, Object> lib = new HashMap<String, Object>();
/**
* Instantiates a new action factory.
*
* @param library
* the library
*/
public ActionFactory(final Map<String, Object> 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<Action> actions = new ArrayList<Action>();
@ -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;

View File

@ -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;
}
}

View File

@ -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<Integer, Action[]> actions = new HashMap<Integer, Action[]>();
// The tresholds of this list
private final List<Integer> tresholds = new ArrayList<Integer>();
/** The thresholds of this list. **/
private final List<Integer> thresholds = new ArrayList<Integer>();
/**
* 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<Integer> getTresholds() {
return tresholds;
public List<Integer> 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);
}
}

View File

@ -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<Object> 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);

View File

@ -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";
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -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";
}
}

View File

@ -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<String, Check> checks = new HashMap<String, Check>();
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<String, ExecutionHistory> histories = new HashMap<String, ExecutionHistory>();
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<? extends CheckConfig> configClass;
private final Class<? extends CheckData> dataClass;
public Check(final String name, final Class<? extends CheckConfig> configClass,
final Class<? extends CheckData> 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);
}

View File

@ -1,3 +0,0 @@
package fr.neatmonster.nocheatplus.checks;
public abstract class CheckConfig {}

View File

@ -1,3 +0,0 @@
package fr.neatmonster.nocheatplus.checks;
public abstract class CheckData {}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<String, BlockBreakConfig> worldsMap = new HashMap<String, BlockBreakConfig>();
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);
}
}

View File

@ -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<String, BlockBreakData> playersMap = new HashMap<String, BlockBreakData>();
// 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;
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<String, BlockPlaceConfig> worldsMap = new HashMap<String, BlockPlaceConfig>();
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<String> fastSignExclusions = new ArrayList<String>();
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);
}
}

View File

@ -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<String, BlockPlaceData> playersMap = new HashMap<String, BlockPlaceData>();
// 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;
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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<Long, String> joins = new HashMap<Long, String>();
/**
* 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<Long> toRemove = new ArrayList<Long>();
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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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<String, ChatConfig> worldsMap = new HashMap<String, ChatConfig>();
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);
}
}

View File

@ -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<String, ChatData> playersMap = new HashMap<String, ChatData>();
// 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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}

View File

@ -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<AngleData> {
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<Long> dTime = new ArrayList<Long>();
final List<Float> dYaw = new ArrayList<Float>();
final List<Double> dMove = new ArrayList<Double>();
AngleData previousAngleData = null;
for (final AngleData angleData : new ArrayList<AngleData>(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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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<AngleData> attacks = new ArrayList<AngleData>();
}

View File

@ -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();
}
}

View File

@ -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<FightCheck> checks = new ArrayList<FightCheck>(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();
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<String, MovingConfig> worldsMap = new HashMap<String, MovingConfig>();
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);
}
}

View File

@ -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<String, MovingData> playersMap = new HashMap<String, MovingData>();
// 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;
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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";
}

Some files were not shown because too many files have changed in this diff Show More