mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-15 02:25:32 -04:00
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:
parent
11b2230b63
commit
89c2ae40f9
@ -140,7 +140,6 @@ namespace ClassicalSharp {
|
||||
int index = 0;
|
||||
SplitUppercase( origName, ref index );
|
||||
normalNames[i] = buffer.ToString();
|
||||
Console.WriteLine( buffer.ToString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -85,7 +85,7 @@ namespace ClassicalSharp {
|
||||
int elements = (max.X + 1 - min.X) * (max.Y + 1 - min.Y) * (max.Z + 1 - min.Z);
|
||||
if( elements > stateCache.Length ) {
|
||||
stateCache = new State[elements];
|
||||
}
|
||||
}
|
||||
|
||||
BoundingBox blockBB = default( BoundingBox );
|
||||
// Order loops so that we minimise cache misses
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
@ -135,7 +148,7 @@ namespace ClassicalSharp.Model {
|
||||
|
||||
float p1, p2;
|
||||
if( firstPart ) { // Need to break into two quads for when drawing a sprite model in hand.
|
||||
rec.U1 = 0.5f; p1 = -5.5f/16; p2 = 0.0f/16;
|
||||
rec.U1 = 0.5f; p1 = -5.5f/16; p2 = 0.0f/16;
|
||||
} else {
|
||||
rec.U2 = 0.5f; p1 = 0.0f/16; p2 = 5.5f/16;
|
||||
}
|
||||
@ -155,7 +168,7 @@ namespace ClassicalSharp.Model {
|
||||
|
||||
float x1, x2, z1, z2;
|
||||
if( firstPart ) {
|
||||
rec.U1 = 0; rec.U2 = 0.5f; x1 = -5.5f/16;
|
||||
rec.U1 = 0; rec.U2 = 0.5f; x1 = -5.5f/16;
|
||||
x2 = 0.0f/16; z1 = 5.5f/16; z2 = 0.0f/16;
|
||||
} else {
|
||||
rec.U1 = 0.5f; rec.U2 = 1f; x1 = 0.0f/16;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user