mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-24 05:10:42 -04:00
Core: Fix respawning in singleplayer sometimes putting you inside a block
also a minor touchup to reduce IModel code
This commit is contained in:
parent
152d222cfa
commit
96710328a8
@ -301,6 +301,7 @@
|
||||
<Compile Include="Utils\Camera.cs" />
|
||||
<Compile Include="Utils\ErrorHandler.cs" />
|
||||
<Compile Include="Utils\Options.cs" />
|
||||
<Compile Include="Utils\Respawn.cs" />
|
||||
<Compile Include="Utils\TextureRectangle.cs" />
|
||||
<Compile Include="Utils\StringBuffer.cs" />
|
||||
<Compile Include="Utils\Utils.cs" />
|
||||
|
@ -12,7 +12,6 @@ namespace ClassicalSharp.Entities {
|
||||
Entity entity;
|
||||
Game game;
|
||||
public HacksComponent Hacks;
|
||||
public CollisionsComponent collisions;
|
||||
public PhysicsComponent physics;
|
||||
|
||||
public InputComponent( Game game, Entity entity ) {
|
||||
@ -71,31 +70,14 @@ namespace ClassicalSharp.Entities {
|
||||
|
||||
void FindHighestFree( ref Vector3 spawn ) {
|
||||
BlockInfo info = game.BlockInfo;
|
||||
Vector3 size = entity.Size;
|
||||
AABB bb = AABB.Make( spawn, size );
|
||||
AABB bb = AABB.Make( spawn, entity.Size );
|
||||
|
||||
Vector3I P = Vector3I.Floor( spawn );
|
||||
int bbMax = Utils.Floor( size.Y );
|
||||
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 intersectAny = false;
|
||||
for( int yy = 0; yy <= bbMax; yy++ )
|
||||
for( int z = minZ; z <= maxZ; z++ )
|
||||
for ( int x = minX; x <= maxX; x++ )
|
||||
{
|
||||
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;
|
||||
intersectAny |= info.Collide[block] == CollideType.Solid;
|
||||
}
|
||||
|
||||
if( !intersectAny ) {
|
||||
byte block = collisions.GetPhysicsBlockId( P.X, y, P.Z );
|
||||
float spawnY = Respawn.HighestFreeY( game, ref bb );
|
||||
if( spawnY == float.NegativeInfinity ) {
|
||||
byte block = game.World.GetPhysicsBlock( P.X, y, P.Z );
|
||||
float height = info.Collide[block] == CollideType.Solid ? info.MaxBB[block].Y : 0;
|
||||
spawn.Y = y + height + Entity.Adjustment;
|
||||
return;
|
||||
|
@ -45,7 +45,7 @@ namespace ClassicalSharp.Entities {
|
||||
sound = new SoundComponent( game, this );
|
||||
|
||||
physics.hacks = Hacks; input.Hacks = Hacks;
|
||||
physics.collisions = collisions; input.collisions = collisions;
|
||||
physics.collisions = collisions;
|
||||
input.physics = physics;
|
||||
}
|
||||
|
||||
|
@ -23,16 +23,17 @@ namespace ClassicalSharp.Model {
|
||||
.TexOrigin( 14, 0 )
|
||||
.RotOrigin( 0, 9, -4 ) );
|
||||
Torso = BuildRotatedBox( MakeRotatedBoxBounds( -3, 5, -4, 3, 11, 3 )
|
||||
.TexOrigin( 0, 9 ) );
|
||||
.TexOrigin( 0, 9 ) );
|
||||
|
||||
LeftLeg = MakeLeg( -3, 0, -2, -1 );
|
||||
RightLeg = MakeLeg( 0, 3, 1, 2 );
|
||||
LeftWing = BuildBox( MakeBoxBounds( -4, 7, -3, -3, 11, 3 )
|
||||
.TexOrigin( 24, 13 )
|
||||
.RotOrigin( -3, 11, 0 ) );
|
||||
RightWing = BuildBox( MakeBoxBounds( 3, 7, -3, 4, 11, 3 )
|
||||
.TexOrigin( 24, 13 )
|
||||
.RotOrigin( 3, 11, 0 ) );
|
||||
|
||||
LeftLeg = MakeLeg( -3, 0, -2, -1 );
|
||||
RightLeg = MakeLeg( 0, 3, 1, 2 );
|
||||
}
|
||||
|
||||
ModelPart MakeLeg( int x1, int x2, int legX1, int legX2 ) {
|
||||
@ -57,16 +58,20 @@ namespace ClassicalSharp.Model {
|
||||
}
|
||||
|
||||
protected override void DrawModel( Player p ) {
|
||||
game.Graphics.BindTexture( GetTexture( p.MobTextureId ) );
|
||||
game.Graphics.BindTexture( GetTexture( p.MobTextureId ) );
|
||||
DrawHeadRotate( -p.PitchRadians, 0, 0, Head );
|
||||
DrawHeadRotate( -p.PitchRadians, 0, 0, Head2 );
|
||||
DrawHeadRotate( -p.PitchRadians, 0, 0, Head3 );
|
||||
|
||||
DrawPart( Torso );
|
||||
DrawRotate( p.anim.legXRot, 0, 0, LeftLeg );
|
||||
DrawRotate( -p.anim.legXRot, 0, 0, RightLeg );
|
||||
DrawRotate( 0, 0, -Math.Abs( p.anim.armXRot ), LeftWing );
|
||||
DrawRotate( 0, 0, Math.Abs( p.anim.armXRot ), RightWing );
|
||||
|
||||
for( int i = 0; i < cols.Length; i++ ) {
|
||||
cols[i] = FastColour.Scale( col, 0.7f ).Pack();
|
||||
}
|
||||
DrawRotate( p.anim.legXRot, 0, 0, LeftLeg );
|
||||
DrawRotate( -p.anim.legXRot, 0, 0, RightLeg );
|
||||
UpdateVB();
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,6 @@ namespace ClassicalSharp.Model {
|
||||
cols[1] = FastColour.Scale( col, FastColour.ShadeYBottom ).Pack();
|
||||
cols[2] = FastColour.Scale( col, FastColour.ShadeZ ).Pack(); cols[3] = cols[2];
|
||||
cols[4] = FastColour.Scale( col, FastColour.ShadeX ).Pack(); cols[5] = cols[4];
|
||||
otherCol = FastColour.Scale( col, 0.7f ).Pack();
|
||||
|
||||
cosYaw = (float)Math.Cos( p.YawDegrees * Utils.Deg2Rad );
|
||||
sinYaw = (float)Math.Sin( p.YawDegrees * Utils.Deg2Rad );
|
||||
@ -119,7 +118,6 @@ namespace ClassicalSharp.Model {
|
||||
|
||||
protected FastColour col;
|
||||
protected int[] cols = new int[6];
|
||||
protected int otherCol;
|
||||
protected internal ModelVertex[] vertices;
|
||||
protected internal int index, texIndex;
|
||||
|
||||
@ -154,7 +152,7 @@ namespace ClassicalSharp.Model {
|
||||
v.X *= scale; v.Y *= scale; v.Z *= scale;
|
||||
v.X += pos.X; v.Y += pos.Y; v.Z += pos.Z;
|
||||
vertex.X = v.X; vertex.Y = v.Y; vertex.Z = v.Z;
|
||||
vertex.Colour = part.Count == boxVertices ? cols[i >> 2] : otherCol;
|
||||
vertex.Colour = cols[i >> 2];
|
||||
|
||||
vertex.U = v.U * uScale; vertex.V = v.V * vScale;
|
||||
int quadI = i & 3;
|
||||
@ -209,7 +207,7 @@ namespace ClassicalSharp.Model {
|
||||
v.X *= scale; v.Y *= scale; v.Z *= scale;
|
||||
v.X += pos.X; v.Y += pos.Y; v.Z += pos.Z;
|
||||
vertex.X = v.X; vertex.Y = v.Y; vertex.Z = v.Z;
|
||||
vertex.Colour = part.Count == boxVertices ? cols[i >> 2] : otherCol;
|
||||
vertex.Colour = cols[i >> 2];
|
||||
|
||||
vertex.U = v.U * uScale; vertex.V = v.V * vScale;
|
||||
int quadI = i & 3;
|
||||
|
@ -43,7 +43,7 @@ namespace ClassicalSharp.Map {
|
||||
|
||||
Uuid = Guid.NewGuid();
|
||||
game.WorldEvents.RaiseOnNewMap();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Updates the underlying block array, heightmap, and dimensions of this map. </summary>
|
||||
public void SetNewMap( byte[] blocks, int width, int height, int length ) {
|
||||
@ -153,10 +153,17 @@ namespace ClassicalSharp.Map {
|
||||
public Vector3I GetCoords( int index ) {
|
||||
if( index < 0 || index >= blocks.Length )
|
||||
return new Vector3I( -1 );
|
||||
|
||||
int x = index % Width;
|
||||
int y = index / oneY; // index / (width * length)
|
||||
int z = (index / Width) % Length;
|
||||
return new Vector3I( x, y, z );
|
||||
}
|
||||
|
||||
public byte GetPhysicsBlock( int x, int y, int z ) {
|
||||
if( x < 0 || x >= Width || z < 0 || z >= Length || y < 0 ) return Block.Bedrock;
|
||||
if( y >= Height ) return Block.Air;
|
||||
return blocks[(y * Length + z) * Width + x];
|
||||
}
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ namespace ClassicalSharp.Physics {
|
||||
for( int z = min.Z; z <= max.Z; z++ )
|
||||
for( int x = min.X; x <= max.X; x++ )
|
||||
{
|
||||
byte block = GetPhysicsBlockId( game.World, x, y, z );
|
||||
byte block = game.World.GetPhysicsBlock( x, y, z );
|
||||
if( info.Collide[block] != CollideType.Solid ) continue;
|
||||
|
||||
blockBB.Min = info.MinBB[block];
|
||||
@ -76,15 +76,7 @@ namespace ClassicalSharp.Physics {
|
||||
QuickSort( stateCache, 0, count - 1 );
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public static byte GetPhysicsBlockId( World world, int x, int y, int z ) {
|
||||
if( x < 0 || x >= world.Width || z < 0 ||
|
||||
z >= world.Length || y < 0 ) return Block.Bedrock;
|
||||
|
||||
if( y >= world.Height ) return Block.Air;
|
||||
return world.GetBlock( x, y, z );
|
||||
}
|
||||
|
||||
|
||||
public static void CalcTime( ref Vector3 vel, ref AABB entityBB, ref AABB blockBB,
|
||||
out float tx, out float ty, out float tz ) {
|
||||
|
@ -5,6 +5,7 @@ using System.Net;
|
||||
using ClassicalSharp.Entities;
|
||||
using ClassicalSharp.Generator;
|
||||
using ClassicalSharp.Gui.Screens;
|
||||
using ClassicalSharp.Physics;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
|
||||
@ -114,12 +115,24 @@ namespace ClassicalSharp.Singleplayer {
|
||||
|
||||
|
||||
void ResetPlayerPosition() {
|
||||
int x = game.World.Width / 2, z = game.World.Length / 2;
|
||||
int y = game.World.GetLightHeight( x, z ) + 2;
|
||||
Vector3 spawn = default(Vector3);
|
||||
spawn.X = (game.World.Width / 2) + 0.5f;
|
||||
spawn.Y = game.World.Height + Entity.Adjustment;
|
||||
spawn.Z = (game.World.Length / 2) + 0.5f;
|
||||
|
||||
LocationUpdate update = LocationUpdate.MakePosAndOri( x, y, z, 0, 0, false );
|
||||
AABB bb = AABB.Make( spawn, game.LocalPlayer.Size );
|
||||
spawn.Y = 0;
|
||||
for( int y = game.World.Height; y >= 0; y-- ) {
|
||||
float highestY = Respawn.HighestFreeY( game, ref bb );
|
||||
if( highestY != float.NegativeInfinity ) {
|
||||
spawn.Y = highestY; break;
|
||||
}
|
||||
bb.Min.Y -= 1; bb.Max.Y -= 1;
|
||||
}
|
||||
|
||||
LocationUpdate update = LocationUpdate.MakePosAndOri( spawn, 0, 0, false );
|
||||
game.LocalPlayer.SetLocation( update, false );
|
||||
game.LocalPlayer.Spawn = new Vector3( x, y, z );
|
||||
game.LocalPlayer.Spawn = spawn;
|
||||
game.CurrentCameraPos = game.Camera.GetCameraPos( 0 );
|
||||
}
|
||||
}
|
||||
|
35
ClassicalSharp/Utils/Respawn.cs
Normal file
35
ClassicalSharp/Utils/Respawn.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using ClassicalSharp.Physics;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
/// <summary> Shared helper class for respawning an entity. </summary>
|
||||
public static class Respawn {
|
||||
|
||||
public static float HighestFreeY( Game game, ref AABB bb ) {
|
||||
int minX = Utils.Floor( bb.Min.X ), maxX = Utils.Floor( bb.Max.X );
|
||||
int minY = Utils.Floor( bb.Min.Y ), maxY = Utils.Floor( bb.Max.Y );
|
||||
int minZ = Utils.Floor( bb.Min.Z ), maxZ = Utils.Floor( bb.Max.Z );
|
||||
|
||||
BlockInfo info = game.BlockInfo;
|
||||
float spawnY = float.NegativeInfinity;
|
||||
AABB blockBB = default(AABB);
|
||||
|
||||
for( int y = minY; y <= maxY; y++ )
|
||||
for( int z = minZ; z <= maxZ; z++ )
|
||||
for ( int x = minX; x <= maxX; x++ )
|
||||
{
|
||||
byte block = game.World.GetPhysicsBlock( x, y, z );
|
||||
blockBB.Min = new Vector3( x, y, z ) + info.MinBB[block];
|
||||
blockBB.Max = new Vector3( x, y, z ) + info.MaxBB[block];
|
||||
|
||||
if( info.Collide[block] != CollideType.Solid ) continue;
|
||||
if( !bb.Intersects( blockBB ) ) continue;
|
||||
spawnY = Math.Max( spawnY, blockBB.Max.Y );
|
||||
}
|
||||
return spawnY;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user