mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-12-30 20:37:52 +01:00
Fixed some problematic cases with teleports
Replaced flight-check completely with newer version Fixed descriptions.txt file not getting automatically generated as promised
This commit is contained in:
parent
0dea0c0285
commit
ad78a91aab
@ -3,7 +3,7 @@ name: NoCheat
|
|||||||
author: Evenprime
|
author: Evenprime
|
||||||
|
|
||||||
main: cc.co.evenprime.bukkit.nocheat.NoCheat
|
main: cc.co.evenprime.bukkit.nocheat.NoCheat
|
||||||
version: 1.08c
|
version: 1.09
|
||||||
|
|
||||||
softdepend: [ Permissions, CraftIRC ]
|
softdepend: [ Permissions, CraftIRC ]
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ public class LogAction extends Action {
|
|||||||
|
|
||||||
public final static LogAction[] log = { loglow, logmed, loghigh };
|
public final static LogAction[] log = { loglow, logmed, loghigh };
|
||||||
|
|
||||||
public LogAction(int firstAfter, boolean repeat, Level level) {
|
private LogAction(int firstAfter, boolean repeat, Level level) {
|
||||||
super(firstAfter, repeat);
|
super(firstAfter, repeat);
|
||||||
this.level = level;
|
this.level = level;
|
||||||
}
|
}
|
||||||
|
@ -16,24 +16,25 @@ public abstract class Check {
|
|||||||
|
|
||||||
private boolean active = false;
|
private boolean active = false;
|
||||||
private boolean listenersRegistered = false;
|
private boolean listenersRegistered = false;
|
||||||
private int permission;
|
private final int permission;
|
||||||
private String name;
|
private final String name;
|
||||||
protected NoCheat plugin;
|
protected final NoCheat plugin;
|
||||||
|
|
||||||
// Should OPs be checked if Permissions plugin is not available?
|
// Should OPs be checked if Permissions plugin is not available?
|
||||||
protected boolean checkOPs = false;
|
public boolean checkOPs;
|
||||||
|
|
||||||
protected Check(NoCheat plugin, String name, int permission, NoCheatConfiguration config) {
|
protected Check(NoCheat plugin, String name, int permission, NoCheatConfiguration config) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.permission = permission;
|
this.permission = permission;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
checkOPs = config.getBooleanValue(name + ".checkops");
|
checkOPs= config.getBooleanValue(name + ".checkops");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
checkOPs = false;
|
checkOPs = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
configure(config);
|
configure(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
src/cc/co/evenprime/bukkit/nocheat/checks/FlyingCheck.java
Normal file
114
src/cc/co/evenprime/bukkit/nocheat/checks/FlyingCheck.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
package cc.co.evenprime.bukkit.nocheat.checks;
|
||||||
|
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* @author Evenprime
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FlyingCheck {
|
||||||
|
|
||||||
|
public FlyingCheck() { }
|
||||||
|
|
||||||
|
// How many move events can a player have in air before he is expected to lose altitude (or eventually land somewhere)
|
||||||
|
private final static int jumpingLimit = 5;
|
||||||
|
|
||||||
|
// How high may a player get compared to his last location with ground contact
|
||||||
|
private final static double jumpHeight = 1.31D;
|
||||||
|
|
||||||
|
// How much points should hovering attempts cause?
|
||||||
|
private final static double hoveringPunishment = 0.2D;
|
||||||
|
|
||||||
|
// How high may a player move in one event on ground
|
||||||
|
private final static double stepHeight = 0.501D;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate if and how much the player "failed" this check. The check should not
|
||||||
|
* modify any data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public double check(final Player player, final Location from, final boolean fromOnGround, final Location to, final boolean toOnGround, final MovingData data) {
|
||||||
|
|
||||||
|
// How much higher did the player move than expected??
|
||||||
|
double distanceAboveLimit = 0.0D;
|
||||||
|
|
||||||
|
final double toY = to.getY();
|
||||||
|
final double fromY = from.getY();
|
||||||
|
|
||||||
|
double limit = calculateVerticalLimit(data, fromOnGround) + jumpHeight;
|
||||||
|
|
||||||
|
// Walk or start Jump
|
||||||
|
if(fromOnGround)
|
||||||
|
{
|
||||||
|
distanceAboveLimit = toY - fromY - limit;
|
||||||
|
}
|
||||||
|
// Land or Fly/Fall
|
||||||
|
else
|
||||||
|
{
|
||||||
|
final Location l;
|
||||||
|
|
||||||
|
if(data.setBackPoint == null)
|
||||||
|
l = from;
|
||||||
|
else
|
||||||
|
l = data.setBackPoint;
|
||||||
|
|
||||||
|
if(data.jumpPhase > jumpingLimit) {
|
||||||
|
limit -= (data.jumpPhase-jumpingLimit) * 0.2D;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(toOnGround) limit += stepHeight;
|
||||||
|
|
||||||
|
distanceAboveLimit = toY - l.getY() - limit;
|
||||||
|
|
||||||
|
// Always give some bonus points in case of identical Y values in midair (hovering player)
|
||||||
|
if(fromY == toY && !toOnGround) {
|
||||||
|
distanceAboveLimit = Math.max(hoveringPunishment, distanceAboveLimit+hoveringPunishment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return distanceAboveLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateVerticalLimit(final MovingData data, final boolean onGroundFrom) {
|
||||||
|
|
||||||
|
// 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" 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--;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double limit = data.vertFreedom;
|
||||||
|
|
||||||
|
// If the event counter has been consumed, remove the vertical movement limit increase when landing the next time
|
||||||
|
if(onGroundFrom && data.vertFreedomCounter <= 0) {
|
||||||
|
data.vertFreedom = 0.0D;
|
||||||
|
}
|
||||||
|
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -12,8 +12,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.Event.Priority;
|
import org.bukkit.event.Event.Priority;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
|
||||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
@ -41,29 +39,19 @@ public class MovingCheck extends Check {
|
|||||||
|
|
||||||
public MovingCheck(NoCheat plugin, NoCheatConfiguration config) {
|
public MovingCheck(NoCheat plugin, NoCheatConfiguration config) {
|
||||||
super(plugin, "moving", PermissionData.PERMISSION_MOVING, config);
|
super(plugin, "moving", PermissionData.PERMISSION_MOVING, config);
|
||||||
|
|
||||||
|
helper = new MovingEventHelper();
|
||||||
|
flyingCheck = new FlyingCheck();
|
||||||
|
runningCheck = new RunningCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
// How many move events can a player have in air before he is expected to lose altitude (or land somewhere)
|
private final int ticksBeforeSummary = 100;
|
||||||
private final static int jumpingLimit = 5;
|
|
||||||
|
|
||||||
// How high may a player get compared to his last location with ground contact
|
|
||||||
private final static double jumpHeight = 1.35D;
|
|
||||||
|
|
||||||
// How high may a player move in one event on ground
|
|
||||||
private final static double stepHeight = 0.501D;
|
|
||||||
|
|
||||||
private final static double stepWidth = 0.22D;
|
|
||||||
private final static double sneakWidth = 0.14D;
|
|
||||||
private final static double swimWidth = 0.18D;
|
|
||||||
|
|
||||||
private int ticksBeforeSummary = 100;
|
|
||||||
|
|
||||||
public long statisticElapsedTimeNano = 0;
|
public long statisticElapsedTimeNano = 0;
|
||||||
|
|
||||||
public boolean allowFlying;
|
public boolean allowFlying;
|
||||||
public boolean allowFakeSneak;
|
public boolean allowFakeSneak;
|
||||||
public boolean allowFastSwim;
|
public boolean allowFastSwim;
|
||||||
public boolean checkOPs;
|
|
||||||
|
|
||||||
private boolean waterElevators;
|
private boolean waterElevators;
|
||||||
|
|
||||||
@ -77,6 +65,9 @@ public class MovingCheck extends Check {
|
|||||||
|
|
||||||
private boolean enforceTeleport;
|
private boolean enforceTeleport;
|
||||||
|
|
||||||
|
private final MovingEventHelper helper;
|
||||||
|
private final FlyingCheck flyingCheck;
|
||||||
|
private final RunningCheck runningCheck;
|
||||||
|
|
||||||
|
|
||||||
private static final double magic = 0.30000001192092896D;
|
private static final double magic = 0.30000001192092896D;
|
||||||
@ -90,203 +81,88 @@ public class MovingCheck extends Check {
|
|||||||
* Fourth treat any occured violations as configured
|
* Fourth treat any occured violations as configured
|
||||||
* @param event
|
* @param event
|
||||||
*/
|
*/
|
||||||
public void check(final PlayerMoveEvent event) {
|
|
||||||
|
|
||||||
final Player player = event.getPlayer();
|
|
||||||
|
|
||||||
// Should we check at all
|
|
||||||
if(skipCheck(player)) { return; }
|
|
||||||
|
|
||||||
|
|
||||||
final long startTime = System.nanoTime();
|
|
||||||
|
|
||||||
// Get the player-specific data
|
|
||||||
final MovingData data = MovingData.get(player);
|
|
||||||
|
|
||||||
|
|
||||||
// Get the two locations of the event
|
|
||||||
final Location to = event.getTo();
|
|
||||||
|
|
||||||
Location from = event.getFrom();
|
|
||||||
|
|
||||||
|
public Location check(Player player, Location from, Location to,
|
||||||
|
MovingData data) {
|
||||||
|
|
||||||
updateVelocity(player.getVelocity(), 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;
|
||||||
|
|
||||||
// event.getFrom() is intentional here
|
/***************** REFINE EVENT DATA FOR CHECKS ***************/
|
||||||
if(shouldBeIgnored(player, data, from, to)) {
|
|
||||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
|
||||||
statisticTotalEvents++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Horizontal movement check START ****/
|
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(), false);
|
||||||
|
final int toType = helper.isLocationOnGround(to.getWorld(), to.getX(), to.getY(),to.getZ(), false);
|
||||||
|
|
||||||
// First check the distance the player has moved horizontally
|
final boolean fromOnGround = fromType != MovingEventHelper.NONSOLID;
|
||||||
final double xDistance = from.getX()-to.getX();
|
final boolean toOnGround = toType != MovingEventHelper.NONSOLID;
|
||||||
final double zDistance = from.getZ()-to.getZ();
|
|
||||||
|
|
||||||
double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance));
|
// Distribute data to checks in the form needed by the checks
|
||||||
|
|
||||||
// If the target is a bed and distance not too big, allow it always
|
/********************* EXECUTE THE CHECKS ********************/
|
||||||
// Bukkit prevents using blocks behind walls already, so I don't have to check for that
|
double result = 0.0D;
|
||||||
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && combined < 8.0D) {
|
|
||||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
|
||||||
statisticTotalEvents++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int onGroundFrom = playerIsOnGround(from, 0.0D);
|
if(flyCheck) {
|
||||||
|
result += Math.max(0D, flyingCheck.check(player, from, fromOnGround, to, toOnGround, data));
|
||||||
double overLimit = 0.0D;
|
|
||||||
|
|
||||||
if(player.isSneaking() && !allowFakeSneak && !plugin.hasPermission(player, PermissionData.PERMISSION_FAKESNEAK, checkOPs)) {
|
|
||||||
overLimit = Math.max(0.0D, combined - (data.horizFreedom + sneakWidth));
|
|
||||||
}
|
|
||||||
else if(onGroundFrom == MovingData.LIQUID && !allowFastSwim && !plugin.hasPermission(player, PermissionData.PERMISSION_FASTSWIM, checkOPs)) {
|
|
||||||
overLimit = Math.max(0.0D, combined - (data.horizFreedom + swimWidth));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
overLimit = Math.max(0.0D, combined - (data.horizFreedom + stepWidth));
|
|
||||||
}
|
|
||||||
|
|
||||||
data.runningThreshold += overLimit;
|
|
||||||
|
|
||||||
int violationLevelHorizontal = limitCheck(data.runningThreshold - 1);
|
|
||||||
|
|
||||||
// Reduce horiz moving freedom with each event
|
|
||||||
data.runningThreshold *= 0.97;
|
|
||||||
data.horizFreedom *= 0.9;
|
|
||||||
|
|
||||||
/**** Horizontal movement check END ****/
|
|
||||||
|
|
||||||
/**** Vertical movement check START ****/
|
|
||||||
|
|
||||||
int violationLevelVertical = -1;
|
|
||||||
|
|
||||||
// The location we'd use as a new setback if there are no violations
|
|
||||||
Location newSetBack = null;
|
|
||||||
|
|
||||||
double limit = calculateVerticalLimit(data, onGroundFrom);
|
|
||||||
|
|
||||||
// Handle 4 distinct cases: Walk, Jump, Land, Fly
|
|
||||||
|
|
||||||
// Walk or start Jump
|
|
||||||
if(onGroundFrom != MovingData.NONSOLID)
|
|
||||||
{
|
|
||||||
limit += jumpHeight;
|
|
||||||
|
|
||||||
final double distance = to.getY() - from.getY();
|
|
||||||
|
|
||||||
violationLevelVertical = limitCheck(distance - limit);
|
|
||||||
|
|
||||||
if(violationLevelVertical < 0)
|
|
||||||
{
|
|
||||||
// reset jumping
|
|
||||||
data.jumpPhase = 0;
|
|
||||||
|
|
||||||
newSetBack = from;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Land or Fly/Fall
|
|
||||||
else
|
|
||||||
{
|
|
||||||
final Location l;
|
|
||||||
|
|
||||||
final boolean canFly = allowFlying || plugin.hasPermission(player, PermissionData.PERMISSION_FLYING, checkOPs);
|
if(runCheck) {
|
||||||
|
result += Math.max(0D, runningCheck.check(from, to,
|
||||||
|
player.isSneaking(), (fromType & toType & MovingEventHelper.LIQUID) > 0, data));
|
||||||
|
}
|
||||||
|
|
||||||
if(data.setBackPoint == null || canFly)
|
|
||||||
l = from;
|
|
||||||
else
|
|
||||||
l = data.setBackPoint;
|
|
||||||
|
|
||||||
if(!canFly && data.jumpPhase > jumpingLimit)
|
/********* HANDLE/COMBINE THE RESULTS OF THE CHECKS ***********/
|
||||||
limit += jumpHeight - (data.jumpPhase-jumpingLimit) * 0.2D;
|
|
||||||
else limit += jumpHeight;
|
|
||||||
|
|
||||||
final int onGroundTo = playerIsOnGround(to, 0.0D);
|
data.jumpPhase++;
|
||||||
|
|
||||||
if(onGroundTo != MovingData.NONSOLID) limit += stepHeight;
|
if(result <= 0) {
|
||||||
|
if(fromOnGround) {
|
||||||
final double distance = to.getY() - l.getY();
|
data.setBackPoint = from;
|
||||||
|
data.jumpPhase = 0;
|
||||||
// Check if player isn't jumping too high
|
|
||||||
violationLevelVertical = limitCheck(distance - limit);
|
|
||||||
|
|
||||||
if(violationLevelVertical < 0) {
|
|
||||||
if(onGroundTo != MovingData.NONSOLID) { // Land
|
|
||||||
data.jumpPhase = 0; // He is on ground now, so reset the jump
|
|
||||||
//newSetBack = to;
|
|
||||||
}
|
}
|
||||||
else { // Fly
|
else if(toOnGround) {
|
||||||
data.jumpPhase++; // Enter next phase of the flight
|
data.jumpPhase = 0;
|
||||||
// If we have no setback point, create one now
|
|
||||||
if(data.setBackPoint == null) {
|
|
||||||
newSetBack = from;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else 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);
|
||||||
|
|
||||||
|
int level = limitCheck(data.violationLevel-1);
|
||||||
|
|
||||||
|
data.violationsInARow[level]++;
|
||||||
|
|
||||||
|
newToLocation = action(player, from, to, actions[level], data.violationsInARow[level], data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** Vertical movement check END ****/
|
// Slowly reduce the level with each event
|
||||||
|
data.violationLevel *= 0.97;
|
||||||
/****** Violation Handling START *****/
|
data.horizFreedom *= 0.97;
|
||||||
int violationLevel = violationLevelHorizontal > violationLevelVertical ? violationLevelHorizontal : violationLevelVertical;
|
|
||||||
|
|
||||||
if(violationLevel < 0 && newSetBack != null) {
|
|
||||||
data.setBackPoint = newSetBack;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we haven't already got a setback point by now, make this location the new setback point
|
|
||||||
if(data.setBackPoint == null) {
|
|
||||||
data.setBackPoint = from;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(violationLevel >= 0) {
|
|
||||||
setupSummaryTask(event.getPlayer(), data);
|
|
||||||
|
|
||||||
data.violationsInARow[violationLevel]++;
|
|
||||||
|
|
||||||
action(event, event.getPlayer(), from, to, actions[violationLevel], data.violationsInARow[violationLevel], data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/****** Violation Handling END *****/
|
|
||||||
|
|
||||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||||
statisticTotalEvents++;
|
statisticTotalEvents++;
|
||||||
}
|
|
||||||
|
|
||||||
private double calculateVerticalLimit(final MovingData data, final int onGroundFrom) {
|
return newToLocation;
|
||||||
|
|
||||||
// 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" 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--;
|
|
||||||
}
|
|
||||||
|
|
||||||
final double limit = data.vertFreedom;
|
|
||||||
|
|
||||||
// If the event counter has been consumed, remove the vertical movement limit increase when landing the next time
|
|
||||||
if(onGroundFrom != MovingData.NONSOLID && data.vertFreedomCounter <= 0) {
|
|
||||||
data.vertFreedom = 0.0D;
|
|
||||||
}
|
|
||||||
|
|
||||||
return limit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -297,45 +173,35 @@ public class MovingCheck extends Check {
|
|||||||
* @param to
|
* @param to
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean shouldBeIgnored(final Player player, final MovingData data, final Location from, final Location to) {
|
public boolean shouldBeApplied(final Player player, final MovingData data, final Location from, final Location to) {
|
||||||
|
|
||||||
if(data.firstEventAfterRespawn) {
|
if(player.isDead() || player.isInsideVehicle() || data.insideVehicle) return false;
|
||||||
data.firstEventAfterRespawn = false;
|
|
||||||
data.teleportTo = from.clone();
|
if(data.wasTeleported) {
|
||||||
|
// Remember this location
|
||||||
|
data.teleportedTo = from.clone();
|
||||||
|
data.wasTeleported = false;
|
||||||
|
data.jumpPhase = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now it gets complicated: (a friendly reminder to myself why this actually works in CB 950+)
|
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
|
||||||
// data.teleportTo gets a location assigned if a teleport event is successfully executed.
|
if(data.teleportedTo.distanceSquared(from) < 0.01D) {
|
||||||
// But there is a delay between the serverside execution of the teleport (instantly) and
|
// Event after Teleport ignored
|
||||||
// the execution on the client side (may take an arbitrary time). During that time, the
|
return false;
|
||||||
// client may send new move events relative to his old location. These events get treated
|
|
||||||
// by bukkit as PLAYER_MOVE events, despite the server not accepting them (the players
|
|
||||||
// serverside location won't get updated). Therefore comparing the teleport destination
|
|
||||||
// with the servers location of the player (which is almost the same as the "from" location
|
|
||||||
// in the move event) tells us if the server is still waiting for the clientside teleporting
|
|
||||||
// to be executed. We are only interested in client's move events after it executed the
|
|
||||||
// teleport, therefore just ignore all events before that.
|
|
||||||
if(data.teleportTo != null && data.teleportTo.getWorld().equals(from.getWorld())) {
|
|
||||||
if(data.teleportTo.distanceSquared(from) < 0.01D) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data.teleportTo = null;
|
// The player finally accepted the teleport with the previous event
|
||||||
|
data.teleportedTo = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dead or in vehicles -> I don't care
|
// If the target is a bed, don't check (going to bed is a kind of mini teleport...)
|
||||||
if(player.isDead() || data.insideVehicle || player.isInsideVehicle()) {
|
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId()) {
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
// If the player moved between worlds between events, don't check (wouldn't make sense
|
|
||||||
// to check coordinates between different worlds...)
|
|
||||||
if(!from.getWorld().equals(data.lastSeenInWorld)) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -355,6 +221,8 @@ public class MovingCheck extends Check {
|
|||||||
if(data.highestLogLevel != null) {
|
if(data.highestLogLevel != null) {
|
||||||
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.violationsInARow[0], data.violationsInARow[1],data.violationsInARow[2]);
|
String logString = String.format(summaryMessage, p.getName(), ticksBeforeSummary/20, data.violationsInARow[0], data.violationsInARow[1],data.violationsInARow[2]);
|
||||||
plugin.log(data.highestLogLevel, logString);
|
plugin.log(data.highestLogLevel, logString);
|
||||||
|
|
||||||
|
data.highestLogLevel = Level.ALL;
|
||||||
}
|
}
|
||||||
// deleting its own reference
|
// deleting its own reference
|
||||||
data.summaryTask = -1;
|
data.summaryTask = -1;
|
||||||
@ -388,7 +256,7 @@ public class MovingCheck extends Check {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!event.isCancelled()) {
|
if(!event.isCancelled()) {
|
||||||
data.teleportTo = event.getTo().clone();
|
data.wasTeleported = true;
|
||||||
data.setBackPoint = event.getTo().clone();
|
data.setBackPoint = event.getTo().clone();
|
||||||
//data.lastLocation = event.getTo().clone();
|
//data.lastLocation = event.getTo().clone();
|
||||||
}
|
}
|
||||||
@ -397,17 +265,6 @@ public class MovingCheck extends Check {
|
|||||||
data.jumpPhase = 0;
|
data.jumpPhase = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a flag to declare that the player recently respawned
|
|
||||||
* @param event
|
|
||||||
*/
|
|
||||||
public void respawned(PlayerRespawnEvent event) {
|
|
||||||
MovingData data = MovingData.get(event.getPlayer());
|
|
||||||
data.firstEventAfterRespawn = true;
|
|
||||||
data.jumpPhase = 0;
|
|
||||||
data.setBackPoint = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the cached values for players velocity to be prepared to
|
* Update the cached values for players velocity to be prepared to
|
||||||
* give them additional movement freedom in their next move events
|
* give them additional movement freedom in their next move events
|
||||||
@ -430,13 +287,16 @@ public class MovingCheck extends Check {
|
|||||||
* Perform actions that were specified in the config file
|
* Perform actions that were specified in the config file
|
||||||
* @param event
|
* @param event
|
||||||
* @param action
|
* @param action
|
||||||
|
* @return
|
||||||
*/
|
*/
|
||||||
private void action(PlayerMoveEvent event, Player player, Location from, Location to, Action[] actions, int violations, MovingData data) {
|
private Location action( Player player, Location from, Location to, Action[] actions, int violations, MovingData data) {
|
||||||
|
|
||||||
if(actions == null) return;
|
|
||||||
|
Location newToLocation = null;
|
||||||
|
|
||||||
|
if(actions == null) return newToLocation;
|
||||||
boolean cancelled = false;
|
boolean cancelled = false;
|
||||||
|
|
||||||
|
|
||||||
for(Action a : actions) {
|
for(Action a : actions) {
|
||||||
if(a.firstAfter <= violations) {
|
if(a.firstAfter <= violations) {
|
||||||
if(a.firstAfter == violations || a.repeat) {
|
if(a.firstAfter == violations || a.repeat) {
|
||||||
@ -469,9 +329,9 @@ public class MovingCheck extends Check {
|
|||||||
data.setBackPoint.setY(y);
|
data.setBackPoint.setY(y);
|
||||||
|
|
||||||
// Remember the location we send the player to, to identify teleports that were started by us
|
// 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(), event.getTo().getYaw(), event.getTo().getPitch());
|
data.teleportInitializedByMe = new Location(data.setBackPoint.getWorld(), data.setBackPoint.getX(), y, data.setBackPoint.getZ(), to.getYaw(), to.getPitch());
|
||||||
|
|
||||||
event.setTo(data.teleportInitializedByMe);
|
newToLocation = data.teleportInitializedByMe;
|
||||||
|
|
||||||
cancelled = true; // just prevent us from treating more than one "cancel" action, which would make no sense
|
cancelled = true; // just prevent us from treating more than one "cancel" action, which would make no sense
|
||||||
}
|
}
|
||||||
@ -480,6 +340,8 @@ public class MovingCheck extends Check {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return newToLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -633,6 +495,8 @@ public class MovingCheck extends Check {
|
|||||||
|
|
||||||
waterElevators = config.getBooleanValue("moving.waterelevators");
|
waterElevators = config.getBooleanValue("moving.waterelevators");
|
||||||
|
|
||||||
|
checkOPs = config.getBooleanValue("moving.checkops");
|
||||||
|
|
||||||
logMessage = config.getStringValue("moving.logmessage").
|
logMessage = config.getStringValue("moving.logmessage").
|
||||||
replace("[player]", "%1$s").
|
replace("[player]", "%1$s").
|
||||||
replace("[world]", "%2$s").
|
replace("[world]", "%2$s").
|
||||||
@ -674,6 +538,8 @@ public class MovingCheck extends Check {
|
|||||||
pm.registerEvent(Event.Type.PLAYER_MOVE, movingPlayerMonitor, Priority.Monitor, plugin);
|
pm.registerEvent(Event.Type.PLAYER_MOVE, movingPlayerMonitor, Priority.Monitor, plugin);
|
||||||
pm.registerEvent(Event.Type.ENTITY_DAMAGE, new MovingEntityListener(this), Priority.Monitor, plugin);
|
pm.registerEvent(Event.Type.ENTITY_DAMAGE, new MovingEntityListener(this), Priority.Monitor, plugin);
|
||||||
pm.registerEvent(Event.Type.PLAYER_TELEPORT, new MovingPlayerMonitor(this), Priority.Monitor, plugin);
|
pm.registerEvent(Event.Type.PLAYER_TELEPORT, new MovingPlayerMonitor(this), Priority.Monitor, plugin);
|
||||||
pm.registerEvent(Event.Type.PLAYER_RESPAWN, new MovingPlayerMonitor(this), Priority.Monitor, plugin);
|
pm.registerEvent(Event.Type.PLAYER_PORTAL, new MovingPlayerMonitor(this), Priority.Monitor, plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
170
src/cc/co/evenprime/bukkit/nocheat/checks/MovingEventHelper.java
Normal file
170
src/cc/co/evenprime/bukkit/nocheat/checks/MovingEventHelper.java
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
package cc.co.evenprime.bukkit.nocheat.checks;
|
||||||
|
|
||||||
|
import net.minecraft.server.Block;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of stuff to process data of move events
|
||||||
|
* @author Evenprime
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MovingEventHelper {
|
||||||
|
|
||||||
|
private final double magic = 0.30000001192092896D;
|
||||||
|
private final double magic2 = 0.69999998807907103D;
|
||||||
|
|
||||||
|
// Block types that may need to be treated specially
|
||||||
|
public static final int NONSOLID = 0; // 0x00000000
|
||||||
|
public static final int SOLID = 1; // 0x00000001
|
||||||
|
public static final int LIQUID = 2; // 0x00000010
|
||||||
|
public static final int LADDER = 4; // 0x00000100
|
||||||
|
public static final int FENCE = 8; // 0x00001000
|
||||||
|
|
||||||
|
// Until I can think of a better way to determine if a block is solid or not, this is what I'll do
|
||||||
|
private final int types[] = new int[256];
|
||||||
|
|
||||||
|
public MovingEventHelper() {
|
||||||
|
// Find and define properties of all blocks
|
||||||
|
for(int i = 0; i < types.length; i++) {
|
||||||
|
|
||||||
|
// Everything is considered nonsolid at first
|
||||||
|
types[i] = NONSOLID;
|
||||||
|
|
||||||
|
if(Block.byId[i] != null) {
|
||||||
|
if(Block.byId[i].material.isSolid()) {
|
||||||
|
// solid blocks like STONE, CAKE, TRAPDOORS
|
||||||
|
types[i] = SOLID;
|
||||||
|
}
|
||||||
|
else if(Block.byId[i].material.isLiquid()){
|
||||||
|
// WATER, LAVA
|
||||||
|
types[i] = LIQUID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special types just for me
|
||||||
|
types[Material.LADDER.getId()]= LADDER | SOLID;
|
||||||
|
types[Material.FENCE.getId()]= FENCE | SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if certain coordinates are considered "on ground"
|
||||||
|
*
|
||||||
|
* @param w The world the coordinates belong to
|
||||||
|
* @param values The coordinates [lowerX, higherX, Y, lowerZ, higherZ] to be checked
|
||||||
|
* @param l The precise location that was used for calculation of "values"
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int isLocationOnGround(final World world, final double x, final double y, final double z, boolean waterElevatorsAllowed) {
|
||||||
|
|
||||||
|
final int lowerX = lowerBorder(x);
|
||||||
|
final int upperX = upperBorder(x);
|
||||||
|
final int Y = (int)Math.floor(y);
|
||||||
|
final int lowerZ = lowerBorder(z);
|
||||||
|
final int higherZ = upperBorder(z);
|
||||||
|
|
||||||
|
|
||||||
|
int result;
|
||||||
|
|
||||||
|
// check in what kind of block the player is standing "in"
|
||||||
|
result = types[world.getBlockTypeIdAt(lowerX, Y, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y, lowerZ)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX, Y, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y, higherZ)];
|
||||||
|
|
||||||
|
if((result & SOLID) != 0) {
|
||||||
|
// return standing
|
||||||
|
return SOLID;
|
||||||
|
}
|
||||||
|
else if((result & LIQUID) != 0) {
|
||||||
|
// return swimming
|
||||||
|
return LIQUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the four borders of the players hitbox for something he could be standing on
|
||||||
|
result = types[world.getBlockTypeIdAt(lowerX, Y-1, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y-1, lowerZ)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX, Y-1, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y-1, higherZ)];
|
||||||
|
|
||||||
|
if((result & SOLID) != 0) {
|
||||||
|
// return standing
|
||||||
|
return SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check if his head is "stuck" in an block
|
||||||
|
result = types[world.getBlockTypeIdAt(lowerX, Y+1, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y+1, lowerZ)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX, Y+1, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y+1, higherZ)];
|
||||||
|
|
||||||
|
if((result & SOLID) != 0) {
|
||||||
|
// return standing
|
||||||
|
return SOLID;
|
||||||
|
}
|
||||||
|
else if((result & LIQUID) != 0) {
|
||||||
|
// return swimming
|
||||||
|
return LIQUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Running on fences causes problems if not treated specially
|
||||||
|
result = types[world.getBlockTypeIdAt(lowerX, Y-2, lowerZ)] | types[world.getBlockTypeIdAt(upperX, Y-2, lowerZ)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX, Y-2, higherZ)] | types[world.getBlockTypeIdAt(upperX, Y-2, higherZ)];
|
||||||
|
|
||||||
|
if((result & FENCE) != 0) {
|
||||||
|
// return standing
|
||||||
|
return SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Water elevators - optional "feature"
|
||||||
|
if(waterElevatorsAllowed) {
|
||||||
|
result = types[world.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ+1)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX+1, Y , lowerZ+1)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX, Y+1, lowerZ+1)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX , Y , lowerZ+1)] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX+1, Y+1, lowerZ )] |
|
||||||
|
types[world.getBlockTypeIdAt(lowerX+1, Y , lowerZ )] ;
|
||||||
|
|
||||||
|
if((result & LIQUID) != 0) {
|
||||||
|
return SOLID; // Solid? Why that? Because that's closer to what the bug actually does than liquid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If nothing matches, he is somewhere in the air
|
||||||
|
return NONSOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Personal Rounding function to determine if a player is still touching a block or not
|
||||||
|
* @param d1
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int lowerBorder(double d1) {
|
||||||
|
|
||||||
|
double floor = Math.floor(d1);
|
||||||
|
double d4 = floor + magic;
|
||||||
|
|
||||||
|
if(d4 <= d1)
|
||||||
|
d4 = 0;
|
||||||
|
else
|
||||||
|
d4 = 1;
|
||||||
|
|
||||||
|
return (int) (floor - d4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Personal Rounding function to determine if a player is still touching a block or not
|
||||||
|
* @param d1
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private int upperBorder(double d1) {
|
||||||
|
|
||||||
|
double floor = Math.floor(d1);
|
||||||
|
double d4 = floor + magic2;
|
||||||
|
|
||||||
|
if(d4 < d1)
|
||||||
|
d4 = -1;
|
||||||
|
else
|
||||||
|
d4 = 0;
|
||||||
|
|
||||||
|
return (int) (floor - d4);
|
||||||
|
}
|
||||||
|
}
|
39
src/cc/co/evenprime/bukkit/nocheat/checks/RunningCheck.java
Normal file
39
src/cc/co/evenprime/bukkit/nocheat/checks/RunningCheck.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package cc.co.evenprime.bukkit.nocheat.checks;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||||
|
|
||||||
|
public class RunningCheck {
|
||||||
|
|
||||||
|
private final static double stepWidth = 0.22D;
|
||||||
|
private final static double sneakWidth = 0.14D;
|
||||||
|
private final static double swimWidth = 0.18D;
|
||||||
|
|
||||||
|
public RunningCheck() { }
|
||||||
|
|
||||||
|
public double check(final Location from, final Location to, final boolean isSneaking, final boolean isSwimming, final MovingData data) {
|
||||||
|
|
||||||
|
// How much further did the player move than expected??
|
||||||
|
double distanceAboveLimit = 0.0D;
|
||||||
|
|
||||||
|
// First calculate the distance the player has moved horizontally
|
||||||
|
final double xDistance = from.getX()-to.getX();
|
||||||
|
final double zDistance = from.getZ()-to.getZ();
|
||||||
|
|
||||||
|
final double totalDistance = Math.sqrt((xDistance*xDistance + zDistance*zDistance));
|
||||||
|
|
||||||
|
// TODO: Also ask cc which to apply
|
||||||
|
if(isSneaking) {
|
||||||
|
distanceAboveLimit = totalDistance - sneakWidth;
|
||||||
|
}
|
||||||
|
else if(isSwimming) {
|
||||||
|
distanceAboveLimit = totalDistance - swimWidth;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
distanceAboveLimit = totalDistance - stepWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return distanceAboveLimit;
|
||||||
|
}
|
||||||
|
}
|
@ -21,8 +21,8 @@ public class LevelOption extends ChildOption {
|
|||||||
HIGH("high", "very important messages", Level.SEVERE);
|
HIGH("high", "very important messages", Level.SEVERE);
|
||||||
|
|
||||||
private final String value;
|
private final String value;
|
||||||
private String description;
|
private final String description;
|
||||||
private Level level;
|
private final Level level;
|
||||||
|
|
||||||
private LogLevel(String value, String description, Level level) {
|
private LogLevel(String value, String description, Level level) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
@ -35,7 +35,7 @@ public class NoCheatConfiguration {
|
|||||||
|
|
||||||
private ParentOption root;
|
private ParentOption root;
|
||||||
|
|
||||||
private Map<String, Action> actionMap = new HashMap<String,Action>();
|
private final Map<String, Action> actionMap = new HashMap<String,Action>();
|
||||||
|
|
||||||
private Map<String, Object> yamlContent = new HashMap<String, Object>();
|
private Map<String, Object> yamlContent = new HashMap<String, Object>();
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ public class NoCheatConfiguration {
|
|||||||
|
|
||||||
// Setup the configuration tree
|
// Setup the configuration tree
|
||||||
config(configurationFile, descriptionsFile);
|
config(configurationFile, descriptionsFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,7 +267,7 @@ public class NoCheatConfiguration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
writeConfigFile(configurationFile, this);
|
writeConfigFile(configurationFile, this);
|
||||||
//writeDescriptionFile(descriptionsFile, this);
|
writeDescriptionFile(descriptionsFile, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setupFileLogger() {
|
public void setupFileLogger() {
|
||||||
@ -301,7 +302,7 @@ public class NoCheatConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action[] stringToActions(String string) {
|
private Action[] stringToActions(String string) {
|
||||||
|
|
||||||
List<Action> as = new LinkedList<Action>();
|
List<Action> as = new LinkedList<Action>();
|
||||||
String[] parts = string.split(" ");
|
String[] parts = string.split(" ");
|
||||||
@ -350,7 +351,7 @@ public class NoCheatConfiguration {
|
|||||||
* Write a file with the descriptions of all options
|
* Write a file with the descriptions of all options
|
||||||
* @param f
|
* @param f
|
||||||
*/
|
*/
|
||||||
public static void writeDescriptionFile(File f, NoCheatConfiguration configuration) {
|
private static void writeDescriptionFile(File f, NoCheatConfiguration configuration) {
|
||||||
try {
|
try {
|
||||||
if(f.getParentFile() != null)
|
if(f.getParentFile() != null)
|
||||||
f.getParentFile().mkdirs();
|
f.getParentFile().mkdirs();
|
||||||
@ -374,7 +375,7 @@ public class NoCheatConfiguration {
|
|||||||
public int getIntegerValue(String optionName) throws ConfigurationException {
|
public int getIntegerValue(String optionName) throws ConfigurationException {
|
||||||
return getIntegerOption(optionName).getIntegerValue();
|
return getIntegerOption(optionName).getIntegerValue();
|
||||||
}
|
}
|
||||||
public IntegerOption getIntegerOption(String optionName) throws ConfigurationException {
|
private IntegerOption getIntegerOption(String optionName) throws ConfigurationException {
|
||||||
|
|
||||||
Option o = getOption(optionName) ;
|
Option o = getOption(optionName) ;
|
||||||
if(o instanceof IntegerOption) {
|
if(o instanceof IntegerOption) {
|
||||||
@ -387,7 +388,7 @@ public class NoCheatConfiguration {
|
|||||||
public String getStringValue(String optionName) throws ConfigurationException {
|
public String getStringValue(String optionName) throws ConfigurationException {
|
||||||
return getStringOption(optionName).getValue();
|
return getStringOption(optionName).getValue();
|
||||||
}
|
}
|
||||||
public TextFieldOption getStringOption(String optionName) throws ConfigurationException {
|
private TextFieldOption getStringOption(String optionName) throws ConfigurationException {
|
||||||
|
|
||||||
Option o = getOption(optionName);
|
Option o = getOption(optionName);
|
||||||
if(o instanceof TextFieldOption) {
|
if(o instanceof TextFieldOption) {
|
||||||
@ -400,7 +401,7 @@ public class NoCheatConfiguration {
|
|||||||
public Level getLogLevelValue(String optionName) throws ConfigurationException {
|
public Level getLogLevelValue(String optionName) throws ConfigurationException {
|
||||||
return getLogLevelOption(optionName).getLevelValue();
|
return getLogLevelOption(optionName).getLevelValue();
|
||||||
}
|
}
|
||||||
public LevelOption getLogLevelOption(String optionName) throws ConfigurationException {
|
private LevelOption getLogLevelOption(String optionName) throws ConfigurationException {
|
||||||
|
|
||||||
Option o = getOption(optionName);
|
Option o = getOption(optionName);
|
||||||
if(o instanceof LevelOption) {
|
if(o instanceof LevelOption) {
|
||||||
@ -414,7 +415,8 @@ public class NoCheatConfiguration {
|
|||||||
public boolean getBooleanValue(String optionName) throws ConfigurationException {
|
public boolean getBooleanValue(String optionName) throws ConfigurationException {
|
||||||
return getBooleanOption(optionName).getBooleanValue();
|
return getBooleanOption(optionName).getBooleanValue();
|
||||||
}
|
}
|
||||||
public BooleanOption getBooleanOption(String optionName) throws ConfigurationException {
|
|
||||||
|
private BooleanOption getBooleanOption(String optionName) throws ConfigurationException {
|
||||||
|
|
||||||
Option o = getOption(optionName);
|
Option o = getOption(optionName);
|
||||||
if(o instanceof BooleanOption) {
|
if(o instanceof BooleanOption) {
|
||||||
|
@ -12,8 +12,8 @@ public class ParentOption extends Option {
|
|||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 3162246550749560727L;
|
private static final long serialVersionUID = 3162246550749560727L;
|
||||||
|
|
||||||
private LinkedList<Option> children = new LinkedList<Option>();
|
private final LinkedList<Option> children = new LinkedList<Option>();
|
||||||
private boolean editable;
|
private final boolean editable;
|
||||||
|
|
||||||
public ParentOption(String identifier, boolean editable) {
|
public ParentOption(String identifier, boolean editable) {
|
||||||
super(identifier);
|
super(identifier);
|
||||||
|
@ -8,7 +8,7 @@ public abstract class TextFieldOption extends ChildOption {
|
|||||||
private static final long serialVersionUID = -8189248456599421250L;
|
private static final long serialVersionUID = -8189248456599421250L;
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
private int length = -1;
|
private final int length;
|
||||||
|
|
||||||
public TextFieldOption(String name, String initialValue, int preferredLength) {
|
public TextFieldOption(String name, String initialValue, int preferredLength) {
|
||||||
|
|
||||||
@ -16,12 +16,6 @@ public abstract class TextFieldOption extends ChildOption {
|
|||||||
this.value = initialValue;
|
this.value = initialValue;
|
||||||
this.length = preferredLength;
|
this.length = preferredLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextFieldOption(String name, String parentName, String initialValue) {
|
|
||||||
|
|
||||||
super(name);
|
|
||||||
this.value = initialValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getValue() {
|
public String getValue() {
|
||||||
|
@ -6,14 +6,13 @@ import net.minecraft.server.Block;
|
|||||||
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
||||||
|
|
||||||
public class MovingData {
|
public class MovingData {
|
||||||
public int jumpPhase = 0;
|
public int jumpPhase = 0;
|
||||||
public int violationsInARow[] = { 0, 0, 0 };
|
public final int violationsInARow[] = { 0, 0, 0 };
|
||||||
public double horizFreedom = 0.0D;
|
public double horizFreedom = 0.0D;
|
||||||
public double vertFreedom = 0.0D;
|
public double vertFreedom = 0.0D;
|
||||||
public int vertFreedomCounter = 0;
|
public int vertFreedomCounter = 0;
|
||||||
@ -25,18 +24,13 @@ public class MovingData {
|
|||||||
public int summaryTask = -1;
|
public int summaryTask = -1;
|
||||||
public Level highestLogLevel = null;
|
public Level highestLogLevel = null;
|
||||||
public double maxYVelocity = 0.0D;
|
public double maxYVelocity = 0.0D;
|
||||||
public double runningThreshold = 0.0D;
|
public double violationLevel = 0.0D;
|
||||||
|
|
||||||
public boolean insideVehicle = false;
|
public boolean insideVehicle = false;
|
||||||
|
|
||||||
// Use to determine if an move event should be handled
|
|
||||||
public Location teleportTo = null;
|
|
||||||
|
|
||||||
// Use to track the world the player is in
|
|
||||||
public World lastSeenInWorld = null;
|
|
||||||
|
|
||||||
public Location teleportInitializedByMe = null;
|
public Location teleportInitializedByMe = null;
|
||||||
public boolean firstEventAfterRespawn = false;
|
public boolean wasTeleported = true;
|
||||||
|
public Location teleportedTo;
|
||||||
|
|
||||||
// Block types that may need to be treated specially
|
// Block types that may need to be treated specially
|
||||||
public static final int NONSOLID = 0; // 0x00000000
|
public static final int NONSOLID = 0; // 0x00000000
|
||||||
@ -80,7 +74,7 @@ public class MovingData {
|
|||||||
|
|
||||||
if(data.moving == null) {
|
if(data.moving == null) {
|
||||||
data.moving = new MovingData();
|
data.moving = new MovingData();
|
||||||
data.moving.lastSeenInWorld = p.getLocation().getWorld();
|
data.moving.teleportedTo = p.getLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
return data.moving;
|
return data.moving;
|
||||||
|
@ -6,8 +6,8 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
|||||||
|
|
||||||
public class PermissionData {
|
public class PermissionData {
|
||||||
|
|
||||||
public long lastUpdate[] = new long[11];
|
public final long lastUpdate[] = new long[11];
|
||||||
public boolean cache[] = new boolean[11];
|
public final boolean cache[] = new boolean[11];
|
||||||
|
|
||||||
public static final String[] permissionNames = new String[11];
|
public static final String[] permissionNames = new String[11];
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ import cc.co.evenprime.bukkit.nocheat.checks.AirbuildCheck;
|
|||||||
*/
|
*/
|
||||||
public class AirbuildBlockListener extends BlockListener {
|
public class AirbuildBlockListener extends BlockListener {
|
||||||
|
|
||||||
private AirbuildCheck check;
|
private final AirbuildCheck check;
|
||||||
|
|
||||||
public AirbuildBlockListener(AirbuildCheck check) {
|
public AirbuildBlockListener(AirbuildCheck check) {
|
||||||
this.check = check;
|
this.check = check;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.BogusitemsCheck;
|
|||||||
|
|
||||||
public class BogusitemsPlayerListener extends PlayerListener {
|
public class BogusitemsPlayerListener extends PlayerListener {
|
||||||
|
|
||||||
private BogusitemsCheck check;
|
private final BogusitemsCheck check;
|
||||||
|
|
||||||
public BogusitemsPlayerListener(BogusitemsCheck bogusitemsCheck) {
|
public BogusitemsPlayerListener(BogusitemsCheck bogusitemsCheck) {
|
||||||
check = bogusitemsCheck;
|
check = bogusitemsCheck;
|
||||||
|
@ -9,7 +9,7 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
|||||||
|
|
||||||
public class MovingEntityListener extends EntityListener {
|
public class MovingEntityListener extends EntityListener {
|
||||||
|
|
||||||
private MovingCheck check;
|
private final MovingCheck check;
|
||||||
|
|
||||||
public MovingEntityListener(MovingCheck check) {
|
public MovingEntityListener(MovingCheck check) {
|
||||||
this.check = check;
|
this.check = check;
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package cc.co.evenprime.bukkit.nocheat.listeners;
|
package cc.co.evenprime.bukkit.nocheat.listeners;
|
||||||
|
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.player.PlayerListener;
|
import org.bukkit.event.player.PlayerListener;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
|
|
||||||
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||||
|
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle events for Player related events
|
* Handle events for Player related events
|
||||||
@ -14,7 +17,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
|||||||
|
|
||||||
public class MovingPlayerListener extends PlayerListener {
|
public class MovingPlayerListener extends PlayerListener {
|
||||||
|
|
||||||
private MovingCheck check;
|
private final MovingCheck check;
|
||||||
|
|
||||||
public MovingPlayerListener(MovingCheck check) {
|
public MovingPlayerListener(MovingCheck check) {
|
||||||
this.check = check;
|
this.check = check;
|
||||||
@ -23,6 +26,28 @@ public class MovingPlayerListener extends PlayerListener {
|
|||||||
@Override
|
@Override
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
|
|
||||||
if(!event.isCancelled()) check.check(event);
|
if(event.isCancelled()) return;
|
||||||
|
|
||||||
|
final Player player = event.getPlayer();
|
||||||
|
|
||||||
|
// Is there something to do at all?
|
||||||
|
if(!check.skipCheck(player)) {
|
||||||
|
|
||||||
|
final MovingData data = MovingData.get(player);
|
||||||
|
final Location from = event.getFrom();
|
||||||
|
final Location to = event.getTo();
|
||||||
|
|
||||||
|
Location newTo = null;
|
||||||
|
|
||||||
|
if(check.shouldBeApplied(player, data, from, to)) {
|
||||||
|
// Check it
|
||||||
|
newTo = check.check(player, from, to, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did the checks decide we need a new To-Location?
|
||||||
|
if(newTo != null) {
|
||||||
|
event.setTo(new Location(newTo.getWorld(), newTo.getX(), newTo.getY(), newTo.getZ(), event.getTo().getYaw(), event.getTo().getPitch()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package cc.co.evenprime.bukkit.nocheat.listeners;
|
|||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
import org.bukkit.event.player.PlayerListener;
|
import org.bukkit.event.player.PlayerListener;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
import org.bukkit.event.player.PlayerPortalEvent;
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
|
||||||
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||||
@ -16,21 +16,22 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
|||||||
*/
|
*/
|
||||||
public class MovingPlayerMonitor extends PlayerListener {
|
public class MovingPlayerMonitor extends PlayerListener {
|
||||||
|
|
||||||
private MovingCheck check;
|
private final MovingCheck check;
|
||||||
|
|
||||||
public MovingPlayerMonitor(MovingCheck check) {
|
public MovingPlayerMonitor(MovingCheck check) {
|
||||||
this.check = check;
|
this.check = check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPlayerPortal(PlayerPortalEvent event) {
|
||||||
|
check.teleported(event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||||
check.teleported(event);
|
check.teleported(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
|
||||||
this.check.respawned(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
@ -41,7 +42,7 @@ public class MovingPlayerMonitor extends PlayerListener {
|
|||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
if(!event.isCancelled()) {
|
if(!event.isCancelled()) {
|
||||||
MovingData data = MovingData.get(event.getPlayer());
|
MovingData data = MovingData.get(event.getPlayer());
|
||||||
data.lastSeenInWorld = event.getPlayer().getLocation().getWorld();
|
|
||||||
if( event.getPlayer().isInsideVehicle()) {
|
if( event.getPlayer().isInsideVehicle()) {
|
||||||
data.setBackPoint = event.getTo();
|
data.setBackPoint = event.getTo();
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.NukeCheck;
|
|||||||
|
|
||||||
public class NukeBlockListener extends BlockListener {
|
public class NukeBlockListener extends BlockListener {
|
||||||
|
|
||||||
private NukeCheck check;
|
private final NukeCheck check;
|
||||||
|
|
||||||
public NukeBlockListener(NukeCheck check) {
|
public NukeBlockListener(NukeCheck check) {
|
||||||
this.check = check;
|
this.check = check;
|
||||||
|
@ -13,7 +13,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.SpeedhackCheck;
|
|||||||
*/
|
*/
|
||||||
public class SpeedhackPlayerListener extends PlayerListener {
|
public class SpeedhackPlayerListener extends PlayerListener {
|
||||||
|
|
||||||
private SpeedhackCheck check;
|
private final SpeedhackCheck check;
|
||||||
|
|
||||||
public SpeedhackPlayerListener(SpeedhackCheck check) {
|
public SpeedhackPlayerListener(SpeedhackCheck check) {
|
||||||
this.check = check;
|
this.check = check;
|
||||||
|
@ -87,7 +87,7 @@ public class SimpleYaml {
|
|||||||
/* Convenience methods for retrieving values start here */
|
/* Convenience methods for retrieving values start here */
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Object getProperty(String path, Map<String, Object> node) {
|
private final static Object getProperty(String path, Map<String, Object> node) {
|
||||||
if (!path.contains(".")) {
|
if (!path.contains(".")) {
|
||||||
return node.get(path);
|
return node.get(path);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user