Core: Fix respawning in singleplayer sometimes putting you inside a block

also a minor touchup to reduce IModel code
This commit is contained in:
UnknownShadow200 2016-11-06 14:40:39 +11:00
parent 152d222cfa
commit 96710328a8
9 changed files with 81 additions and 48 deletions

View File

@ -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" />

View File

@ -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;

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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];
}
}
}

View File

@ -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 ) {

View File

@ -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 );
}
}

View 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;
}
}
}