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;
|
int index = 0;
|
||||||
SplitUppercase( origName, ref index );
|
SplitUppercase( origName, ref index );
|
||||||
normalNames[i] = buffer.ToString();
|
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>
|
/// <summary> Returns the size of the model that is used for collision detection. </summary>
|
||||||
public virtual Vector3 CollisionSize {
|
public virtual Vector3 CollisionSize {
|
||||||
get { return new Vector3( 8/16f, 28.5f/16f, 8/16f );
|
get { UpdateModel(); return Model.CollisionSize; }
|
||||||
//Model.CollisionSize; TODO: for non humanoid models
|
}
|
||||||
}
|
|
||||||
|
void UpdateModel() {
|
||||||
|
BlockModel model = Model as BlockModel;
|
||||||
|
if( model != null )
|
||||||
|
model.CalcState( byte.Parse( ModelName ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary> Bounding box of the model that collision detection
|
/// <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>
|
/// bounding box of this entity are lava or still lava. </summary>
|
||||||
protected bool TouchesAnyLava() {
|
protected bool TouchesAnyLava() {
|
||||||
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
|
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
|
||||||
// Even though we collide with lava 3 blocks above our feet, vanilla client thinks
|
AdjustLiquidTestBounds( ref bounds );
|
||||||
// that we do not.. so we have to maintain compatibility here.
|
|
||||||
bounds.Max.Y -= 4/16f;
|
|
||||||
return TouchesAny( bounds,
|
return TouchesAny( bounds,
|
||||||
b => b == (byte)Block.Lava || b == (byte)Block.StillLava );
|
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>
|
/// bounding box of this entity are water or still water. </summary>
|
||||||
protected bool TouchesAnyWater() {
|
protected bool TouchesAnyWater() {
|
||||||
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
|
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
|
||||||
bounds.Max.Y -= 4/16f;
|
AdjustLiquidTestBounds( ref bounds );
|
||||||
return TouchesAny( bounds,
|
return TouchesAny( bounds,
|
||||||
b => b == (byte)Block.Water || b == (byte)Block.StillWater );
|
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 ) {
|
if( !jumping ) {
|
||||||
canLiquidJump = false;
|
canLiquidJump = false; return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool touchWater = TouchesAnyWater();
|
bool touchWater = TouchesAnyWater();
|
||||||
bool touchLava = TouchesAnyLava();
|
bool touchLava = TouchesAnyLava();
|
||||||
|
Console.WriteLine( touchWater );
|
||||||
if( touchWater || touchLava ) {
|
if( touchWater || touchLava ) {
|
||||||
BoundingBox bounds = CollisionBounds;
|
BoundingBox bounds = CollisionBounds;
|
||||||
int feetY = Utils.Floor( bounds.Min.Y ), bodyY = feetY + 1;
|
int feetY = Utils.Floor( bounds.Min.Y ), bodyY = feetY + 1;
|
||||||
int headY = Utils.Floor( bounds.Max.Y );
|
int headY = Utils.Floor( bounds.Max.Y );
|
||||||
|
if( bodyY > headY ) bodyY = headY;
|
||||||
|
|
||||||
bounds.Max.Y = bounds.Min.Y = feetY;
|
bounds.Max.Y = bounds.Min.Y = feetY;
|
||||||
bool liquidFeet = TouchesAny( bounds, StandardLiquid );
|
bool liquidFeet = TouchesAny( bounds, StandardLiquid );
|
||||||
bounds.Max.Y = bounds.Min.Y = bodyY;
|
bounds.Min.Y = Math.Min( bodyY, headY );
|
||||||
bool liquidBody = TouchesAny( bounds, StandardLiquid );
|
bounds.Max.Y = Math.Max( bodyY, headY );
|
||||||
bounds.Max.Y = bounds.Min.Y = headY;
|
bool liquidRest = TouchesAny( bounds, StandardLiquid );
|
||||||
bool liquidHead = TouchesAny( bounds, StandardLiquid );
|
|
||||||
|
|
||||||
bool pastJumpPoint = liquidFeet && !(liquidBody || liquidHead)
|
bool pastJumpPoint = liquidFeet && !liquidRest && (Position.Y % 1 >= 0.4);
|
||||||
&& (Position.Y % 1 >= 0.4);
|
|
||||||
if( !pastJumpPoint ) {
|
if( !pastJumpPoint ) {
|
||||||
canLiquidJump = true;
|
canLiquidJump = true;
|
||||||
Velocity.Y += speeding ? 0.08f : 0.04f;
|
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);
|
int elements = (max.X + 1 - min.X) * (max.Y + 1 - min.Y) * (max.Z + 1 - min.Z);
|
||||||
if( elements > stateCache.Length ) {
|
if( elements > stateCache.Length ) {
|
||||||
stateCache = new State[elements];
|
stateCache = new State[elements];
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox blockBB = default( BoundingBox );
|
BoundingBox blockBB = default( BoundingBox );
|
||||||
// Order loops so that we minimise cache misses
|
// Order loops so that we minimise cache misses
|
||||||
@ -160,27 +160,17 @@ namespace ClassicalSharp {
|
|||||||
ref BoundingBox entityBB, ref BoundingBox entityExtentBB ) {
|
ref BoundingBox entityBB, ref BoundingBox entityExtentBB ) {
|
||||||
float yDist = blockBB.Max.Y - entityBB.Min.Y;
|
float yDist = blockBB.Max.Y - entityBB.Min.Y;
|
||||||
if( yDist > 0 && yDist <= StepSize + 0.01f ) {
|
if( yDist > 0 && yDist <= StepSize + 0.01f ) {
|
||||||
|
|
||||||
// Adjust entity bounding box to include the block being tested
|
// Adjust entity bounding box to include the block being tested
|
||||||
BoundingBox adjFinalBB = finalBB;
|
BoundingBox adjFinalBB = finalBB;
|
||||||
adjFinalBB.Min.X = Math.Min( finalBB.Min.X, blockBB.Min.X + Adjustment );
|
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.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.Max.Y = adjFinalBB.Min.Y + size.Y;
|
||||||
adjFinalBB.Min.Z = Math.Min( finalBB.Min.Z, blockBB.Min.Z + Adjustment );
|
adjFinalBB.Min.Z = Math.Min( finalBB.Min.Z, blockBB.Min.Z + Adjustment );
|
||||||
adjFinalBB.Max.Z = Math.Max( finalBB.Max.Z, blockBB.Max.Z - Adjustment );
|
adjFinalBB.Max.Z = Math.Max( finalBB.Max.Z, blockBB.Max.Z - Adjustment );
|
||||||
|
|
||||||
Vector3I min = Vector3I.Floor( adjFinalBB.Min );
|
if( !CanSlideThrough( ref adjFinalBB ) )
|
||||||
Vector3I max = Vector3I.Floor( adjFinalBB.Max );
|
return false;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Position.Y = blockBB.Max.Y + Adjustment;
|
Position.Y = blockBB.Max.Y + Adjustment;
|
||||||
onGround = true;
|
onGround = true;
|
||||||
ClipY( ref size, ref entityBB, ref entityExtentBB );
|
ClipY( ref size, ref entityBB, ref entityExtentBB );
|
||||||
@ -189,6 +179,27 @@ namespace ClassicalSharp {
|
|||||||
return false;
|
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 ) {
|
void ClipX( ref Vector3 size, ref BoundingBox entityBB, ref BoundingBox entityExtentBB ) {
|
||||||
Velocity.X = 0;
|
Velocity.X = 0;
|
||||||
entityBB.Min.X = entityExtentBB.Min.X = Position.X - size.X / 2;
|
entityBB.Min.X = entityExtentBB.Min.X = Position.X - size.X / 2;
|
||||||
|
@ -14,9 +14,7 @@ namespace ClassicalSharp.Generator {
|
|||||||
public sealed class ImprovedNoise : Noise {
|
public sealed class ImprovedNoise : Noise {
|
||||||
|
|
||||||
public ImprovedNoise( Random rnd ) {
|
public ImprovedNoise( Random rnd ) {
|
||||||
// make a random initial permutation based on rnd's seed,
|
// shuffle randomly using fisher-yates
|
||||||
// shuffle using fisher-yates
|
|
||||||
|
|
||||||
for( int i = 0; i < 256; i++ )
|
for( int i = 0; i < 256; i++ )
|
||||||
p[i] = (byte)i;
|
p[i] = (byte)i;
|
||||||
|
|
||||||
@ -28,7 +26,6 @@ namespace ClassicalSharp.Generator {
|
|||||||
p[i + 256] = p[i];
|
p[i + 256] = p[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: need to half this maybe?
|
|
||||||
public override double Compute( double x, double y ) {
|
public override double Compute( double x, double y ) {
|
||||||
int xFloor = x >= 0 ? (int)x : (int)x - 1;
|
int xFloor = x >= 0 ? (int)x : (int)x - 1;
|
||||||
int yFloor = y >= 0 ? (int)y : (int)y - 1;
|
int yFloor = y >= 0 ? (int)y : (int)y - 1;
|
||||||
|
@ -10,8 +10,9 @@ namespace ClassicalSharp.Model {
|
|||||||
byte block = (byte)Block.Air;
|
byte block = (byte)Block.Air;
|
||||||
float blockHeight;
|
float blockHeight;
|
||||||
TerrainAtlas1D atlas;
|
TerrainAtlas1D atlas;
|
||||||
const float adjust = 0.1f, extent = 0.5f;
|
const float extent = 0.5f, adjust = 0.5f/16f;
|
||||||
bool bright;
|
bool bright;
|
||||||
|
Vector3 minBB, maxBB;
|
||||||
|
|
||||||
public BlockModel( Game game ) : base( game ) {
|
public BlockModel( Game game ) : base( game ) {
|
||||||
}
|
}
|
||||||
@ -30,13 +31,27 @@ namespace ClassicalSharp.Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override Vector3 CollisionSize {
|
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 {
|
public override BoundingBox PickingBounds {
|
||||||
get { return new BoundingBox( -extent, 0f, -extent, extent, blockHeight, extent ); }
|
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;
|
int lastTexId = -1;
|
||||||
protected override void DrawPlayerModel( Player p ) {
|
protected override void DrawPlayerModel( Player p ) {
|
||||||
// TODO: using 'is' is ugly, but means we can avoid creating
|
// TODO: using 'is' is ugly, but means we can avoid creating
|
||||||
@ -49,14 +64,12 @@ namespace ClassicalSharp.Model {
|
|||||||
} else {
|
} else {
|
||||||
block = Byte.Parse( p.ModelName );
|
block = Byte.Parse( p.ModelName );
|
||||||
}
|
}
|
||||||
if( block == 0 ) {
|
|
||||||
blockHeight = 1;
|
CalcState( block );
|
||||||
|
if( block == 0 )
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
lastTexId = -1;
|
lastTexId = -1;
|
||||||
blockHeight = game.BlockInfo.Height[block];
|
|
||||||
atlas = game.TerrainAtlas1D;
|
atlas = game.TerrainAtlas1D;
|
||||||
bright = game.BlockInfo.FullBright[block];
|
|
||||||
|
|
||||||
if( game.BlockInfo.IsSprite[block] ) {
|
if( game.BlockInfo.IsSprite[block] ) {
|
||||||
SpriteXQuad( TileSide.Right, true );
|
SpriteXQuad( TileSide.Right, true );
|
||||||
@ -135,7 +148,7 @@ namespace ClassicalSharp.Model {
|
|||||||
|
|
||||||
float p1, p2;
|
float p1, p2;
|
||||||
if( firstPart ) { // Need to break into two quads for when drawing a sprite model in hand.
|
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 {
|
} else {
|
||||||
rec.U2 = 0.5f; p1 = 0.0f/16; p2 = 5.5f/16;
|
rec.U2 = 0.5f; p1 = 0.0f/16; p2 = 5.5f/16;
|
||||||
}
|
}
|
||||||
@ -155,7 +168,7 @@ namespace ClassicalSharp.Model {
|
|||||||
|
|
||||||
float x1, x2, z1, z2;
|
float x1, x2, z1, z2;
|
||||||
if( firstPart ) {
|
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;
|
x2 = 0.0f/16; z1 = 5.5f/16; z2 = 0.0f/16;
|
||||||
} else {
|
} else {
|
||||||
rec.U1 = 0.5f; rec.U2 = 1f; x1 = 0.0f/16;
|
rec.U1 = 0.5f; rec.U2 = 1f; x1 = 0.0f/16;
|
||||||
|
@ -50,7 +50,6 @@ namespace ClassicalSharp.Model {
|
|||||||
DrawPart( Link );
|
DrawPart( Link );
|
||||||
DrawPart( End );
|
DrawPart( End );
|
||||||
|
|
||||||
// TODO: leg animations
|
|
||||||
float rotX = (float)(Math.Sin( p.walkTime ) * p.swing * Math.PI);
|
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 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);
|
float rotY = (float)(Math.Sin( p.walkTime * 2 ) * p.swing * Math.PI / 32f);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user