mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-03-02 10:31:25 +01:00
Version 0.6.4, Commands and code cleanup
This commit is contained in:
parent
45b4f11452
commit
4a09449d2c
10
plugin.yml
10
plugin.yml
@ -3,5 +3,13 @@ name: NoCheatPlugin
|
|||||||
author: Evenprime
|
author: Evenprime
|
||||||
|
|
||||||
main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin
|
main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin
|
||||||
version: 0.6.3a
|
version: 0.6.4
|
||||||
|
|
||||||
|
commands:
|
||||||
|
nocheat:
|
||||||
|
description: Provides information about the current status of the NoCheatPlugin
|
||||||
|
usage: |
|
||||||
|
/<command>
|
||||||
|
Example: /<command> | Displays version, enabled checks and bugfixes
|
||||||
|
Example: /<command> -p | Get your permissions, * = check disabled globally
|
||||||
|
Example: /<command> -p [player] | Get permissions of the player, * = check disabled globally
|
@ -170,7 +170,7 @@ public class NoCheatConfiguration {
|
|||||||
w.write(" low: 30"); w.newLine();
|
w.write(" low: 30"); w.newLine();
|
||||||
w.write(" med: 45"); w.newLine();
|
w.write(" med: 45"); w.newLine();
|
||||||
w.write(" high: 60"); w.newLine();
|
w.write(" high: 60"); w.newLine();
|
||||||
w.write("# Speedhack Action, one or more of loglow logmed loghigh reset"); w.newLine();
|
w.write("# Speedhack Action, one or more of 'loglow logmed loghigh reset'"); w.newLine();
|
||||||
w.write(" action:"); w.newLine();
|
w.write(" action:"); w.newLine();
|
||||||
w.write(" low: loglow reset"); w.newLine();
|
w.write(" low: loglow reset"); w.newLine();
|
||||||
w.write(" med: logmed reset"); w.newLine();
|
w.write(" med: logmed reset"); w.newLine();
|
||||||
@ -178,14 +178,14 @@ public class NoCheatConfiguration {
|
|||||||
w.write("# Moving specific optionse") ;w.newLine();
|
w.write("# Moving specific optionse") ;w.newLine();
|
||||||
w.write("moving:"); w.newLine();
|
w.write("moving:"); w.newLine();
|
||||||
w.write(" freemoves: 10"); w.newLine();
|
w.write(" freemoves: 10"); w.newLine();
|
||||||
w.write("# Moving Action, one or more of loglow logmed loghigh reset"); w.newLine();
|
w.write("# Moving Action, one or more of 'loglow logmed loghigh reset'"); w.newLine();
|
||||||
w.write(" action:"); w.newLine();
|
w.write(" action:"); w.newLine();
|
||||||
w.write(" low: loglow reset"); w.newLine();
|
w.write(" low: loglow reset"); w.newLine();
|
||||||
w.write(" med: logmed reset"); w.newLine();
|
w.write(" med: logmed reset"); w.newLine();
|
||||||
w.write(" high: loghigh reset"); w.newLine();
|
w.write(" high: loghigh reset"); w.newLine();
|
||||||
w.write("# Airbuild specific options"); w.newLine();
|
w.write("# Airbuild specific options"); w.newLine();
|
||||||
w.write("airbuild:"); w.newLine();
|
w.write("airbuild:"); w.newLine();
|
||||||
w.write("# Airbuild Action, one or more of loglow logmed loghigh deny"); w.newLine();
|
w.write("# Airbuild Action, one or more of 'loglow logmed loghigh deny'"); w.newLine();
|
||||||
w.write(" action: logmed deny"); w.newLine();
|
w.write(" action: logmed deny"); w.newLine();
|
||||||
w.write("# Dupebydeath specific options (none exist yet)"); w.newLine();
|
w.write("# Dupebydeath specific options (none exist yet)"); w.newLine();
|
||||||
w.write("dupebydeath:"); w.newLine();
|
w.write("dupebydeath:"); w.newLine();
|
||||||
|
@ -6,6 +6,8 @@ import java.util.Map;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Event.Priority;
|
import org.bukkit.event.Event.Priority;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
@ -22,45 +24,45 @@ import com.nijiko.permissions.PermissionHandler;
|
|||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* NoCheatPlugin
|
* NoCheatPlugin
|
||||||
*
|
*
|
||||||
* Check various player events for their plausibilty and log/deny them based on configuration
|
* Check various player events for their plausibilty and log/deny them based on configuration
|
||||||
*
|
*
|
||||||
* @author Evenprime
|
* @author Evenprime
|
||||||
*/
|
*/
|
||||||
public class NoCheatPlugin extends JavaPlugin {
|
public class NoCheatPlugin extends JavaPlugin {
|
||||||
|
|
||||||
// Various listeners needed for different Checks
|
// Various listeners needed for different Checks
|
||||||
private NoCheatPlayerListener playerListener;
|
private NoCheatPlayerListener playerListener;
|
||||||
private NoCheatBlockListener blockListener;
|
private NoCheatBlockListener blockListener;
|
||||||
private NoCheatEntityListener entityListener;
|
private NoCheatEntityListener entityListener;
|
||||||
|
|
||||||
// My main logger
|
// My main logger
|
||||||
private static Logger log;
|
private static Logger log;
|
||||||
|
|
||||||
private static NoCheatPlugin p;
|
private static NoCheatPlugin p;
|
||||||
|
|
||||||
// Permissions 2.0, if available
|
// Permissions 2.0, if available
|
||||||
public static PermissionHandler Permissions = null;
|
public static PermissionHandler Permissions = null;
|
||||||
|
|
||||||
// Store data between Events
|
// Store data between Events
|
||||||
public static Map<Player, NoCheatData> playerData = new HashMap<Player, NoCheatData>();
|
public static Map<Player, NoCheatData> playerData = new HashMap<Player, NoCheatData>();
|
||||||
|
|
||||||
public NoCheatPlugin() {
|
public NoCheatPlugin() {
|
||||||
p = this;
|
p = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main access to data that needs to be stored between different events.
|
* Main access to data that needs to be stored between different events.
|
||||||
* Always returns a NoCheatData object, because if there isn't one
|
* Always returns a NoCheatData object, because if there isn't one
|
||||||
* for the specified player, one will be created.
|
* for the specified player, one will be created.
|
||||||
*
|
*
|
||||||
* @param p
|
* @param p
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static NoCheatData getPlayerData(Player p) {
|
public static NoCheatData getPlayerData(Player p) {
|
||||||
NoCheatData data = null;
|
NoCheatData data = null;
|
||||||
|
|
||||||
if((data = playerData.get(p)) == null ) {
|
if((data = playerData.get(p)) == null ) {
|
||||||
synchronized(playerData) {
|
synchronized(playerData) {
|
||||||
@ -74,92 +76,132 @@ public class NoCheatPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String commandLabel, String[] args)
|
||||||
|
{
|
||||||
|
if(sender instanceof Player) {
|
||||||
|
if(!hasPermission((Player)sender, "nocheat.p")) {
|
||||||
|
sender.sendMessage("NC: You are not allowed to use this command.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(args.length == 0) {
|
||||||
|
sender.sendMessage("NC: Using "+ ((Permissions == null) ? "isOp()" : "Permissions") + ". Activated checks/bugfixes: " + getActiveChecksAsString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(args.length == 1 && args[0] != null && args[0].trim().equals("-p")) {
|
||||||
|
if(sender instanceof Player) {
|
||||||
|
Player p = (Player) sender;
|
||||||
|
|
||||||
|
sender.sendMessage("NC: You have permissions: " + getPermissionsForPlayerAsString(p));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sender.sendMessage("NC: You have to be a player to use this command");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(args.length == 2 && args[0] != null && args[0].trim().equals("-p")) {
|
||||||
|
Player p = getServer().getPlayer(args[1]);
|
||||||
|
|
||||||
|
if(p != null) {
|
||||||
|
sender.sendMessage("NC: "+p.getName() + " has permissions: " + getPermissionsForPlayerAsString(p));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sender.sendMessage("NC: Player " + args[1] + " was not found.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
PluginDescriptionFile pdfFile = this.getDescription();
|
PluginDescriptionFile pdfFile = this.getDescription();
|
||||||
Logger.getLogger("Minecraft").info( "[NoCheatPlugin] version [" + pdfFile.getVersion() + "] is disabled.");
|
Logger.getLogger("Minecraft").info( "[NoCheatPlugin] version [" + pdfFile.getVersion() + "] is disabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
// Create our listeners and feed them with neccessary information
|
// Create our listeners and feed them with neccessary information
|
||||||
playerListener = new NoCheatPlayerListener();
|
playerListener = new NoCheatPlayerListener();
|
||||||
blockListener = new NoCheatBlockListener();
|
blockListener = new NoCheatBlockListener();
|
||||||
entityListener = new NoCheatEntityListener();
|
entityListener = new NoCheatEntityListener();
|
||||||
|
|
||||||
log = NoCheatConfiguration.logger;
|
log = NoCheatConfiguration.logger;
|
||||||
|
|
||||||
PluginManager pm = getServer().getPluginManager();
|
PluginManager pm = getServer().getPluginManager();
|
||||||
pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Lowest, this); // needed for speedhack and moving checks
|
pm.registerEvent(Event.Type.PLAYER_MOVE, playerListener, Priority.Lowest, this); // used for speedhack and moving checks
|
||||||
pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this); // used to delete old data of users
|
pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this); // used to delete old data of users
|
||||||
pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Low, this); // used for airbuild check
|
pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Low, this); // used for airbuild check
|
||||||
pm.registerEvent(Event.Type.ENTITY_DEATH, entityListener, Priority.Highest, this); // used for dupebydeath check
|
pm.registerEvent(Event.Type.ENTITY_DEATH, entityListener, Priority.Highest, this); // used for dupebydeath check
|
||||||
pm.registerEvent(Event.Type.PLAYER_TELEPORT, playerListener, Priority.Lowest, this); // used for teleportfrombed check
|
pm.registerEvent(Event.Type.PLAYER_TELEPORT, playerListener, Priority.Lowest, this); // used for teleportfrombed check
|
||||||
|
|
||||||
PluginDescriptionFile pdfFile = this.getDescription();
|
PluginDescriptionFile pdfFile = this.getDescription();
|
||||||
|
|
||||||
// Get, if available, the Permissions plugin
|
// Get, if available, the Permissions plugin
|
||||||
setupPermissions();
|
setupPermissions();
|
||||||
|
|
||||||
// parse the nocheat.yml config file
|
// parse the nocheat.yml config file
|
||||||
setupConfig();
|
setupConfig();
|
||||||
|
|
||||||
String checks = (NoCheatConfiguration.movingCheckActive ? "moving ": "") +
|
Logger.getLogger("Minecraft").info( "[NoCheatPlugin] version [" + pdfFile.getVersion() + "] is enabled with the following checks: "+getActiveChecksAsString());
|
||||||
(NoCheatConfiguration.speedhackCheckActive ? "speedhack " : "") +
|
}
|
||||||
(NoCheatConfiguration.airbuildCheckActive ? "airbuild " : "") +
|
|
||||||
(NoCheatConfiguration.dupebydeathCheckActive ? "dupebydeath " : "") +
|
|
||||||
(NoCheatConfiguration.bedteleportCheckActive ? "bedteleport " : "");
|
|
||||||
|
|
||||||
Logger.getLogger("Minecraft").info( "[NoCheatPlugin] version [" + pdfFile.getVersion() + "] is enabled with the following checks: "+checks);
|
/**
|
||||||
}
|
* Get, if available, a reference to the Permissions-plugin
|
||||||
|
*/
|
||||||
|
public void setupPermissions() {
|
||||||
|
PermissionHandler p = null;
|
||||||
|
|
||||||
/**
|
Plugin test = this.getServer().getPluginManager().getPlugin("Permissions");
|
||||||
* Get, if available, a reference to the Permissions-plugin
|
|
||||||
*/
|
|
||||||
public void setupPermissions() {
|
|
||||||
Permissions = null;
|
|
||||||
|
|
||||||
Plugin test = this.getServer().getPluginManager().getPlugin("Permissions");
|
if(test != null) {
|
||||||
|
p = ((Permissions)test).getHandler();
|
||||||
|
if(p == null) {
|
||||||
|
this.getServer().getPluginManager().enablePlugin(test);
|
||||||
|
}
|
||||||
|
p = ((Permissions)test).getHandler();
|
||||||
|
}
|
||||||
|
|
||||||
if(test != null) {
|
if(p == null) {
|
||||||
Permissions = ((Permissions)test).getHandler();
|
PluginDescriptionFile pdfFile = this.getDescription();
|
||||||
if(Permissions == null) {
|
log.info("[NoCheatPlugin] version [" + pdfFile.getVersion() + "] couldn't find Permissions plugin. Fallback to 'isOp()' equals 'nocheat.*'");
|
||||||
this.getServer().getPluginManager().enablePlugin(test);
|
Permissions = null;
|
||||||
}
|
}
|
||||||
Permissions = ((Permissions)test).getHandler();
|
else
|
||||||
}
|
Permissions = p;
|
||||||
|
}
|
||||||
|
|
||||||
if(Permissions == null) {
|
/**
|
||||||
log.info("Nocheat couldn't find Permissions plugin. Fallback to 'isOp()' equals 'all allowed'.");
|
* Log a violation message to all locations declared in the config file
|
||||||
}
|
* @param message
|
||||||
}
|
*/
|
||||||
|
private static void log(Level l, String message) {
|
||||||
/**
|
if(l != null) {
|
||||||
* Log a violation message to all locations declared in the config file
|
logToChat(l, message);
|
||||||
* @param message
|
log.log(l, message);
|
||||||
*/
|
}
|
||||||
private static void log(Level l, String message) {
|
}
|
||||||
if(l != null) {
|
|
||||||
logToChat(l, message);
|
|
||||||
log.log(l, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void logToChat(Level l, String message) {
|
||||||
|
if(NoCheatConfiguration.notifyLevel.intValue() <= l.intValue()) {
|
||||||
|
for(Player player : p.getServer().getOnlinePlayers()) {
|
||||||
|
if(hasPermission(player, "nocheat.notify")) {
|
||||||
|
player.sendMessage("["+l.getName()+"] " + message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void logToChat(Level l, String message) {
|
public static void logAction(String actions, String message) {
|
||||||
if(NoCheatConfiguration.notifyLevel.intValue() <= l.intValue()) {
|
if(actions == null) return;
|
||||||
for(Player player : p.getServer().getOnlinePlayers()) {
|
|
||||||
if((Permissions != null && Permissions.has(player, "nocheat.notify")) ||
|
|
||||||
(Permissions == null && player.isOp())) {
|
|
||||||
player.sendMessage("["+l.getName()+"] " + message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void logAction(String actions, String message) {
|
|
||||||
if(actions == null) return;
|
|
||||||
|
|
||||||
// LOGGING IF NEEDED AND WHERE NEEDED
|
// LOGGING IF NEEDED AND WHERE NEEDED
|
||||||
Level logLevel = null;
|
Level logLevel = null;
|
||||||
@ -177,11 +219,47 @@ public class NoCheatPlugin extends JavaPlugin {
|
|||||||
if(logLevel != null) {
|
if(logLevel != null) {
|
||||||
NoCheatPlugin.log(logLevel, "NC: "+message);
|
NoCheatPlugin.log(logLevel, "NC: "+message);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasPermission(Player player, String permission) {
|
||||||
|
|
||||||
|
if(player == null || permission == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(player, permission))
|
||||||
|
return true;
|
||||||
|
else if(NoCheatPlugin.Permissions == null && player.isOp())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the config file
|
||||||
|
*/
|
||||||
|
public void setupConfig() {
|
||||||
|
NoCheatConfiguration.config(new File("plugins/NoCheat/nocheat.yml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getActiveChecksAsString() {
|
||||||
|
return (NoCheatConfiguration.movingCheckActive ? "moving ": "") +
|
||||||
|
(NoCheatConfiguration.speedhackCheckActive ? "speedhack " : "") +
|
||||||
|
(NoCheatConfiguration.airbuildCheckActive ? "airbuild " : "") +
|
||||||
|
(NoCheatConfiguration.dupebydeathCheckActive ? "dupebydeath " : "") +
|
||||||
|
(NoCheatConfiguration.bedteleportCheckActive ? "bedteleport " : "");
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Read the config file
|
|
||||||
*/
|
private String getPermissionsForPlayerAsString(Player p) {
|
||||||
public void setupConfig() {
|
return (!NoCheatConfiguration.movingCheckActive ? "moving* ": (hasPermission(p, "nocheat.moving") ? "moving " : "") +
|
||||||
NoCheatConfiguration.config(new File("plugins/NoCheat/nocheat.yml"));
|
(!NoCheatConfiguration.speedhackCheckActive ? "speedhack* " : (hasPermission(p, "nocheat.speedhack") ? "speedhack " : "")) +
|
||||||
|
(!NoCheatConfiguration.airbuildCheckActive ? "airbuild* " : (hasPermission(p, "nocheat.airbuild") ? "airbuild " : "")) +
|
||||||
|
(!NoCheatConfiguration.dupebydeathCheckActive ? "dupebydeath* " : (hasPermission(p, "nocheat.dupebydeath") ? "dupebydeath " : "")) +
|
||||||
|
(!NoCheatConfiguration.bedteleportCheckActive ? "bedteleport* " : (hasPermission(p, "nocheat.bedteleport") ? "bedteleport " : "")) +
|
||||||
|
(hasPermission(p, "nocheat.notify") ? "notify " : ""));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,12 +21,8 @@ public class AirbuildCheck {
|
|||||||
public static void check(BlockPlaceEvent event) {
|
public static void check(BlockPlaceEvent event) {
|
||||||
|
|
||||||
// Should we check at all?
|
// Should we check at all?
|
||||||
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.airbuild")) {
|
if(NoCheatPlugin.hasPermission(event.getPlayer(), "nocheat.airbuild"))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Location l = event.getBlockPlaced().getLocation();
|
Location l = event.getBlockPlaced().getLocation();
|
||||||
World w = event.getBlock().getWorld();
|
World w = event.getBlock().getWorld();
|
||||||
|
@ -5,29 +5,20 @@ import org.bukkit.event.player.PlayerMoveEvent;
|
|||||||
|
|
||||||
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Evenprime
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class BedteleportCheck {
|
public class BedteleportCheck {
|
||||||
|
|
||||||
|
|
||||||
public static void check(PlayerMoveEvent event) {
|
public static void check(PlayerMoveEvent event) {
|
||||||
|
|
||||||
// Should we check at all
|
// Should we check at all?
|
||||||
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.bedteleport")) {
|
if(NoCheatPlugin.hasPermission(event.getPlayer(), "nocheat.bedteleport"))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(event.getFrom().getWorld().getBlockTypeIdAt(event.getFrom()) == Material.BED_BLOCK.getId()) {
|
if(event.getFrom().getWorld().getBlockTypeIdAt(event.getFrom()) == Material.BED_BLOCK.getId()) {
|
||||||
double yRest = Math.floor(event.getFrom().getY()) - event.getFrom().getY();
|
double yRest = Math.floor(event.getFrom().getY()) - event.getFrom().getY();
|
||||||
if(yRest > 0.099 && yRest < 0.101)
|
if(yRest > 0.099 && yRest < 0.101)
|
||||||
// Don't allow the teleport
|
// Don't allow the teleport
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,6 @@ import org.bukkit.inventory.PlayerInventory;
|
|||||||
|
|
||||||
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Evenprime
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class DupebydeathCheck {
|
public class DupebydeathCheck {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,12 +22,8 @@ public class DupebydeathCheck {
|
|||||||
Player p = (Player)event.getEntity();
|
Player p = (Player)event.getEntity();
|
||||||
|
|
||||||
// Should we prevent at all?
|
// Should we prevent at all?
|
||||||
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(p, "nocheat.dupebydeath")) {
|
if(NoCheatPlugin.hasPermission(p, "nocheat.dupebydeath"))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
else if(NoCheatPlugin.Permissions == null && p.isOp() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerInventory playerInventory = p.getInventory();
|
PlayerInventory playerInventory = p.getInventory();
|
||||||
List<ItemStack> drops = event.getDrops();
|
List<ItemStack> drops = event.getDrops();
|
||||||
|
@ -21,288 +21,283 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
|||||||
public class MovingCheck {
|
public class MovingCheck {
|
||||||
|
|
||||||
// previously-calculated upper bound values for jumps. Minecraft is very deterministic when it comes to jumps
|
// previously-calculated upper bound values for jumps. Minecraft is very deterministic when it comes to jumps
|
||||||
// Each entry represents the maximum gain in height per move event.
|
// Each entry represents the maximum gain in height per move event.
|
||||||
private static double jumpingPhases[] = new double[]{ 0.501D, 0.34D, 0.26D, 0.17D, 0.09D, 0.02D, 0.00D, -0.07D, -0.15D, -0.22D, -0.29D, -0.36D, -0.43D, -0.49D };
|
private static double jumpingPhases[] = new double[]{ 0.501D, 0.34D, 0.26D, 0.17D, 0.09D, 0.02D, 0.00D, -0.07D, -0.15D, -0.22D, -0.29D, -0.36D, -0.43D, -0.49D };
|
||||||
|
|
||||||
// Limits for the moving check
|
// Limits for the moving check
|
||||||
public static double movingDistanceLow = 0.1D;
|
public static double movingDistanceLow = 0.1D;
|
||||||
public static double movingDistanceMed = 2.0D;
|
public static double movingDistanceMed = 2.0D;
|
||||||
public static double movingDistanceHigh = 5.0D;
|
public static double movingDistanceHigh = 5.0D;
|
||||||
|
|
||||||
// Block types that may be treated specially
|
// Block types that may be treated specially
|
||||||
private enum BlockType {
|
private enum BlockType {
|
||||||
SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN;
|
SOLID, NONSOLID, LADDER, LIQUID, UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Until I can think of a better way to determine if a block is solid or not, this is what I'll do
|
// 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 BlockType types[] = new BlockType[256];
|
private static BlockType types[] = new BlockType[256];
|
||||||
static {
|
static {
|
||||||
|
|
||||||
for(int i = 0; i < types.length; i++) {
|
for(int i = 0; i < types.length; i++) {
|
||||||
types[i] = BlockType.UNKNOWN;
|
types[i] = BlockType.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
types[Material.AIR.getId()] = BlockType.NONSOLID;
|
types[Material.AIR.getId()] = BlockType.NONSOLID;
|
||||||
types[Material.STONE.getId()] = BlockType.SOLID;
|
types[Material.STONE.getId()] = BlockType.SOLID;
|
||||||
types[Material.GRASS.getId()] = BlockType.SOLID;
|
types[Material.GRASS.getId()] = BlockType.SOLID;
|
||||||
types[Material.DIRT.getId()] = BlockType.SOLID;
|
types[Material.DIRT.getId()] = BlockType.SOLID;
|
||||||
types[Material.COBBLESTONE.getId()] = BlockType.SOLID;
|
types[Material.COBBLESTONE.getId()] = BlockType.SOLID;
|
||||||
types[Material.WOOD.getId()] = BlockType.SOLID;
|
types[Material.WOOD.getId()] = BlockType.SOLID;
|
||||||
types[Material.SAPLING.getId()] = BlockType.NONSOLID;
|
types[Material.SAPLING.getId()] = BlockType.NONSOLID;
|
||||||
types[Material.BEDROCK.getId()] = BlockType.SOLID;
|
types[Material.BEDROCK.getId()] = BlockType.SOLID;
|
||||||
types[Material.WATER.getId()] = BlockType.LIQUID;
|
types[Material.WATER.getId()] = BlockType.LIQUID;
|
||||||
types[Material.STATIONARY_WATER.getId()] = BlockType.LIQUID;
|
types[Material.STATIONARY_WATER.getId()] = BlockType.LIQUID;
|
||||||
types[Material.LAVA.getId()] = BlockType.LIQUID;
|
types[Material.LAVA.getId()] = BlockType.LIQUID;
|
||||||
types[Material.STATIONARY_LAVA.getId()] = BlockType.LIQUID;
|
types[Material.STATIONARY_LAVA.getId()] = BlockType.LIQUID;
|
||||||
types[Material.SAND.getId()] = BlockType.SOLID;
|
types[Material.SAND.getId()] = BlockType.SOLID;
|
||||||
types[Material.GRAVEL.getId()] = BlockType.SOLID;
|
types[Material.GRAVEL.getId()] = BlockType.SOLID;
|
||||||
types[Material.GOLD_ORE.getId()] = BlockType.SOLID;
|
types[Material.GOLD_ORE.getId()] = BlockType.SOLID;
|
||||||
types[Material.IRON_ORE.getId()] = BlockType.SOLID;
|
types[Material.IRON_ORE.getId()] = BlockType.SOLID;
|
||||||
types[Material.COAL_ORE.getId()] = BlockType.SOLID;
|
types[Material.COAL_ORE.getId()] = BlockType.SOLID;
|
||||||
types[Material.LOG.getId()] = BlockType.SOLID;
|
types[Material.LOG.getId()] = BlockType.SOLID;
|
||||||
types[Material.LEAVES.getId()] = BlockType.SOLID;
|
types[Material.LEAVES.getId()] = BlockType.SOLID;
|
||||||
types[Material.SPONGE.getId()] = BlockType.SOLID;
|
types[Material.SPONGE.getId()] = BlockType.SOLID;
|
||||||
types[Material.GLASS.getId()] = BlockType.SOLID;
|
types[Material.GLASS.getId()] = BlockType.SOLID;
|
||||||
types[Material.LAPIS_ORE.getId()] = BlockType.SOLID;
|
types[Material.LAPIS_ORE.getId()] = BlockType.SOLID;
|
||||||
types[Material.LAPIS_BLOCK.getId()] = BlockType.SOLID;
|
types[Material.LAPIS_BLOCK.getId()] = BlockType.SOLID;
|
||||||
types[Material.DISPENSER.getId()] = BlockType.SOLID;
|
types[Material.DISPENSER.getId()] = BlockType.SOLID;
|
||||||
types[Material.SANDSTONE.getId()] = BlockType.SOLID;
|
types[Material.SANDSTONE.getId()] = BlockType.SOLID;
|
||||||
types[Material.NOTE_BLOCK.getId()]= BlockType.SOLID;
|
types[Material.NOTE_BLOCK.getId()]= BlockType.SOLID;
|
||||||
types[Material.WOOL.getId()]= BlockType.SOLID;
|
types[Material.WOOL.getId()]= BlockType.SOLID;
|
||||||
types[Material.YELLOW_FLOWER.getId()]= BlockType.NONSOLID;
|
types[Material.YELLOW_FLOWER.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.RED_ROSE.getId()]= BlockType.NONSOLID;
|
types[Material.RED_ROSE.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.BROWN_MUSHROOM.getId()]= BlockType.NONSOLID;
|
types[Material.BROWN_MUSHROOM.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.RED_MUSHROOM.getId()]= BlockType.NONSOLID;
|
types[Material.RED_MUSHROOM.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.GOLD_BLOCK.getId()]= BlockType.SOLID;
|
types[Material.GOLD_BLOCK.getId()]= BlockType.SOLID;
|
||||||
types[Material.IRON_BLOCK.getId()]= BlockType.SOLID;
|
types[Material.IRON_BLOCK.getId()]= BlockType.SOLID;
|
||||||
types[Material.DOUBLE_STEP.getId()]= BlockType.UNKNOWN;
|
types[Material.DOUBLE_STEP.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.STEP.getId()]= BlockType.UNKNOWN;
|
types[Material.STEP.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.BRICK.getId()]= BlockType.SOLID;
|
types[Material.BRICK.getId()]= BlockType.SOLID;
|
||||||
types[Material.TNT.getId()]= BlockType.SOLID;
|
types[Material.TNT.getId()]= BlockType.SOLID;
|
||||||
types[Material.BOOKSHELF.getId()]= BlockType.SOLID;
|
types[Material.BOOKSHELF.getId()]= BlockType.SOLID;
|
||||||
types[Material.MOSSY_COBBLESTONE.getId()] = BlockType.SOLID;
|
types[Material.MOSSY_COBBLESTONE.getId()] = BlockType.SOLID;
|
||||||
types[Material.OBSIDIAN.getId()]= BlockType.SOLID;
|
types[Material.OBSIDIAN.getId()]= BlockType.SOLID;
|
||||||
types[Material.TORCH.getId()]= BlockType.NONSOLID;
|
types[Material.TORCH.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.FIRE.getId()]= BlockType.NONSOLID;
|
types[Material.FIRE.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.MOB_SPAWNER.getId()]= BlockType.SOLID;
|
types[Material.MOB_SPAWNER.getId()]= BlockType.SOLID;
|
||||||
types[Material.WOOD_STAIRS.getId()]= BlockType.UNKNOWN;
|
types[Material.WOOD_STAIRS.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.CHEST.getId()]= BlockType.SOLID;
|
types[Material.CHEST.getId()]= BlockType.SOLID;
|
||||||
types[Material.REDSTONE_WIRE.getId()]= BlockType.NONSOLID;
|
types[Material.REDSTONE_WIRE.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.DIAMOND_ORE.getId()]= BlockType.SOLID;
|
types[Material.DIAMOND_ORE.getId()]= BlockType.SOLID;
|
||||||
types[Material.DIAMOND_BLOCK.getId()]= BlockType.SOLID;
|
types[Material.DIAMOND_BLOCK.getId()]= BlockType.SOLID;
|
||||||
types[Material.WORKBENCH.getId()]= BlockType.SOLID;
|
types[Material.WORKBENCH.getId()]= BlockType.SOLID;
|
||||||
types[Material.CROPS.getId()]= BlockType.NONSOLID;
|
types[Material.CROPS.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.SOIL.getId()]= BlockType.SOLID;
|
types[Material.SOIL.getId()]= BlockType.SOLID;
|
||||||
types[Material.FURNACE.getId()]= BlockType.SOLID;
|
types[Material.FURNACE.getId()]= BlockType.SOLID;
|
||||||
types[Material.BURNING_FURNACE.getId()]= BlockType.SOLID;
|
types[Material.BURNING_FURNACE.getId()]= BlockType.SOLID;
|
||||||
types[Material.SIGN_POST.getId()]= BlockType.NONSOLID;
|
types[Material.SIGN_POST.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.WOODEN_DOOR.getId()]= BlockType.NONSOLID;
|
types[Material.WOODEN_DOOR.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.LADDER.getId()]= BlockType.LADDER;
|
types[Material.LADDER.getId()]= BlockType.LADDER;
|
||||||
types[Material.RAILS.getId()]= BlockType.NONSOLID;
|
types[Material.RAILS.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.COBBLESTONE_STAIRS.getId()]= BlockType.UNKNOWN;
|
types[Material.COBBLESTONE_STAIRS.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.WALL_SIGN.getId()]= BlockType.NONSOLID;
|
types[Material.WALL_SIGN.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.LEVER.getId()]= BlockType.NONSOLID;
|
types[Material.LEVER.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.STONE_PLATE.getId()]= BlockType.UNKNOWN;
|
types[Material.STONE_PLATE.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.IRON_DOOR_BLOCK.getId()]= BlockType.NONSOLID;
|
types[Material.IRON_DOOR_BLOCK.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.WOOD_PLATE.getId()]= BlockType.NONSOLID;
|
types[Material.WOOD_PLATE.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.REDSTONE_ORE.getId()]= BlockType.SOLID;
|
types[Material.REDSTONE_ORE.getId()]= BlockType.SOLID;
|
||||||
types[Material.GLOWING_REDSTONE_ORE.getId()]= BlockType.SOLID;
|
types[Material.GLOWING_REDSTONE_ORE.getId()]= BlockType.SOLID;
|
||||||
types[Material.REDSTONE_TORCH_OFF.getId()]= BlockType.NONSOLID;
|
types[Material.REDSTONE_TORCH_OFF.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.REDSTONE_TORCH_ON.getId()]= BlockType.NONSOLID;
|
types[Material.REDSTONE_TORCH_ON.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.STONE_BUTTON.getId()]= BlockType.NONSOLID;
|
types[Material.STONE_BUTTON.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.SNOW.getId()]= BlockType.UNKNOWN;
|
types[Material.SNOW.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.ICE.getId()]= BlockType.UNKNOWN;
|
types[Material.ICE.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.SNOW_BLOCK.getId()]= BlockType.SOLID;
|
types[Material.SNOW_BLOCK.getId()]= BlockType.SOLID;
|
||||||
types[Material.CACTUS.getId()]= BlockType.SOLID;
|
types[Material.CACTUS.getId()]= BlockType.SOLID;
|
||||||
types[Material.CLAY.getId()]= BlockType.SOLID;
|
types[Material.CLAY.getId()]= BlockType.SOLID;
|
||||||
types[Material.SUGAR_CANE_BLOCK.getId()]= BlockType.NONSOLID;
|
types[Material.SUGAR_CANE_BLOCK.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.JUKEBOX.getId()]= BlockType.SOLID;
|
types[Material.JUKEBOX.getId()]= BlockType.SOLID;
|
||||||
types[Material.FENCE.getId()]= BlockType.UNKNOWN;
|
types[Material.FENCE.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.PUMPKIN.getId()]= BlockType.SOLID;
|
types[Material.PUMPKIN.getId()]= BlockType.SOLID;
|
||||||
types[Material.NETHERRACK.getId()]= BlockType.SOLID;
|
types[Material.NETHERRACK.getId()]= BlockType.SOLID;
|
||||||
types[Material.SOUL_SAND.getId()]= BlockType.UNKNOWN;
|
types[Material.SOUL_SAND.getId()]= BlockType.UNKNOWN;
|
||||||
types[Material.GLOWSTONE.getId()]= BlockType.SOLID;
|
types[Material.GLOWSTONE.getId()]= BlockType.SOLID;
|
||||||
types[Material.PORTAL.getId()]= BlockType.NONSOLID;
|
types[Material.PORTAL.getId()]= BlockType.NONSOLID;
|
||||||
types[Material.JACK_O_LANTERN.getId()]= BlockType.SOLID;
|
types[Material.JACK_O_LANTERN.getId()]= BlockType.SOLID;
|
||||||
types[Material.CAKE_BLOCK.getId()]= BlockType.UNKNOWN;
|
types[Material.CAKE_BLOCK.getId()]= BlockType.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void check(NoCheatData data, PlayerMoveEvent event) {
|
public static void check(NoCheatData data, PlayerMoveEvent event) {
|
||||||
|
|
||||||
// Should we check at all
|
// Should we check at all
|
||||||
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.moving")) {
|
if(NoCheatPlugin.hasPermission(event.getPlayer(), "nocheat.moving"))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the two locations of the event
|
// Get the two locations of the event
|
||||||
Location from = event.getFrom();
|
Location from = event.getFrom();
|
||||||
Location to = event.getTo();
|
Location to = event.getTo();
|
||||||
|
|
||||||
System.out.println(from.getY() + " " + to.getY());
|
// First check the distance the player has moved horizontally
|
||||||
// First check the distance the player has moved horizontally
|
// TODO: Make this check much more precise
|
||||||
// TODO: Make this check much more precise
|
double xDistance = Math.abs(from.getX() - to.getX());
|
||||||
double xDistance = Math.abs(from.getX() - to.getX());
|
double zDistance = Math.abs(from.getZ() - to.getZ());
|
||||||
double zDistance = Math.abs(from.getZ() - to.getZ());
|
double combined = xDistance * xDistance + zDistance * zDistance;
|
||||||
double combined = xDistance * xDistance + zDistance * zDistance;
|
|
||||||
|
|
||||||
// If the target is a bed and distance not too big, allow it
|
// If the target is a bed and distance not too big, allow it
|
||||||
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && xDistance < 5.0D && zDistance < 5.0D) {
|
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && xDistance < 5.0D && zDistance < 5.0D) {
|
||||||
return; // players are allowed to "teleport" into a bed over short distances
|
return; // players are allowed to "teleport" into a bed over short distances
|
||||||
}
|
}
|
||||||
|
|
||||||
Level vl = null; // The violation level (none, minor, normal, heavy)
|
Level vl = null; // The violation level (none, minor, normal, heavy)
|
||||||
|
|
||||||
// How far are we off?
|
// How far are we off?
|
||||||
if(combined > movingDistanceHigh) {
|
if(combined > movingDistanceHigh) {
|
||||||
vl = max(vl, Level.SEVERE);
|
vl = max(vl, Level.SEVERE);
|
||||||
}
|
}
|
||||||
else if(combined > movingDistanceMed) {
|
else if(combined > movingDistanceMed) {
|
||||||
vl = max(vl, Level.WARNING);
|
vl = max(vl, Level.WARNING);
|
||||||
}
|
}
|
||||||
else if(combined > movingDistanceLow) {
|
else if(combined > movingDistanceLow) {
|
||||||
vl = max(vl, Level.INFO);
|
vl = max(vl, Level.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pre-calculate boundary values that are needed multiple times in the following checks
|
// pre-calculate boundary values that are needed multiple times in the following checks
|
||||||
// the array each contains [lowerX, higherX, Y, lowerZ, higherZ]
|
// the array each contains [lowerX, higherX, Y, lowerZ, higherZ]
|
||||||
int fromValues[] = {floor_double(from.getX() - 0.3D), (int)Math.floor(from.getX() + 0.3D), from.getBlockY(), floor_double(from.getZ() - 0.3D),(int)Math.floor(from.getZ() + 0.3D) };
|
int fromValues[] = {floor_double(from.getX() - 0.3D), (int)Math.floor(from.getX() + 0.3D), from.getBlockY(), floor_double(from.getZ() - 0.3D),(int)Math.floor(from.getZ() + 0.3D) };
|
||||||
int toValues[] = {floor_double(to.getX() - 0.3D), (int)Math.floor(to.getX() + 0.3D), to.getBlockY(), floor_double(to.getZ() - 0.3D), (int)Math.floor(to.getZ() + 0.3D) };
|
int toValues[] = {floor_double(to.getX() - 0.3D), (int)Math.floor(to.getX() + 0.3D), to.getBlockY(), floor_double(to.getZ() - 0.3D), (int)Math.floor(to.getZ() + 0.3D) };
|
||||||
|
|
||||||
// compare locations to the world to guess if the player is standing on the ground, a half-block or next to a ladder
|
// compare locations to the world to guess if the player is standing on the ground, a half-block or next to a ladder
|
||||||
boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from);
|
boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from);
|
||||||
boolean onGroundTo = playerIsOnGround(from.getWorld(), toValues, to);
|
boolean onGroundTo = playerIsOnGround(from.getWorld(), toValues, to);
|
||||||
|
|
||||||
// Both locations seem to be on solid ground or at a ladder
|
// Both locations seem to be on solid ground or at a ladder
|
||||||
if(onGroundFrom && onGroundTo)
|
if(onGroundFrom && onGroundTo)
|
||||||
{
|
{
|
||||||
// reset jumping
|
// reset jumping
|
||||||
data.movingJumpPhase = 0;
|
data.movingJumpPhase = 0;
|
||||||
|
|
||||||
// Check if the player isn't 'walking' up unrealistically far in one step
|
// Check if the player isn't 'walking' up unrealistically far in one step
|
||||||
// Finally found out why this can happen:
|
// Finally found out why this can happen:
|
||||||
// If a player runs into a wall at an angle from above, the game tries to
|
// If a player runs into a wall at an angle from above, the game tries to
|
||||||
// place him above the block he bumped into, by placing him 0.5 m above
|
// place him above the block he bumped into, by placing him 0.5 m above
|
||||||
// the target block
|
// the target block
|
||||||
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
||||||
|
|
||||||
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
||||||
|
|
||||||
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
||||||
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
||||||
else vl = max(vl, Level.INFO);
|
else vl = max(vl, Level.INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// player is starting to jump (or starting to fall down somewhere)
|
// player is starting to jump (or starting to fall down somewhere)
|
||||||
else if(onGroundFrom && !onGroundTo)
|
else if(onGroundFrom && !onGroundTo)
|
||||||
{
|
{
|
||||||
// reset jumping
|
// reset jumping
|
||||||
data.movingJumpPhase = 0;
|
data.movingJumpPhase = 0;
|
||||||
|
|
||||||
// Check if player isn't jumping too high
|
// Check if player isn't jumping too high
|
||||||
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
||||||
|
|
||||||
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
||||||
|
|
||||||
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
||||||
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
||||||
else vl = max(vl, Level.INFO);
|
else vl = max(vl, Level.INFO);
|
||||||
}
|
}
|
||||||
else if(to.getY() <= from.getY()) {
|
else if(to.getY() <= from.getY()) {
|
||||||
// Very special case if running over a cliff and then immediately jumping.
|
// Very special case if running over a cliff and then immediately jumping.
|
||||||
// Some sort of "air jump", MC allows it, so we have to do so too.
|
// Some sort of "air jump", MC allows it, so we have to do so too.
|
||||||
}
|
}
|
||||||
else data.movingJumpPhase++; // Setup next phase of the jump
|
else data.movingJumpPhase++; // Setup next phase of the jump
|
||||||
}
|
}
|
||||||
// player is probably landing somewhere
|
// player is probably landing somewhere
|
||||||
else if(!onGroundFrom && onGroundTo)
|
else if(!onGroundFrom && onGroundTo)
|
||||||
{
|
{
|
||||||
// Check if player isn't landing to high (sounds weird, but has its use)
|
// Check if player isn't landing to high (sounds weird, but has its use)
|
||||||
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
||||||
|
|
||||||
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
||||||
|
|
||||||
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
||||||
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
||||||
else vl = max(vl, Level.INFO);
|
else vl = max(vl, Level.INFO);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data.movingJumpPhase = 0; // He is on ground now, so reset the jump
|
data.movingJumpPhase = 0; // He is on ground now, so reset the jump
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Player is moving through air (during jumping, falling)
|
// Player is moving through air (during jumping, falling)
|
||||||
else {
|
else {
|
||||||
// May also be at the very edge of a platform (I seem to not be able to reliably tell if that's the case)
|
// May also be at the very edge of a platform (I seem to not be able to reliably tell if that's the case)
|
||||||
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
if(!(to.getY() - from.getY() < jumpingPhases[data.movingJumpPhase])) {
|
||||||
|
|
||||||
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
double offset = (to.getY() - from.getY()) - jumpingPhases[data.movingJumpPhase];
|
||||||
|
|
||||||
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
if(offset > 2D) vl = max(vl, Level.SEVERE);
|
||||||
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
else if(offset > 1D) vl = max(vl, Level.WARNING);
|
||||||
else vl = max(vl, Level.INFO);
|
else vl = max(vl, Level.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.movingJumpPhase++; // Enter next phase of the flight
|
data.movingJumpPhase++; // Enter next phase of the flight
|
||||||
}
|
}
|
||||||
|
|
||||||
// do a security check on the jumping phase, such that we don't get
|
// do a security check on the jumping phase, such that we don't get
|
||||||
// OutOfArrayBoundsExceptions at long air times (falling off high places)
|
// OutOfArrayBoundsExceptions at long air times (falling off high places)
|
||||||
if(!(data.movingJumpPhase < jumpingPhases.length)) {
|
if(!(data.movingJumpPhase < jumpingPhases.length)) {
|
||||||
data.movingJumpPhase = jumpingPhases.length - 1;
|
data.movingJumpPhase = jumpingPhases.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vl == null) {
|
if(vl == null) {
|
||||||
legitimateMove(data, event);
|
legitimateMove(data, event);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String actions = null;
|
String actions = null;
|
||||||
boolean log = true;
|
boolean log = true;
|
||||||
|
|
||||||
// If it is the first violation, store the "from" location for potential later use
|
// If it is the first violation, store the "from" location for potential later use
|
||||||
if(data.movingSetBackPoint == null) {
|
if(data.movingSetBackPoint == null) {
|
||||||
data.movingSetBackPoint = event.getFrom().clone();
|
data.movingSetBackPoint = event.getFrom().clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find out with what actions to treat the violation(s)
|
// Find out with what actions to treat the violation(s)
|
||||||
if(Level.INFO.equals(vl)) {
|
if(Level.INFO.equals(vl)) {
|
||||||
data.movingMinorViolationsInARow++;
|
data.movingMinorViolationsInARow++;
|
||||||
|
|
||||||
actions = NoCheatConfiguration.movingActionMinor;
|
actions = NoCheatConfiguration.movingActionMinor;
|
||||||
|
|
||||||
// React only after the freebee illegal moves have all been used
|
// React only after the freebee illegal moves have all been used
|
||||||
if(data.movingMinorViolationsInARow % (NoCheatConfiguration.movingFreeMoves) != 0) {
|
if(data.movingMinorViolationsInARow % (NoCheatConfiguration.movingFreeMoves) != 0) {
|
||||||
vl = null;
|
vl = null;
|
||||||
actions = null;
|
actions = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.movingMinorViolationsInARow != NoCheatConfiguration.movingFreeMoves) {
|
if(data.movingMinorViolationsInARow != NoCheatConfiguration.movingFreeMoves) {
|
||||||
log = false;
|
log = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// using up all free moves 4 times in a row counts as one normal violation
|
// using up all free moves 4 times in a row counts as one normal violation
|
||||||
if(data.movingMinorViolationsInARow % (NoCheatConfiguration.movingFreeMoves * 4) == 0) {
|
if(data.movingMinorViolationsInARow % (NoCheatConfiguration.movingFreeMoves * 4) == 0) {
|
||||||
vl = Level.WARNING;
|
vl = Level.WARNING;
|
||||||
log = true;
|
log = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Level.WARNING.equals(vl)) {
|
if(Level.WARNING.equals(vl)) {
|
||||||
if(data.movingNormalViolationsInARow > 0) log = false;
|
if(data.movingNormalViolationsInARow > 0) log = false;
|
||||||
data.movingNormalViolationsInARow++;
|
data.movingNormalViolationsInARow++;
|
||||||
actions = NoCheatConfiguration.movingActionNormal;
|
actions = NoCheatConfiguration.movingActionNormal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Level.SEVERE.equals(vl)) {
|
if(Level.SEVERE.equals(vl)) {
|
||||||
if(data.movingHeavyViolationsInARow > 0) log = false;
|
if(data.movingHeavyViolationsInARow > 0) log = false;
|
||||||
data.movingHeavyViolationsInARow++;
|
data.movingHeavyViolationsInARow++;
|
||||||
actions = NoCheatConfiguration.movingActionHeavy;
|
actions = NoCheatConfiguration.movingActionHeavy;
|
||||||
}
|
}
|
||||||
|
|
||||||
action(event, actions, log);
|
action(event, actions, log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -387,65 +382,65 @@ public class MovingCheck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the four edges of the player's approximated Bounding Box for blocks or ladders,
|
* Check the four edges of the player's approximated Bounding Box for blocks or ladders,
|
||||||
* at his own height (values[2]) and below his feet (values[2]-1). Also, check at his "head"
|
* at his own height (values[2]) and below his feet (values[2]-1). Also, check at his "head"
|
||||||
* for ladders.
|
* for ladders.
|
||||||
*
|
*
|
||||||
* If there is one, the player is considered as standing on it/hanging to it.
|
* If there is one, the player is considered as standing on it/hanging to it.
|
||||||
*
|
*
|
||||||
* Not perfect at all and will produce some false negatives. Probably will be refined
|
* Not perfect at all and will produce some false negatives. Probably will be refined
|
||||||
* later.
|
* later.
|
||||||
*
|
*
|
||||||
* @param w The world the coordinates belong to
|
* @param w The world the coordinates belong to
|
||||||
* @param values The coordinates [lowerX, higherX, Y, lowerZ, higherZ]
|
* @param values The coordinates [lowerX, higherX, Y, lowerZ, higherZ]
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static boolean playerIsOnGround(World w, int values[], Location l) {
|
private static boolean playerIsOnGround(World w, int values[], Location l) {
|
||||||
|
|
||||||
// Completely revamped collision detection
|
// Completely revamped collision detection
|
||||||
// What it does:
|
// What it does:
|
||||||
// Check the blocks below the player. If they aren't not solid (sic!) and the blocks directly above
|
// Check the blocks below the player. If they aren't not solid (sic!) and the blocks directly above
|
||||||
// them aren't solid, The player is considered to be standing on the lower block
|
// them aren't solid, The player is considered to be standing on the lower block
|
||||||
// Plus the player can hang onto a ladder that is one field above him
|
// Plus the player can hang onto a ladder that is one field above him
|
||||||
|
|
||||||
// Check the four borders of the players hitbox for something he could be standing on
|
// Check the four borders of the players hitbox for something he could be standing on
|
||||||
if(types[w.getBlockTypeIdAt(values[0], values[2]-1, values[3])] != BlockType.NONSOLID ||
|
if(types[w.getBlockTypeIdAt(values[0], values[2]-1, values[3])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[1], values[2]-1, values[3])] != BlockType.NONSOLID ||
|
types[w.getBlockTypeIdAt(values[1], values[2]-1, values[3])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[0], values[2]-1, values[4])] != BlockType.NONSOLID ||
|
types[w.getBlockTypeIdAt(values[0], values[2]-1, values[4])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[1], values[2]-1, values[4])] != BlockType.NONSOLID )
|
types[w.getBlockTypeIdAt(values[1], values[2]-1, values[4])] != BlockType.NONSOLID )
|
||||||
return true;
|
return true;
|
||||||
// Check if he is hanging onto a ladder
|
// Check if he is hanging onto a ladder
|
||||||
else if(types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ())] == BlockType.LADDER ||
|
else if(types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY(), l.getBlockZ())] == BlockType.LADDER ||
|
||||||
types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()+1, l.getBlockZ())] == BlockType.LADDER)
|
types[w.getBlockTypeIdAt(l.getBlockX(), l.getBlockY()+1, l.getBlockZ())] == BlockType.LADDER)
|
||||||
return true;
|
return true;
|
||||||
// check if he is standing "in" an block that's potentially solid (we give him the benefit of a doubt and see that as a legit move)
|
// check if he is standing "in" an block that's potentially solid (we give him the benefit of a doubt and see that as a legit move)
|
||||||
// If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case)
|
// If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case)
|
||||||
else if(types[w.getBlockTypeIdAt(values[0], values[2], values[3])] != BlockType.NONSOLID ||
|
else if(types[w.getBlockTypeIdAt(values[0], values[2], values[3])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[1], values[2], values[3])] != BlockType.NONSOLID||
|
types[w.getBlockTypeIdAt(values[1], values[2], values[3])] != BlockType.NONSOLID||
|
||||||
types[w.getBlockTypeIdAt(values[0], values[2], values[4])] != BlockType.NONSOLID ||
|
types[w.getBlockTypeIdAt(values[0], values[2], values[4])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[1], values[2], values[4])] != BlockType.NONSOLID)
|
types[w.getBlockTypeIdAt(values[1], values[2], values[4])] != BlockType.NONSOLID)
|
||||||
return true;
|
return true;
|
||||||
// check if his head is "stuck" in an block that's potentially solid (we give him the benefit of a doubt and see that as a legit move)
|
// check if his head is "stuck" in an block that's potentially solid (we give him the benefit of a doubt and see that as a legit move)
|
||||||
// If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case)
|
// If it is not legit, the MC server already has a safeguard against that (You'll get "xy moved wrongly" on the console in that case)
|
||||||
else if(types[w.getBlockTypeIdAt(values[0], values[2]+1, values[3])] != BlockType.NONSOLID ||
|
else if(types[w.getBlockTypeIdAt(values[0], values[2]+1, values[3])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[1], values[2]+1, values[3])] != BlockType.NONSOLID ||
|
types[w.getBlockTypeIdAt(values[1], values[2]+1, values[3])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[0], values[2]+1, values[4])] != BlockType.NONSOLID ||
|
types[w.getBlockTypeIdAt(values[0], values[2]+1, values[4])] != BlockType.NONSOLID ||
|
||||||
types[w.getBlockTypeIdAt(values[1], values[2]+1, values[4])] != BlockType.NONSOLID)
|
types[w.getBlockTypeIdAt(values[1], values[2]+1, values[4])] != BlockType.NONSOLID)
|
||||||
return true;
|
return true;
|
||||||
// Allow using a bug called "water elevator"
|
// Allow using a bug called "water elevator"
|
||||||
else if(types[w.getBlockTypeIdAt(values[0]+1, values[2]-1, values[3]+1)] == BlockType.LIQUID ||
|
else if(types[w.getBlockTypeIdAt(values[0]+1, values[2]-1, values[3]+1)] == BlockType.LIQUID ||
|
||||||
types[w.getBlockTypeIdAt(values[0]+1, values[2], values[3]+1)] == BlockType.LIQUID ||
|
types[w.getBlockTypeIdAt(values[0]+1, values[2], values[3]+1)] == BlockType.LIQUID ||
|
||||||
types[w.getBlockTypeIdAt(values[0]+1, values[2]+1, values[3]+1)] == BlockType.LIQUID)
|
types[w.getBlockTypeIdAt(values[0]+1, values[2]+1, values[3]+1)] == BlockType.LIQUID)
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static int floor_double(double d)
|
public static int floor_double(double d)
|
||||||
{
|
{
|
||||||
int i = (int)d;
|
int i = (int)d;
|
||||||
return d > (double)i ? i : i - 1;
|
return d > (double)i ? i : i - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,14 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
|||||||
public class SpeedhackCheck {
|
public class SpeedhackCheck {
|
||||||
|
|
||||||
|
|
||||||
private static final long interval = 1000;
|
private static final long interval = 1000;
|
||||||
private static final int violationsLimit = 3;
|
private static final int violationsLimit = 3;
|
||||||
|
|
||||||
public static void check(NoCheatData data, PlayerMoveEvent event) {
|
public static void check(NoCheatData data, PlayerMoveEvent event) {
|
||||||
|
|
||||||
// Should we check at all?
|
// Should we check at all?
|
||||||
if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.speedhack")) {
|
if(NoCheatPlugin.hasPermission(event.getPlayer(), "nocheat.speedhack"))
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the time of the server
|
// Get the time of the server
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
|
@ -7,11 +7,6 @@ import org.bukkit.event.entity.EntityListener;
|
|||||||
import cc.co.evenprime.bukkit.nocheat.NoCheatConfiguration;
|
import cc.co.evenprime.bukkit.nocheat.NoCheatConfiguration;
|
||||||
import cc.co.evenprime.bukkit.nocheat.checks.DupebydeathCheck;
|
import cc.co.evenprime.bukkit.nocheat.checks.DupebydeathCheck;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Evenprime
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class NoCheatEntityListener extends EntityListener {
|
public class NoCheatEntityListener extends EntityListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cc.co.evenprime.bukkit.nocheat.listeners;
|
package cc.co.evenprime.bukkit.nocheat.listeners;
|
||||||
|
|
||||||
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
import org.bukkit.event.player.PlayerListener;
|
import org.bukkit.event.player.PlayerListener;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
@ -19,32 +20,33 @@ import cc.co.evenprime.bukkit.nocheat.checks.SpeedhackCheck;
|
|||||||
|
|
||||||
public class NoCheatPlayerListener extends PlayerListener {
|
public class NoCheatPlayerListener extends PlayerListener {
|
||||||
|
|
||||||
public NoCheatPlayerListener() { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlayerQuit(PlayerEvent event) {
|
|
||||||
NoCheatPlugin.playerData.remove(event.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public NoCheatPlayerListener() { }
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerQuit(PlayerEvent event) {
|
||||||
|
NoCheatPlugin.playerData.remove(event.getPlayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
|
|
||||||
// Get the player-specific data
|
// Get the player-specific data
|
||||||
NoCheatData data = NoCheatPlugin.getPlayerData(event.getPlayer());
|
NoCheatData data = NoCheatPlugin.getPlayerData(event.getPlayer());
|
||||||
|
|
||||||
if(!event.isCancelled() && NoCheatConfiguration.speedhackCheckActive)
|
if(!event.isCancelled() && NoCheatConfiguration.speedhackCheckActive)
|
||||||
SpeedhackCheck.check(data, event);
|
SpeedhackCheck.check(data, event);
|
||||||
|
|
||||||
if(!event.isCancelled() && NoCheatConfiguration.movingCheckActive)
|
if(!event.isCancelled() && NoCheatConfiguration.movingCheckActive)
|
||||||
MovingCheck.check(data, event);
|
MovingCheck.check(data, event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
@Override
|
public void onPlayerTeleport(PlayerMoveEvent event) {
|
||||||
public void onPlayerTeleport(PlayerMoveEvent event) {
|
|
||||||
|
|
||||||
if(!event.isCancelled() && NoCheatConfiguration.bedteleportCheckActive) {
|
if(!event.isCancelled() && NoCheatConfiguration.bedteleportCheckActive) {
|
||||||
BedteleportCheck.check(event);
|
BedteleportCheck.check(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user