diff --git a/plugin.yml b/plugin.yml index be14f216..42fe71a6 100644 --- a/plugin.yml +++ b/plugin.yml @@ -3,5 +3,5 @@ name: NoCheatPlugin author: Evenprime main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin -version: 0.5.2 +version: 0.5.2a diff --git a/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java new file mode 100644 index 00000000..6e7cbf2b --- /dev/null +++ b/src/cc/co/evenprime/bukkit/nocheat/BlockPlacingCheck.java @@ -0,0 +1,24 @@ +package cc.co.evenprime.bukkit.nocheat; + +import org.bukkit.Material; +import org.bukkit.event.block.BlockPlaceEvent; + +public class BlockPlacingCheck { + + public static void check(BlockPlaceEvent event) { + + + if(NoCheatPlugin.Permissions != null && NoCheatPlugin.Permissions.has(event.getPlayer(), "nocheat.airbuild")) { + return; + } + else if(NoCheatPlugin.Permissions == null && event.getPlayer().isOp() ) { + return; + } + + if(event.getBlockAgainst().getType() == Material.AIR) { + event.setCancelled(true); + NoCheatPlugin.log.warning("NoCheatPlugin: Airbuild violation: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " against air"); + + } + } +} diff --git a/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java b/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java index a53c3b4e..9637fe8c 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/MovingCheck.java @@ -6,7 +6,6 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.event.player.PlayerMoveEvent; -import cc.co.evenprime.bukkit.nocheat.NoCheatPluginPlayerListener.NoCheatPluginData; public class MovingCheck { @@ -134,114 +133,109 @@ public class MovingCheck { // First check the distance the player has moved horizontally // TODO: Make this check much more precise - if(!event.isCancelled()) { - double xDistance = Math.abs(from.getX() - to.getX()); - double zDistance = Math.abs(from.getZ() - to.getZ()); + double xDistance = Math.abs(from.getX() - to.getX()); + double zDistance = Math.abs(from.getZ() - to.getZ()); - // How far are we off? - if(xDistance > NoCheatConfiguration.movingDistanceHigh || zDistance > NoCheatConfiguration.movingDistanceHigh) { - vl = vl > HEAVY ? vl : HEAVY; - } - else if(xDistance > NoCheatConfiguration.movingDistanceMed || zDistance > NoCheatConfiguration.movingDistanceMed) { - vl = vl > NORMAL ? vl : NORMAL; - } - else if(xDistance > NoCheatConfiguration.movingDistanceLow || zDistance > NoCheatConfiguration.movingDistanceLow) { - vl = vl > MINOR ? vl : MINOR; - } + // How far are we off? + if(xDistance > NoCheatConfiguration.movingDistanceHigh || zDistance > NoCheatConfiguration.movingDistanceHigh) { + vl = vl > HEAVY ? vl : HEAVY; + } + else if(xDistance > NoCheatConfiguration.movingDistanceMed || zDistance > NoCheatConfiguration.movingDistanceMed) { + vl = vl > NORMAL ? vl : NORMAL; + } + else if(xDistance > NoCheatConfiguration.movingDistanceLow || zDistance > NoCheatConfiguration.movingDistanceLow) { + vl = vl > MINOR ? vl : MINOR; } - // If we didn't already cancel the event, check the vertical movement - if(!event.isCancelled()) { - // pre-calculate boundary values that are needed multiple times in the following checks - // 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 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) }; + // pre-calculate boundary values that are needed multiple times in the following checks + // 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 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 - boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from); - boolean onGroundTo = playerIsOnGround(from.getWorld(), toValues, to); + // 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 onGroundTo = playerIsOnGround(from.getWorld(), toValues, to); - // Both locations seem to be on solid ground or at a ladder - if(onGroundFrom && onGroundTo) - { - // reset jumping - data.phase = 0; + // Both locations seem to be on solid ground or at a ladder + if(onGroundFrom && onGroundTo) + { + // reset jumping + data.phase = 0; - // Check if the player isn't 'walking' up unrealistically far in one step - // Finally found out why this can happen: - // 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 - // the target block - if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { - - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; - - if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; - else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; - else vl = vl > MINOR ? vl : MINOR; - } + // Check if the player isn't 'walking' up unrealistically far in one step + // Finally found out why this can happen: + // 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 + // the target block + if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { + + double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + + if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; + else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; + else vl = vl > MINOR ? vl : MINOR; } - // player is starting to jump (or starting to fall down somewhere) - else if(onGroundFrom && !onGroundTo) - { - // reset jumping - data.phase = 0; + } + // player is starting to jump (or starting to fall down somewhere) + else if(onGroundFrom && !onGroundTo) + { + // reset jumping + data.phase = 0; - // Check if player isn't jumping too high - if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { - - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; - - if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; - else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; - else vl = vl > MINOR ? vl : MINOR; - } - else if(to.getY() <= from.getY()) { - // 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. - } - else data.phase++; // Setup next phase of the jump + // Check if player isn't jumping too high + if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { + + double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + + if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; + else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; + else vl = vl > MINOR ? vl : MINOR; } - // player is probably landing somewhere - else if(!onGroundFrom && onGroundTo) - { - // Check if player isn't landing to high (sounds weird, but has its use) - if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { - - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; - - if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; - else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; - else vl = vl > MINOR ? vl : MINOR; - } - else { - data.phase = 0; // He is on ground now, so reset the jump - } + else if(to.getY() <= from.getY()) { + // 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. + } + else data.phase++; // Setup next phase of the jump + } + // player is probably landing somewhere + else if(!onGroundFrom && onGroundTo) + { + // Check if player isn't landing to high (sounds weird, but has its use) + if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { + + double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + + if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; + else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; + else vl = vl > MINOR ? vl : MINOR; } - // Player is moving through air (during jumping, falling) 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) - if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { - - double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; - - if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; - else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; - else vl = vl > MINOR ? vl : MINOR; - } - else { - data.phase++; // Enter next phase of the flight - } - } - - // do a security check on the jumping phase, such that we don't get - // OutOfArrayBoundsExceptions at long air times (falling off high places) - if(!(data.phase < jumpingPhases.length)) { - data.phase = jumpingPhases.length - 1; + data.phase = 0; // He is on ground now, so reset the jump } } - + // Player is moving through air (during jumping, falling) + 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) + if(!(to.getY() - from.getY() < jumpingPhases[data.phase])) { + + double offset = (to.getY() - from.getY()) - jumpingPhases[data.phase]; + + if(offset > 2D) vl = vl > HEAVY ? vl : HEAVY; + else if(offset > 0.6D) vl = vl > NORMAL ? vl : NORMAL; + else vl = vl > MINOR ? vl : MINOR; + } + else { + data.phase++; // Enter next phase of the flight + } + } + + // do a security check on the jumping phase, such that we don't get + // OutOfArrayBoundsExceptions at long air times (falling off high places) + if(!(data.phase < jumpingPhases.length)) { + data.phase = jumpingPhases.length - 1; + } + // Treat the violation(s) switch(vl) { case MINOR: @@ -273,27 +267,30 @@ public class MovingCheck { } else if(data.minorViolationsInARow % 2 == 0) { // now we need it - resetPlayer(data, event); NoCheatPlugin.log.info("NoCheatPlugin: Moving violation: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); + resetPlayer(data, event); } } protected static void normalViolation(NoCheatPluginData data, PlayerMoveEvent event) { - resetPlayer(data, event); - - data.normalViolationsInARow++; // Log the first violation in a row if(data.normalViolationsInARow <= 1) NoCheatPlugin.log.warning("NoCheatPlugin: Moving violation: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); - } + + resetPlayer(data, event); + + data.normalViolationsInARow++; + } protected static void heavyViolation(NoCheatPluginData data, PlayerMoveEvent event) { + + if(data.heavyViolationsInARow == 0) + NoCheatPlugin.log.severe("NoCheatPlugin: Moving violation: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); + resetPlayer(data, event); data.heavyViolationsInARow++; // Log the first violation in a row - if(data.heavyViolationsInARow <= 1) - NoCheatPlugin.log.severe("NoCheatPlugin: Moving violation: "+event.getPlayer().getName()+" from " + String.format("(%.5f, %.5f, %.5f) to (%.5f, %.5f, %.5f)", event.getFrom().getX(), event.getFrom().getY(), event.getFrom().getZ(), event.getTo().getX(), event.getTo().getY(), event.getTo().getZ())); } protected static void legitimateMove(NoCheatPluginData data, PlayerMoveEvent event) { diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java index 631db67b..536f4593 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPlugin.java @@ -1,8 +1,11 @@ package cc.co.evenprime.bukkit.nocheat; import java.io.File; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Logger; +import org.bukkit.entity.Player; import org.bukkit.event.Event.Priority; import org.bukkit.event.Event; import org.bukkit.plugin.PluginDescriptionFile; @@ -25,17 +28,39 @@ public class NoCheatPlugin extends JavaPlugin { private final NoCheatPluginPlayerListener playerListener; private final NoCheatPluginVehicleListener vehicleListener; + private final NoCheatPluginBlockListener blockListener; public static Logger log; public static PermissionHandler Permissions = null; + + // Store data between Events + public static Map playerData = new HashMap(); public NoCheatPlugin() { - playerListener = new NoCheatPluginPlayerListener(this); - vehicleListener = new NoCheatPluginVehicleListener(this, playerListener); + playerListener = new NoCheatPluginPlayerListener(); + vehicleListener = new NoCheatPluginVehicleListener(playerListener); + blockListener = new NoCheatPluginBlockListener(); log = NoCheatConfiguration.logger; } + + public static NoCheatPluginData getPlayerData(Player p) { + NoCheatPluginData data = null; + + if((data = playerData.get(p)) == null ) { + synchronized(playerData) { + data = playerData.get(p); + if(data == null) { + // If we have no data for the player, create some + data = new NoCheatPluginData(); + playerData.put(p, data); + } + } + } + + return data; + } public void onDisable() { } @@ -47,6 +72,7 @@ public class NoCheatPlugin extends JavaPlugin { pm.registerEvent(Event.Type.PLAYER_QUIT, playerListener, Priority.Monitor, this); pm.registerEvent(Event.Type.VEHICLE_EXIT, vehicleListener, Priority.Monitor, this); pm.registerEvent(Event.Type.VEHICLE_DAMAGE, vehicleListener, Priority.Monitor, this); + pm.registerEvent(Event.Type.BLOCK_PLACED, blockListener, Priority.Low, this); PluginDescriptionFile pdfFile = this.getDescription(); Logger.getLogger("Minecraft").info( "NoCheat version " + pdfFile.getVersion() + " is enabled!" ); @@ -58,14 +84,11 @@ public class NoCheatPlugin extends JavaPlugin { public void setupPermissions() { Plugin test = this.getServer().getPluginManager().getPlugin("Permissions"); - - if(Permissions == null) { - if(test != null) { - Permissions = ((Permissions)test).getHandler(); - } else { - log.info("Nocheat couldn't find Permissions plugin. Fallback to OP -> all allowed."); - this.getServer().getPluginManager().disablePlugin(this); - } + if(test != null) { + Permissions = ((Permissions)test).getHandler(); + } else { + log.info("Nocheat couldn't find Permissions plugin. Fallback to 'isOp()' equals 'all allowed'."); + this.getServer().getPluginManager().disablePlugin(this); } } diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java new file mode 100644 index 00000000..f7b79b5a --- /dev/null +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginBlockListener.java @@ -0,0 +1,19 @@ +package cc.co.evenprime.bukkit.nocheat; + +import org.bukkit.event.block.BlockListener; +import org.bukkit.event.block.BlockPlaceEvent; + +public class NoCheatPluginBlockListener extends BlockListener { + + + public NoCheatPluginBlockListener() { + + } + + @Override + public void onBlockPlace(BlockPlaceEvent event) { + + if(!event.isCancelled() && NoCheatConfiguration.speedhackCheckActive) + BlockPlacingCheck.check(event); + } +} diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java new file mode 100644 index 00000000..9aa499b8 --- /dev/null +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginData.java @@ -0,0 +1,26 @@ +package cc.co.evenprime.bukkit.nocheat; + +import org.bukkit.Location; + +/** + * Storage for data persistence between events + * + */ +public class NoCheatPluginData { + + /** + * Don't rely on any of these yet, they are likely going to + * change their name/functionality + */ + int phase = 0; // current jumpingPhase + long lastSpeedHackCheck = System.currentTimeMillis(); // timestamp of last check for speedhacks + int eventsSinceLastSpeedHackCheck = 0; // used to identify speedhacks + int ignoreNextXEvents = 0; + + int minorViolationsInARow = 0; + int normalViolationsInARow = 0; + int heavyViolationsInARow = 0; + Location movingSetBackPoint = null; + + NoCheatPluginData() { } +} \ No newline at end of file diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java index 197878d4..fd703381 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginPlayerListener.java @@ -1,12 +1,8 @@ package cc.co.evenprime.bukkit.nocheat; -import java.util.HashMap; -import java.util.Map; -import org.bukkit.Location; import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerEvent; import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerMoveEvent; @@ -18,47 +14,18 @@ import org.bukkit.event.player.PlayerMoveEvent; public class NoCheatPluginPlayerListener extends PlayerListener { - /** - * Storage for data persistence between events - * - */ - public class NoCheatPluginData { - - /** - * Don't rely on any of these yet, they are likely going to - * change their name/functionality - */ - int phase = 0; // current jumpingPhase - long lastSpeedHackCheck = System.currentTimeMillis(); // timestamp of last check for speedhacks - int eventsSinceLastSpeedHackCheck = 0; // used to identify speedhacks - int ignoreNextXEvents = 0; - - int minorViolationsInARow = 0; - int normalViolationsInARow = 0; - int heavyViolationsInARow = 0; - Location movingSetBackPoint = null; - - private NoCheatPluginData() { } - } - - private final NoCheatPlugin plugin; - - // Store data between Events - private static Map playerData = new HashMap(); - - - public NoCheatPluginPlayerListener(NoCheatPlugin instance) { - plugin = instance; - } + + + public NoCheatPluginPlayerListener() { } @Override public void onPlayerQuit(PlayerEvent event) { - playerData.remove(event.getPlayer()); + NoCheatPlugin.playerData.remove(event.getPlayer()); } public void ingoreNextXEvents(Entity player, int count) { - NoCheatPluginData data = playerData.get(player); + NoCheatPluginData data = NoCheatPlugin.playerData.get(player); if(data != null) { data.ignoreNextXEvents = count; } @@ -68,14 +35,8 @@ public class NoCheatPluginPlayerListener extends PlayerListener { public void onPlayerMove(PlayerMoveEvent event) { // Get the player-specific data - NoCheatPluginData data = null; - - if((data = playerData.get(event.getPlayer())) == null ) { - // If we have no data for the player, create some - data = new NoCheatPluginData(); - playerData.put(event.getPlayer(), data); - } - + NoCheatPluginData data = NoCheatPlugin.getPlayerData(event.getPlayer()); + if(data.ignoreNextXEvents > 0 ) { data.ignoreNextXEvents--; return; diff --git a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java index 450ea4f1..b3fc1823 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java +++ b/src/cc/co/evenprime/bukkit/nocheat/NoCheatPluginVehicleListener.java @@ -12,11 +12,9 @@ import org.bukkit.event.vehicle.VehicleListener; public class NoCheatPluginVehicleListener extends VehicleListener { - private final NoCheatPlugin plugin; private final NoCheatPluginPlayerListener playerListener; - public NoCheatPluginVehicleListener(NoCheatPlugin plugin, NoCheatPluginPlayerListener playerListener) { - this.plugin = plugin; + public NoCheatPluginVehicleListener(NoCheatPluginPlayerListener playerListener) { this.playerListener = playerListener; } diff --git a/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java b/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java index 760cd8bb..2beb73c5 100644 --- a/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java +++ b/src/cc/co/evenprime/bukkit/nocheat/SpeedhackCheck.java @@ -2,7 +2,6 @@ package cc.co.evenprime.bukkit.nocheat; import org.bukkit.event.player.PlayerMoveEvent; -import cc.co.evenprime.bukkit.nocheat.NoCheatPluginPlayerListener.NoCheatPluginData; public class SpeedhackCheck {