Removed the workaround for the "Bukkit blocks Zombe" issue, improved the

NoFall and SurvivalFly checks.
This commit is contained in:
NeatMonster 2012-08-12 19:26:26 +02:00
parent 1a5908b907
commit 7a0fa252bd
9 changed files with 61 additions and 148 deletions

View File

@ -1,5 +1,5 @@
name: ${project.name} name: ${project.name}
version: ${project.Version}-b${BUILD_NUMBER} version: ${project.version}-b${BUILD_NUMBER}
description: ${project.description} description: ${project.description}
author: NeatMonster author: NeatMonster
@ -110,8 +110,6 @@ permissions:
description: Allow the player to bypass the MorePackets check. description: Allow the player to bypass the MorePackets check.
nocheatplus.checks.moving.morepacketsvehicle: nocheatplus.checks.moving.morepacketsvehicle:
description: Allow the player to bypass the MorePacketsVehicle check. description: Allow the player to bypass the MorePacketsVehicle check.
nocheatplus.checks.moving.nobukkitcheck:
description: Allwo the player to bypass the internal Bukkit check.
nocheatplus.checks.moving.nofall: nocheatplus.checks.moving.nofall:
description: Allow the player to bypass the NoFall check. description: Allow the player to bypass the NoFall check.
nocheatplus.checks.moving.survivalfly: nocheatplus.checks.moving.survivalfly:

View File

@ -49,8 +49,6 @@ public class CustomNetServerHandler extends NetServerHandler {
*/ */
@Override @Override
public void a(final Packet10Flying packet) { public void a(final Packet10Flying packet) {
// if (player.getBukkitEntity().hasPermission(Permissions.MOVING_NOBUKKITCHECK))
// checkMovement = false;
MovingListener.noFall.handlePacket(player, packet); MovingListener.noFall.handlePacket(player, packet);
super.a(packet); super.a(packet);
} }

View File

@ -17,7 +17,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.plugin.PluginDescriptionFile; import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
@ -122,17 +121,6 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
final void onExecuteActions(final ExecuteActionsEvent event) { final void onExecuteActions(final ExecuteActionsEvent event) {
event.executeActions(); event.executeActions();
} }
/**
* Setting the net server handler at the earliest possible point.
* @param event
*/
@EventHandler(
priority = EventPriority.LOWEST)
public void onPlayerJoinLowest(final PlayerJoinEvent event) {
// Set the NetServerHandler of the player.
setCustomNetServerHandler(event.getPlayer());
}
/** /**
* This event handler is used to send all the disabling messages to the client. * This event handler is used to send all the disabling messages to the client.
@ -224,6 +212,18 @@ public class NoCheatPlus extends JavaPlugin implements Listener {
player.sendMessage(message); player.sendMessage(message);
} }
/**
* Setting the net server handler at the earliest possible point.
*
* @param event
*/
@EventHandler(
priority = EventPriority.LOWEST)
public void onPlayerJoinLowest(final PlayerJoinEvent event) {
// Set the NetServerHandler of the player.
setCustomNetServerHandler(event.getPlayer());
}
private boolean setCustomNetServerHandler(final Player player) { private boolean setCustomNetServerHandler(final Player player) {
final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
final NetServerHandler oldNSH = entityPlayer.netServerHandler; final NetServerHandler oldNSH = entityPlayer.netServerHandler;

View File

@ -84,11 +84,11 @@ public class MovingData implements CheckData {
// Data of the no fall check. // Data of the no fall check.
public double noFallFallDistance; public double noFallFallDistance;
public double noFallNewFallDistance;
public boolean noFallOnGroundClient; public boolean noFallOnGroundClient;
public boolean noFallOnGroundServer; public boolean noFallOnGroundServer;
public boolean noFallWasOnGroundClient; public boolean noFallWasOnGroundClient;
public boolean noFallWasOnGroundServer; public boolean noFallWasOnGroundServer;
public double noFallY; // Absolute reference might be good with packet inspections.
// Data of the survival fly check. // Data of the survival fly check.
public int survivalFlyJumpPhase; public int survivalFlyJumpPhase;

View File

@ -479,30 +479,21 @@ public class MovingListener implements Listener {
*/ */
// Don't care if a player isn't inside the vehicle, for movements that are very high distance or to another // Don't care if a player isn't inside the vehicle, for movements that are very high distance or to another
// world (such that it is very likely the event dataFactory was modified by another plugin before we got it). // world (such that it is very likely the event dataFactory was modified by another plugin before we got it).
final Location to = event.getTo();
if (event.getVehicle().getPassenger() == null || !(event.getVehicle().getPassenger() instanceof Player) if (event.getVehicle().getPassenger() == null || !(event.getVehicle().getPassenger() instanceof Player)
|| !event.getFrom().getWorld().equals(to.getWorld()) || !event.getFrom().getWorld().equals(event.getTo().getWorld())
|| event.getFrom().distanceSquared(to) > 400D) || event.getFrom().distanceSquared(event.getTo()) > 400D)
return; return;
final Player player = (Player) event.getVehicle().getPassenger(); final Player player = (Player) event.getVehicle().getPassenger();
Location newTo = null; Location newTo = null;
// Emergency fix attempt:
final MovingData data = MovingData.getData(player);
data.clearFlyData();
player.setFallDistance(0.0f);
data.noFallY = to.getY();
if (morePacketsVehicle.isEnabled(player)) if (morePacketsVehicle.isEnabled(player))
// If the player is handled by the more packets vehicle check, execute it. // If the player is handled by the more packets vehicle check, execute it.
newTo = morePacketsVehicle.check(player, event.getFrom(), to); newTo = morePacketsVehicle.check(player, event.getFrom(), event.getTo());
else else
// Otherwise we need to clear his dataFactory. // Otherwise we need to clear his dataFactory.
data.clearMorePacketsData(); MovingData.getData(player).clearMorePacketsData();
// Did one of the checks decide we need a new "to"-location? // Did one of the checks decide we need a new "to"-location?
if (newTo != null) if (newTo != null)

View File

@ -3,13 +3,12 @@ package fr.neatmonster.nocheatplus.checks.moving;
import java.util.Locale; import java.util.Locale;
import net.minecraft.server.AxisAlignedBB; import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.DamageSource;
import net.minecraft.server.EntityPlayer; import net.minecraft.server.EntityPlayer;
import net.minecraft.server.Packet10Flying; import net.minecraft.server.Packet10Flying;
import org.bukkit.Bukkit; import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.GameMode;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import fr.neatmonster.nocheatplus.actions.ParameterName; import fr.neatmonster.nocheatplus.actions.ParameterName;
import fr.neatmonster.nocheatplus.checks.Check; import fr.neatmonster.nocheatplus.checks.Check;
@ -51,102 +50,48 @@ public class NoFall extends Check {
public void check(final Player player, final PlayerLocation from, final PlayerLocation to) { public void check(final Player player, final PlayerLocation from, final PlayerLocation to) {
final MovingConfig cc = MovingConfig.getConfig(player); final MovingConfig cc = MovingConfig.getConfig(player);
final MovingData data = MovingData.getData(player); final MovingData data = MovingData.getData(player);
if (player.isInsideVehicle()){
// Emergency fix attempt:
data.clearFlyData();
data.noFallFallDistance = 0D;
data.noFallY = to.getY();
player.setFallDistance(0.0f);
return;
}
// If the player has just started falling, is falling into a liquid, in web or is on a ladder. // If the player has just started falling, is falling into a liquid, in web or is on a ladder.
if (to.isInLiquid()){ if (to.isInLiquid() || to.isInWeb() || to.isOnLadder())
// TODO: check if it is deep liquid
final double dist = data.noFallY - to.getY();
if (dist > 0 ){
// TODO: ? different model, at least distinguish water, lava, flowing.
final double fFLuid = 0.55;
data.noFallY = to.getY() + dist *fFLuid;
data.noFallFallDistance *= fFLuid;
}
}
else if (to.isInWeb() || to.isOnLadder()){
// Reset his fall distance. // Reset his fall distance.
data.noFallFallDistance = 0D; data.noFallFallDistance = data.noFallNewFallDistance = 0D;
data.noFallY = to.getY();
player.setFallDistance(0.0f);
return;
}
// data.noFallFallDistance = data.noFallFallDistance;
/*
* TODO: This might actually (probably) calculated before ordinary fall damage can be dealt (!)
* So NoCheatPlus takes over ALL fall damage dealing, currently :) -
* This should not lead to alerts and trigger normal fall damage, probably,
* in case it is not cheating (how to distinguish...).
*/
// If the player just touched the ground for the server, but no for the client. // If the player just touched the ground for the server, but no for the client.
if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer
&& (data.noFallWasOnGroundClient || !data.noFallOnGroundClient)) { && (data.noFallWasOnGroundClient || !data.noFallOnGroundClient)) {
// Calculate the fall damages to be dealt. // Calculate the fall damages to be dealt.
final int fallDamage = (int) data.noFallFallDistance - 2; // Blocks - 3 ? final int fallDamage = (int) data.noFallFallDistance - 2;
// TODO: set accurate fall damage (Boots with feather falling or protection).
if (fallDamage > 0) { if (fallDamage > 0) {
// Add the fall distance to the violation level. // Add the fall distance to the violation level.
data.noFallVL += data.noFallFallDistance; data.noFallVL += data.noFallFallDistance;
// Execute the actions to find out if we need to cancel the event or not. // Execute the actions to find out if we need to cancel the event or not.
if (executeActions(player, data.noFallVL, cc.noFallActions)){ if (executeActions(player, data.noFallVL, cc.noFallActions))
// Deal the fall damages to the player. // Calling this method will send the event for us.
if (player.getGameMode() != GameMode.CREATIVE){ ((CraftPlayer) player).getHandle().damageEntity(DamageSource.FALL, fallDamage);
final NoFallDamageEvent damageEvent = new NoFallDamageEvent(player, DamageCause.FALL, fallDamage);
Bukkit.getPluginManager().callEvent(damageEvent);
if (!damageEvent.isCancelled()) player.damage(damageEvent.getDamage());
}
// Reset fall distances:
data.noFallFallDistance = 0.0;
data.noFallY = to.getY();
player.setFallDistance(0.0f);
}
} }
} }
// If the player just touched the ground for the server. // If the player just touched the ground for the server.
else if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer) { else if (!data.noFallWasOnGroundServer && data.noFallOnGroundServer) {
// Calculate the difference between the fall distance calculated by the server and by the plugin. // If the difference between the fall distance recorded by Bukkit and NoCheatPlus is too big and the fall
// distance bigger than 2.
// TODO: What does the divisor do, is this experience ? if (data.noFallFallDistance - player.getFallDistance() > 1D && (int) data.noFallFallDistance > 2) {
final double difference = (data.noFallFallDistance - player.getFallDistance()) / data.noFallFallDistance;
// If the difference is too big and the fall distance calculated by the plugin should hurt the player.
if (difference > 0.15D && (int) data.noFallFallDistance > 2) {
// Add the difference to the violation level. // Add the difference to the violation level.
data.noFallVL += data.noFallFallDistance - player.getFallDistance(); data.noFallVL += data.noFallFallDistance - player.getFallDistance();
// Execute the actions to find out if we need to cancel the event or not. // Execute the actions to find out if we need to cancel the event or not.
if (executeActions(player, data.noFallVL, cc.noFallActions)){ if (executeActions(player, data.noFallVL, cc.noFallActions))
// Set the fall distance to its right value. // player.sendMessage("");
// Set the fall distance to its right value.
player.setFallDistance((float) data.noFallFallDistance); player.setFallDistance((float) data.noFallFallDistance);
}
} else } else
// Reward the player by lowering his violation level. // Reward the player by lowering his violation level.
data.noFallVL *= 0.95D; data.noFallVL *= 0.95D;
} else } else
// Reward the player by lowering his violation level. // Reward the player by lowering his violation level.
data.noFallVL *= 0.95D; data.noFallVL *= 0.95D;
if (data.noFallOnGroundServer){
data.noFallY = to.getY();
data.noFallFallDistance = 0.0;
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -171,33 +116,17 @@ public class NoFall extends Check {
*/ */
public void handlePacket(final EntityPlayer player, final Packet10Flying packet) { public void handlePacket(final EntityPlayer player, final Packet10Flying packet) {
final MovingData data = MovingData.getData(player.getBukkitEntity()); final MovingData data = MovingData.getData(player.getBukkitEntity());
// Attempt to fix vehicle problems:
if (player.getBukkitEntity().isInsideVehicle()){
// rely on vehicle-move for most.
data.noFallFallDistance = 0.0;
data.noFallY = player.locY;
return;
}
// Suggestion: use reference y position in data and calculate difference to that one!
data.noFallWasOnGroundClient = data.noFallOnGroundClient; data.noFallWasOnGroundClient = data.noFallOnGroundClient;
data.noFallWasOnGroundServer = data.noFallOnGroundServer; data.noFallWasOnGroundServer = data.noFallOnGroundServer;
data.noFallOnGroundClient = packet.g; data.noFallOnGroundClient = packet.g;
final AxisAlignedBB boundingBoxGround = player.boundingBox.clone().d(packet.x - player.locX, final AxisAlignedBB boundingBoxGround = player.boundingBox.clone().d(packet.x - player.locX,
packet.y - player.locY - 0.001D, packet.z - player.locZ); packet.y - player.locY - 0.001D, packet.z - player.locZ);
data.noFallOnGroundServer = player.world.getCubes(player, boundingBoxGround).size() > 0; data.noFallOnGroundServer = player.world.getCubes(player, boundingBoxGround).size() > 0;
// make use of data.noFallY (absolute reference for falling height). if (packet.hasPos && packet.y > 0 && data.noFallWasOnGroundServer && !data.noFallOnGroundServer)
if (packet.hasPos){ data.noFallFallDistance = data.noFallNewFallDistance = 0D;
// TODO: not 100% sure which to use as reference... else if (packet.hasPos && packet.y > 0 && player.locY - packet.y > 0D) {
if (data.noFallWasOnGroundServer && !data.noFallOnGroundServer){ data.noFallFallDistance = data.noFallNewFallDistance;
data.noFallFallDistance = 0D; data.noFallNewFallDistance += player.locY - packet.y;
data.noFallY = player.locY;
}
else if (data.noFallY - packet.y > 0D)
data.noFallFallDistance = Math.max(0.0, data.noFallY - packet.y); //+= player.locY - packet.y;
else if (data.noFallOnGroundServer) data.noFallY = player.locY;
} }
} }
} }

View File

@ -1,18 +0,0 @@
package fr.neatmonster.nocheatplus.checks.moving;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.EntityDamageEvent;
/**
* Very simple version to allow canceling.
* @author mc_dev
*
*/
public class NoFallDamageEvent extends EntityDamageEvent {
public NoFallDamageEvent(Entity damagee, DamageCause cause, int damage) {
super(damagee, cause, damage);
}
}

View File

@ -82,6 +82,7 @@ public class SurvivalFly extends Check {
// A player is considered sprinting if the flag is set and if he has enough food level. // A player is considered sprinting if the flag is set and if he has enough food level.
final boolean sprinting = player.isSprinting() && player.getFoodLevel() > 5; final boolean sprinting = player.isSprinting() && player.getFoodLevel() > 5;
// If we don't have any setBack, choose the location the player comes from.
if (data.setBack == null) if (data.setBack == null)
data.setBack = from.getLocation(); data.setBack = from.getLocation();
@ -91,6 +92,7 @@ public class SurvivalFly extends Check {
else if (data.survivalFlyOnIce > 0) else if (data.survivalFlyOnIce > 0)
data.survivalFlyOnIce--; data.survivalFlyOnIce--;
// Choose the right horizontal speed limit for the current activity.
double hAllowedDistance = 0D; double hAllowedDistance = 0D;
if (player.isSneaking() && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SNEAKING)) if (player.isSneaking() && !player.hasPermission(Permissions.MOVING_SURVIVALFLY_SNEAKING))
hAllowedDistance = 0.14D * cc.survivalFlySneakingSpeed / 100D; hAllowedDistance = 0.14D * cc.survivalFlySneakingSpeed / 100D;
@ -167,15 +169,24 @@ public class SurvivalFly extends Check {
if (jumpAmplifier > data.jumpAmplifier) if (jumpAmplifier > data.jumpAmplifier)
data.jumpAmplifier = jumpAmplifier; data.jumpAmplifier = jumpAmplifier;
double vAllowedDistance = 1.35D + data.verticalFreedom; // If the player has made a "double-jump" which hasn't been noticed by the plugin, the issue is fixed here.
if (!from.isOnGround() && to.isOnGround() && to.getY() - from.getY() > 0D && to.getY() - from.getY() <= 0.5D
&& to.getY() - data.setBack.getY() > 0D && to.getY() - data.setBack.getY() <= 1.5D) {
data.setBack = to.getLocation();
data.survivalFlyJumpPhase = 0;
}
// Calculate the vertical speed limit based on the current jump phase.
double vAllowedDistance = (!from.isOnGround() && !to.isOnGround() ? 1.45D : 1.35D) + data.verticalFreedom;
vAllowedDistance *= data.jumpAmplifier; vAllowedDistance *= data.jumpAmplifier;
if (data.survivalFlyJumpPhase > 6 + data.jumpAmplifier) if (data.survivalFlyJumpPhase > 6 + data.jumpAmplifier)
vAllowedDistance -= (data.survivalFlyJumpPhase - 6) * 0.15D; vAllowedDistance -= (data.survivalFlyJumpPhase - 6) * 0.15D;
// If the player has touched the ground and this actions hasn't been noticed by the plugin, the issue is fixed
// here.
final double vDistance = to.getY() - data.setBack.getY(); final double vDistance = to.getY() - data.setBack.getY();
if (data.survivalFlyLastDistances[0] < data.survivalFlyLastDistances[1] if (data.survivalFlyLastDistances[0] < data.survivalFlyLastDistances[1]
&& vDistance > data.survivalFlyLastDistances[0] && data.survivalFlyJumpPhase >= 7 && vDistance > data.survivalFlyLastDistances[0] && vDistance > 0 && vDistance < 0.5D)
&& data.survivalFlyJumpPhase <= 8)
data.survivalFlyJumpPhase = 0; data.survivalFlyJumpPhase = 0;
else if (vDistance <= 0D) else if (vDistance <= 0D)
data.survivalFlyJumpPhase = 0; data.survivalFlyJumpPhase = 0;
@ -183,10 +194,15 @@ public class SurvivalFly extends Check {
data.survivalFlyLastDistances[0] = vDistance; data.survivalFlyLastDistances[0] = vDistance;
double vDistanceAboveLimit = vDistance - vAllowedDistance; double vDistanceAboveLimit = vDistance - vAllowedDistance;
// Fix for the issue with stairs.
if (from.isOnStairs() || to.isOnStairs() && vDistanceAboveLimit < 0.15D) { if (from.isOnStairs() || to.isOnStairs() && vDistanceAboveLimit < 0.15D) {
data.jumpAmplifier = 0D; data.jumpAmplifier = 0D;
data.noFallOnGroundClient = data.noFallOnGroundServer = true;
vDistanceAboveLimit = 0D; vDistanceAboveLimit = 0D;
} else if (from.isOnGround() || to.isOnGround()) }
if (from.isOnGround() || to.isOnGround())
data.jumpAmplifier = 0D; data.jumpAmplifier = 0D;
final double result = (Math.max(hDistanceAboveLimit, 0D) + Math.max(vDistanceAboveLimit, 0D)) * 100D; final double result = (Math.max(hDistanceAboveLimit, 0D) + Math.max(vDistanceAboveLimit, 0D)) * 100D;

View File

@ -126,7 +126,6 @@ public class Permissions {
public static final String MOVING_CREATIVEFLY = MOVING + ".creativefly"; public static final String MOVING_CREATIVEFLY = MOVING + ".creativefly";
public static final String MOVING_MOREPACKETS = MOVING + ".morepackets"; public static final String MOVING_MOREPACKETS = MOVING + ".morepackets";
public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle"; public static final String MOVING_MOREPACKETSVEHICLE = MOVING + ".morepacketsvehicle";
public static final String MOVING_NOBUKKITCHECK = MOVING + ".nobukkitcheck";
public static final String MOVING_NOFALL = MOVING + ".nofall"; public static final String MOVING_NOFALL = MOVING + ".nofall";
public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly"; public static final String MOVING_SURVIVALFLY = MOVING + ".survivalfly";
public static final String MOVING_SURVIVALFLY_BLOCKING = MOVING_SURVIVALFLY + ".blocking"; public static final String MOVING_SURVIVALFLY_BLOCKING = MOVING_SURVIVALFLY + ".blocking";