mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-01-29 19:01:22 +01:00
[Development] BlockBreak, BlockPlace, Chat & Moving checks rewritten but
untested. This version is far from being complete.
This commit is contained in:
parent
2feceae9b0
commit
3d88aed041
3
.gitignore
vendored
3
.gitignore
vendored
@ -28,4 +28,5 @@
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
.idea/
|
||||
/auth.properties
|
||||
|
94
pom.xml
94
pom.xml
@ -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 -->
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
package fr.neatmonster.nocheatplus.checks;
|
||||
|
||||
public abstract class CheckConfig {}
|
@ -1,3 +0,0 @@
|
||||
package fr.neatmonster.nocheatplus.checks;
|
||||
|
||||
public abstract class CheckData {}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
76
src/fr/neatmonster/nocheatplus/checks/Workarounds.java
Normal file
76
src/fr/neatmonster/nocheatplus/checks/Workarounds.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
104
src/fr/neatmonster/nocheatplus/checks/blockbreak/Direction.java
Normal file
104
src/fr/neatmonster/nocheatplus/checks/blockbreak/Direction.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
131
src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreak.java
Normal file
131
src/fr/neatmonster/nocheatplus/checks/blockbreak/FastBreak.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
105
src/fr/neatmonster/nocheatplus/checks/blockbreak/Reach.java
Normal file
105
src/fr/neatmonster/nocheatplus/checks/blockbreak/Reach.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
104
src/fr/neatmonster/nocheatplus/checks/blockplace/Direction.java
Normal file
104
src/fr/neatmonster/nocheatplus/checks/blockplace/Direction.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
106
src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlace.java
Normal file
106
src/fr/neatmonster/nocheatplus/checks/blockplace/FastPlace.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
105
src/fr/neatmonster/nocheatplus/checks/blockplace/Reach.java
Normal file
105
src/fr/neatmonster/nocheatplus/checks/blockplace/Reach.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
101
src/fr/neatmonster/nocheatplus/checks/blockplace/Speed.java
Normal file
101
src/fr/neatmonster/nocheatplus/checks/blockplace/Speed.java
Normal 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;
|
||||
}
|
||||
}
|
103
src/fr/neatmonster/nocheatplus/checks/chat/Arrivals.java
Normal file
103
src/fr/neatmonster/nocheatplus/checks/chat/Arrivals.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
90
src/fr/neatmonster/nocheatplus/checks/chat/Color.java
Normal file
90
src/fr/neatmonster/nocheatplus/checks/chat/Color.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
276
src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java
Normal file
276
src/fr/neatmonster/nocheatplus/checks/chat/NoPwnage.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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>();
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
188
src/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java
Normal file
188
src/fr/neatmonster/nocheatplus/checks/moving/CreativeFly.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
156
src/fr/neatmonster/nocheatplus/checks/moving/MorePackets.java
Normal file
156
src/fr/neatmonster/nocheatplus/checks/moving/MorePackets.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
167
src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java
Normal file
167
src/fr/neatmonster/nocheatplus/checks/moving/NoFall.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
359
src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java
Normal file
359
src/fr/neatmonster/nocheatplus/checks/moving/SurvivalFly.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user