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;