mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-10-06 10:27:26 +02:00
Preparations for implementation of Custom Actions + better lag
resistance for the Moving-check in combination with serverside velocity changes for the player
This commit is contained in:
parent
4535efd2eb
commit
085cad8ee8
@ -3,7 +3,7 @@ name: NoCheatPlugin
|
||||
author: Evenprime
|
||||
|
||||
main: cc.co.evenprime.bukkit.nocheat.NoCheatPlugin
|
||||
version: 0.7.7a
|
||||
version: 0.7.7b
|
||||
|
||||
commands:
|
||||
nocheat:
|
||||
|
20
src/cc/co/evenprime/bukkit/nocheat/CustomAction.java
Normal file
20
src/cc/co/evenprime/bukkit/nocheat/CustomAction.java
Normal file
@ -0,0 +1,20 @@
|
||||
package cc.co.evenprime.bukkit.nocheat;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.Action;
|
||||
|
||||
public class CustomAction implements Action {
|
||||
|
||||
private final int id;
|
||||
private final String command;
|
||||
|
||||
public CustomAction(int id, String command) {
|
||||
this.id = id;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public void execute(Player player) {
|
||||
// TODO: add command execution
|
||||
}
|
||||
}
|
@ -4,12 +4,18 @@ import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.util.config.Configuration;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.Action;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
|
||||
|
||||
/**
|
||||
* Central location for everything that's described in the configuration file
|
||||
*
|
||||
@ -81,21 +87,21 @@ public class NoCheatConfiguration {
|
||||
plugin.speedhackCheck.limits[1] = c.getInt("speedhack.limits.med", plugin.speedhackCheck.limits[1]);
|
||||
plugin.speedhackCheck.limits[2] = c.getInt("speedhack.limits.high", plugin.speedhackCheck.limits[2]);
|
||||
|
||||
plugin.movingCheck.actions[0] = c.getString("moving.action.low", plugin.movingCheck.actions[0]);
|
||||
plugin.movingCheck.actions[1] = c.getString("moving.action.med", plugin.movingCheck.actions[1]);
|
||||
plugin.movingCheck.actions[2] = c.getString("moving.action.high", plugin.movingCheck.actions[2]);
|
||||
plugin.movingCheck.actions[0] = stringToActions(c.getString("moving.action.low"), plugin.movingCheck.actions[0]);
|
||||
plugin.movingCheck.actions[1] = stringToActions(c.getString("moving.action.med"), plugin.movingCheck.actions[1]);
|
||||
plugin.movingCheck.actions[2] = stringToActions(c.getString("moving.action.high"), plugin.movingCheck.actions[2]);
|
||||
|
||||
plugin.speedhackCheck.actions[0] = c.getString("speedhack.action.low", plugin.speedhackCheck.actions[0]);
|
||||
plugin.speedhackCheck.actions[1] = c.getString("speedhack.action.med", plugin.speedhackCheck.actions[1]);
|
||||
plugin.speedhackCheck.actions[2] = c.getString("speedhack.action.high", plugin.speedhackCheck.actions[2]);
|
||||
plugin.speedhackCheck.actions[0] = stringToActions(c.getString("speedhack.action.low"), plugin.speedhackCheck.actions[0]);
|
||||
plugin.speedhackCheck.actions[1] = stringToActions(c.getString("speedhack.action.med"), plugin.speedhackCheck.actions[1]);
|
||||
plugin.speedhackCheck.actions[2] = stringToActions(c.getString("speedhack.action.high"), plugin.speedhackCheck.actions[2]);
|
||||
|
||||
plugin.airbuildCheck.limits[0] = c.getInt("airbuild.limits.low", plugin.airbuildCheck.limits[0]);
|
||||
plugin.airbuildCheck.limits[1] = c.getInt("airbuild.limits.med", plugin.airbuildCheck.limits[1]);
|
||||
plugin.airbuildCheck.limits[2] = c.getInt("airbuild.limits.high", plugin.airbuildCheck.limits[2]);
|
||||
|
||||
plugin.airbuildCheck.actions[0] = c.getString("airbuild.action.low", plugin.airbuildCheck.actions[0]);
|
||||
plugin.airbuildCheck.actions[1] = c.getString("airbuild.action.med", plugin.airbuildCheck.actions[1]);
|
||||
plugin.airbuildCheck.actions[2] = c.getString("airbuild.action.high", plugin.airbuildCheck.actions[2]);
|
||||
plugin.airbuildCheck.actions[0] = stringToActions(c.getString("airbuild.action.low"), plugin.airbuildCheck.actions[0]);
|
||||
plugin.airbuildCheck.actions[1] = stringToActions(c.getString("airbuild.action.med"), plugin.airbuildCheck.actions[1]);
|
||||
plugin.airbuildCheck.actions[2] = stringToActions(c.getString("airbuild.action.high"), plugin.airbuildCheck.actions[2]);
|
||||
|
||||
plugin.speedhackCheck.setActive(c.getBoolean("active.speedhack", plugin.speedhackCheck.isActive()));
|
||||
plugin.movingCheck.setActive(c.getBoolean("active.moving", plugin.movingCheck.isActive()));
|
||||
@ -103,6 +109,39 @@ public class NoCheatConfiguration {
|
||||
plugin.bedteleportCheck.setActive(c.getBoolean("active.bedteleport", plugin.bedteleportCheck.isActive()));
|
||||
}
|
||||
|
||||
private Action[] stringToActions(String string, Action[] actions) {
|
||||
|
||||
if(string == null) return actions;
|
||||
|
||||
List<Action> as = new LinkedList<Action>();
|
||||
String[] parts = string.split(" ");
|
||||
|
||||
for(String s : parts) {
|
||||
if(s.equals("loglow"))
|
||||
as.add(LogAction.logLow);
|
||||
else if(s.equals("logmed"))
|
||||
as.add(LogAction.logMed);
|
||||
else if(s.equals("loghigh"))
|
||||
as.add(LogAction.logHigh);
|
||||
else if(s.equals("deny"))
|
||||
as.add(CancelAction.deny);
|
||||
else if(s.equals("reset"))
|
||||
as.add(CancelAction.reset);
|
||||
else if(s.startsWith("custom")) {
|
||||
try {
|
||||
// TODO: Implement Custom Action
|
||||
//as.add(new CustomAction(Integer.parseInt(s.substring(6))));
|
||||
}
|
||||
catch(Exception e) {
|
||||
plugin.log(Level.WARNING, "Couldn't parse number of custom action '" + s + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return as.toArray(actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string into a log level
|
||||
* @param string
|
||||
|
@ -18,7 +18,9 @@ public class NoCheatData {
|
||||
public int movingJumpPhase = 0; // current jumpingPhase
|
||||
public int movingViolationsInARow[] = { 0, 0, 0 };
|
||||
public World movingLastWorld = null;
|
||||
public int movingHorizFreeMoves = 2;
|
||||
public double movingHorizFreedom = 0.0D;
|
||||
public double movingVertFreedom = 0.0D;
|
||||
public int movingVertFreedomCounter = 0;
|
||||
public Location movingSetBackPoint = null;
|
||||
public Location movingLocation = null;
|
||||
public Runnable movingRunnable = null;
|
||||
@ -37,5 +39,8 @@ public class NoCheatData {
|
||||
public Runnable airbuildRunnable = null;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public NoCheatData() { }
|
||||
}
|
@ -237,16 +237,16 @@ public class NoCheatPlugin extends JavaPlugin {
|
||||
* Log a violation message to all locations declared in the config file
|
||||
* @param message
|
||||
*/
|
||||
private void log(Level l, String message) {
|
||||
public void log(Level l, String message) {
|
||||
if(l != null && message != null) {
|
||||
message = "NC: " + message;
|
||||
logToChat(l, message);
|
||||
logToIRC(l, message);
|
||||
logToConsole(l, message);
|
||||
config.logger.log(l, message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void logToChat(Level l, String message) {
|
||||
if(config.chatLevel.intValue() <= l.intValue()) {
|
||||
for(Player player : getServer().getOnlinePlayers()) {
|
||||
@ -269,26 +269,6 @@ public class NoCheatPlugin extends JavaPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
public void logAction(String actions, String message) {
|
||||
if(actions == null) return;
|
||||
|
||||
// LOGGING IF NEEDED AND WHERE NEEDED
|
||||
Level logLevel = null;
|
||||
|
||||
if(actions.contains("loglow")) {
|
||||
logLevel = Level.INFO;
|
||||
}
|
||||
if(actions.contains("logmed")) {
|
||||
logLevel = Level.WARNING;
|
||||
}
|
||||
if(actions.contains("loghigh")) {
|
||||
logLevel = Level.SEVERE;
|
||||
}
|
||||
|
||||
if(logLevel != null) {
|
||||
log(logLevel, "NC: "+message);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasPermission(Player player, String permission) {
|
||||
|
||||
|
5
src/cc/co/evenprime/bukkit/nocheat/actions/Action.java
Normal file
5
src/cc/co/evenprime/bukkit/nocheat/actions/Action.java
Normal file
@ -0,0 +1,5 @@
|
||||
package cc.co.evenprime.bukkit.nocheat.actions;
|
||||
|
||||
public interface Action {
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package cc.co.evenprime.bukkit.nocheat.actions;
|
||||
|
||||
public class CancelAction implements Action {
|
||||
|
||||
public static final CancelAction deny = new CancelAction();
|
||||
public static final CancelAction reset = new CancelAction();
|
||||
|
||||
private CancelAction() { }
|
||||
}
|
28
src/cc/co/evenprime/bukkit/nocheat/actions/LogAction.java
Normal file
28
src/cc/co/evenprime/bukkit/nocheat/actions/LogAction.java
Normal file
@ -0,0 +1,28 @@
|
||||
package cc.co.evenprime.bukkit.nocheat.actions;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class LogAction implements Action {
|
||||
|
||||
private final int index;
|
||||
private final Level level;
|
||||
|
||||
public final static LogAction logLow = new LogAction(0, Level.INFO);
|
||||
public final static LogAction logMed = new LogAction(1, Level.WARNING);
|
||||
public final static LogAction logHigh = new LogAction(2, Level.SEVERE);
|
||||
|
||||
public final static LogAction log[] = { logLow, logMed, logHigh };
|
||||
|
||||
private LogAction(int index, Level level) {
|
||||
this.index = index;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public Level getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
}
|
@ -7,6 +7,9 @@ import org.bukkit.event.block.BlockPlaceEvent;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.Action;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
|
||||
|
||||
|
||||
/**
|
||||
@ -18,7 +21,10 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
||||
public class AirbuildCheck extends Check {
|
||||
|
||||
// How should airbuild violations be treated?
|
||||
public final String actions[] = { "loglow deny", "logmed deny", "loghigh deny" };
|
||||
public final Action actions[][] = {
|
||||
{ LogAction.logLow, CancelAction.deny },
|
||||
{ LogAction.logMed, CancelAction.deny },
|
||||
{ LogAction.logHigh, CancelAction.deny } };
|
||||
|
||||
public final int limits[] = { 1, 3, 10 };
|
||||
|
||||
@ -71,17 +77,15 @@ public class AirbuildCheck extends Check {
|
||||
}
|
||||
}
|
||||
|
||||
private void action(String action, BlockPlaceEvent event, boolean log) {
|
||||
private void action(Action actions[], BlockPlaceEvent event, boolean log) {
|
||||
|
||||
// LOG IF NEEDED
|
||||
if(log && action.contains("log")) {
|
||||
Location l = event.getBlockPlaced().getLocation();
|
||||
plugin.logAction(action, "Airbuild violation: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() +"," + l.getBlockZ());
|
||||
}
|
||||
|
||||
// DENY IF NEEDED
|
||||
if(action.contains("deny")) {
|
||||
event.setCancelled(true);
|
||||
for(Action a : actions) {
|
||||
if(log && a instanceof LogAction) {
|
||||
final Location l = event.getBlockPlaced().getLocation();
|
||||
plugin.log(((LogAction)a).getLevel(), "Airbuild: "+event.getPlayer().getName()+" tried to place block " + event.getBlockPlaced().getType() + " in the air at " + l.getBlockX() + "," + l.getBlockY() +"," + l.getBlockZ());
|
||||
}
|
||||
else if(a instanceof CancelAction)
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +94,7 @@ public class AirbuildCheck extends Check {
|
||||
// Give a summary according to the highest violation level we encountered in that second
|
||||
for(int i = limits.length-1; i >= 0; i--) {
|
||||
if(data.airbuildPerSecond >= limits[i]) {
|
||||
plugin.logAction(actions[i], "Airbuild violation summary: " +player.getName() + " total events per second: " + data.airbuildPerSecond);
|
||||
plugin.log(LogAction.log[i].getLevel(), "Airbuild summary: " +player.getName() + " total violations per second: " + data.airbuildPerSecond);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,9 @@ import org.bukkit.util.Vector;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.Action;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
|
||||
|
||||
/**
|
||||
* Check if the player should be allowed to make that move, e.g. is he allowed to jump here or move that far in one step
|
||||
@ -34,13 +37,16 @@ public class MovingCheck extends Check {
|
||||
|
||||
// Limits
|
||||
public final double moveLimits[] = { 0.0D, 0.5D, 2.0D };
|
||||
|
||||
|
||||
public final double heightLimits[] = { 0.0D, 0.5D, 2.0D };
|
||||
|
||||
|
||||
public int ticksBeforeSummary = 100;
|
||||
|
||||
// How should moving violations be treated?
|
||||
public final String actions[] = { "loglow reset", "logmed reset", "loghigh reset" };
|
||||
public final Action actions[][] = {
|
||||
{ LogAction.logLow, CancelAction.reset },
|
||||
{ LogAction.logMed, CancelAction.reset },
|
||||
{ LogAction.logHigh, CancelAction.reset } };
|
||||
|
||||
private static final double magic = 0.30000001192092896D;
|
||||
private static final double magic2 = 0.69999998807907103D;
|
||||
@ -155,11 +161,11 @@ public class MovingCheck extends Check {
|
||||
|
||||
// Get the two locations of the event
|
||||
final Location to = event.getTo();
|
||||
|
||||
|
||||
// WORKAROUND for changed PLAYER_MOVE logic
|
||||
final Location from = data.movingTeleportTo == null ? event.getFrom() : data.movingTeleportTo;
|
||||
data.movingTeleportTo = null;
|
||||
|
||||
|
||||
// Notice to myself: How world changes with e.g. command /world work:
|
||||
// 1. TeleportEvent from the players current position to another position in the _same_ world
|
||||
// 2. MoveEvent(s) (yes, multiple events can be triggered) from that position in the _new_ world
|
||||
@ -168,17 +174,15 @@ public class MovingCheck extends Check {
|
||||
|
||||
// I've no real way to get informed about a world change, therefore I have to
|
||||
// store the "lastWorld" and compare it to the world of the next event
|
||||
// Fun fact: Move event locations always have the same world in from/to, therefore
|
||||
// it doesn't matter which one I use
|
||||
if(data.movingLastWorld != from.getWorld()) {
|
||||
if(data.movingLastWorld != to.getWorld()) {
|
||||
|
||||
data.movingLastWorld = from.getWorld();
|
||||
data.movingLastWorld = to.getWorld();
|
||||
// "Forget" previous setback points
|
||||
data.movingSetBackPoint = null;
|
||||
data.speedhackSetBackPoint = null;
|
||||
|
||||
// Store the destination that this move goes to for later use
|
||||
data.movingLocation = to;
|
||||
data.movingLocation = to.clone();
|
||||
|
||||
// the world changed since our last check, therefore I can't check anything
|
||||
// for this event (reliably)
|
||||
@ -200,47 +204,46 @@ public class MovingCheck extends Check {
|
||||
data.speedhackSetBackPoint = null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The actual movingCheck starts here
|
||||
|
||||
|
||||
|
||||
// First check the distance the player has moved horizontally
|
||||
double xDistance = from.getX()-to.getX();
|
||||
double zDistance = from.getZ()-to.getZ();
|
||||
double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance)) - 0.6D ;
|
||||
|
||||
// Give additional movement based on velocity (not too precise yet, but still better than false positives)
|
||||
Vector v = event.getPlayer().getVelocity();
|
||||
combined -= Math.abs(v.getX()*2);
|
||||
combined -= Math.abs(v.getZ()*2);
|
||||
|
||||
|
||||
// If the target is a bed and distance not too big, allow it
|
||||
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && xDistance < 8.0D && zDistance < 8.0D) {
|
||||
return; // players are allowed to "teleport" into a bed over "short" distances
|
||||
}
|
||||
|
||||
int vl = -1;
|
||||
// Calculate the horizontal distance
|
||||
double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance)) - 0.6D ;
|
||||
|
||||
// Give additional movement based on velocity (not too precise, but still better than false positives)
|
||||
Vector v = event.getPlayer().getVelocity();
|
||||
|
||||
// Compare the velocity vector to the existing movement freedom that we've from previous events
|
||||
double tmp = Math.abs(v.getX()*5D) + Math.abs(v.getZ()*5D);
|
||||
data.movingHorizFreedom = tmp > data.movingHorizFreedom * 0.9D ? tmp : data.movingHorizFreedom * 0.9D;
|
||||
|
||||
// subtract the additional freedom
|
||||
combined -= data.movingHorizFreedom;
|
||||
|
||||
// Violation level
|
||||
int vl1 = -1;
|
||||
|
||||
// How far are we off?
|
||||
if(combined > moveLimits[2]) {
|
||||
vl = max(vl, 2);
|
||||
vl1 = max(vl1, 2);
|
||||
}
|
||||
else if(combined > moveLimits[1]) {
|
||||
vl = max(vl, 1);
|
||||
vl1 = max(vl1, 1);
|
||||
}
|
||||
else if(combined > moveLimits[0]) {
|
||||
if(data.movingHorizFreeMoves > 0) {
|
||||
data.movingHorizFreeMoves--;
|
||||
}
|
||||
else vl = max(vl, 0);
|
||||
}
|
||||
else{
|
||||
data.movingHorizFreeMoves = 2;
|
||||
vl1 = max(vl1, 0);
|
||||
}
|
||||
|
||||
|
||||
// pre-calculate boundary values that are needed multiple times in the following checks
|
||||
// the array each contains [lowerX, higherX, Y, lowerZ, higherZ]
|
||||
int fromValues[] = {lowerBorder(from.getX()), upperBorder(from.getX()), (int)Math.floor(from.getY()+0.5D), lowerBorder(from.getZ()),upperBorder(from.getZ()) };
|
||||
@ -250,24 +253,53 @@ public class MovingCheck extends Check {
|
||||
final boolean onGroundFrom = playerIsOnGround(from.getWorld(), fromValues, from);
|
||||
final boolean onGroundTo = playerIsOnGround(to.getWorld(), toValues, to);
|
||||
|
||||
// Ignore events if the player has positive y-Velocity
|
||||
if(event.getPlayer().getVelocity().getY() > 0.0D) {
|
||||
data.movingSetBackPoint = from.clone();
|
||||
data.movingJumpPhase = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Handle 4 distinct cases: Walk, Jump, Land, Fly
|
||||
|
||||
int vl2 = -1;
|
||||
|
||||
// A halfway lag-resistant method of allowing vertical acceleration without allowing blatant cheating
|
||||
|
||||
// FACT: Minecraft server sends player "velocity" to the client and lets the client calculate the movement
|
||||
// PROBLEM: There may be an arbitrary amount of other move events between the server sending the data
|
||||
// and the client accepting it/reacting to it. The server can't know when the client starts to
|
||||
// consider the sent "velocity" in its movement.
|
||||
// SOLUTION: Give the client at least 10 events after sending "velocity" to actually use the velocity for
|
||||
// its movement, plus additional events if the "velocity" was big and can cause longer flights
|
||||
|
||||
// The server sent the player a "velocity" a short time ago
|
||||
if(v.getY() > 0.0D) {
|
||||
if(data.movingVertFreedomCounter < 10)
|
||||
data.movingVertFreedomCounter = 10;
|
||||
|
||||
// Be generous with the height limit for the client
|
||||
data.movingVertFreedom += v.getY()*3D;
|
||||
|
||||
// Set a top limit for how many events a client has to "consume" the sent velocity
|
||||
if(data.movingVertFreedomCounter < 30)
|
||||
data.movingVertFreedomCounter++;
|
||||
}
|
||||
// If the server no longer has a positive velocity, start consuming the event counter for this client
|
||||
else if(data.movingVertFreedomCounter > 0) {
|
||||
data.movingVertFreedomCounter--;
|
||||
}
|
||||
|
||||
// If the event counter has been consumed, remove the vertical movement limit increase
|
||||
if(data.movingVertFreedomCounter <= 0) {
|
||||
data.movingVertFreedom = 0.0D;
|
||||
}
|
||||
|
||||
double limit = data.movingVertFreedom;
|
||||
|
||||
// Walk
|
||||
if(onGroundFrom && onGroundTo)
|
||||
{
|
||||
double limit = jumpHeight;
|
||||
limit += jumpHeight;
|
||||
double distance = to.getY() - from.getY();
|
||||
|
||||
vl = max(vl, heightLimitCheck(limit, distance));
|
||||
vl2 = heightLimitCheck(limit, distance);
|
||||
|
||||
if(vl < 0)
|
||||
if(vl1 < 0 && vl2 < 0)
|
||||
{
|
||||
// reset jumping
|
||||
data.movingJumpPhase = 0;
|
||||
@ -277,13 +309,13 @@ public class MovingCheck extends Check {
|
||||
// Jump
|
||||
else if(onGroundFrom && !onGroundTo)
|
||||
{
|
||||
double limit = jumpHeight;
|
||||
limit += jumpHeight;
|
||||
double distance = to.getY() - from.getY();
|
||||
|
||||
// Check if player isn't jumping too high
|
||||
vl = max(vl, heightLimitCheck(limit, distance));
|
||||
|
||||
if(vl < 0) {
|
||||
// Check if player isn't jumping too high
|
||||
vl2 = heightLimitCheck(limit, distance);
|
||||
|
||||
if(vl1 < 0 && vl2 < 0) {
|
||||
// Setup next phase of the jump
|
||||
data.movingJumpPhase = 1;
|
||||
data.movingSetBackPoint = from.clone();
|
||||
@ -294,18 +326,16 @@ public class MovingCheck extends Check {
|
||||
{
|
||||
Location l = data.movingSetBackPoint == null ? from : data.movingSetBackPoint;
|
||||
|
||||
double limit;
|
||||
|
||||
if(data.movingJumpPhase > jumpingLimit)
|
||||
limit = jumpHeight + stepHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
|
||||
else limit = jumpHeight;
|
||||
limit += jumpHeight + stepHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
|
||||
else limit += jumpHeight;
|
||||
|
||||
double distance = to.getY() - l.getY();
|
||||
|
||||
// Check if player isn't jumping too high
|
||||
vl = max(vl, heightLimitCheck(limit, distance));
|
||||
vl2 = heightLimitCheck(limit, distance);
|
||||
|
||||
if(vl < 0) {
|
||||
if(vl1 < 0 && vl2 < 0) {
|
||||
data.movingJumpPhase = 0; // He is on ground now, so reset the jump
|
||||
data.movingSetBackPoint = to.clone();
|
||||
}
|
||||
@ -314,18 +344,16 @@ public class MovingCheck extends Check {
|
||||
else {
|
||||
Location l = data.movingSetBackPoint == null ? from : data.movingSetBackPoint;
|
||||
|
||||
double limit;
|
||||
|
||||
if(data.movingJumpPhase > jumpingLimit)
|
||||
limit = jumpHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
|
||||
else limit = jumpHeight;
|
||||
|
||||
limit += jumpHeight - (data.movingJumpPhase-jumpingLimit) * 0.2D;
|
||||
else limit += jumpHeight;
|
||||
|
||||
double distance = to.getY() - l.getY();
|
||||
|
||||
// Check if player isn't jumping too high
|
||||
vl = max(vl, heightLimitCheck(limit, distance));
|
||||
vl2 = heightLimitCheck(limit, distance);
|
||||
|
||||
if(vl < 0) {
|
||||
if(vl1 < 0 && vl2 < 0) {
|
||||
data.movingJumpPhase++; // Enter next phase of the flight
|
||||
// Setback point stays the same. If we don't have one, take the "from" location as a setback point for now
|
||||
if(data.movingSetBackPoint == null) {
|
||||
@ -334,6 +362,8 @@ public class MovingCheck extends Check {
|
||||
}
|
||||
}
|
||||
|
||||
int vl = max(vl1, vl2);
|
||||
|
||||
if(vl >= 0) {
|
||||
final Player p = event.getPlayer();
|
||||
final NoCheatData d = data;
|
||||
@ -359,21 +389,19 @@ public class MovingCheck extends Check {
|
||||
data.movingSetBackPoint = event.getFrom().clone();
|
||||
}
|
||||
|
||||
String action = null;
|
||||
Action action[] = null;
|
||||
boolean log = true;
|
||||
|
||||
// Find out with what actions to treat the violation(s)
|
||||
if(vl >= 0) {
|
||||
if(data.movingViolationsInARow[vl] > 0) log = false; // only log the first violation of that level
|
||||
data.movingViolationsInARow[vl]++;
|
||||
action = actions[vl];
|
||||
}
|
||||
if(data.movingViolationsInARow[vl] > 0) log = false; // only log the first violation of that level
|
||||
data.movingViolationsInARow[vl]++;
|
||||
action = actions[vl];
|
||||
|
||||
action(event, event.getPlayer(), from, to, action, log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void teleported(PlayerMoveEvent event) {
|
||||
NoCheatData data = plugin.getPlayerData(event.getPlayer());
|
||||
|
||||
@ -390,8 +418,7 @@ public class MovingCheck extends Check {
|
||||
data.movingJumpPhase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// WORKAROUND for changed PLAYER_MOVE logic
|
||||
data.movingTeleportTo = event.getTo();
|
||||
}
|
||||
@ -399,41 +426,43 @@ public class MovingCheck extends Check {
|
||||
/**
|
||||
* Perform actions that were specified by the admin
|
||||
* @param event
|
||||
* @param actions
|
||||
* @param action
|
||||
*/
|
||||
private void action(PlayerMoveEvent event, Player player, Location from, Location to, String actions, boolean log) {
|
||||
private void action(PlayerMoveEvent event, Player player, Location from, Location to, Action[] actions, boolean log) {
|
||||
|
||||
if(actions == null) return;
|
||||
// LOGGING IF NEEDED
|
||||
if(log && actions.contains("log")) {
|
||||
plugin.logAction(actions, "Moving violation: "+player.getName()+" from " + String.format("%s (%.5f, %.5f, %.5f) to %s (%.5f, %.5f, %.5f)", from.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getWorld().getName(), to.getX(), to.getY(), to.getZ()));
|
||||
}
|
||||
|
||||
// RESET IF NEEDED
|
||||
if(actions.contains("reset")) {
|
||||
resetPlayer(event, from);
|
||||
for(Action a : actions) {
|
||||
if(a instanceof LogAction)
|
||||
plugin.log(((LogAction)a).getLevel(), "Moving violation: "+player.getName()+" from " + String.format("%s (%.5f, %.5f, %.5f) to %s (%.5f, %.5f, %.5f)", from.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getWorld().getName(), to.getX(), to.getY(), to.getZ()));
|
||||
else if(a.equals(CancelAction.reset))
|
||||
resetPlayer(event, from);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void summary(Player p, NoCheatData data) {
|
||||
String action;
|
||||
// Give a summary (to the highest violation level that occured)
|
||||
if(data.movingViolationsInARow[2] > 0) action = actions[2];
|
||||
else if(data.movingViolationsInARow[1] > 0) action = actions[1];
|
||||
else if(data.movingViolationsInARow[0] > 0) action = actions[0];
|
||||
else action = "";
|
||||
|
||||
plugin.logAction(action, "Moving summary of last ~5 seconds: "+p.getName() + " total Violations: ("+ data.movingViolationsInARow[0] + "," + data.movingViolationsInARow[1] + "," + data.movingViolationsInARow[2] + ")");
|
||||
|
||||
data.movingViolationsInARow[2] = 0;
|
||||
data.movingViolationsInARow[1] = 0;
|
||||
data.movingViolationsInARow[0] = 0;
|
||||
LogAction log = null;
|
||||
|
||||
String logString = "Moving summary of last ~" + (ticksBeforeSummary/20) + " seconds: "+p.getName() + " total Violations: ("+ data.movingViolationsInARow[0] + "," + data.movingViolationsInARow[1] + "," + data.movingViolationsInARow[2] + ")";
|
||||
// Find out the biggest applicable log level
|
||||
for(int i = 0; i < data.movingViolationsInARow.length; i++) {
|
||||
if(data.movingViolationsInARow[i] > 0)
|
||||
for(Action a : actions[i])
|
||||
if(a instanceof LogAction)
|
||||
if(log == null || ((LogAction)a).getIndex() > log.getIndex())
|
||||
log = (LogAction)a;
|
||||
data.movingViolationsInARow[i] = 0;
|
||||
}
|
||||
|
||||
if(log != null)
|
||||
plugin.log(log.getLevel(), logString);
|
||||
}
|
||||
|
||||
|
||||
private int heightLimitCheck(double limit, double value) {
|
||||
|
||||
|
||||
double offset = value - limit;
|
||||
|
||||
|
||||
for(int i = heightLimits.length - 1; i >= 0; i--) {
|
||||
if(offset > heightLimits[i]) {
|
||||
return i;
|
||||
@ -442,7 +471,7 @@ public class MovingCheck extends Check {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
private static int max(int a, int b) {
|
||||
if(a > b) {
|
||||
return a;
|
||||
@ -464,6 +493,7 @@ public class MovingCheck extends Check {
|
||||
// still have to allow the player some freedom with vertical movement due
|
||||
// to lost vertical momentum to prevent him from getting stuck
|
||||
data.movingJumpPhase = 0;
|
||||
data.movingVertFreedom = 0.0D;
|
||||
|
||||
Location l = data.movingSetBackPoint;
|
||||
|
||||
|
@ -5,6 +5,9 @@ import org.bukkit.event.player.PlayerMoveEvent;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatPlugin;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.Action;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.CancelAction;
|
||||
import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
|
||||
|
||||
/**
|
||||
* Log if a player sends to many move events in a specific time frame, usually the result of tinkering with the system clock
|
||||
@ -26,7 +29,10 @@ public class SpeedhackCheck extends Check {
|
||||
public int limits[] = { 30, 45, 60 };
|
||||
|
||||
// How should speedhack violations be treated?
|
||||
public String actions[] = { "loglow reset", "logmed reset", "loghigh reset" };
|
||||
public Action actions[][] = {
|
||||
{ LogAction.logLow, CancelAction.reset },
|
||||
{ LogAction.logMed, CancelAction.reset },
|
||||
{ LogAction.logHigh, CancelAction.reset } };
|
||||
|
||||
public void check(PlayerMoveEvent event) {
|
||||
|
||||
@ -54,7 +60,7 @@ public class SpeedhackCheck extends Check {
|
||||
if(time > interval + data.speedhackLastCheck ) {
|
||||
// Yes
|
||||
// TODO: Needs some better handling for server lag
|
||||
String action = null;
|
||||
Action action[] = null;
|
||||
|
||||
int low = (int)((limits[0] * (time - data.speedhackLastCheck)) / interval);
|
||||
int med = (int)((limits[1] * (time - data.speedhackLastCheck)) / interval);
|
||||
@ -90,16 +96,15 @@ public class SpeedhackCheck extends Check {
|
||||
data.speedhackEventsSinceLastCheck++;
|
||||
}
|
||||
|
||||
private void action(String actions, PlayerMoveEvent event, NoCheatData data) {
|
||||
private void action(Action actions[], PlayerMoveEvent event, NoCheatData data) {
|
||||
|
||||
if(actions == null) return;
|
||||
// LOGGING IF NEEDED
|
||||
if(actions.contains("log")) {
|
||||
plugin.logAction(actions, event.getPlayer().getName()+" sent "+ data.speedhackEventsSinceLastCheck + " move events, but only "+limits[0]+ " were allowed. Speedhack?");
|
||||
}
|
||||
// RESET IF NEEDED
|
||||
if(actions.contains("reset")) {
|
||||
resetPlayer(event, data);
|
||||
|
||||
for(Action a : actions) {
|
||||
if(a instanceof LogAction)
|
||||
plugin.log(((LogAction)a).getLevel(), event.getPlayer().getName()+" sent "+ data.speedhackEventsSinceLastCheck + " move events, but only "+limits[0]+ " were allowed. Speedhack?");
|
||||
else if(a.equals(CancelAction.reset))
|
||||
resetPlayer(event, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user