Fix survivalfly alerts for moving downstream in water.

This commit is contained in:
asofold 2012-10-07 21:47:54 +02:00
parent 1372a462d9
commit d9038010d8
2 changed files with 96 additions and 20 deletions

View File

@ -45,6 +45,9 @@ public class SurvivalFly extends Check {
public static final double webSpeed = 0.105D; // TODO: walkingSpeed * 0.15D; <- does not work
public static final double modIce = 2.5D;
/** Faster moving down stream (water mainly). */
public static final double modDownStream = 0.19 / swimmingSpeed;
/**
* Instantiates a new survival fly check.
@ -112,20 +115,25 @@ public class SurvivalFly extends Check {
final double setBackYDistance = to.getY() - data.setBack.getY();
// If the player has touched the ground but it hasn't been noticed by the plugin, the workaround is here.
if (!fromOnGround && (from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D
&& setBackYDistance > 0D && setBackYDistance <= 1.5D && !BlockProperties.isPassable(from.getTypeIdBelow())
|| !toOnGround && to.isAboveStairs())) {
// Set the new setBack and reset the jumpPhase.
// Maybe don't adapt the setback (unless null)!
data.setBack = from.getLocation();
data.setBack.setY(Math.floor(data.setBack.getY()));
// data.ground ?
data.survivalFlyJumpPhase = 0;
data.clearAccounting();
// Tell NoFall that we assume the player to have been on ground somehow.
data.noFallAssumeGround = true;
if (cc.debug) System.out.println(player.getName() + " Y INCONSISTENCY WORKAROUND USED");
if (!fromOnGround){
// TODO: more precise
final boolean inconsistent = from.getY() < data.survivalFlyLastFromY && yDistance > 0D && yDistance < 0.5D
&& setBackYDistance > 0D && setBackYDistance <= 1.5D
&& !BlockProperties.isPassable(from.getTypeIdBelow());
// TODO: fromAboveStairs ?
if (inconsistent || from.isAboveStairs()){ // !toOnGround && to.isAboveStairs()) {
// Set the new setBack and reset the jumpPhase.
// Maybe don't adapt the setback (unless null)!
data.setBack = from.getLocation();
data.setBack.setY(Math.floor(data.setBack.getY()));
// data.ground ?
data.survivalFlyJumpPhase = 0;
data.clearAccounting();
// Tell NoFall that we assume the player to have been on ground somehow.
data.noFallAssumeGround = true;
if (cc.debug) System.out.println(player.getName() + " Y INCONSISTENCY WORKAROUND USED");
}
}
data.survivalFlyLastFromY = from.getY();
@ -158,7 +166,7 @@ public class SurvivalFly extends Check {
// Speeding bypass permission (can be combined with other bypasses).
// TODO: How exactly to bring it on finally.
if (player.hasPermission(Permissions.MOVING_SURVIVALFLY_SPEEDING))
hAllowedDistance = hAllowedDistance * cc.survivalFlySpeedingSpeed/ 100D;
hAllowedDistance *= cc.survivalFlySpeedingSpeed/ 100D;
}
// TODO: Optimize: maybe only do the permission checks and modifiers if the distance is too big.
@ -172,6 +180,11 @@ public class SurvivalFly extends Check {
final EntityPlayer entity = ((CraftPlayer) player).getHandle();
if (entity.hasEffect(MobEffectList.FASTER_MOVEMENT))
hAllowedDistance *= 1.0D + 0.2D * (entity.getEffect(MobEffectList.FASTER_MOVEMENT).getAmplifier() + 1);
// Account for flowing liquids (only if needed).
if (hDistance > swimmingSpeed && from.isInLiquid() && from.isDownStream(xDistance, zDistance)){
hAllowedDistance *= modDownStream;
}
// Judge if horizontal speed is above limit.
double hDistanceAboveLimit = hDistance - hAllowedDistance - data.horizontalFreedom;
@ -252,7 +265,7 @@ public class SurvivalFly extends Check {
vAllowedDistance *= data.jumpAmplifier;
if (data.survivalFlyJumpPhase > 6 + data.jumpAmplifier && data.verticalVelocityCounter <= 0){
vAllowedDistance -= (data.survivalFlyJumpPhase - 6) * 0.15D;
// System.out.println("jumpphase -> " + data.survivalFlyJumpPhase);
if (cc.debug) System.out.println("jumpphase -> " + data.survivalFlyJumpPhase);
}
vDistanceAboveLimit = to.getY() - data.setBack.getY() - vAllowedDistance;
@ -281,14 +294,14 @@ public class SurvivalFly extends Check {
data.vDistSum.add(now, (float) (yDistance));
data.vDistCount.add(now, 1f);
}
if (useH && data.hDistCount.getScore(2) > 0){
if (useH && data.hDistCount.getScore(2) > 0 && data.hDistCount.getScore(1) > 0){
final float hsc0 = data.hDistSum.getScore(1);
final float hsc1 = data.hDistSum.getScore(2);
if (hsc0 < hsc1 || hDistance < 3.9 && hsc0 == hsc1){
hDistanceAboveLimit = Math.max(hDistanceAboveLimit, hsc0 - hsc1);
}
}
if (useV && data.vDistCount.getScore(2) > 0){
if (useV && data.vDistCount.getScore(2) > 0 && data.vDistCount.getScore(1) > 0){
final float vsc0 = data.vDistSum.getScore(1);
final float vsc1 = data.vDistSum.getScore(2);
if (vsc0 < vsc1 || yDistance < 3.9 && vsc0 == vsc1){

View File

@ -40,6 +40,8 @@ public class PlayerLocation {
/** Type id of the block below. */
private Integer typeIdBelow;
private Integer data;
/** Is the player above stairs? */
private Boolean aboveStairs;
@ -259,9 +261,9 @@ public class PlayerLocation {
}
/**
* Checks if the player is on a ladder.
* Checks if the player is on a ladder or vine.
*
* @return true, if the player is on a ladder
* @return If so.
*/
public boolean isOnLadder() {
if (onLadder == null){
@ -271,6 +273,17 @@ public class PlayerLocation {
return onLadder;
}
/**
* Checks if the player is above a ladder or vine.<br>
* Does not save back value to field.
*
* @return If so.
*/
public boolean isAboveLadder() {
final int typeId = getTypeIdBelow();
return typeId == Material.LADDER.getId() || typeId == Material.VINE.getId();
}
/**
* Sets the player location object.
*
@ -332,6 +345,56 @@ public class PlayerLocation {
if (typeIdBelow == null) typeIdBelow = worldServer.getTypeId(blockX, blockY - 1, blockZ);
return typeIdBelow;
}
public Integer getData(){
if (data == null) data = worldServer.getData(blockX, blockY, blockZ);
return data;
}
public boolean isDownStream(final double xDistance, final double zDistance){
// x > 0 -> south, z > 0 -> west
final int fromData = getData();
if ((fromData & 0x8) == 0){
// not falling.
if ((xDistance > 0)){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX + 1, blockY, blockZ)) && worldServer.getData(blockX + 1, blockY, blockZ) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX - 1, blockY, blockZ)) && worldServer.getData(blockX - 1, blockY, blockZ) < fromData){
// reverse direction.
return true;
}
} else if (xDistance < 0){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX - 1, blockY, blockZ)) && worldServer.getData(blockX - 1, blockY, blockZ) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX + 1, blockY, blockZ)) && worldServer.getData(blockX + 1, blockY, blockZ) < fromData){
// reverse direction.
return true;
}
}
if (zDistance > 0){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX, blockY, blockZ + 1)) && worldServer.getData(blockX, blockY, blockZ + 1) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX , blockY, blockZ - 1)) && worldServer.getData(blockX, blockY, blockZ - 1) < fromData){
// reverse direction.
return true;
}
}
else if (zDistance < 0 ){
if (fromData < 7 && BlockProperties.isLiquid(worldServer.getTypeId(blockX, blockY, blockZ - 1)) && worldServer.getData(blockX, blockY, blockZ - 1) > fromData){
return true;
}
else if (fromData > 0 && BlockProperties.isLiquid(worldServer.getTypeId(blockX , blockY, blockZ + 1)) && worldServer.getData(blockX, blockY, blockZ + 1) < fromData){
// reverse direction.
return true;
}
}
}
return false;
}
public final boolean isSameBlock(final PlayerLocation other) {
// Maybe make block coordinate fields later.