Protected more against moving up (ladder, vine, water).

Prevent climbing too high up vine that are not attached to solid
blocks. Prevent too high speed moving up on ladders, vine, liquid.
Refine treatment of exiting boats.
This commit is contained in:
asofold 2013-02-03 16:32:22 +01:00
parent 70e47e03c1
commit 930228bc6c
4 changed files with 99 additions and 23 deletions

View File

@ -936,6 +936,30 @@ public class BlockProperties {
public static final void setBlockFlags(final int id, final long flags){
blockFlags[id] = flags;
}
/**
* Auxiliary check for if this block is climbable and allows climbing up. Does not account for jumping off ground etc.
* @param cache
* @param x
* @param y
* @param z
* @return
*/
public static final boolean canClimbUp(final BlockCache cache, final int x, final int y, final int z){
final int id = cache.getTypeId(x, y, z);
if ((blockFlags[id] & F_CLIMBABLE) == 0) return false;
if (id == Material.LADDER.getId()) return true;
// The direct way is a problem (backwards compatibility to before 1.4.5-R1.0).
if ((blockFlags[cache.getTypeId(x + 1, y, z)] & F_SOLID) != 0) return true;
if ((blockFlags[cache.getTypeId(x - 1, y, z)] & F_SOLID) != 0) return true;
if ((blockFlags[cache.getTypeId(x, y, z + 1)] & F_SOLID) != 0) return true;
if ((blockFlags[cache.getTypeId(x, y, z - 1)] & F_SOLID) != 0) return true;
return false;
}
public static final boolean isClimbable(final int id) {
return (blockFlags[id] & F_CLIMBABLE) != 0;
}
public static final boolean isStairs(final int id) {
return (blockFlags[id] & F_STAIRS) != 0;
@ -1484,4 +1508,5 @@ public class BlockProperties {
blockCache = null;
// TODO: might empty mappings...
}
}

View File

@ -342,6 +342,38 @@ public class PlayerLocation {
}
return onClimbable;
}
/**
* Check if a player may climb upwards (isOnClimbable returned true, player does not move from/to ground).<br>
* Having checked the other stuff is prerequisite for calling this (!).
* @param jumpHeigth Height the player is allowed to have jumped.
* @return
*/
public boolean canClimbUp(double jumpHeigth){
// TODO: distinguish vines.
if (getTypeId() == Material.VINE.getId()){
// Check if vine is attached to something solid
if (BlockProperties.canClimbUp(blockCache, blockX, blockY, blockZ)){
return true;
}
// Check the block at head height.
final int headY = Location.locToBlock(y + player.getEyeHeight());
if (headY > blockY){
for (int cy = blockY + 1; cy <= headY; cy ++){
if (BlockProperties.canClimbUp(blockCache, blockX, cy, blockZ)){
return true;
}
}
}
// Finally check possible jump height.
// TODO: This too is inaccurate.
if (isOnGround(jumpHeigth)){
return true;
}
return false;
}
return true;
}
/**
* Checks if the player is above a ladder or vine.<br>

View File

@ -1100,9 +1100,12 @@ public class MovingListener extends CheckListener implements TickListener, IRemo
}
data.resetPositions(loc);
data.setSetBack(loc);
// Experiment: add some horizontal velocity (fake).
data.horizontalVelocityCounter = 4;
data.horizontalFreedom = 0.6;
// Experiment: add some velocity (fake).
data.horizontalVelocityCounter = 1;
data.horizontalFreedom = 0.75;
data.verticalVelocityCounter = 1;
data.verticalFreedom = 1.2;
data.verticalVelocity = 0.1;
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)

View File

@ -44,7 +44,7 @@ public class SurvivalFly extends Check {
public static final double swimmingSpeed = 0.115D;
public static final double webSpeed = 0.105D; // TODO: walkingSpeed * 0.15D; <- does not work
// public static final double climbSpeed = sprintingSpeed; // TODO.
public static final double climbSpeed = sprintingSpeed; // TODO.
public static final double modIce = 2.5D;
@ -232,29 +232,45 @@ public class SurvivalFly extends Check {
}
if (vDistanceAboveLimit > 0) tags.add("vweb");
}
// else if (data.verticalFreedom <= 0.001 && from.isOnClimbable()){
// // Ladder types.
else if (data.verticalFreedom <= 0.001 && from.isOnClimbable()){
// Ladder types.
// TODO: bring in in-medium accounting.
// // TODO: make these extra checks to the jumpphase thing ?
// if (fromOnGround) vAllowedDistance = climbSpeed + 0.3;
// else vAllowedDistance = climbSpeed;
// vDistanceAboveLimit = Math.abs(yDistance) - vAllowedDistance;
// if (vDistanceAboveLimit > 0) tags.add("vclimb");
// }
// else if (data.verticalFreedom <= 0.001 && from.isInLiquid()){
// // Swimming...
// // TODO: This is more complex, depends on speed of diving into it.
// if (yDistance >= 0){
// // TODO: This is more simple to test.
// if (!to.isInLiquid()){
// vAllowedDistance = swimmingSpeed + 0.3;
// }
// else{
// vAllowedDistance = swimmingSpeed;
//
// }
// vDistanceAboveLimit = yDistance - vAllowedDistance;
// if (vDistanceAboveLimit > 0) tags.add("swimup");
// }
if (yDistance > climbSpeed){
tags.add("climbspeed");
Math.max(vDistanceAboveLimit, yDistance - climbSpeed);
}
if (yDistance > 0){
if (!fromOnGround && ! toOnGround && !data.noFallAssumeGround){
// Check if player may climb up.
final double jumpHeight = 1.45 + (data.jumpAmplifier > 0 ? (0.5 + data.jumpAmplifier - 1.0) : 0.0);
if (!from.canClimbUp(jumpHeight)){
tags.add("climbup");
vDistanceAboveLimit = Math.max(vDistanceAboveLimit, yDistance);
}
}
}
}
else if (data.verticalFreedom <= 0.001 && from.isInLiquid()){
// Swimming...
if (yDistance >= 0){
// TODO: This is more simple to test.
if (!to.isInLiquid()){
vAllowedDistance = swimmingSpeed + 0.5;
}
else{
vAllowedDistance = swimmingSpeed;
}
vDistanceAboveLimit = yDistance - vAllowedDistance;
if (vDistanceAboveLimit > 0) tags.add("swimup");
}
// TODO: This is more complex, depends on speed of diving into it.
// else{
// // TODO
// if (-yDistance > swimmingSpeed * modDownStream){
@ -275,7 +291,7 @@ public class SurvivalFly extends Check {
// vAllowedDistance = Math.abs(yDistance);
// }
// }
// }
}
else{
// Check traveled y-distance, orientation is air + jumping + velocity (as far as it gets).
vAllowedDistance = (!(fromOnGround || data.noFallAssumeGround) && !toOnGround ? 1.45D : 1.35D) + data.verticalFreedom;