Fix not being able to slide up small blocks with height < slab height (Thanks Empy), now use actual model's collision size instead of the default humanoid collision size, closes #110.

This commit is contained in:
UnknownShadow200 2015-12-15 23:32:37 +11:00
parent 11b2230b63
commit 89c2ae40f9
7 changed files with 72 additions and 44 deletions

View File

@ -140,7 +140,6 @@ namespace ClassicalSharp {
int index = 0;
SplitUppercase( origName, ref index );
normalNames[i] = buffer.ToString();
Console.WriteLine( buffer.ToString() );
}
}

View File

@ -38,9 +38,13 @@ namespace ClassicalSharp {
/// <summary> Returns the size of the model that is used for collision detection. </summary>
public virtual Vector3 CollisionSize {
get { return new Vector3( 8/16f, 28.5f/16f, 8/16f );
//Model.CollisionSize; TODO: for non humanoid models
}
get { UpdateModel(); return Model.CollisionSize; }
}
void UpdateModel() {
BlockModel model = Model as BlockModel;
if( model != null )
model.CalcState( byte.Parse( ModelName ) );
}
/// <summary> Bounding box of the model that collision detection
@ -103,9 +107,7 @@ namespace ClassicalSharp {
/// bounding box of this entity are lava or still lava. </summary>
protected bool TouchesAnyLava() {
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
// Even though we collide with lava 3 blocks above our feet, vanilla client thinks
// that we do not.. so we have to maintain compatibility here.
bounds.Max.Y -= 4/16f;
AdjustLiquidTestBounds( ref bounds );
return TouchesAny( bounds,
b => b == (byte)Block.Lava || b == (byte)Block.StillLava );
}
@ -121,9 +123,17 @@ namespace ClassicalSharp {
/// bounding box of this entity are water or still water. </summary>
protected bool TouchesAnyWater() {
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
bounds.Max.Y -= 4/16f;
AdjustLiquidTestBounds( ref bounds );
return TouchesAny( bounds,
b => b == (byte)Block.Water || b == (byte)Block.StillWater );
}
void AdjustLiquidTestBounds( ref BoundingBox bounds ) {
// Even though we collide with lava 3 blocks above our feet, vanilla client thinks
// that we do not.. so we have to maintain compatibility here.
float height = bounds.Max.Y - bounds.Min.Y;
const float pHeight = (28.5f - 4f)/16f;
bounds.Max.Y = bounds.Min.Y + Math.Min( height, pHeight );
}
}
}

View File

@ -165,26 +165,25 @@ namespace ClassicalSharp {
}
if( !jumping ) {
canLiquidJump = false;
return;
canLiquidJump = false; return;
}
bool touchWater = TouchesAnyWater();
bool touchLava = TouchesAnyLava();
Console.WriteLine( touchWater );
if( touchWater || touchLava ) {
BoundingBox bounds = CollisionBounds;
int feetY = Utils.Floor( bounds.Min.Y ), bodyY = feetY + 1;
int headY = Utils.Floor( bounds.Max.Y );
if( bodyY > headY ) bodyY = headY;
bounds.Max.Y = bounds.Min.Y = feetY;
bool liquidFeet = TouchesAny( bounds, StandardLiquid );
bounds.Max.Y = bounds.Min.Y = bodyY;
bool liquidBody = TouchesAny( bounds, StandardLiquid );
bounds.Max.Y = bounds.Min.Y = headY;
bool liquidHead = TouchesAny( bounds, StandardLiquid );
bounds.Min.Y = Math.Min( bodyY, headY );
bounds.Max.Y = Math.Max( bodyY, headY );
bool liquidRest = TouchesAny( bounds, StandardLiquid );
bool pastJumpPoint = liquidFeet && !(liquidBody || liquidHead)
&& (Position.Y % 1 >= 0.4);
bool pastJumpPoint = liquidFeet && !liquidRest && (Position.Y % 1 >= 0.4);
if( !pastJumpPoint ) {
canLiquidJump = true;
Velocity.Y += speeding ? 0.08f : 0.04f;

View File

@ -160,27 +160,17 @@ namespace ClassicalSharp {
ref BoundingBox entityBB, ref BoundingBox entityExtentBB ) {
float yDist = blockBB.Max.Y - entityBB.Min.Y;
if( yDist > 0 && yDist <= StepSize + 0.01f ) {
// Adjust entity bounding box to include the block being tested
BoundingBox adjFinalBB = finalBB;
adjFinalBB.Min.X = Math.Min( finalBB.Min.X, blockBB.Min.X + Adjustment );
adjFinalBB.Max.X = Math.Max( finalBB.Max.X, blockBB.Max.X - Adjustment );
adjFinalBB.Min.Y = (float)Math.Ceiling( blockBB.Max.Y ) + Adjustment;
adjFinalBB.Min.Y = blockBB.Max.Y + Adjustment;
adjFinalBB.Max.Y = adjFinalBB.Min.Y + size.Y;
adjFinalBB.Min.Z = Math.Min( finalBB.Min.Z, blockBB.Min.Z + Adjustment );
adjFinalBB.Max.Z = Math.Max( finalBB.Max.Z, blockBB.Max.Z - Adjustment );
Vector3I min = Vector3I.Floor( adjFinalBB.Min );
Vector3I max = Vector3I.Floor( adjFinalBB.Max );
for( int x = min.X; x <= max.X; x++ ) {
for( int y = min.Y; y <= max.Y; y++ ) {
for( int z = min.Z; z <= max.Z; z++ ) {
if( info.CollideType[GetPhysicsBlockId( x, y, z )] == BlockCollideType.Solid )
return false;
}
}
}
if( !CanSlideThrough( ref adjFinalBB ) )
return false;
Position.Y = blockBB.Max.Y + Adjustment;
onGround = true;
ClipY( ref size, ref entityBB, ref entityExtentBB );
@ -189,6 +179,27 @@ namespace ClassicalSharp {
return false;
}
bool CanSlideThrough( ref BoundingBox adjFinalBB ) {
Vector3I bbMin = Vector3I.Floor( adjFinalBB.Min );
Vector3I bbMax = Vector3I.Floor( adjFinalBB.Max );
for( int y = bbMin.Y; y <= bbMax.Y; y++ )
for( int z = bbMin.Z; z <= bbMax.Z; z++ )
for( int x = bbMin.X; x <= bbMax.X; x++ )
{
byte block = GetPhysicsBlockId( x, y, z );
Vector3 min = new Vector3( x, y, z ) + info.MinBB[block];
Vector3 max = new Vector3( x, y, z ) + info.MaxBB[block];
BoundingBox blockBB = new BoundingBox( min, max );
if( !blockBB.Intersects( adjFinalBB ) )
continue;
if( info.CollideType[GetPhysicsBlockId( x, y, z )] == BlockCollideType.Solid )
return false;
}
return true;
}
void ClipX( ref Vector3 size, ref BoundingBox entityBB, ref BoundingBox entityExtentBB ) {
Velocity.X = 0;
entityBB.Min.X = entityExtentBB.Min.X = Position.X - size.X / 2;

View File

@ -14,9 +14,7 @@ namespace ClassicalSharp.Generator {
public sealed class ImprovedNoise : Noise {
public ImprovedNoise( Random rnd ) {
// make a random initial permutation based on rnd's seed,
// shuffle using fisher-yates
// shuffle randomly using fisher-yates
for( int i = 0; i < 256; i++ )
p[i] = (byte)i;
@ -28,7 +26,6 @@ namespace ClassicalSharp.Generator {
p[i + 256] = p[i];
}
// TODO: need to half this maybe?
public override double Compute( double x, double y ) {
int xFloor = x >= 0 ? (int)x : (int)x - 1;
int yFloor = y >= 0 ? (int)y : (int)y - 1;

View File

@ -10,8 +10,9 @@ namespace ClassicalSharp.Model {
byte block = (byte)Block.Air;
float blockHeight;
TerrainAtlas1D atlas;
const float adjust = 0.1f, extent = 0.5f;
const float extent = 0.5f, adjust = 0.5f/16f;
bool bright;
Vector3 minBB, maxBB;
public BlockModel( Game game ) : base( game ) {
}
@ -30,13 +31,27 @@ namespace ClassicalSharp.Model {
}
public override Vector3 CollisionSize {
get { return new Vector3( 1 - adjust, blockHeight - adjust, 1 - adjust ); }
get { return (maxBB - minBB) - new Vector3( adjust ); }
}
public override BoundingBox PickingBounds {
get { return new BoundingBox( -extent, 0f, -extent, extent, blockHeight, extent ); }
}
public void CalcState( byte block ) {
if( block == 0 ) {
blockHeight = 1;
bright = false;
minBB = Vector3.Zero;
maxBB = Vector3.One;
} else {
blockHeight = game.BlockInfo.Height[block];
bright = game.BlockInfo.FullBright[block];
minBB = game.BlockInfo.MinBB[block];
maxBB = game.BlockInfo.MaxBB[block];
}
}
int lastTexId = -1;
protected override void DrawPlayerModel( Player p ) {
// TODO: using 'is' is ugly, but means we can avoid creating
@ -49,14 +64,12 @@ namespace ClassicalSharp.Model {
} else {
block = Byte.Parse( p.ModelName );
}
if( block == 0 ) {
blockHeight = 1;
CalcState( block );
if( block == 0 )
return;
}
lastTexId = -1;
blockHeight = game.BlockInfo.Height[block];
atlas = game.TerrainAtlas1D;
bright = game.BlockInfo.FullBright[block];
if( game.BlockInfo.IsSprite[block] ) {
SpriteXQuad( TileSide.Right, true );

View File

@ -50,7 +50,6 @@ namespace ClassicalSharp.Model {
DrawPart( Link );
DrawPart( End );
// TODO: leg animations
float rotX = (float)(Math.Sin( p.walkTime ) * p.swing * Math.PI);
float rotZ = (float)(Math.Cos( p.walkTime * 2 ) * p.swing * Math.PI / 16f);
float rotY = (float)(Math.Sin( p.walkTime * 2 ) * p.swing * Math.PI / 32f);