diff --git a/ClassicalSharp/Entities/Components/InputComponent.cs b/ClassicalSharp/Entities/Components/InputComponent.cs
index c13003a9c..fea44b525 100644
--- a/ClassicalSharp/Entities/Components/InputComponent.cs
+++ b/ClassicalSharp/Entities/Components/InputComponent.cs
@@ -33,6 +33,8 @@ namespace ClassicalSharp.Entities {
entity.SetLocation( update, false );
} else if( key == keys[KeyBinding.SetSpawn] && Hacks.CanRespawn ) {
p.Spawn = entity.Position;
+ p.Spawn.X = Utils.Floor( p.Spawn.X ) + 0.5f;
+ p.Spawn.Z = Utils.Floor( p.Spawn.Z ) + 0.5f;
p.SpawnYaw = entity.YawDegrees;
p.SpawnPitch = entity.PitchDegrees;
@@ -61,33 +63,35 @@ namespace ClassicalSharp.Entities {
void FindHighestFree( ref Vector3 spawn ) {
BlockInfo info = game.BlockInfo;
Vector3 size = entity.CollisionSize;
- AABB bb = entity.CollisionBounds;
+ AABB bb = AABB.Make( spawn, size );
+
Vector3I P = Vector3I.Floor( spawn );
int bbMax = Utils.Floor( size.Y );
- int minX = Utils.Floor( -size.X / 2 ), maxX = Utils.Floor( size.X / 2 );
- int minZ = Utils.Floor( -size.Z / 2 ), maxZ = Utils.Floor( size.Z / 2 );
+ int minX = Utils.Floor( P.X - size.X / 2 ), maxX = Utils.Floor( P.X + size.X / 2 );
+ int minZ = Utils.Floor( P.Z - size.Z / 2 ), maxZ = Utils.Floor( P.Z + size.Z / 2 );
// Spawn player at highest valid position.
for( int y = P.Y; y <= game.World.Height; y++ ) {
- bool anyHit = false;
+ bool intersectAny = false;
for( int yy = 0; yy <= bbMax; yy++ )
- for( int zz = minZ; zz <= maxZ; zz++ )
- for ( int xx = minX; xx <= maxX; xx++ )
+ for( int z = minZ; z <= maxZ; z++ )
+ for ( int x = minX; x <= maxX; x++ )
{
- Vector3I coords = new Vector3I( P.X + xx, y + yy, P.Z + zz );
+ Vector3I coords = new Vector3I( x, y + yy, z );
byte block = collisions.GetPhysicsBlockId( coords.X, coords.Y, coords.Z );
Vector3 min = info.MinBB[block] + (Vector3)coords;
Vector3 max = info.MaxBB[block] + (Vector3)coords;
if( !bb.Intersects( new AABB( min, max ) ) ) continue;
- anyHit |= info.Collide[block] == CollideType.Solid;
+ intersectAny |= info.Collide[block] == CollideType.Solid;
}
- if( !anyHit ) {
+ if( !intersectAny ) {
byte block = collisions.GetPhysicsBlockId( P.X, y, P.Z );
float height = info.Collide[block] == CollideType.Solid ? info.MaxBB[block].Y : 0;
spawn.Y = y + height + Entity.Adjustment;
return;
}
+ bb.Min.Y += 1; bb.Max.Y += 1;
}
}
}
diff --git a/ClassicalSharp/Entities/Entity.Bounds.cs b/ClassicalSharp/Entities/Entity.Bounds.cs
index 51e6ac648..fb78e52ad 100644
--- a/ClassicalSharp/Entities/Entity.Bounds.cs
+++ b/ClassicalSharp/Entities/Entity.Bounds.cs
@@ -19,12 +19,7 @@ namespace ClassicalSharp.Entities {
/// Bounding box of the model that collision detection
/// is performed with, in world coordinates.
public virtual AABB CollisionBounds {
- get {
- Vector3 pos = Position;
- Vector3 size = CollisionSize;
- return new AABB( pos.X - size.X / 2, pos.Y, pos.Z - size.Z / 2,
- pos.X + size.X / 2, pos.Y + size.Y, pos.Z + size.Z / 2 );
- }
+ get { return AABB.Make( Position, CollisionSize ); }
}
/// Determines whether any of the blocks that intersect the
diff --git a/ClassicalSharp/Math/AABB.cs b/ClassicalSharp/Math/AABB.cs
index 5d4b3577f..6710ad06d 100644
--- a/ClassicalSharp/Math/AABB.cs
+++ b/ClassicalSharp/Math/AABB.cs
@@ -23,25 +23,30 @@ namespace ClassicalSharp {
Max = max;
}
- /// Returns a new bounding box, with the minimum and maximum coordinates
+ public static AABB Make( Vector3 pos, Vector3 size ) {
+ return new AABB( pos.X - size.X / 2, pos.Y, pos.Z - size.Z / 2,
+ pos.X + size.X / 2, pos.Y + size.Y, pos.Z + size.Z / 2 );
+ }
+
+ /// Returns a new bounding box, with the minimum and maximum coordinates
/// of the original bounding box translated by the given vector.
public AABB Offset( Vector3 amount ) {
return new AABB( Min + amount, Max + amount );
}
- /// Returns a new bounding box, with the minimum and maximum coordinates
+ /// Returns a new bounding box, with the minimum and maximum coordinates
/// of the original bounding box expanded away from origin the given vector.
public AABB Expand( Vector3 amount ) {
return new AABB( Min - amount, Max + amount );
}
- /// Returns a new bounding box, with the minimum and maximum coordinates
+ /// Returns a new bounding box, with the minimum and maximum coordinates
/// of the original bounding box scaled away from origin the given value.
public AABB Scale( float scale ) {
return new AABB( Min * scale, Max * scale );
}
- /// Determines whether this bounding box intersects
+ /// Determines whether this bounding box intersects
/// the given bounding box on any axes.
public bool Intersects( AABB other ) {
if( Max.X >= other.Min.X && Min.X <= other.Max.X ) {
@@ -53,33 +58,33 @@ namespace ClassicalSharp {
return false;
}
- /// Determines whether this bounding box entirely contains
+ /// Determines whether this bounding box entirely contains
/// the given bounding box on all axes.
public bool Contains( AABB other ) {
return other.Min.X >= Min.X && other.Min.Y >= Min.Y && other.Min.Z >= Min.Z &&
other.Max.X <= Max.X && other.Max.Y <= Max.Y && other.Max.Z <= Max.Z;
}
- /// Determines whether this bounding box entirely contains
+ /// Determines whether this bounding box entirely contains
/// the coordinates on all axes.
public bool Contains( Vector3 P ) {
return P.X >= Min.X && P.Y >= Min.Y && P.Z >= Min.Z &&
P.X <= Max.X && P.Y <= Max.Y && P.Z <= Max.Z;
}
- /// Determines whether this bounding box intersects
+ /// Determines whether this bounding box intersects
/// the given bounding box on the X axis.
public bool XIntersects( AABB box ) {
return Max.X >= box.Min.X && Min.X <= box.Max.X;
}
- /// Determines whether this bounding box intersects
+ /// Determines whether this bounding box intersects
/// the given bounding box on the Y axis.
public bool YIntersects( AABB box ) {
return Max.Y >= box.Min.Y && Min.Y <= box.Max.Y;
}
- /// Determines whether this bounding box intersects
+ /// Determines whether this bounding box intersects
/// the given bounding box on the Z axis.
public bool ZIntersects( AABB box ) {
return Max.Z >= box.Min.Z && Min.Z <= box.Max.Z;