mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-12-29 03:48:50 +01:00
Updated for CB #1046. Use new PlayerVelocity event + adapt to new
player move events + use new method to find out if "allow-flight" was set.
This commit is contained in:
parent
91c77a1aab
commit
33e9c46716
@ -3,7 +3,7 @@ name: NoCheat
|
||||
author: Evenprime
|
||||
|
||||
main: cc.co.evenprime.bukkit.nocheat.NoCheat
|
||||
version: 1.11d
|
||||
version: 1.12
|
||||
|
||||
softdepend: [ Permissions, CraftIRC ]
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
package cc.co.evenprime.bukkit.nocheat;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -66,7 +64,6 @@ public class NoCheat extends JavaPlugin {
|
||||
|
||||
// CraftIRC, if available
|
||||
private CraftIRC irc;
|
||||
private boolean allowFlightSet;
|
||||
|
||||
private Level chatLevel;
|
||||
private Level ircLevel;
|
||||
@ -85,7 +82,7 @@ public class NoCheat extends JavaPlugin {
|
||||
|
||||
public String[] getMessagesOfTheDay() {
|
||||
|
||||
return new String[] {"NoCheat now supports the new Bukkit-Permission system. You can activate it in the config file.", "There will be a change in the near future to how movement in CraftBukkit works, which will break NoCheats moving-check(s) completely, causing tons of false positives. Be careful if you tend to run bleeding edge builds of CraftBukkit.", "This version of NoCheat was written for CraftBukkit RB 1000, but may still work for some older or newer versions.", "You can find detailed information about all configuration options of NoCheat in the file \"descriptions.txt\" in your \"plugins/NoCheat\" folder", "You can deactivate these Messages in the config file, if they annoy you."};
|
||||
return new String[] {"This version of NoCheat was written for CraftBukkit CB #1046, it will NOT work on older versions.", "NoCheat supports the new SuperPerms system. You can activate it in the config file.", "You can find detailed information about all configuration options of NoCheat in the file \"descriptions.txt\" in your \"plugins/NoCheat\" folder", "You can deactivate these Messages in the config file, if they annoy you."};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -153,7 +150,7 @@ public class NoCheat extends JavaPlugin {
|
||||
// just for convenience
|
||||
checks = new Check[] {movingCheck, speedhackCheck, airbuildCheck, bogusitemsCheck, nukeCheck};
|
||||
|
||||
if(!allowFlightSet && movingCheck.isActive()) {
|
||||
if(!this.getServer().getAllowFlight() && movingCheck.isActive()) {
|
||||
Logger.getLogger("Minecraft").warning("[NoCheat] you have set \"allow-flight=false\" in your server.properties file. That builtin anti-flying-mechanism will likely conflict with this plugin. Please consider deactivating it by setting it to \"true\"");
|
||||
}
|
||||
|
||||
@ -385,24 +382,6 @@ public class NoCheat extends JavaPlugin {
|
||||
e.printStackTrace();
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new FileReader(new File("server.properties")));
|
||||
|
||||
allowFlightSet = true;
|
||||
String s = null;
|
||||
|
||||
while((s = reader.readLine()) != null) {
|
||||
if(s.startsWith("allow-flight=false")) {
|
||||
allowFlightSet = false;
|
||||
}
|
||||
|
||||
}
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
// ignore errors
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getActiveChecksAsString() {
|
||||
|
@ -88,18 +88,12 @@ public class FlyingCheck {
|
||||
// its movement, plus additional events if the "velocity" was big and can cause longer flights
|
||||
|
||||
// The server sent the player a "velocity" packet a short time ago
|
||||
if(data.maxYVelocity > 0.0D) {
|
||||
|
||||
data.vertFreedomCounter = 30;
|
||||
|
||||
// Be generous with the height limit for the client
|
||||
data.vertFreedom += data.maxYVelocity*2D;
|
||||
data.maxYVelocity = 0.0D;
|
||||
}
|
||||
|
||||
// consume a counter for this client
|
||||
if(data.vertFreedomCounter > 0) {
|
||||
data.vertFreedomCounter--;
|
||||
data.vertFreedom += data.maxYVelocity*2D;
|
||||
data.maxYVelocity *= 0.90D;
|
||||
}
|
||||
|
||||
final double limit = data.vertFreedom;
|
||||
|
@ -23,7 +23,6 @@ import cc.co.evenprime.bukkit.nocheat.actions.LogAction;
|
||||
import cc.co.evenprime.bukkit.nocheat.config.NoCheatConfiguration;
|
||||
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||
import cc.co.evenprime.bukkit.nocheat.data.PermissionData;
|
||||
import cc.co.evenprime.bukkit.nocheat.listeners.MovingEntityListener;
|
||||
import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerListener;
|
||||
import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerMonitor;
|
||||
|
||||
@ -35,392 +34,390 @@ import cc.co.evenprime.bukkit.nocheat.listeners.MovingPlayerMonitor;
|
||||
*/
|
||||
public class MovingCheck extends Check {
|
||||
|
||||
public MovingCheck(NoCheat plugin, NoCheatConfiguration config) {
|
||||
super(plugin, "moving", PermissionData.PERMISSION_MOVING, config);
|
||||
|
||||
helper = new MovingEventHelper();
|
||||
flyingCheck = new FlyingCheck();
|
||||
runningCheck = new RunningCheck();
|
||||
}
|
||||
public MovingCheck(NoCheat plugin, NoCheatConfiguration config) {
|
||||
super(plugin, "moving", PermissionData.PERMISSION_MOVING, config);
|
||||
|
||||
private int ticksBeforeSummary;
|
||||
helper = new MovingEventHelper();
|
||||
flyingCheck = new FlyingCheck();
|
||||
runningCheck = new RunningCheck();
|
||||
}
|
||||
|
||||
public long statisticElapsedTimeNano = 0;
|
||||
private int ticksBeforeSummary;
|
||||
|
||||
public boolean allowFlying;
|
||||
public boolean allowFakeSneak;
|
||||
public boolean allowFastSwim;
|
||||
public long statisticElapsedTimeNano = 0;
|
||||
|
||||
public double stepWidth;
|
||||
public double sneakWidth;
|
||||
public double swimWidth;
|
||||
|
||||
private boolean waterElevators;
|
||||
public boolean allowFlying;
|
||||
public boolean allowFakeSneak;
|
||||
public boolean allowFastSwim;
|
||||
|
||||
private String logMessage;
|
||||
private String summaryMessage;
|
||||
public double stepWidth;
|
||||
public double sneakWidth;
|
||||
public double swimWidth;
|
||||
|
||||
// How should moving violations be treated?
|
||||
private Action actions[][];
|
||||
private boolean waterElevators;
|
||||
|
||||
public long statisticTotalEvents = 1; // Prevent accidental division by 0 at some point
|
||||
private String logMessage;
|
||||
private String summaryMessage;
|
||||
|
||||
private boolean enforceTeleport;
|
||||
// How should moving violations be treated?
|
||||
private Action actions[][];
|
||||
|
||||
private final MovingEventHelper helper;
|
||||
private final FlyingCheck flyingCheck;
|
||||
private final RunningCheck runningCheck;
|
||||
public long statisticTotalEvents = 1; // Prevent accidental division by 0 at some point
|
||||
|
||||
/**
|
||||
* The actual check.
|
||||
* First find out if the event needs to be handled at all
|
||||
* Second check if the player moved too far horizontally
|
||||
* Third check if the player moved too high vertically
|
||||
* Fourth treat any occured violations as configured
|
||||
* @param event
|
||||
*/
|
||||
private boolean enforceTeleport;
|
||||
|
||||
public Location check(Player player, Location from, Location to,
|
||||
MovingData data) {
|
||||
|
||||
updateVelocity(player.getVelocity(), data);
|
||||
|
||||
Location newToLocation = null;
|
||||
|
||||
final long startTime = System.nanoTime();
|
||||
|
||||
/************* DECIDE WHICH CHECKS NEED TO BE RUN *************/
|
||||
final boolean flyCheck = !allowFlying && !plugin.hasPermission(player, PermissionData.PERMISSION_FLYING, checkOPs);
|
||||
final boolean runCheck = true;
|
||||
private final MovingEventHelper helper;
|
||||
private final FlyingCheck flyingCheck;
|
||||
private final RunningCheck runningCheck;
|
||||
|
||||
/***************** REFINE EVENT DATA FOR CHECKS ***************/
|
||||
/**
|
||||
* The actual check.
|
||||
* First find out if the event needs to be handled at all
|
||||
* Second check if the player moved too far horizontally
|
||||
* Third check if the player moved too high vertically
|
||||
* Fourth treat any occured violations as configured
|
||||
* @param event
|
||||
*/
|
||||
|
||||
if(flyCheck || runCheck) {
|
||||
|
||||
// In both cases it will be interesting to know the type of underground the player
|
||||
// is in or goes to
|
||||
final int fromType = helper.isLocationOnGround(from.getWorld(), from.getX(), from.getY(), from.getZ(), waterElevators);
|
||||
final int toType = helper.isLocationOnGround(to.getWorld(), to.getX(), to.getY(),to.getZ(), waterElevators);
|
||||
public Location check(Player player, Location from, Location to,
|
||||
MovingData data) {
|
||||
|
||||
final boolean fromOnGround = fromType != MovingEventHelper.NONSOLID;
|
||||
final boolean toOnGround = toType != MovingEventHelper.NONSOLID;
|
||||
Location newToLocation = null;
|
||||
|
||||
// Distribute data to checks in the form needed by the checks
|
||||
final long startTime = System.nanoTime();
|
||||
|
||||
/********************* EXECUTE THE CHECKS ********************/
|
||||
double result = 0.0D;
|
||||
/************* DECIDE WHICH CHECKS NEED TO BE RUN *************/
|
||||
final boolean flyCheck = !allowFlying && !plugin.hasPermission(player, PermissionData.PERMISSION_FLYING, checkOPs);
|
||||
final boolean runCheck = true;
|
||||
|
||||
if(flyCheck) {
|
||||
result += Math.max(0D, flyingCheck.check(player, from, fromOnGround, to, toOnGround, data));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If players are allowed to fly, there's no need to remember the last location on ground
|
||||
data.setBackPoint = from;
|
||||
}
|
||||
/***************** REFINE EVENT DATA FOR CHECKS ***************/
|
||||
|
||||
if(runCheck) {
|
||||
result += Math.max(0D, runningCheck.check(from, to,
|
||||
!allowFakeSneak && player.isSneaking(), !allowFastSwim && (fromType & toType & MovingEventHelper.LIQUID) > 0, data, this));
|
||||
}
|
||||
|
||||
/********* HANDLE/COMBINE THE RESULTS OF THE CHECKS ***********/
|
||||
if(flyCheck || runCheck) {
|
||||
|
||||
data.jumpPhase++;
|
||||
|
||||
if(fromOnGround) {
|
||||
// In both cases it will be interesting to know the type of underground the player
|
||||
// is in or goes to
|
||||
final int fromType = helper.isLocationOnGround(from.getWorld(), from.getX(), from.getY(), from.getZ(), waterElevators);
|
||||
final int toType = helper.isLocationOnGround(to.getWorld(), to.getX(), to.getY(),to.getZ(), waterElevators);
|
||||
|
||||
final boolean fromOnGround = fromType != MovingEventHelper.NONSOLID;
|
||||
final boolean toOnGround = toType != MovingEventHelper.NONSOLID;
|
||||
|
||||
// Distribute data to checks in the form needed by the checks
|
||||
|
||||
/********************* EXECUTE THE CHECKS ********************/
|
||||
double result = 0.0D;
|
||||
|
||||
if(flyCheck) {
|
||||
result += Math.max(0D, flyingCheck.check(player, from, fromOnGround, to, toOnGround, data));
|
||||
}
|
||||
else
|
||||
{
|
||||
// If players are allowed to fly, there's no need to remember the last location on ground
|
||||
data.setBackPoint = from;
|
||||
}
|
||||
|
||||
if(runCheck) {
|
||||
result += Math.max(0D, runningCheck.check(from, to,
|
||||
!allowFakeSneak && player.isSneaking(), !allowFastSwim && (fromType & toType & MovingEventHelper.LIQUID) > 0, data, this));
|
||||
}
|
||||
|
||||
/********* HANDLE/COMBINE THE RESULTS OF THE CHECKS ***********/
|
||||
|
||||
data.jumpPhase++;
|
||||
|
||||
if(fromOnGround) {
|
||||
data.setBackPoint = from;
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
else if(result <= 0 && toOnGround) {
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
|
||||
if(result > 0) {
|
||||
// Increment violation counter
|
||||
data.violationLevel += result;
|
||||
if(data.setBackPoint == null) data.setBackPoint = from;
|
||||
}
|
||||
|
||||
if(result > 0 && data.violationLevel > 1) {
|
||||
|
||||
setupSummaryTask(player, data);
|
||||
if(result > 0) {
|
||||
// Increment violation counter
|
||||
data.violationLevel += result;
|
||||
if(data.setBackPoint == null) data.setBackPoint = from;
|
||||
}
|
||||
|
||||
int level = limitCheck(data.violationLevel-1);
|
||||
|
||||
data.violationsInARow[level]++;
|
||||
if(result > 0 && data.violationLevel > 1) {
|
||||
|
||||
newToLocation = action(player, from, to, actions[level], data.violationsInARow[level], data, helper);
|
||||
}
|
||||
}
|
||||
|
||||
// Slowly reduce the level with each event
|
||||
data.violationLevel *= 0.97;
|
||||
data.horizFreedom *= 0.97;
|
||||
|
||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||
statisticTotalEvents++;
|
||||
|
||||
|
||||
return newToLocation;
|
||||
}
|
||||
setupSummaryTask(player, data);
|
||||
|
||||
/**
|
||||
* Various corner cases that would cause this check to fail or require special treatment
|
||||
* @param player
|
||||
* @param data
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public boolean shouldBeApplied(final Player player, final MovingData data, final Location from, final Location to) {
|
||||
int level = limitCheck(data.violationLevel-1);
|
||||
|
||||
if(player.isDead() || player.isInsideVehicle()) return false;
|
||||
data.violationsInARow[level]++;
|
||||
|
||||
if(data.wasTeleported) {
|
||||
// Remember this location
|
||||
data.teleportedTo = from.clone();
|
||||
data.wasTeleported = false;
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
newToLocation = action(player, from, to, actions[level], data.violationsInARow[level], data, helper);
|
||||
}
|
||||
}
|
||||
|
||||
if(data.teleportedTo != null && data.teleportedTo.getWorld().equals(from.getWorld())) {
|
||||
// As long as the from-Location doesn't change, the player didn't accept the teleport
|
||||
if(data.teleportedTo.distanceSquared(from) < 0.01D) {
|
||||
// Event after Teleport ignored
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// The player finally accepted the teleport with the previous event
|
||||
data.teleportedTo = null;
|
||||
}
|
||||
}
|
||||
// Slowly reduce the level with each event
|
||||
data.violationLevel *= 0.97;
|
||||
data.horizFreedom *= 0.97;
|
||||
|
||||
return true;
|
||||
}
|
||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||
statisticTotalEvents++;
|
||||
|
||||
|
||||
/**
|
||||
* Register a task with bukkit that will be run a short time from now, displaying how many
|
||||
* violations happened in that timeframe
|
||||
* @param p
|
||||
* @param data
|
||||
*/
|
||||
private void setupSummaryTask(final Player p, final MovingData data) {
|
||||
// Setup task to display summary later
|
||||
if(data.summaryTask == -1) {
|
||||
Runnable r = new Runnable() {
|
||||
return newToLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
if(data.highestLogLevel != null) {
|
||||
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.violationsInARow[0], data.violationsInARow[1],data.violationsInARow[2]);
|
||||
plugin.log(data.highestLogLevel, logString);
|
||||
|
||||
data.highestLogLevel = Level.ALL;
|
||||
}
|
||||
// deleting its own reference
|
||||
data.summaryTask = -1;
|
||||
/**
|
||||
* Various corner cases that would cause this check to fail or require special treatment
|
||||
* @param player
|
||||
* @param data
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public boolean shouldBeApplied(final Player player, final MovingData data, final Location from, final Location to) {
|
||||
|
||||
data.violationsInARow[0] = 0;
|
||||
data.violationsInARow[1] = 0;
|
||||
data.violationsInARow[2] = 0;
|
||||
}
|
||||
catch(Exception e) { }
|
||||
}
|
||||
};
|
||||
if(player.isDead() || player.isInsideVehicle()) return false;
|
||||
|
||||
// Give a summary in x ticks. 20 ticks ~ 1 second
|
||||
data.summaryTask = plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, r, ticksBeforeSummary);
|
||||
}
|
||||
}
|
||||
if(data.wasTeleported) {
|
||||
// Remember this location
|
||||
data.teleportedTo = from.clone();
|
||||
data.wasTeleported = false;
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this when a player got successfully teleported with the corresponding event to adjust stored
|
||||
* data to the new situation
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public void teleported(PlayerTeleportEvent event) {
|
||||
if(data.teleportedTo != null && data.teleportedTo.getWorld().equals(from.getWorld())) {
|
||||
// As long as the from-Location doesn't change, the player didn't accept the teleport
|
||||
if(data.teleportedTo.distanceSquared(from) < 0.01D) {
|
||||
// Event after Teleport ignored
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// The player finally accepted the teleport with the previous event
|
||||
data.teleportedTo = null;
|
||||
}
|
||||
}
|
||||
|
||||
MovingData data = plugin.getDataManager().getMovingData(event.getPlayer());
|
||||
|
||||
// We can enforce a teleport, if that flag is explicitly set (but I'd rather have other plugins
|
||||
// not arbitrarily cancel teleport events in the first place...
|
||||
if(data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) {
|
||||
event.setCancelled(false);
|
||||
data.teleportInitializedByMe = null;
|
||||
}
|
||||
|
||||
if(!event.isCancelled()) {
|
||||
data.wasTeleported = true;
|
||||
data.setBackPoint = event.getTo().clone();
|
||||
//data.lastLocation = event.getTo().clone();
|
||||
}
|
||||
|
||||
// reset anyway - if another plugin cancelled our teleport it's no use to try and be precise
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cached values for players velocity to be prepared to
|
||||
* give them additional movement freedom in their next move events
|
||||
* @param v
|
||||
* @param data
|
||||
*/
|
||||
public void updateVelocity(Vector v, MovingData data) {
|
||||
|
||||
// Compare the velocity vector to the existing movement freedom that we've from previous events
|
||||
double tmp = (Math.abs(v.getX()) + Math.abs(v.getZ())) * 3D;
|
||||
if(tmp > data.horizFreedom)
|
||||
data.horizFreedom = tmp;
|
||||
|
||||
if(v.getY() > data.maxYVelocity) {
|
||||
data.maxYVelocity = v.getY();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform actions that were specified in the config file
|
||||
* @param event
|
||||
* @param action
|
||||
* @return
|
||||
*/
|
||||
private Location action( Player player, Location from, Location to, Action[] actions, int violations, MovingData data, MovingEventHelper helper) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Location newToLocation = null;
|
||||
|
||||
if(actions == null) return newToLocation;
|
||||
boolean cancelled = false;
|
||||
/**
|
||||
* Register a task with bukkit that will be run a short time from now, displaying how many
|
||||
* violations happened in that timeframe
|
||||
* @param p
|
||||
* @param data
|
||||
*/
|
||||
private void setupSummaryTask(final Player p, final MovingData data) {
|
||||
// Setup task to display summary later
|
||||
if(data.summaryTask == -1) {
|
||||
Runnable r = new Runnable() {
|
||||
|
||||
for(Action a : actions) {
|
||||
if(a.firstAfter <= violations) {
|
||||
if(a.firstAfter == violations || a.repeat) {
|
||||
if(a instanceof LogAction) {
|
||||
// prepare log message if necessary
|
||||
String log = String.format(Locale.US, logMessage, player.getName(), from.getWorld().getName(), to.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ(), Math.abs(from.getX()-to.getX()),to.getY()-from.getY(), Math.abs(from.getZ()-to.getZ()));
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
plugin.log(((LogAction)a).level, log);
|
||||
try {
|
||||
if(data.highestLogLevel != null) {
|
||||
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.violationsInARow[0], data.violationsInARow[1],data.violationsInARow[2]);
|
||||
plugin.log(data.highestLogLevel, logString);
|
||||
|
||||
// Remember the highest log level we encountered to determine what level the summary log message should have
|
||||
if(data.highestLogLevel == null) data.highestLogLevel = Level.ALL;
|
||||
if(data.highestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.highestLogLevel = ((LogAction)a).level;
|
||||
}
|
||||
else if(!cancelled && a instanceof CancelAction) {
|
||||
// Make a modified copy of the setBackPoint to prevent other plugins from accidentally modifying it
|
||||
// and keep the current pitch and yaw (setbacks "feel" better that way). Plus try to adapt the Y-coord
|
||||
// to place the player close to ground
|
||||
data.highestLogLevel = Level.ALL;
|
||||
}
|
||||
// deleting its own reference
|
||||
data.summaryTask = -1;
|
||||
|
||||
double y = data.setBackPoint.getY();
|
||||
data.violationsInARow[0] = 0;
|
||||
data.violationsInARow[1] = 0;
|
||||
data.violationsInARow[2] = 0;
|
||||
}
|
||||
catch(Exception e) { }
|
||||
}
|
||||
};
|
||||
|
||||
// search for the first solid block up to 5 blocks below the setbackpoint and teleport the player there
|
||||
int i = 0;
|
||||
for(; i < 20; i++) {
|
||||
if(helper.isLocationOnGround(data.setBackPoint.getWorld(), data.setBackPoint.getX(), data.setBackPoint.getY() - 0.5*i, data.setBackPoint.getZ(), waterElevators) != MovingData.NONSOLID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
y -= 0.5*i;
|
||||
// Give a summary in x ticks. 20 ticks ~ 1 second
|
||||
data.summaryTask = plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, r, ticksBeforeSummary);
|
||||
}
|
||||
}
|
||||
|
||||
data.setBackPoint.setY(y);
|
||||
/**
|
||||
* Call this when a player got successfully teleported with the corresponding event to adjust stored
|
||||
* data to the new situation
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
public void teleported(PlayerTeleportEvent event) {
|
||||
|
||||
// Remember the location we send the player to, to identify teleports that were started by us
|
||||
data.teleportInitializedByMe = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), to.getYaw(), to.getPitch());
|
||||
MovingData data = plugin.getDataManager().getMovingData(event.getPlayer());
|
||||
|
||||
newToLocation = data.teleportInitializedByMe;
|
||||
// We can enforce a teleport, if that flag is explicitly set (but I'd rather have other plugins
|
||||
// not arbitrarily cancel teleport events in the first place...
|
||||
if(data.teleportInitializedByMe != null && event.isCancelled() && enforceTeleport && event.getTo().equals(data.teleportInitializedByMe)) {
|
||||
event.setCancelled(false);
|
||||
data.teleportInitializedByMe = null;
|
||||
}
|
||||
|
||||
cancelled = true; // just prevent us from treating more than one "cancel" action, which would make no sense
|
||||
}
|
||||
else if(a instanceof CustomAction)
|
||||
plugin.handleCustomAction((CustomAction)a, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newToLocation;
|
||||
}
|
||||
if(!event.isCancelled()) {
|
||||
data.wasTeleported = true;
|
||||
data.setBackPoint = event.getTo().clone();
|
||||
//data.lastLocation = event.getTo().clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a value against an array of sorted values to find out
|
||||
* where it fits in
|
||||
* @param value
|
||||
* @param limits
|
||||
* @return
|
||||
*/
|
||||
private static int limitCheck(final double value) {
|
||||
// reset anyway - if another plugin cancelled our teleport it's no use to try and be precise
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
|
||||
if(value > 0.0D) {
|
||||
if(value > 0.5D) {
|
||||
if(value > 2.0D)
|
||||
return 2;
|
||||
return 1; }
|
||||
return 0; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NoCheatConfiguration config) {
|
||||
/**
|
||||
* Update the cached values for players velocity to be prepared to
|
||||
* give them additional movement freedom in their next move events
|
||||
* @param v
|
||||
* @param data
|
||||
*/
|
||||
public void updateVelocity(Vector v, MovingData data) {
|
||||
|
||||
try {
|
||||
allowFlying = config.getBooleanValue("moving.allowflying");
|
||||
allowFakeSneak = config.getBooleanValue("moving.allowfakesneak");
|
||||
allowFastSwim = config.getBooleanValue("moving.allowfastswim");
|
||||
// Compare the velocity vector to the existing movement freedom that we've from previous events
|
||||
double tmp = (Math.abs(v.getX()) + Math.abs(v.getZ())) * 3D;
|
||||
if(tmp > data.horizFreedom)
|
||||
data.horizFreedom = tmp;
|
||||
|
||||
waterElevators = config.getBooleanValue("moving.waterelevators");
|
||||
if(v.getY() > 0.0D) {
|
||||
data.vertFreedomCounter = 50;
|
||||
data.maxYVelocity += v.getY();
|
||||
}
|
||||
}
|
||||
|
||||
checkOPs = config.getBooleanValue("moving.checkops");
|
||||
|
||||
logMessage = config.getStringValue("moving.logmessage").
|
||||
replace("[player]", "%1$s").
|
||||
replace("[world]", "%2$s").
|
||||
replace("[from]", "(%4$.1f, %5$.1f, %6$.1f)").
|
||||
replace("[to]", "(%7$.1f, %8$.1f, %9$.1f)").
|
||||
replace("[distance]", "(%10$.1f, %11$.1f, %12$.1f)");
|
||||
/**
|
||||
* Perform actions that were specified in the config file
|
||||
* @param event
|
||||
* @param action
|
||||
* @return
|
||||
*/
|
||||
private Location action( Player player, Location from, Location to, Action[] actions, int violations, MovingData data, MovingEventHelper helper) {
|
||||
|
||||
summaryMessage = config.getStringValue("moving.summarymessage").
|
||||
replace("[timeframe]", "%2$d").
|
||||
replace("[player]", "%1$s").
|
||||
replace("[violations]", "(%3$d,%4$d,%5$d)");
|
||||
|
||||
ticksBeforeSummary = config.getIntegerValue("moving.summaryafter")*20;
|
||||
|
||||
actions = new Action[3][];
|
||||
Location newToLocation = null;
|
||||
|
||||
actions[0] = config.getActionValue("moving.action.low");
|
||||
actions[1] = config.getActionValue("moving.action.med");
|
||||
actions[2] = config.getActionValue("moving.action.high");
|
||||
if(actions == null) return newToLocation;
|
||||
boolean cancelled = false;
|
||||
|
||||
setActive(config.getBooleanValue("active.moving"));
|
||||
for(Action a : actions) {
|
||||
if(a.firstAfter <= violations) {
|
||||
if(a.firstAfter == violations || a.repeat) {
|
||||
if(a instanceof LogAction) {
|
||||
// prepare log message if necessary
|
||||
String log = String.format(Locale.US, logMessage, player.getName(), from.getWorld().getName(), to.getWorld().getName(), from.getX(), from.getY(), from.getZ(), to.getX(), to.getY(), to.getZ(), Math.abs(from.getX()-to.getX()),to.getY()-from.getY(), Math.abs(from.getZ()-to.getZ()));
|
||||
|
||||
enforceTeleport = config.getBooleanValue("moving.enforceteleport");
|
||||
|
||||
stepWidth = ((double)config.getIntegerValue("moving.limits.walking")) /100D;
|
||||
sneakWidth = ((double)config.getIntegerValue("moving.limits.sneaking"))/100D;
|
||||
swimWidth = ((double)config.getIntegerValue("moving.limits.swimming"))/100D;
|
||||
plugin.log(((LogAction)a).level, log);
|
||||
|
||||
} catch (ConfigurationException e) {
|
||||
setActive(false);
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Remember the highest log level we encountered to determine what level the summary log message should have
|
||||
if(data.highestLogLevel == null) data.highestLogLevel = Level.ALL;
|
||||
if(data.highestLogLevel.intValue() < ((LogAction)a).level.intValue()) data.highestLogLevel = ((LogAction)a).level;
|
||||
}
|
||||
else if(!cancelled && a instanceof CancelAction) {
|
||||
// Make a modified copy of the setBackPoint to prevent other plugins from accidentally modifying it
|
||||
// and keep the current pitch and yaw (setbacks "feel" better that way). Plus try to adapt the Y-coord
|
||||
// to place the player close to ground
|
||||
|
||||
}
|
||||
double y = data.setBackPoint.getY();
|
||||
|
||||
@Override
|
||||
protected void registerListeners() {
|
||||
PluginManager pm = Bukkit.getServer().getPluginManager();
|
||||
// search for the first solid block up to 5 blocks below the setbackpoint and teleport the player there
|
||||
int i = 0;
|
||||
for(; i < 20; i++) {
|
||||
if(helper.isLocationOnGround(data.setBackPoint.getWorld(), data.setBackPoint.getX(), data.setBackPoint.getY() - 0.5*i, data.setBackPoint.getZ(), waterElevators) != MovingData.NONSOLID) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
y -= 0.5*i;
|
||||
|
||||
Listener movingPlayerMonitor = new MovingPlayerMonitor(plugin.getDataManager(), this);
|
||||
data.setBackPoint.setY(y);
|
||||
|
||||
// Register listeners for moving check
|
||||
pm.registerEvent(Event.Type.PLAYER_MOVE, new MovingPlayerListener(plugin.getDataManager(), this), Priority.Lowest, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_INTERACT, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_MOVE, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.ENTITY_DAMAGE, new MovingEntityListener(plugin.getDataManager(), this), Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_TELEPORT, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_PORTAL, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_RESPAWN, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
}
|
||||
// Remember the location we send the player to, to identify teleports that were started by us
|
||||
data.teleportInitializedByMe = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), to.getYaw(), to.getPitch());
|
||||
|
||||
newToLocation = data.teleportInitializedByMe;
|
||||
|
||||
cancelled = true; // just prevent us from treating more than one "cancel" action, which would make no sense
|
||||
}
|
||||
else if(a instanceof CustomAction)
|
||||
plugin.handleCustomAction((CustomAction)a, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newToLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a value against an array of sorted values to find out
|
||||
* where it fits in
|
||||
* @param value
|
||||
* @param limits
|
||||
* @return
|
||||
*/
|
||||
private static int limitCheck(final double value) {
|
||||
|
||||
if(value > 0.0D) {
|
||||
if(value > 0.5D) {
|
||||
if(value > 2.0D)
|
||||
return 2;
|
||||
return 1; }
|
||||
return 0; }
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(NoCheatConfiguration config) {
|
||||
|
||||
try {
|
||||
allowFlying = config.getBooleanValue("moving.allowflying");
|
||||
allowFakeSneak = config.getBooleanValue("moving.allowfakesneak");
|
||||
allowFastSwim = config.getBooleanValue("moving.allowfastswim");
|
||||
|
||||
waterElevators = config.getBooleanValue("moving.waterelevators");
|
||||
|
||||
checkOPs = config.getBooleanValue("moving.checkops");
|
||||
|
||||
logMessage = config.getStringValue("moving.logmessage").
|
||||
replace("[player]", "%1$s").
|
||||
replace("[world]", "%2$s").
|
||||
replace("[from]", "(%4$.1f, %5$.1f, %6$.1f)").
|
||||
replace("[to]", "(%7$.1f, %8$.1f, %9$.1f)").
|
||||
replace("[distance]", "(%10$.1f, %11$.1f, %12$.1f)");
|
||||
|
||||
summaryMessage = config.getStringValue("moving.summarymessage").
|
||||
replace("[timeframe]", "%2$d").
|
||||
replace("[player]", "%1$s").
|
||||
replace("[violations]", "(%3$d,%4$d,%5$d)");
|
||||
|
||||
ticksBeforeSummary = config.getIntegerValue("moving.summaryafter")*20;
|
||||
|
||||
actions = new Action[3][];
|
||||
|
||||
actions[0] = config.getActionValue("moving.action.low");
|
||||
actions[1] = config.getActionValue("moving.action.med");
|
||||
actions[2] = config.getActionValue("moving.action.high");
|
||||
|
||||
setActive(config.getBooleanValue("active.moving"));
|
||||
|
||||
enforceTeleport = config.getBooleanValue("moving.enforceteleport");
|
||||
|
||||
stepWidth = ((double)config.getIntegerValue("moving.limits.walking")) /100D;
|
||||
sneakWidth = ((double)config.getIntegerValue("moving.limits.sneaking"))/100D;
|
||||
swimWidth = ((double)config.getIntegerValue("moving.limits.swimming"))/100D;
|
||||
|
||||
} catch (ConfigurationException e) {
|
||||
setActive(false);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerListeners() {
|
||||
PluginManager pm = Bukkit.getServer().getPluginManager();
|
||||
|
||||
Listener movingPlayerMonitor = new MovingPlayerMonitor(plugin.getDataManager(), this);
|
||||
|
||||
// Register listeners for moving check
|
||||
pm.registerEvent(Event.Type.PLAYER_MOVE, new MovingPlayerListener(plugin.getDataManager(), this), Priority.Lowest, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_MOVE, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_TELEPORT, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_PORTAL, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_RESPAWN, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
pm.registerEvent(Event.Type.PLAYER_VELOCITY, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
package cc.co.evenprime.bukkit.nocheat.listeners;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityListener;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.DataManager;
|
||||
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||
|
||||
public class MovingEntityListener extends EntityListener {
|
||||
|
||||
private final MovingCheck check;
|
||||
private final DataManager dataManager;
|
||||
|
||||
public MovingEntityListener(DataManager dataManager, MovingCheck check) {
|
||||
this.dataManager = dataManager;
|
||||
this.check = check;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
if(event.getEntity() instanceof Player) {
|
||||
check.updateVelocity(event.getEntity().getVelocity(), dataManager.getMovingData((Player)event.getEntity()));
|
||||
}
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ public class MovingPlayerListener extends PlayerListener {
|
||||
if(!check.skipCheck(player)) {
|
||||
|
||||
final MovingData data = dataManager.getMovingData(player);
|
||||
final Location from = event.getFrom();
|
||||
final Location from = player.getLocation();
|
||||
final Location to = event.getTo();
|
||||
|
||||
Location newTo = null;
|
||||
|
@ -1,11 +1,11 @@
|
||||
package cc.co.evenprime.bukkit.nocheat.listeners;
|
||||
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerListener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerPortalEvent;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.player.PlayerVelocityEvent;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.DataManager;
|
||||
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||
@ -18,48 +18,45 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||
*/
|
||||
public class MovingPlayerMonitor extends PlayerListener {
|
||||
|
||||
private final MovingCheck check;
|
||||
private final DataManager dataManager;
|
||||
private final MovingCheck check;
|
||||
private final DataManager dataManager;
|
||||
|
||||
public MovingPlayerMonitor(DataManager dataManager, MovingCheck check) {
|
||||
this.dataManager = dataManager;
|
||||
this.check = check;
|
||||
}
|
||||
public MovingPlayerMonitor(DataManager dataManager, MovingCheck check) {
|
||||
this.dataManager = dataManager;
|
||||
this.check = check;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
MovingData data = dataManager.getMovingData(event.getPlayer());
|
||||
data.wasTeleported = true;
|
||||
data.setBackPoint = null;
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
@Override
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
MovingData data = dataManager.getMovingData(event.getPlayer());
|
||||
data.wasTeleported = true;
|
||||
data.setBackPoint = null;
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerPortal(PlayerPortalEvent event) {
|
||||
check.teleported(event);
|
||||
}
|
||||
@Override
|
||||
public void onPlayerPortal(PlayerPortalEvent event) {
|
||||
check.teleported(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
check.teleported(event);
|
||||
}
|
||||
@Override
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
check.teleported(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerVelocity(PlayerVelocityEvent event) {
|
||||
check.updateVelocity(event.getVelocity(), dataManager.getMovingData(event.getPlayer()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
|
||||
@Override
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
check.updateVelocity(event.getPlayer().getVelocity(), dataManager.getMovingData(event.getPlayer()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
MovingData data = dataManager.getMovingData(event.getPlayer());
|
||||
|
||||
check.updateVelocity(event.getPlayer().getVelocity(), data);
|
||||
|
||||
if(!event.isCancelled()) {
|
||||
if( event.getPlayer().isInsideVehicle()) {
|
||||
data.setBackPoint = event.getTo();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!event.isCancelled()) {
|
||||
if( event.getPlayer().isInsideVehicle()) {
|
||||
MovingData data = dataManager.getMovingData(event.getPlayer());
|
||||
data.setBackPoint = event.getTo();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user