[BLEEDING/INCOMPLETE] More strict go on vehicles.

Roughly this line of develpment has to do with:
* Prevent destroying ones own vehicle [INCOMPLETE: conflict with older
MC versions.].
* More careful set-back handling.
* Reset the players position to that of the vehicle if the player moves
too far off (likely does not have effect, needs more testing). In
principle this is intended to trigger a teleport, the normal player is
intended to not notice, but no guarantees yet.

Not configurable yet, might not work 100%, yet.
This commit is contained in:
asofold 2013-11-04 09:22:33 +01:00
parent ae6510aaa0
commit f597f8bded
3 changed files with 275 additions and 254 deletions

View File

@ -76,7 +76,7 @@ public class MovingData extends ACheckData {
return playersMap.remove(playerName);
}
public static void clear(){
public static void clear() {
playersMap.clear();
}
@ -84,9 +84,9 @@ public class MovingData extends ACheckData {
* Clear data related to the given world.
* @param world The world that gets unloaded.
*/
public static void onWorldUnload(final World world){
public static void onWorldUnload(final World world) {
final String worldName = world.getName();
for (final MovingData data : playersMap.values()){
for (final MovingData data : playersMap.values()) {
data.onWorldUnload(worldName);
}
}
@ -263,7 +263,7 @@ public class MovingData extends ACheckData {
/**
* Move event: Mildly reset some data, prepare setting a new to-Location.
*/
public void prepareSetBack(final Location loc){
public void prepareSetBack(final Location loc) {
clearAccounting();
sfJumpPhase = 0;
sfLastYDist = sfLastHDist = Double.MAX_VALUE;
@ -278,7 +278,7 @@ public class MovingData extends ACheckData {
* Just reset the "last locations" references.
* @param loc
*/
public void resetPositions(final Location loc){
public void resetPositions(final Location loc) {
if (loc == null) resetPositions(Double.MAX_VALUE, 0, 0);
else resetPositions(loc.getX(), loc.getY(), loc.getZ());
}
@ -323,6 +323,7 @@ public class MovingData extends ACheckData {
public void clearMorePacketsData() {
morePacketsSetback = null;
morePacketsVehicleSetback = null;
// TODO: Also reset other data ?
}
/**
@ -338,8 +339,8 @@ public class MovingData extends ACheckData {
* Set the set-back location, this will also adjust the y-coordinate for some block types (at least air).
* @param loc
*/
public void setSetBack(final PlayerLocation loc){
if (setBack == null){
public void setSetBack(final PlayerLocation loc) {
if (setBack == null) {
setBack = loc.getLocation();
}
else{
@ -352,8 +353,8 @@ public class MovingData extends ACheckData {
* Convenience method.
* @param loc
*/
public void setSetBack(final Location loc){
if (setBack == null){
public void setSetBack(final Location loc) {
if (setBack == null) {
setBack = LocUtil.clone(loc);
}
else{
@ -366,7 +367,7 @@ public class MovingData extends ACheckData {
* @param ref
* @return
*/
public Location getSetBack(final Location ref){
public Location getSetBack(final Location ref) {
return LocUtil.clone(setBack, ref);
}
@ -409,7 +410,7 @@ public class MovingData extends ACheckData {
* Return a copy of the teleported-to Location.
* @return
*/
public final Location getTeleported(){
public final Location getTeleported() {
// TODO: here a reference might do.
return teleported == null ? teleported : LocUtil.clone(teleported);
}
@ -489,7 +490,7 @@ public class MovingData extends ACheckData {
/**
* Currently only applies to horizontal velocity.
*/
public void removeAllVelocity(){
public void removeAllVelocity() {
hVelActive.clear();
hVelQueued.clear();
}
@ -504,20 +505,20 @@ public class MovingData extends ACheckData {
Iterator<Velocity> it;
// Active.
it = hVelActive.iterator();
while (it.hasNext()){
while (it.hasNext()) {
final Velocity vel = it.next();
// TODO: 0.001 can be stretched somewhere else, most likely...
// TODO: Somehow use tick here too (actCount, valCount)?
if (vel.valCount <= 0 || vel.value <= 0.001){
if (vel.valCount <= 0 || vel.value <= 0.001) {
// System.out.prsintln("Invalidate active: " + vel);
it.remove();
}
}
// Queued.
it = hVelQueued.iterator();
while (it.hasNext()){
while (it.hasNext()) {
final Velocity vel = it.next();
if (vel.actCount <= 0 || vel.tick < tick){
if (vel.actCount <= 0 || vel.tick < tick) {
// System.out.println("Invalidate queued: " + vel);
it.remove();
}
@ -527,12 +528,12 @@ public class MovingData extends ACheckData {
/**
* Called for moving events, increase age of velocity, decrease amounts, check which entries are invalid. Both horizontal and vertical.
*/
public void velocityTick(){
public void velocityTick() {
// Horizontal velocity (intermediate concept).
// Decrease counts for active.
// TODO: Actual friction. Could pass as an argument (special value for not to be used).
// TODO: Consider removing already invalidated here.
for (final Velocity vel : hVelActive){
for (final Velocity vel : hVelActive) {
vel.valCount --;
vel.sum += vel.value;
vel.value *= 0.93; // vel.frictionFactor;
@ -540,12 +541,12 @@ public class MovingData extends ACheckData {
}
// Decrease counts for queued.
final Iterator<Velocity> it = hVelQueued.iterator();
while (it.hasNext()){
while (it.hasNext()) {
it.next().actCount --;
}
// Vertical velocity (old concept).
if (verticalVelocity <= 0.09D){
if (verticalVelocity <= 0.09D) {
verticalVelocityUsed ++;
verticalVelocityCounter--;
}
@ -554,8 +555,8 @@ public class MovingData extends ACheckData {
verticalFreedom += verticalVelocity;
verticalVelocity = Math.max(0.0, verticalVelocity -0.09);
// TODO: Consider using up counter ? / better use velocity entries / even better use x,y,z entries right away .
} else if (verticalFreedom > 0.001D){
if (verticalVelocityUsed == 1 && verticalVelocity > 1.0){
} else if (verticalFreedom > 0.001D) {
if (verticalVelocityUsed == 1 && verticalVelocity > 1.0) {
// Workarounds.
verticalVelocityUsed = 0;
verticalVelocity = 0;
@ -576,7 +577,7 @@ public class MovingData extends ACheckData {
public double getHorizontalFreedom() {
// TODO: model/calculate it as accurate as possible...
double f = 0;
for (final Velocity vel : hVelActive){
for (final Velocity vel : hVelActive) {
f += vel.value;
}
return f;
@ -593,12 +594,12 @@ public class MovingData extends ACheckData {
public double useHorizontalVelocity(final double amount) {
final Iterator<Velocity> it = hVelQueued.iterator();
double used = 0;
while (it.hasNext()){
while (it.hasNext()) {
final Velocity vel = it.next();
used += vel.value;
hVelActive.add(vel);
it.remove();
if (used >= amount){
if (used >= amount) {
break;
}
}
@ -612,10 +613,10 @@ public class MovingData extends ACheckData {
* @return
*/
public boolean isSetBack(final Location loc) {
if (loc == null || setBack == null){
if (loc == null || setBack == null) {
return false;
}
if (!loc.getWorld().getName().equals(setBack.getWorld().getName())){
if (!loc.getWorld().getName().equals(setBack.getWorld().getName())) {
return false;
}
return loc.getX() == setBack.getX() && loc.getY() == setBack.getY() && loc.getZ() == setBack.getZ();
@ -632,15 +633,15 @@ public class MovingData extends ACheckData {
* Clean up data related to worlds with the given name (not case-sensitive).
* @param worldName
*/
public void onWorldUnload(final String worldName){
public void onWorldUnload(final String worldName) {
// TODO: Unlink world references.
if (teleported != null && worldName.equalsIgnoreCase(teleported.getWorld().getName())){
if (teleported != null && worldName.equalsIgnoreCase(teleported.getWorld().getName())) {
resetTeleported();
}
if (setBack != null && worldName.equalsIgnoreCase(setBack.getWorld().getName())){
if (setBack != null && worldName.equalsIgnoreCase(setBack.getWorld().getName())) {
clearFlyData();
}
if (morePacketsSetback != null && worldName.equalsIgnoreCase(morePacketsSetback.getWorld().getName()) || morePacketsVehicleSetback != null && worldName.equalsIgnoreCase(morePacketsVehicleSetback.getWorld().getName())){
if (morePacketsSetback != null && worldName.equalsIgnoreCase(morePacketsSetback.getWorld().getName()) || morePacketsVehicleSetback != null && worldName.equalsIgnoreCase(morePacketsVehicleSetback.getWorld().getName())) {
clearMorePacketsData();
clearNoFallData(); // just in case.
}
@ -650,7 +651,7 @@ public class MovingData extends ACheckData {
if (walkSpeed > this.walkSpeed) {
this.walkSpeed = walkSpeed;
this.speedTick = tick;
} else if (walkSpeed < this.walkSpeed){
} else if (walkSpeed < this.walkSpeed) {
if (tick - this.speedTick > speedGrace) {
this.walkSpeed = walkSpeed;
this.speedTick = tick;
@ -664,7 +665,7 @@ public class MovingData extends ACheckData {
if (flySpeed > this.flySpeed) {
this.flySpeed = flySpeed;
this.speedTick = tick;
} else if (flySpeed < this.flySpeed){
} else if (flySpeed < this.flySpeed) {
if (tick - this.speedTick > speedGrace) {
this.flySpeed = flySpeed;
this.speedTick = tick;

View File

@ -106,7 +106,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @param cc
* @return
*/
public static final boolean shouldCheckSurvivalFly(final Player player, final MovingData data, final MovingConfig cc){
public static final boolean shouldCheckSurvivalFly(final Player player, final MovingData data, final MovingConfig cc) {
return cc.survivalFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_SURVIVALFLY) && !player.hasPermission(Permissions.MOVING_SURVIVALFLY) &&
(cc.ignoreCreative || player.getGameMode() != GameMode.CREATIVE) && !player.isFlying() && (cc.ignoreAllowFlight || !player.getAllowFlight());
}
@ -127,14 +127,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (!restored && data.hasSetBack()) {
final Location setBack = data.getSetBack(loc);
pLoc.set(setBack, player);
if (!pLoc.isIllegal()){
if (!pLoc.isIllegal()) {
event.setFrom(setBack);
event.setTo(setBack);
restored = true;
}
else data.resetSetBack();
}
if (!restored){
if (!restored) {
pLoc.set(loc, player);
if (!pLoc.isIllegal()) {
event.setFrom(loc);
@ -143,7 +143,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
}
pLoc.cleanup();
if (!restored && MovingConfig.getConfig(player).tempKickIllegal){
if (!restored && MovingConfig.getConfig(player).tempKickIllegal) {
// TODO: correct the location ?
NCPAPIProvider.getNoCheatPlusAPI().denyLogin(player.getName(), 24L * 60L * 60L * 1000L);
LogUtil.logSevere("[NCP] could not restore location for " + player.getName() + " deny login for 24 hours");
@ -255,7 +255,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @param id
* @return
*/
private static boolean canJumpOffTop(final int id){
private static boolean canJumpOffTop(final int id) {
// TODO: Test if this can be removed!
return BlockProperties.isGround(id) || BlockProperties.isSolid(id);
}
@ -308,13 +308,13 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
Location target = null;
final boolean sfCheck = shouldCheckSurvivalFly(player, data, cc);
if (sfCheck) target = data.getSetBack(loc);
if (target == null){
if (target == null) {
// TODO: Add something to guess the best set back location (possibly data.guessSetBack(Location)).
target = loc;
}
if (target != null){
if (target != null) {
// Actually this should not possibly be null, this is a block for "future" purpose, feel free to criticize it.
if (sfCheck && cc.sfFallDamage && noFall.isEnabled(player)){
if (sfCheck && cc.sfFallDamage && noFall.isEnabled(player)) {
// Check if to deal damage.
double y = loc.getY();
if (data.hasSetBack()) y = Math.min(y, data.getSetBackY());
@ -381,10 +381,11 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* \____|_| |_|\__,_|_| |_|\__, |\___|
* |___/
*/
if (event.getPlayer().getGameMode() == GameMode.CREATIVE || event.getNewGameMode() == GameMode.CREATIVE){
if (event.getPlayer().getGameMode() == GameMode.CREATIVE || event.getNewGameMode() == GameMode.CREATIVE) {
final MovingData data = MovingData.getData(event.getPlayer());
data.clearFlyData();
data.clearMorePacketsData();
// TODO: Set new set-back if any fly check is activated.
}
}
@ -416,59 +417,53 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingData data = MovingData.getData(player);
// TODO: Check illegal moves here anyway (!).
final Location from = event.getFrom();
final Location to = event.getTo();
Location newTo = null;
// Ignore players in vehicles.
if (player.isInsideVehicle()){
// Workaround for pigs and other (1.5.x and before)!
// Note that with 1.6 not even PlayerMove fires for horses and pigs.
// (isInsideVehicle is the faster check without object creation, do re-check though, if it changes to only check for Vehicle instances.)
final Entity vehicle = CheckUtils.getLastNonPlayerVehicle(player);
data.wasInVehicle = true;
// TODO: Check illegal moves here anyway (!).
// TODO: Check if vehicle move logs correctly (fake).
// Early return checks (no full processing).
final boolean earlyReturn;
if (player.isInsideVehicle()) {
// No full processing for players in vehicles.
newTo = onPlayerMoveVehicle(player, from, to, data);
earlyReturn = true;
} else if (player.isDead() || player.isSleeping()) {
// Ignore dead players.
data.sfHoverTicks = -1;
data.removeAllVelocity();
data.sfLowJump = false;
if (vehicle != null){
final Location vLoc = vehicle.getLocation();
// (Auto detection of missing events, might fire one time too many per plugin run.)
if (!normalVehicles.contains(vehicle.getType())) {
onVehicleMove(vehicle, vLoc, vLoc, true);
} else {
data.vehicleConsistency = MoveConsistency.getConsistency(event.getFrom(), event.getTo(), vLoc);
// TODO: Consider TeleportUtil.forceMount or similar.
}
earlyReturn = true;
} else if (player.isSleeping()) {
// Ignore sleeping playerrs.
// TODO: sleeping: (which cb!) System.out.println("-> " + player.isSleepingIgnored());
data.sfHoverTicks = -1;
earlyReturn = true;
} else if (!from.getWorld().equals(to.getWorld())) {
// Keep hover ticks.
// Ignore changing worlds.
earlyReturn = true;
} else {
// COntinue with full processing.
earlyReturn = false;
}
// TODO: Might log base parts here (+extras).
if (earlyReturn) {
// TODO: Log "early return: " + tags.
if (newTo != null) {
event.setTo(newTo);
}
return;
}
// Ignore dead players.
if (player.isDead()){
data.sfHoverTicks = -1;
return;
}
// Ignore sleeping players.
if (player.isSleeping()){
data.sfHoverTicks = -1;
// TODO: check (which cb!) System.out.println("-> " + player.isSleepingIgnored());
return;
}
final Location from = event.getFrom();
final Location to = event.getTo();
// Ignore changing worlds.
if (!from.getWorld().equals(to.getWorld())){
// Keep hover ticks.
return;
}
// TODO: Order this to above "early return"?
// Set up data / caching.
final MoveInfo moveInfo;
if (parkedInfo.isEmpty()) moveInfo = new MoveInfo(mcAccess);
else moveInfo = parkedInfo.remove(parkedInfo.size() - 1);
final MovingConfig cc = MovingConfig.getConfig(player);
moveInfo.set(player, from, to, cc.yOnGround);
// TODO: Data resetting above ?
data.noFallAssumeGround = false;
data.resetTeleported();
// Debug.
@ -484,12 +479,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
final long time = System.currentTimeMillis();
if (player.isSprinting()){
if (player.isSprinting()) {
//
if (player.getFoodLevel() > 5){
if (player.getFoodLevel() > 5) {
data.timeSprinting = time;
}
else if (time < data.timeSprinting){
else if (time < data.timeSprinting) {
data.timeSprinting = 0;
}
// else: keep sprinting time.
@ -506,17 +501,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
pTo = moveInfo.to;
// HOT FIX - for VehicleLeaveEvent missing.
if (data.wasInVehicle){
if (cc.debug){
LogUtil.logWarning("[NoCheatPlus] VehicleExitEvent missing for: " + player.getName());
}
onPlayerVehicleLeave(player, null);
// if (BlockProperties.isRails(pFrom.getTypeId())){
// Always clear no fall data, let Minecraft do fall damage.
data.noFallSkipAirCheck = true; // Might allow one time cheat.
data.sfLowJump = false;
data.clearNoFallData();
// }
if (data.wasInVehicle) {
onVehicleLeaveMiss(player, data, cc);
}
// Potion effect "Jump".
@ -535,8 +521,6 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// The players location.
// TODO: Change to getLocation(moveInfo.loc) once 1.4.5 support is dropped.
final Location loc = (cc.noFallCheck || cc.passableCheck) ? player.getLocation() : null;
Location newTo = null;
// Check passable first to prevent set-back override.
// TODO: Redesign to set set-backs later (queue + invalidate).
@ -544,7 +528,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (newTo == null && cc.passableCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_PASSABLE) && !player.hasPermission(Permissions.MOVING_PASSABLE)) {
// Passable is checked first to get the original set-back locations from the other checks, if needed.
newTo = passable.check(player, loc, pFrom, pTo, data, cc);
if (newTo != null){
if (newTo != null) {
// Check if to skip the nofall check.
mightSkipNoFall = true;
}
@ -553,13 +537,13 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Check which fly check to use.
final boolean checkCf;
final boolean checkSf;
if (shouldCheckSurvivalFly(player, data, cc)){
if (shouldCheckSurvivalFly(player, data, cc)) {
checkCf = false;
checkSf = true;
data.adjustWalkSpeed(player.getWalkSpeed(), tick, cc.speedGrace);
}
else if (cc.creativeFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_CREATIVEFLY) && !player.hasPermission(Permissions.MOVING_CREATIVEFLY)){
else if (cc.creativeFlyCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_CREATIVEFLY) && !player.hasPermission(Permissions.MOVING_CREATIVEFLY)) {
checkCf = true;
checkSf = false;
data.adjustFlySpeed(player.getFlySpeed(), tick, cc.speedGrace);
@ -570,14 +554,14 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Flying checks.
if (checkSf){
if (checkSf) {
// SurvivalFly
// Collect block flags.
// TODO: Could further differentiate if really needed to (newTo / NoFall).
final double maxYNoFall = Math.max(cc.noFallyOnGround, cc.yOnGround);
pFrom.collectBlockFlags(maxYNoFall);
if (pFrom.isSamePos(pTo)){
if (pFrom.isSamePos(pTo)) {
// TODO: Could consider pTo = pFrom, set pitch / yaw elsewhere.
// Sets all properties, but only once.
pTo.prepare(pFrom);
@ -588,15 +572,15 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Actual check.
if (newTo == null){
if (newTo == null) {
// Only check if passable has not already set back.
newTo = survivalFly.check(player, pFrom, pTo, data, cc, time);
}
final boolean checkNf = cc.noFallCheck && !NCPExemptionManager.isExempted(player, CheckType.MOVING_NOFALL) && !player.hasPermission(Permissions.MOVING_NOFALL);
if (newTo == null){
if (newTo == null) {
// Hover.
// TODO: Could reset for from-on-ground as well, for not too big moves.
if (cc.sfHoverCheck && !data.toWasReset && !pTo.isOnGround()){
if (cc.sfHoverCheck && !data.toWasReset && !pTo.isOnGround()) {
// Start counting ticks.
hoverTicks.add(playerName);
data.sfHoverTicks = 0;
@ -605,34 +589,34 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.sfHoverTicks = -1;
}
// NoFall.
if (checkNf){
if (checkNf) {
noFall.check(player, loc, pFrom, pTo, data, cc);
}
}
else{
if (checkNf && cc.sfFallDamage){
if (mightSkipNoFall){
if (checkNf && cc.sfFallDamage) {
if (mightSkipNoFall) {
// Check if to really skip.
if (!pFrom.isOnGround() && !pFrom.isResetCond()){
if (!pFrom.isOnGround() && !pFrom.isResetCond()) {
mightSkipNoFall = false;
}
}
if (!mightSkipNoFall){
if (!mightSkipNoFall) {
noFall.checkDamage(player, data, Math.min(Math.min(from.getY(), to.getY()), loc.getY()));
}
}
}
}
else if (checkCf){
else if (checkCf) {
// CreativeFly
if (newTo == null){
if (newTo == null) {
newTo = creativeFly.check(player, pFrom, pTo, data, cc, time);
}
data.sfHoverTicks = -1;
data.sfLowJump = false;
}
else{
// No fly :).
// No fly checking :(.
data.clearFlyData();
}
@ -647,8 +631,8 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Reset jump amplifier if needed.
if ((checkSf || checkCf) && jumpAmplifier != data.jumpAmplifier){
if (data.noFallAssumeGround || pFrom.isOnGround() || pTo.isOnGround()){
if ((checkSf || checkCf) && jumpAmplifier != data.jumpAmplifier) {
if (data.noFallAssumeGround || pFrom.isOnGround() || pTo.isOnGround()) {
data.jumpAmplifier = jumpAmplifier;
}
}
@ -664,7 +648,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
event.setTo(newTo);
// Debug.
if (cc.debug){
if (cc.debug) {
System.out.println(player.getName() + " set back to: " + newTo.getWorld() + StringUtil.fdec3.format(newTo.getX()) + ", " + StringUtil.fdec3.format(newTo.getY()) + ", " + StringUtil.fdec3.format(newTo.getZ()));
}
}
@ -682,47 +666,77 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
moveInfo.cleanup();
parkedInfo.add(moveInfo);
}
// /**
// * A workaround for cancelled PlayerMoveEvents.
// *
// * @param event
// * the event
// */
// @EventHandler(priority = EventPriority.HIGHEST)
// public void onPlayerMoveHighest(final PlayerMoveEvent event) {
// /*
// * _____ _ __ __
// * | __ \| | | \/ |
// * | |__) | | __ _ _ _ ___ _ __ | \ / | _____ _____
// * | ___/| |/ _` | | | |/ _ \ '__| | |\/| |/ _ \ \ / / _ \
// * | | | | (_| | |_| | __/ | | | | | (_) \ V / __/
// * |_| |_|\__,_|\__, |\___|_| |_| |_|\___/ \_/ \___|
// * __/ |
// * |___/
// */
// // No typo here. I really only handle cancelled events and ignore others.
// if (!event.isCancelled() || event.getPlayer().isDead())
// return;
//
// // Fix a common mistake that other developers make (cancelling move events is crazy, rather set the target
// // location to the from location).
// event.setCancelled(false);
// event.setTo(event.getFrom()); // TODO: revise this (old!) strategy, cancelled events just teleport to from, basically.
// }
/**
* Called from player-move checking, if the player is inside of a vehicle.
* @param player
* @param from
* @param to
* @param data
*/
private Location onPlayerMoveVehicle(final Player player, final Location from, final Location to, final MovingData data) {
// Workaround for pigs and other (1.5.x and before)!
// Note that with 1.6 not even PlayerMove fires for horses and pigs.
// (isInsideVehicle is the faster check without object creation, do re-check though, if it changes to only check for Vehicle instances.)
final Entity vehicle = CheckUtils.getLastNonPlayerVehicle(player);
data.wasInVehicle = true;
data.sfHoverTicks = -1;
data.removeAllVelocity();
data.sfLowJump = false;
// TODO: What with processingEvents.remove(player.getName());
if (vehicle != null) {
final Location vLoc = vehicle.getLocation();
// (Auto detection of missing events, might fire one time too many per plugin run.)
if (!normalVehicles.contains(vehicle.getType())) {
onVehicleMove(vehicle, vLoc, vLoc, true);
return null;
} else {
data.vehicleConsistency = MoveConsistency.getConsistency(from, to, vLoc);
// TODO: Consider TeleportUtil.forceMount or similar.
if (data.vehicleConsistency == MoveConsistency.INCONSISTENT) {
return vLoc;
} else {
data.resetPositions(vLoc);
return null;
}
}
}
return null;
}
/**
* Called from player-move checking, if vehicle-leave has not been called after entering, but the player is not inside of a vehicle anymore.
* @param player
* @param data
* @param cc
*/
private void onVehicleLeaveMiss(final Player player, final MovingData data, final MovingConfig cc) {
if (cc.debug) {
LogUtil.logWarning("[NoCheatPlus] VehicleExitEvent missing for: " + player.getName());
}
onPlayerVehicleLeave(player, null);
// if (BlockProperties.isRails(pFrom.getTypeId())) {
// Always clear no fall data, let Minecraft do fall damage.
data.noFallSkipAirCheck = true; // Might allow one time cheat.
data.sfLowJump = false;
data.clearNoFallData();
// TODO: What with processingEvents.remove(player.getName());
// }
}
/**
* Monitor level PlayerMoveEvent.
* @param event
*/
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled = false)
public void onPlayerMoveMonitor(final PlayerMoveEvent event){
public void onPlayerMoveMonitor(final PlayerMoveEvent event) {
// TODO: revise: cancelled events.
final long now = System.currentTimeMillis();
final Player player = event.getPlayer();
if (processingEvents.remove(player.getName()) == null){
if (processingEvents.remove(player.getName()) == null) {
// This means moving data has been reset by a teleport.
// TODO: vehicles, cancelled, ...
return;
}
@ -736,12 +750,16 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final String fromWorldName = from.getWorld().getName();
// Feed yawrate and reset moving data positions if necessary.
if (!event.isCancelled()){
if (!event.isCancelled()) {
final Location to = event.getTo();
final String toWorldName = to.getWorld().getName();
Combined.feedYawRate(player, to.getYaw(), now, toWorldName, data);
// TODO: maybe even not count vehicles at all ?
if (player.isInsideVehicle() || !fromWorldName.equals(toWorldName)){
if (player.isInsideVehicle()) {
// TODO: refine (!).
MovingData.getData(player).resetPositions(player.getVehicle().getLocation());
}
else if (!fromWorldName.equals(toWorldName)) {
MovingData.getData(player).resetPositions(to);
}
else{
@ -776,6 +794,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingData data = MovingData.getData(event.getPlayer());
data.clearFlyData();
data.clearMorePacketsData();
// TODO: This event might be redundant (!).
}
/**
@ -799,12 +818,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final MovingData data = MovingData.getData(player);
data.clearFlyData();
data.clearMorePacketsData();
data.resetSetBack();
data.setSetBack(event.getRespawnLocation());
// TODO: consider data.resetPositions(data.setBack);
// (Not putting hover in at respawn due to chunk sending.)
// TODO: Might use grace ticks for this too (and bigger teleports).
// final MovingConfig cc = MovingConfig.getConfig(player);
// if (cc.sfHoverCheck){
// if (cc.sfHoverCheck) {
// // Assume the player might be hovering.
// data.sfHoverTicks = 0;
// hoverTicks.add(player.getName());
@ -869,7 +888,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
} else {
final MovingConfig cc = MovingConfig.getConfig(player);
// Only if it wasn't NoCheatPlus, drop data from more packets check.
if (to != null && !event.isCancelled()){
if (to != null && !event.isCancelled()) {
// Normal teleport.
// Detect small distance teleports.
@ -882,22 +901,22 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final TeleportCause cause = event.getCause();
if (cause == TeleportCause.UNKNOWN){
if (cause == TeleportCause.UNKNOWN) {
// Check special small range teleports (moved too quickly).
if (from != null && from.getWorld().equals(to.getWorld())){
if (TrigUtil.distance(from, to) < margin){
if (from != null && from.getWorld().equals(to.getWorld())) {
if (TrigUtil.distance(from, to) < margin) {
smallRange = true;
}
else if (data.toX != Double.MAX_VALUE && data.hasSetBack()){
else if (data.toX != Double.MAX_VALUE && data.hasSetBack()) {
final Location setBack = data.getSetBack(to);
if (TrigUtil.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin){
if (TrigUtil.distance(to.getX(), to.getY(), to.getZ(), setBack.getX(), setBack.getY(), setBack.getZ()) < margin) {
smallRange = true;
}
}
}
}
else if (cause == TeleportCause.ENDER_PEARL){
if (CombinedConfig.getConfig(player). enderPearlCheck && !BlockProperties.isPassable(to)){ // || !BlockProperties.isOnGroundOrResetCond(player, to, 1.0)){
else if (cause == TeleportCause.ENDER_PEARL) {
if (CombinedConfig.getConfig(player). enderPearlCheck && !BlockProperties.isPassable(to)) { // || !BlockProperties.isOnGroundOrResetCond(player, to, 1.0)) {
// Not check on-ground: Check the second throw.
cancel = true;
}
@ -906,13 +925,13 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
}
// if (pass){
// if (pass) {
// ref = to;
// }
// else
if (cancel){
if (cancel) {
// Cancel!
if (data.hasSetBack() && !data.hasSetBackWorldChanged(to)){
if (data.hasSetBack() && !data.hasSetBackWorldChanged(to)) {
ref = data.getSetBack(to);
event.setTo(ref);
}
@ -921,15 +940,15 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
event.setCancelled(true);
}
}
else if (smallRange){
else if (smallRange) {
// Very small range teleport, keep set back etc.
ref = to;
// if (data.hasSetBack() && !data.hasSetBackWorldChanged(to)){
// if (data.hasSetBack() && !data.hasSetBackWorldChanged(to)) {
// final Location setBack = data.getSetBack(from);
// Bukkit.getScheduler().scheduleSyncDelayedTask(this.plugin, new Runnable() {
// @Override
// public void run() {
// if (!data.hasSetBackWorldChanged(setBack)){ // && data.isSetBack(setBack)){
// if (!data.hasSetBackWorldChanged(setBack)) { // && data.isSetBack(setBack)) {
// player.sendMessage("SETBACK FROM MC DERP.");
// player.teleport(setBack);
// }
@ -952,21 +971,21 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
data.setSetBack(to);
// TODO: How to account for plugins that reset the fall distance here?
if (fallDistance > 1.0 && fallDistance - player.getFallDistance() > 0.0){
if (fallDistance > 1.0 && fallDistance - player.getFallDistance() > 0.0) {
// Reset fall distance if set so in the config.
if (!cc.noFallTpReset){
if (!cc.noFallTpReset) {
// (Set fall distance if set to not reset.)
player.setFallDistance((float) fallDistance);
}
}
if (event.getCause() == TeleportCause.ENDER_PEARL){
if (event.getCause() == TeleportCause.ENDER_PEARL) {
// Prevent NoFall violations for ender-pearls.
data.noFallSkipAirCheck = true;
}
data.sfHoverTicks = -1; // Important against concurrent modification exception.
}
if (cc.debug && BuildParameters.debugLevel > 0){
if (cc.debug && BuildParameters.debugLevel > 0) {
System.out.println(player.getName() + " TP" + (smallRange ? " (small-range)" : "") + (cancel ? " (cancelled)" : "") + ": " + to);
}
}
@ -974,7 +993,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Cancelled, not a set back, ignore it, basically.
// Better reset teleported (compatibility). Might have drawbacks.
data.resetTeleported();
if (cc.debug && BuildParameters.debugLevel > 0){
if (cc.debug && BuildParameters.debugLevel > 0) {
System.out.println(player.getName() + " TP (cancelled): " + to);
}
return;
@ -1009,7 +1028,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final Player player = event.getPlayer();
final MovingData data = MovingData.getData(player);
// Ignore velocity if inside of vehicles.
if (player.isInsideVehicle()){
if (player.isInsideVehicle()) {
data.removeAllVelocity();
return;
}
@ -1021,7 +1040,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final Vector velocity = event.getVelocity();
if (cc.debug){
if (cc.debug) {
System.out.println(event.getPlayer().getName() + " new velocity: " + velocity);
}
@ -1029,7 +1048,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
boolean used = false;
if (newVal >= 0D) {
used = true;
if (data.verticalFreedom <= 0.001 && data.verticalVelocityCounter >= 0){
if (data.verticalFreedom <= 0.001 && data.verticalVelocityCounter >= 0) {
data.verticalVelocity = 0;
}
data.verticalVelocity += newVal;
@ -1049,7 +1068,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Set dirty flag here.
if (used){
if (used) {
data.sfDirty = true;
data.sfNoLowJump = true;
}
@ -1068,16 +1087,16 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
public void onVehicleMove(final VehicleMoveEvent event) {
final Vehicle vehicle = event.getVehicle();
final EntityType entityType = vehicle.getType();
if (!normalVehicles.contains(entityType)){
if (!normalVehicles.contains(entityType)) {
// A little extra sweep to check for debug flags.
normalVehicles.add(entityType);
if (MovingConfig.getConfig(vehicle.getWorld().getName()).debug){
if (MovingConfig.getConfig(vehicle.getWorld().getName()).debug) {
System.out.println("[NoCheatPlus] VehicleMoveEvent fired for: " + entityType);
}
}
// TODO: Might account for the case of a player letting the vehicle move but not himself (do mind latency).
// Mind that players could be riding horses inside of minecarts etc.
if (vehicle.getVehicle() != null){
if (vehicle.getVehicle() != null) {
// Do ignore events for vehicles inside of other vehicles.
return;
}
@ -1088,7 +1107,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
public void onVehicleMove(final Entity vehicle, final Location from, final Location to, final boolean fake) {
// (No re-check for vehicles that have vehicles, pre condition is that this has already been checked.)
final Player player = CheckUtils.getFirstPlayerPassenger(vehicle);
if (player == null){
if (player == null) {
return;
}
if (vehicle.isDead() || !vehicle.isValid()) {
@ -1106,6 +1125,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
break;
case INCONSISTENT:
// TODO: Any exploits exist? -> TeleportUtil.forceMount(player, vehicle)
// TODO: Test with latency.
break;
}
@ -1113,7 +1133,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
data.sfNoLowJump = true;
final MovingConfig cc = MovingConfig.getConfig(player);
if (cc.noFallVehicleReset){
if (cc.noFallVehicleReset) {
// Reset noFall data.
data.noFallSkipAirCheck = true; // Might allow one time cheat.
data.sfLowJump = false;
@ -1125,7 +1145,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
DebugUtil.outputDebugVehicleMove(player, vehicle, from, to, fake);
}
if (morePacketsVehicle.isEnabled(player)){
if (morePacketsVehicle.isEnabled(player)) {
// If the player is handled by the more packets vehicle check, execute it.
newTo = morePacketsVehicle.check(player, from, to, data, cc);
}
@ -1135,7 +1155,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Schedule a set-back?
if (newTo != null && data.morePacketsVehicleTaskId == -1){
if (newTo != null && data.morePacketsVehicleTaskId == -1) {
// Schedule a delayed task to teleport back the vehicle with the player.
// (Only schedule if not already scheduled.)
// TODO: Might log debug if skipping.
@ -1146,20 +1166,20 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onEntityDamage(final EntityDamageEvent event){
public void onEntityDamage(final EntityDamageEvent event) {
if (event.getCause() != DamageCause.FALL) return;
final Entity entity = event.getEntity();
if (!(entity instanceof Player)) return;
final Player player = (Player) entity;
final MovingData data = MovingData.getData(player);
final MovingConfig cc = MovingConfig.getConfig(player);
if (event.isCancelled() || !shouldCheckSurvivalFly(player, data, cc) || !noFall.isEnabled(player)){
if (event.isCancelled() || !shouldCheckSurvivalFly(player, data, cc) || !noFall.isEnabled(player)) {
data.clearNoFallData();
return;
}
final Location loc = player.getLocation();
boolean allowReset = true;
if (!data.noFallSkipAirCheck){
if (!data.noFallSkipAirCheck) {
final MoveInfo moveInfo;
if (parkedInfo.isEmpty()) moveInfo = new MoveInfo(mcAccess);
else moveInfo = parkedInfo.remove(parkedInfo.size() - 1);
@ -1170,10 +1190,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Be sure not to lose that block.
data.noFallFallDistance += 1.0;
// TODO: Accound for liquid too?
if (!pLoc.isOnGround(1.0, 0.3, 0.1) && !pLoc.isResetCond() && !pLoc.isAboveLadder() && !pLoc.isAboveStairs()){
if (!pLoc.isOnGround(1.0, 0.3, 0.1) && !pLoc.isResetCond() && !pLoc.isAboveLadder() && !pLoc.isAboveStairs()) {
// Likely a new style no-fall bypass (damage in mid-air).
data.noFallVL += 1.0;
if (noFall.executeActions(player, data.noFallVL, 1.0, cc.noFallActions, true) && data.hasSetBack()){
if (noFall.executeActions(player, data.noFallVL, 1.0, cc.noFallActions, true) && data.hasSetBack()) {
// Cancel the event and restore fall distance.
// NoFall data will not be reset
allowReset = false;
@ -1191,30 +1211,30 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final float fallDistance = player.getFallDistance();
final double damage = BridgeHealth.getDamage(event);
final float yDiff = (float) (data.noFallMaxY - loc.getY());
if (cc.debug){
if (cc.debug) {
System.out.println(player.getName() + " damage(FALL): " + damage + " / dist=" + player.getFallDistance() + " nf=" + data.noFallFallDistance + " yDiff=" + yDiff);
}
// Fall-back check.
final double maxD = NoFall.getDamage(Math.max(yDiff, Math.max(data.noFallFallDistance, fallDistance))) + (allowReset ? 0.0 : 3.0);
if (maxD > damage){
if (maxD > damage) {
// TODO: respect dealDamage ?
BridgeHealth.setDamage(event, maxD);
if (cc.debug){
if (cc.debug) {
System.out.println(player.getName() + " Adjust fall damage to: " + maxD);
}
}
if (allowReset){
if (allowReset) {
// Normal fall damage, reset data.
data.clearNoFallData();
}
else{
// Minecraft/NCP bug or cheating.
// (Do not cancel the event, otherwise: "moved too quickly exploit".)
if (cc.noFallViolationReset){
if (cc.noFallViolationReset) {
data.clearNoFallData();
}
// Add player to hover checks.
if (cc.sfHoverCheck && data.sfHoverTicks < 0){
if (cc.sfHoverCheck && data.sfHoverTicks < 0) {
data.sfHoverTicks = 0;
hoverTicks.add(player.getName());
}
@ -1231,19 +1251,19 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final Location loc = player.getLocation();
// Correct set-back on world changes.
if (loc == null){
if (loc == null) {
// Bug on server side ?
data.clearFlyData();
}
else if (!data.hasSetBack()){
else if (!data.hasSetBack()) {
// TODO: Might consider something else like with respawn. Check if it is passable ?
data.setSetBack(loc);
}
else if (data.hasSetBackWorldChanged(loc)){
else if (data.hasSetBackWorldChanged(loc)) {
data.clearFlyData();
data.setSetBack(loc);
}
if (data.fromX == Double.MAX_VALUE && data.toX == Double.MAX_VALUE){
if (data.fromX == Double.MAX_VALUE && data.toX == Double.MAX_VALUE) {
// TODO: re-think: more fine grained reset?
data.resetPositions(loc);
}
@ -1256,7 +1276,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
// Hover.
final MovingConfig cc = MovingConfig.getConfig(player);
// Reset hover ticks until a better method is used.
if (cc.sfHoverCheck){
if (cc.sfHoverCheck) {
// Start as if hovering already.
// Could check shouldCheckSurvivalFly(player, data, cc), but this should be more sharp (gets checked on violation).
data.sfHoverTicks = 0;
@ -1269,9 +1289,9 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Check loaded chunks.
if (cc.loadChunksOnJoin){
if (cc.loadChunksOnJoin) {
final int loaded = BlockCache.ensureChunksLoaded(loc.getWorld(), loc.getX(), loc.getZ(), 3.0);
if (loaded > 0 && cc.debug && BuildParameters.debugLevel > 0){
if (loaded > 0 && cc.debug && BuildParameters.debugLevel > 0) {
// DEBUG
LogUtil.logInfo("[NoCheatPlus] Player join: Loaded " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " for player: " + player.getName());
}
@ -1289,20 +1309,20 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onWorldunload(final WorldUnloadEvent event){
public void onWorldunload(final WorldUnloadEvent event) {
// TODO: Consider removing the world-related data anyway (even if the event is cancelled).
MovingData.onWorldUnload(event.getWorld());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onVehicleExit(final VehicleExitEvent event){
public void onVehicleExit(final VehicleExitEvent event) {
final Entity entity = event.getExited();
if (!(entity instanceof Player)) return;
onPlayerVehicleLeave((Player) entity, event.getVehicle());
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onVehicleDestroyLowest(final VehicleDestroyEvent event){
public void onVehicleDestroyLowest(final VehicleDestroyEvent event) {
// Prevent destroying ones own vehicle.
final Entity attacker = event.getAttacker();
if (!(attacker instanceof Player)) {
@ -1321,16 +1341,16 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onVehicleDestroy(final VehicleDestroyEvent event){
public void onVehicleDestroy(final VehicleDestroyEvent event) {
final Entity entity = event.getVehicle().getPassenger();
if (!(entity instanceof Player)) return;
onPlayerVehicleLeave((Player) entity, event.getVehicle());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerVehicleEnter(final VehicleEnterEvent event){
public void onPlayerVehicleEnter(final VehicleEnterEvent event) {
final Entity entity = event.getEntered();
if (!(entity instanceof Player)){
if (!(entity instanceof Player)) {
return;
}
final Player player = (Player) entity;
@ -1346,10 +1366,10 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
* @param player
* @param vehicle May be null in case of "not possible to determine".
*/
private void onPlayerVehicleLeave(final Player player, final Entity vehicle){
private void onPlayerVehicleLeave(final Player player, final Entity vehicle) {
final MovingData data = MovingData.getData(player);
data.wasInVehicle = false;
// if (data.morePacketsVehicleTaskId != -1){
// if (data.morePacketsVehicleTaskId != -1) {
// // Await set-back.
// // TODO: might still set ordinary set-backs ?
// return;
@ -1364,7 +1384,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (vehicle != null) {
final Location vLoc = vehicle.getLocation();
// Workaround for some entities/animals that don't fire VehicleMoveEventS.
if (!normalVehicles.contains(vehicle.getType()) || cc.noFallVehicleReset){
if (!normalVehicles.contains(vehicle.getType()) || cc.noFallVehicleReset) {
data.noFallSkipAirCheck = true; // Might allow one time cheat.
data.clearNoFallData();
}
@ -1387,7 +1407,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
// Adjust loc if in liquid (meant for boats !?).
if (BlockProperties.isLiquid(loc.getBlock().getTypeId())){
if (BlockProperties.isLiquid(loc.getBlock().getTypeId())) {
loc.setY(Location.locToBlock(loc.getY()) + 1.25);
}
@ -1406,13 +1426,13 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerToggleSneak(final PlayerToggleSneakEvent event){
public void onPlayerToggleSneak(final PlayerToggleSneakEvent event) {
survivalFly.setReallySneaking(event.getPlayer(), event.isSneaking());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerToggleSprint(final PlayerToggleSprintEvent event){
if (!event.isSprinting()){
public void onPlayerToggleSprint(final PlayerToggleSprintEvent event) {
if (!event.isSprinting()) {
MovingData.getData(event.getPlayer()).timeSprinting = 0;
}
}
@ -1420,7 +1440,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
@Override
public void onTick(final int tick, final long timeLast) {
// Hover checks !
if (tick % hoverTicksStep != 0){
if (tick % hoverTicksStep != 0) {
// Only check every so and so ticks.
return;
}
@ -1428,43 +1448,43 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
if (parkedInfo.isEmpty()) info = new MoveInfo(mcAccess);
else info = parkedInfo.remove(parkedInfo.size() - 1);
final List<String> rem = new ArrayList<String>(hoverTicks.size()); // Pessimistic.
for (final String playerName : hoverTicks){
for (final String playerName : hoverTicks) {
// TODO: put players into the set (+- one tick would not matter ?)
// TODO: might add an online flag to data !
final Player player = DataManager.getPlayerExact(playerName);
if (player == null || !player.isOnline()){
if (player == null || !player.isOnline()) {
rem.add(playerName);
continue;
}
final MovingData data = MovingData.getData(player);
if (player.isDead() || player.isSleeping() || player.isInsideVehicle()){
if (player.isDead() || player.isSleeping() || player.isInsideVehicle()) {
data.sfHoverTicks = -1;
// (Removed below.)
}
if (data.sfHoverTicks < 0){
if (data.sfHoverTicks < 0) {
data.sfHoverLoginTicks = 0;
rem.add(playerName);
continue;
}
else if (data.sfHoverLoginTicks > 0){
else if (data.sfHoverLoginTicks > 0) {
// Additional "grace period".
data.sfHoverLoginTicks --;
continue;
}
final MovingConfig cc = MovingConfig.getConfig(player);
// Check if enabled at all.
if (!cc.sfHoverCheck){
if (!cc.sfHoverCheck) {
rem.add(playerName);
data.sfHoverTicks = -1;
continue;
}
// Increase ticks here.
data.sfHoverTicks += hoverTicksStep;
if (data.sfHoverTicks < cc.sfHoverTicks){
if (data.sfHoverTicks < cc.sfHoverTicks) {
// Don't do the heavier checking here, let moving checks reset these.
continue;
}
if (checkHover(player, data, cc, info)){
if (checkHover(player, data, cc, info)) {
rem.add(playerName);
}
}
@ -1489,18 +1509,18 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
final boolean res;
// TODO: Collect flags, more margin ?
final int loaded = info.from.ensureChunksLoaded();
if (loaded > 0 && cc.debug && BuildParameters.debugLevel > 0){
if (loaded > 0 && cc.debug && BuildParameters.debugLevel > 0) {
// DEBUG
LogUtil.logInfo("[NoCheatPlus] Hover check: Needed to load " + loaded + " chunk" + (loaded == 1 ? "" : "s") + " for the world " + loc.getWorld().getName() + " around " + loc.getBlockX() + "," + loc.getBlockZ() + " in order to check player: " + player.getName());
}
if (info.from.isOnGround() || info.from.isResetCond() || info.from.isAboveLadder() || info.from.isAboveStairs()){
if (info.from.isOnGround() || info.from.isResetCond() || info.from.isAboveLadder() || info.from.isAboveStairs()) {
res = true;
data.sfHoverTicks = 0;
}
else{
if (data.sfHoverTicks > cc.sfHoverTicks){
if (data.sfHoverTicks > cc.sfHoverTicks) {
// Re-Check if survivalfly can apply at all.
if (shouldCheckSurvivalFly(player, data, cc)){
if (shouldCheckSurvivalFly(player, data, cc)) {
handleHoverViolation(player, loc, cc, data);
// Assume the player might still be hovering.
res = false;
@ -1520,7 +1540,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
private void handleHoverViolation(final Player player, final Location loc, final MovingConfig cc, final MovingData data) {
// Check nofall damage (!).
if (cc.sfHoverFallDamage && noFall.isEnabled(player)){
if (cc.sfHoverFallDamage && noFall.isEnabled(player)) {
// Consider adding 3/3.5 to fall distance if fall distance > 0?
noFall.checkDamage(player, data, loc.getY());
}
@ -1548,7 +1568,7 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
@Override
public void onReload() {
for (final MoveInfo info : parkedInfo){
for (final MoveInfo info : parkedInfo) {
// Just in case.
info.cleanup();
}

View File

@ -23,29 +23,29 @@ public class Passable extends Check {
public Location check(final Player player, Location loc, final PlayerLocation from, final PlayerLocation to, final MovingData data, final MovingConfig cc)
{
// TODO: if (!from.isSameCoords(loc)){...check passable for loc -> from !?... + sf etc too?}
// TODO: if (!from.isSameCoords(loc)) {...check passable for loc -> from !?... + sf etc too?}
// TODO: Future: Account for the players bounding box? [test very-strict setting for at least the end points...]
String tags = "";
// Block distances (sum, max) for from-to (not for loc!).
final int manhattan = from.manhattan(to);
// Skip moves inside of ignored blocks right away.
if (manhattan == 0 && (BlockProperties.getBlockFlags(from.getTypeId()) & BlockProperties.F_IGN_PASSABLE) != 0){
if (manhattan == 0 && (BlockProperties.getBlockFlags(from.getTypeId()) & BlockProperties.F_IGN_PASSABLE) != 0) {
return null;
}
boolean toPassable = to.isPassable();
// General condition check for using ray-tracing.
if (toPassable && cc.passableRayTracingCheck && (!cc.passableRayTracingVclipOnly || from.getY() != to.getY()) && (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)){
if (toPassable && cc.passableRayTracingCheck && (!cc.passableRayTracingVclipOnly || from.getY() != to.getY()) && (!cc.passableRayTracingBlockChangeOnly || manhattan > 0)) {
rayTracing.set(from, to);
rayTracing.loop();
if (rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps()){
if (rayTracing.collides() || rayTracing.getStepsDone() >= rayTracing.getMaxSteps()) {
final int maxBlockDist = manhattan <= 1 ? manhattan : from.maxBlockDist(to);
if (maxBlockDist <= 1 && rayTracing.getStepsDone() == 1 && !from.isPassable()){
if (maxBlockDist <= 1 && rayTracing.getStepsDone() == 1 && !from.isPassable()) {
// Redo ray-tracing for moving out of blocks.
if (collidesIgnoreFirst(from, to)){
if (collidesIgnoreFirst(from, to)) {
toPassable = false;
tags = "raytracing_2x_";
}
else if (cc.debug){
else if (cc.debug) {
System.out.println(player.getName() + " passable: allow moving out of a block.");
}
}
@ -61,7 +61,7 @@ public class Passable extends Check {
}
// TODO: Checking order: If loc is not the same as from, a quick return here might not be wanted.
if (toPassable){
if (toPassable) {
// Quick return.
// (Might consider if vl>=1: only decrease if from and loc are passable too, though micro...)
data.passableVL *= 0.99;
@ -82,11 +82,11 @@ public class Passable extends Check {
final int lbZ = loc.getBlockZ();
// First check if the player is moving from a passable location.
// If not, the move might still be allowed, if moving inside of the same block, or from and to have head position passable.
if (from.isPassable()){
if (from.isPassable()) {
// Put one workaround for 1.5 high blocks here:
if (from.isBlockAbove(to) && (BlockProperties.getBlockFlags(to.getTypeId()) & BlockProperties.F_HEIGHT150) != 0){
if (from.isBlockAbove(to) && (BlockProperties.getBlockFlags(to.getTypeId()) & BlockProperties.F_HEIGHT150) != 0) {
// Check if the move went from inside of the block.
if (BlockProperties.collidesBlock(to.getBlockCache(), from.getX(), from.getY(), from.getZ(), from.getX(), from.getY(), from.getZ(), to.getBlockX(), to.getBlockY(), to.getBlockZ(), to.getTypeId())){
if (BlockProperties.collidesBlock(to.getBlockCache(), from.getX(), from.getY(), from.getZ(), from.getX(), from.getY(), from.getZ(), to.getBlockX(), to.getBlockY(), to.getBlockZ(), to.getTypeId())) {
// Allow moving inside of 1.5 high blocks.
return null;
}
@ -94,23 +94,23 @@ public class Passable extends Check {
// From should be the set-back.
loc = null;
tags += "into";
} else if (BlockProperties.isPassable(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))){
} else if (BlockProperties.isPassable(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))) {
tags += "into_shift";
}
// } else if (BlockProperties.isPassableExact(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))){
// } else if (BlockProperties.isPassableExact(from.getBlockCache(), loc.getX(), loc.getY(), loc.getZ(), from.getTypeId(lbX, lbY, lbZ))) {
// (Mind that this can be the case on the same block theoretically.)
// Keep loc as set-back.
// }
else if (!from.isSameBlock(lbX, lbY, lbZ)){
else if (!from.isSameBlock(lbX, lbY, lbZ)) {
// Otherwise keep loc as set-back.
tags += "cross_shift";
}
else if (manhattan == 1 && to.isBlockAbove(from) && BlockProperties.isPassable(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))){
// else if (to.isBlockAbove(from) && BlockProperties.isPassableExact(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))){
else if (manhattan == 1 && to.isBlockAbove(from) && BlockProperties.isPassable(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))) {
// else if (to.isBlockAbove(from) && BlockProperties.isPassableExact(from.getBlockCache(), from.getX(), from.getY() + player.getEyeHeight(), from.getZ(), from.getTypeId(from.getBlockX(), Location.locToBlock(from.getY() + player.getEyeHeight()), from.getBlockZ()))) {
// Allow the move up if the head is free.
return null;
}
else if (manhattan > 0){
else if (manhattan > 0) {
// Otherwise keep from as set-back.
loc = null;
tags += "cross";
@ -127,14 +127,16 @@ public class Passable extends Check {
}
// Prefer the set-back location from the data.
if (data.hasSetBack()){
if (data.hasSetBack()) {
final Location ref = data.getSetBack(to);
if (BlockProperties.isPassable(from.getBlockCache(), ref) || loc != null && TrigUtil.distance(from, loc) > 0.13){
// if (BlockProperties.isPassableExact(from.getBlockCache(), ref)){
if (BlockProperties.isPassable(from.getBlockCache(), ref) || loc == null || TrigUtil.distance(from, loc) > 0.13) {
// if (BlockProperties.isPassableExact(from.getBlockCache(), ref)) {
loc = ref;
if (cc.debug) {
System.out.println(player.getName() + " Using set-back location for passable.");
}
} else if (cc.debug) {
System.out.println(player.getName() + " Ignorng set-back for passable.");
}
}
@ -143,9 +145,9 @@ public class Passable extends Check {
// Return the reset position.
data.passableVL += 1d;
final ViolationData vd = new ViolationData(this, player, data.passableVL, 1, cc.passableActions);
if (cc.debug || vd.needsParameters()){
if (cc.debug || vd.needsParameters()) {
vd.setParameter(ParameterName.BLOCK_ID, "" + to.getTypeId());
if (!tags.isEmpty()){
if (!tags.isEmpty()) {
vd.setParameter(ParameterName.TAGS, tags);
}
}
@ -154,9 +156,7 @@ public class Passable extends Check {
final Location newTo;
if (loc != null) {
newTo = loc;
}
else {
// TODO: Consider logging this one.
} else {
newTo = from.getLocation();
if (cc.debug) {
System.out.println(player.getName() + " Using from location for passable.");
@ -194,7 +194,7 @@ public class Passable extends Check {
*/
private boolean allowsSplitMove(final PlayerLocation from, final PlayerLocation to, int manhattan) {
final double yDiff = to.getY() - from.getY() ;
if (manhattan <= 3 && yDiff > 0.0 && Math.abs(yDiff) < 1.0){
if (manhattan <= 3 && yDiff > 0.0 && Math.abs(yDiff) < 1.0) {
// Workaround for client-side calculations not being possible (y vs. horizontal move).
// TODO: Alternative: Test if "real" ray-tracing would fix it (might not!).
if (yDiff > 0.0) {