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
|
||||
|
||||
main: cc.co.evenprime.bukkit.nocheat.NoCheat
|
||||
version: 1.08c
|
||||
version: 1.09
|
||||
|
||||
softdepend: [ Permissions, CraftIRC ]
|
||||
|
||||
|
@ -17,7 +17,7 @@ public class LogAction extends Action {
|
||||
|
||||
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);
|
||||
this.level = level;
|
||||
}
|
||||
|
@ -16,12 +16,12 @@ public abstract class Check {
|
||||
|
||||
private boolean active = false;
|
||||
private boolean listenersRegistered = false;
|
||||
private int permission;
|
||||
private String name;
|
||||
protected NoCheat plugin;
|
||||
private final int permission;
|
||||
private final String name;
|
||||
protected final NoCheat plugin;
|
||||
|
||||
// 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) {
|
||||
this.plugin = plugin;
|
||||
@ -34,6 +34,7 @@ public abstract class Check {
|
||||
checkOPs = false;
|
||||
}
|
||||
|
||||
|
||||
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.Listener;
|
||||
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.plugin.PluginManager;
|
||||
import org.bukkit.util.Vector;
|
||||
@ -41,29 +39,19 @@ 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();
|
||||
}
|
||||
|
||||
// How many move events can a player have in air before he is expected to lose altitude (or 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.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;
|
||||
private final int ticksBeforeSummary = 100;
|
||||
|
||||
public long statisticElapsedTimeNano = 0;
|
||||
|
||||
public boolean allowFlying;
|
||||
public boolean allowFakeSneak;
|
||||
public boolean allowFastSwim;
|
||||
public boolean checkOPs;
|
||||
|
||||
private boolean waterElevators;
|
||||
|
||||
@ -77,6 +65,9 @@ public class MovingCheck extends Check {
|
||||
|
||||
private boolean enforceTeleport;
|
||||
|
||||
private final MovingEventHelper helper;
|
||||
private final FlyingCheck flyingCheck;
|
||||
private final RunningCheck runningCheck;
|
||||
|
||||
|
||||
private static final double magic = 0.30000001192092896D;
|
||||
@ -90,203 +81,88 @@ public class MovingCheck extends Check {
|
||||
* Fourth treat any occured violations as configured
|
||||
* @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);
|
||||
|
||||
// event.getFrom() is intentional here
|
||||
if(shouldBeIgnored(player, data, from, to)) {
|
||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||
statisticTotalEvents++;
|
||||
return;
|
||||
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;
|
||||
|
||||
/***************** REFINE EVENT DATA FOR CHECKS ***************/
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/**** Horizontal movement check START ****/
|
||||
|
||||
// First check the distance the player has moved horizontally
|
||||
final double xDistance = from.getX()-to.getX();
|
||||
final double zDistance = from.getZ()-to.getZ();
|
||||
|
||||
double combined = Math.sqrt((xDistance*xDistance + zDistance*zDistance));
|
||||
|
||||
// If the target is a bed and distance not too big, allow it always
|
||||
// Bukkit prevents using blocks behind walls already, so I don't have to check for that
|
||||
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId() && combined < 8.0D) {
|
||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||
statisticTotalEvents++;
|
||||
return;
|
||||
if(runCheck) {
|
||||
result += Math.max(0D, runningCheck.check(from, to,
|
||||
player.isSneaking(), (fromType & toType & MovingEventHelper.LIQUID) > 0, data));
|
||||
}
|
||||
|
||||
final int onGroundFrom = playerIsOnGround(from, 0.0D);
|
||||
|
||||
double overLimit = 0.0D;
|
||||
/********* HANDLE/COMBINE THE RESULTS OF THE CHECKS ***********/
|
||||
|
||||
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.jumpPhase++;
|
||||
|
||||
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(data.setBackPoint == null || canFly)
|
||||
l = from;
|
||||
else
|
||||
l = data.setBackPoint;
|
||||
|
||||
if(!canFly && data.jumpPhase > jumpingLimit)
|
||||
limit += jumpHeight - (data.jumpPhase-jumpingLimit) * 0.2D;
|
||||
else limit += jumpHeight;
|
||||
|
||||
final int onGroundTo = playerIsOnGround(to, 0.0D);
|
||||
|
||||
if(onGroundTo != MovingData.NONSOLID) limit += stepHeight;
|
||||
|
||||
final double distance = to.getY() - l.getY();
|
||||
|
||||
// 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
|
||||
data.jumpPhase++; // Enter next phase of the flight
|
||||
// If we have no setback point, create one now
|
||||
if(data.setBackPoint == null) {
|
||||
newSetBack = from;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**** Vertical movement check END ****/
|
||||
|
||||
/****** Violation Handling START *****/
|
||||
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) {
|
||||
if(result <= 0) {
|
||||
if(fromOnGround) {
|
||||
data.setBackPoint = from;
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
else if(toOnGround) {
|
||||
data.jumpPhase = 0;
|
||||
}
|
||||
}
|
||||
else if(result > 0) {
|
||||
// Increment violation counter
|
||||
data.violationLevel += result;
|
||||
if(data.setBackPoint == null) data.setBackPoint = from;
|
||||
}
|
||||
|
||||
if(violationLevel >= 0) {
|
||||
setupSummaryTask(event.getPlayer(), data);
|
||||
|
||||
data.violationsInARow[violationLevel]++;
|
||||
if(result > 0 && data.violationLevel > 1) {
|
||||
|
||||
action(event, event.getPlayer(), from, to, actions[violationLevel], data.violationsInARow[violationLevel], data);
|
||||
setupSummaryTask(player, data);
|
||||
|
||||
int level = limitCheck(data.violationLevel-1);
|
||||
|
||||
data.violationsInARow[level]++;
|
||||
|
||||
newToLocation = action(player, from, to, actions[level], data.violationsInARow[level], data);
|
||||
}
|
||||
}
|
||||
|
||||
/****** Violation Handling END *****/
|
||||
// Slowly reduce the level with each event
|
||||
data.violationLevel *= 0.97;
|
||||
data.horizFreedom *= 0.97;
|
||||
|
||||
statisticElapsedTimeNano += System.nanoTime() - startTime;
|
||||
statisticTotalEvents++;
|
||||
}
|
||||
|
||||
private double calculateVerticalLimit(final MovingData data, final int 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 != MovingData.NONSOLID && data.vertFreedomCounter <= 0) {
|
||||
data.vertFreedom = 0.0D;
|
||||
}
|
||||
|
||||
return limit;
|
||||
return newToLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,47 +173,37 @@ public class MovingCheck extends Check {
|
||||
* @param to
|
||||
* @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) {
|
||||
data.firstEventAfterRespawn = false;
|
||||
data.teleportTo = from.clone();
|
||||
if(player.isDead() || player.isInsideVehicle() || data.insideVehicle) return false;
|
||||
|
||||
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+)
|
||||
|
||||
// data.teleportTo gets a location assigned if a teleport event is successfully executed.
|
||||
// But there is a delay between the serverside execution of the teleport (instantly) and
|
||||
// the execution on the client side (may take an arbitrary time). During that time, the
|
||||
// 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;
|
||||
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 {
|
||||
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(player.isDead() || data.insideVehicle || player.isInsideVehicle()) {
|
||||
return true;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
// If the target is a bed, don't check (going to bed is a kind of mini teleport...)
|
||||
if(to.getWorld().getBlockTypeIdAt(to) == Material.BED_BLOCK.getId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a task with bukkit that will be run a short time from now, displaying how many
|
||||
@ -355,6 +221,8 @@ public class MovingCheck extends Check {
|
||||
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;
|
||||
@ -388,7 +256,7 @@ public class MovingCheck extends Check {
|
||||
}
|
||||
|
||||
if(!event.isCancelled()) {
|
||||
data.teleportTo = event.getTo().clone();
|
||||
data.wasTeleported = true;
|
||||
data.setBackPoint = event.getTo().clone();
|
||||
//data.lastLocation = event.getTo().clone();
|
||||
}
|
||||
@ -397,17 +265,6 @@ public class MovingCheck extends Check {
|
||||
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
|
||||
* 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
|
||||
* @param event
|
||||
* @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;
|
||||
|
||||
|
||||
for(Action a : actions) {
|
||||
if(a.firstAfter <= violations) {
|
||||
if(a.firstAfter == violations || a.repeat) {
|
||||
@ -469,9 +329,9 @@ public class MovingCheck extends Check {
|
||||
data.setBackPoint.setY(y);
|
||||
|
||||
// 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
|
||||
}
|
||||
@ -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");
|
||||
|
||||
checkOPs = config.getBooleanValue("moving.checkops");
|
||||
|
||||
logMessage = config.getStringValue("moving.logmessage").
|
||||
replace("[player]", "%1$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.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_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);
|
||||
|
||||
private final String value;
|
||||
private String description;
|
||||
private Level level;
|
||||
private final String description;
|
||||
private final Level level;
|
||||
|
||||
private LogLevel(String value, String description, Level level) {
|
||||
this.value = value;
|
||||
|
@ -35,7 +35,7 @@ public class NoCheatConfiguration {
|
||||
|
||||
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>();
|
||||
|
||||
@ -50,6 +50,7 @@ public class NoCheatConfiguration {
|
||||
|
||||
// Setup the configuration tree
|
||||
config(configurationFile, descriptionsFile);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -266,7 +267,7 @@ public class NoCheatConfiguration {
|
||||
}
|
||||
|
||||
writeConfigFile(configurationFile, this);
|
||||
//writeDescriptionFile(descriptionsFile, this);
|
||||
writeDescriptionFile(descriptionsFile, this);
|
||||
}
|
||||
|
||||
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>();
|
||||
String[] parts = string.split(" ");
|
||||
@ -350,7 +351,7 @@ public class NoCheatConfiguration {
|
||||
* Write a file with the descriptions of all options
|
||||
* @param f
|
||||
*/
|
||||
public static void writeDescriptionFile(File f, NoCheatConfiguration configuration) {
|
||||
private static void writeDescriptionFile(File f, NoCheatConfiguration configuration) {
|
||||
try {
|
||||
if(f.getParentFile() != null)
|
||||
f.getParentFile().mkdirs();
|
||||
@ -374,7 +375,7 @@ public class NoCheatConfiguration {
|
||||
public int getIntegerValue(String optionName) throws ConfigurationException {
|
||||
return getIntegerOption(optionName).getIntegerValue();
|
||||
}
|
||||
public IntegerOption getIntegerOption(String optionName) throws ConfigurationException {
|
||||
private IntegerOption getIntegerOption(String optionName) throws ConfigurationException {
|
||||
|
||||
Option o = getOption(optionName) ;
|
||||
if(o instanceof IntegerOption) {
|
||||
@ -387,7 +388,7 @@ public class NoCheatConfiguration {
|
||||
public String getStringValue(String optionName) throws ConfigurationException {
|
||||
return getStringOption(optionName).getValue();
|
||||
}
|
||||
public TextFieldOption getStringOption(String optionName) throws ConfigurationException {
|
||||
private TextFieldOption getStringOption(String optionName) throws ConfigurationException {
|
||||
|
||||
Option o = getOption(optionName);
|
||||
if(o instanceof TextFieldOption) {
|
||||
@ -400,7 +401,7 @@ public class NoCheatConfiguration {
|
||||
public Level getLogLevelValue(String optionName) throws ConfigurationException {
|
||||
return getLogLevelOption(optionName).getLevelValue();
|
||||
}
|
||||
public LevelOption getLogLevelOption(String optionName) throws ConfigurationException {
|
||||
private LevelOption getLogLevelOption(String optionName) throws ConfigurationException {
|
||||
|
||||
Option o = getOption(optionName);
|
||||
if(o instanceof LevelOption) {
|
||||
@ -414,7 +415,8 @@ public class NoCheatConfiguration {
|
||||
public boolean getBooleanValue(String optionName) throws ConfigurationException {
|
||||
return getBooleanOption(optionName).getBooleanValue();
|
||||
}
|
||||
public BooleanOption getBooleanOption(String optionName) throws ConfigurationException {
|
||||
|
||||
private BooleanOption getBooleanOption(String optionName) throws ConfigurationException {
|
||||
|
||||
Option o = getOption(optionName);
|
||||
if(o instanceof BooleanOption) {
|
||||
|
@ -12,8 +12,8 @@ public class ParentOption extends Option {
|
||||
*/
|
||||
private static final long serialVersionUID = 3162246550749560727L;
|
||||
|
||||
private LinkedList<Option> children = new LinkedList<Option>();
|
||||
private boolean editable;
|
||||
private final LinkedList<Option> children = new LinkedList<Option>();
|
||||
private final boolean editable;
|
||||
|
||||
public ParentOption(String identifier, boolean editable) {
|
||||
super(identifier);
|
||||
|
@ -8,7 +8,7 @@ public abstract class TextFieldOption extends ChildOption {
|
||||
private static final long serialVersionUID = -8189248456599421250L;
|
||||
|
||||
private String value;
|
||||
private int length = -1;
|
||||
private final int length;
|
||||
|
||||
public TextFieldOption(String name, String initialValue, int preferredLength) {
|
||||
|
||||
@ -17,12 +17,6 @@ public abstract class TextFieldOption extends ChildOption {
|
||||
this.length = preferredLength;
|
||||
}
|
||||
|
||||
public TextFieldOption(String name, String parentName, String initialValue) {
|
||||
|
||||
super(name);
|
||||
this.value = initialValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
|
@ -6,14 +6,13 @@ import net.minecraft.server.Block;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
||||
|
||||
public class MovingData {
|
||||
public int jumpPhase = 0;
|
||||
public int violationsInARow[] = { 0, 0, 0 };
|
||||
public final int violationsInARow[] = { 0, 0, 0 };
|
||||
public double horizFreedom = 0.0D;
|
||||
public double vertFreedom = 0.0D;
|
||||
public int vertFreedomCounter = 0;
|
||||
@ -25,18 +24,13 @@ public class MovingData {
|
||||
public int summaryTask = -1;
|
||||
public Level highestLogLevel = null;
|
||||
public double maxYVelocity = 0.0D;
|
||||
public double runningThreshold = 0.0D;
|
||||
public double violationLevel = 0.0D;
|
||||
|
||||
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 boolean firstEventAfterRespawn = false;
|
||||
public boolean wasTeleported = true;
|
||||
public Location teleportedTo;
|
||||
|
||||
// Block types that may need to be treated specially
|
||||
public static final int NONSOLID = 0; // 0x00000000
|
||||
@ -80,7 +74,7 @@ public class MovingData {
|
||||
|
||||
if(data.moving == null) {
|
||||
data.moving = new MovingData();
|
||||
data.moving.lastSeenInWorld = p.getLocation().getWorld();
|
||||
data.moving.teleportedTo = p.getLocation();
|
||||
}
|
||||
|
||||
return data.moving;
|
||||
|
@ -6,8 +6,8 @@ import cc.co.evenprime.bukkit.nocheat.NoCheatData;
|
||||
|
||||
public class PermissionData {
|
||||
|
||||
public long lastUpdate[] = new long[11];
|
||||
public boolean cache[] = new boolean[11];
|
||||
public final long lastUpdate[] = new long[11];
|
||||
public final boolean cache[] = new boolean[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 {
|
||||
|
||||
private AirbuildCheck check;
|
||||
private final AirbuildCheck check;
|
||||
|
||||
public AirbuildBlockListener(AirbuildCheck check) {
|
||||
this.check = check;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.BogusitemsCheck;
|
||||
|
||||
public class BogusitemsPlayerListener extends PlayerListener {
|
||||
|
||||
private BogusitemsCheck check;
|
||||
private final BogusitemsCheck check;
|
||||
|
||||
public BogusitemsPlayerListener(BogusitemsCheck bogusitemsCheck) {
|
||||
check = bogusitemsCheck;
|
||||
|
@ -9,7 +9,7 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||
|
||||
public class MovingEntityListener extends EntityListener {
|
||||
|
||||
private MovingCheck check;
|
||||
private final MovingCheck check;
|
||||
|
||||
public MovingEntityListener(MovingCheck check) {
|
||||
this.check = check;
|
||||
|
@ -1,10 +1,13 @@
|
||||
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.PlayerMoveEvent;
|
||||
|
||||
import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||
import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||
|
||||
/**
|
||||
* Handle events for Player related events
|
||||
@ -14,7 +17,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||
|
||||
public class MovingPlayerListener extends PlayerListener {
|
||||
|
||||
private MovingCheck check;
|
||||
private final MovingCheck check;
|
||||
|
||||
public MovingPlayerListener(MovingCheck check) {
|
||||
this.check = check;
|
||||
@ -23,6 +26,28 @@ public class MovingPlayerListener extends PlayerListener {
|
||||
@Override
|
||||
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.PlayerListener;
|
||||
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 cc.co.evenprime.bukkit.nocheat.checks.MovingCheck;
|
||||
@ -16,21 +16,22 @@ import cc.co.evenprime.bukkit.nocheat.data.MovingData;
|
||||
*/
|
||||
public class MovingPlayerMonitor extends PlayerListener {
|
||||
|
||||
private MovingCheck check;
|
||||
private final MovingCheck check;
|
||||
|
||||
public MovingPlayerMonitor(MovingCheck check) {
|
||||
this.check = check;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerPortal(PlayerPortalEvent event) {
|
||||
check.teleported(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
||||
check.teleported(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
||||
this.check.respawned(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||
@ -41,7 +42,7 @@ public class MovingPlayerMonitor extends PlayerListener {
|
||||
public void onPlayerMove(PlayerMoveEvent event) {
|
||||
if(!event.isCancelled()) {
|
||||
MovingData data = MovingData.get(event.getPlayer());
|
||||
data.lastSeenInWorld = event.getPlayer().getLocation().getWorld();
|
||||
|
||||
if( event.getPlayer().isInsideVehicle()) {
|
||||
data.setBackPoint = event.getTo();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.NukeCheck;
|
||||
|
||||
public class NukeBlockListener extends BlockListener {
|
||||
|
||||
private NukeCheck check;
|
||||
private final NukeCheck check;
|
||||
|
||||
public NukeBlockListener(NukeCheck check) {
|
||||
this.check = check;
|
||||
|
@ -13,7 +13,7 @@ import cc.co.evenprime.bukkit.nocheat.checks.SpeedhackCheck;
|
||||
*/
|
||||
public class SpeedhackPlayerListener extends PlayerListener {
|
||||
|
||||
private SpeedhackCheck check;
|
||||
private final SpeedhackCheck check;
|
||||
|
||||
public SpeedhackPlayerListener(SpeedhackCheck check) {
|
||||
this.check = check;
|
||||
|
@ -87,7 +87,7 @@ public class SimpleYaml {
|
||||
/* Convenience methods for retrieving values start here */
|
||||
|
||||
@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(".")) {
|
||||
return node.get(path);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user