Modularise Entity and Player class more.

This commit is contained in:
UnknownShadow200 2016-02-16 23:58:17 +11:00
parent eb3bbc168a
commit 2cb3322c34
15 changed files with 144 additions and 184 deletions

View File

@ -148,6 +148,7 @@
<Compile Include="Entities\Components\HacksComponent.cs" />
<Compile Include="Entities\Components\InterpolatedComponent.cs" />
<Compile Include="Entities\Components\PhysicsComponent.cs" />
<Compile Include="Entities\Entity.Bounds.cs" />
<Compile Include="Entities\Entity.cs" />
<Compile Include="Entities\EntityList.cs" />
<Compile Include="Entities\LocalPlayer.cs" />

View File

@ -0,0 +1,94 @@
using System;
using ClassicalSharp.Model;
using OpenTK;
namespace ClassicalSharp {
/// <summary> Contains a model, along with position, velocity, and rotation.
/// May also contain other fields and properties. </summary>
public abstract partial class Entity {
/// <summary> Returns the bounding box that contains the model, assuming it is not rotated. </summary>
public BoundingBox PickingBounds {
get { UpdateModel(); return Model.PickingBounds.Offset( Position ); }
}
/// <summary> Bounding box of the model that collision detection
/// is performed with, in world coordinates. </summary>
public virtual BoundingBox CollisionBounds {
get {
Vector3 pos = Position;
Vector3 size = CollisionSize;
return new BoundingBox( 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 );
}
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity satisfy the given condition. </summary>
public bool TouchesAny( Predicate<byte> condition ) {
return TouchesAny( CollisionBounds, condition );
}
/// <summary> Determines whether any of the blocks that intersect the
/// given bounding box satisfy the given condition. </summary>
public bool TouchesAny( BoundingBox bounds, Predicate<byte> condition ) {
Vector3I bbMin = Vector3I.Floor( bounds.Min );
Vector3I bbMax = Vector3I.Floor( bounds.Max );
// Order loops so that we minimise cache misses
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++ )
{
if( !game.Map.IsValidPos( x, y, z ) ) continue;
byte block = game.Map.GetBlock( 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( bounds ) ) continue;
if( condition( block ) ) return true;
}
return false;
}
/// <summary> Constant offset used to avoid floating point roundoff errors. </summary>
public const float Adjustment = 0.001f;
static readonly Vector3 liqExpand = new Vector3( 0.25f/16f, 0/16f, 0.25f/16f );
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are lava or still lava. </summary>
protected bool TouchesAnyLava() {
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
AdjustLiquidTestBounds( ref bounds );
return TouchesAny( bounds,
b => b == (byte)Block.Lava || b == (byte)Block.StillLava );
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are rope. </summary>
protected bool TouchesAnyRope() {
BoundingBox bounds = CollisionBounds;
bounds.Max.Y += 0.5f/16f;
return TouchesAny( bounds, b => b == (byte)Block.Rope );
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are water or still water. </summary>
protected bool TouchesAnyWater() {
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
AdjustLiquidTestBounds( ref bounds );
return TouchesAny( bounds,
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 );
}
}
}

View File

@ -6,7 +6,7 @@ namespace ClassicalSharp {
/// <summary> Contains a model, along with position, velocity, and rotation.
/// May also contain other fields and properties. </summary>
public abstract class Entity {
public abstract partial class Entity {
public Entity( Game game ) {
this.game = game;
@ -49,28 +49,12 @@ namespace ClassicalSharp {
get { UpdateModel(); return Model.CollisionSize; }
}
/// <summary> Returns the bounding box that contains the model, assuming it is not rotated. </summary>
public BoundingBox PickingBounds {
get { UpdateModel(); return Model.PickingBounds.Offset( Position ); }
}
void UpdateModel() {
BlockModel model = Model as BlockModel;
if( model != null )
model.CalcState( byte.Parse( ModelName ) );
}
/// <summary> Bounding box of the model that collision detection
/// is performed with, in world coordinates. </summary>
public virtual BoundingBox CollisionBounds {
get {
Vector3 pos = Position;
Vector3 size = CollisionSize;
return new BoundingBox( 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 );
}
}
public abstract void Tick( double delta );
public abstract void SetLocation( LocationUpdate update, bool interpolate );
@ -84,71 +68,23 @@ namespace ClassicalSharp {
/// <remarks> Assumes that RenderModel was previously called this frame. </remarks>
public abstract void RenderName();
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity satisfy the given condition. </summary>
public bool TouchesAny( Predicate<byte> condition ) {
return TouchesAny( CollisionBounds, condition );
/// <summary> Gets the position of the player's eye in the world. </summary>
public Vector3 EyePosition {
get { return new Vector3( Position.X, Position.Y + Model.GetEyeY( this ), Position.Z ); }
}
/// <summary> Gets the block just underneath the player's feet position. </summary>
public Block BlockUnderFeet {
get { return GetBlock( new Vector3( Position.X, Position.Y - 0.01f, Position.Z ) ); }
}
/// <summary> Determines whether any of the blocks that intersect the
/// given bounding box satisfy the given condition. </summary>
public bool TouchesAny( BoundingBox bounds, Predicate<byte> condition ) {
Vector3I bbMin = Vector3I.Floor( bounds.Min );
Vector3I bbMax = Vector3I.Floor( bounds.Max );
// Order loops so that we minimise cache misses
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++ )
{
if( !game.Map.IsValidPos( x, y, z ) ) continue;
byte block = game.Map.GetBlock( 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( bounds ) ) continue;
if( condition( block ) ) return true;
}
return false;
/// <summary> Gets the block at player's eye position. </summary>
public Block BlockAtHead {
get { return GetBlock( EyePosition ); }
}
/// <summary> Constant offset used to avoid floating point roundoff errors. </summary>
public const float Adjustment = 0.001f;
static readonly Vector3 liqExpand = new Vector3( 0.25f/16f, 0/16f, 0.25f/16f );
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are lava or still lava. </summary>
protected bool TouchesAnyLava() {
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
AdjustLiquidTestBounds( ref bounds );
return TouchesAny( bounds,
b => b == (byte)Block.Lava || b == (byte)Block.StillLava );
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are rope. </summary>
protected bool TouchesAnyRope() {
BoundingBox bounds = CollisionBounds;
bounds.Max.Y += 0.5f/16f;
return TouchesAny( bounds, b => b == (byte)Block.Rope );
}
/// <summary> Determines whether any of the blocks that intersect the
/// bounding box of this entity are water or still water. </summary>
protected bool TouchesAnyWater() {
BoundingBox bounds = CollisionBounds.Expand( liqExpand );
AdjustLiquidTestBounds( ref bounds );
return TouchesAny( bounds,
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 );
protected Block GetBlock( Vector3 coords ) {
return (Block)game.Map.SafeGetBlock( Vector3I.Floor( coords ) );
}
}
}

View File

@ -228,6 +228,12 @@ namespace ClassicalSharp {
}
}
void RemoveOldest<T>(T[] array, ref int count) {
for( int i = 0; i < array.Length - 1; i++ )
array[i] = array[i + 1];
count--;
}
internal bool HandleKeyDown( Key key ) {
KeyMap keys = game.InputHandler.Keys;
if( key == keys[KeyBinding.Respawn] && Hacks.CanRespawn ) {

View File

@ -11,11 +11,6 @@ namespace ClassicalSharp {
public abstract partial class Player : Entity {
/// <summary> Gets the position of the player's eye in the world. </summary>
public Vector3 EyePosition {
get { return new Vector3( Position.X, Position.Y + Model.GetEyeY( this ), Position.Z ); }
}
public string DisplayName, SkinName, SkinIdentifier;
public SkinType SkinType;
internal AnimatedComponent anim;
@ -28,20 +23,6 @@ namespace ClassicalSharp {
SetModel( "humanoid" );
}
/// <summary> Gets the block just underneath the player's feet position. </summary>
public Block BlockUnderFeet {
get { return GetBlock( new Vector3( Position.X, Position.Y - 0.01f, Position.Z ) ); }
}
/// <summary> Gets the block at player's eye position. </summary>
public Block BlockAtHead {
get { return GetBlock( EyePosition ); }
}
protected Block GetBlock( Vector3 coords ) {
return (Block)game.Map.SafeGetBlock( Vector3I.Floor( coords ) );
}
protected void CheckSkin() {
DownloadedItem item;
game.AsyncDownloader.TryGetItem( SkinIdentifier, out item );
@ -113,11 +94,5 @@ namespace ClassicalSharp {
}
}
}
protected void RemoveOldest<T>(T[] array, ref int count) {
for( int i = 0; i < array.Length - 1; i++ )
array[i] = array[i + 1];
count--;
}
}
}

View File

@ -17,16 +17,12 @@ namespace ClassicalSharp.Model {
public BlockModel( Game game ) : base( game ) {
}
public override bool Bobbing {
get { return false; }
}
public override bool Bobbing { get { return false; } }
public override float NameYOffset {
get { return height + 0.075f; }
}
public override float NameYOffset { get { return height + 0.075f; } }
public override float GetEyeY( Player player ) {
byte block = Byte.Parse( player.ModelName );
public override float GetEyeY( Entity entity ) {
byte block = Byte.Parse( entity.ModelName );
float minY = game.BlockInfo.MinBB[block].Y;
float maxY = game.BlockInfo.MaxBB[block].Y;
return block == 0 ? 1 : (minY + maxY) / 2;

View File

@ -32,17 +32,11 @@ namespace ClassicalSharp.Model {
return new ModelPart( index - 2 * 4, 2 * 4 );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 1.0125f; }
}
public override float NameYOffset { get { return 1.0125f; } }
public override float GetEyeY( Player player ) {
return 14/16f;
}
public override float GetEyeY( Entity entity ) { return 14/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 8/16f, 12/16f, 8/16f ); }

View File

@ -23,17 +23,11 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 0, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 1.7f; }
}
public override float NameYOffset { get { return 1.7f; } }
public override float GetEyeY( Player player ) {
return 22/16f;
}
public override float GetEyeY( Entity entity ) { return 22/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 8/16f, 26/16f, 8/16f ); }

View File

@ -32,7 +32,7 @@ namespace ClassicalSharp.Model {
public abstract float NameYOffset { get; }
/// <summary> Vertical offset from the model's feet/base that the model's eye is located. </summary>
public abstract float GetEyeY( Player player );
public abstract float GetEyeY( Entity entity );
/// <summary> The size of the bounding box that is used when
/// performing collision detection for this model. </summary>

View File

@ -22,17 +22,11 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 0, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 1.075f; }
}
public override float NameYOffset { get { return 1.075f; } }
public override float GetEyeY( Player player ) {
return 12/16f;
}
public override float GetEyeY( Entity entity ) { return 12/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 14/16f, 14/16f, 14/16f ); }

View File

@ -40,17 +40,11 @@ namespace ClassicalSharp.Model {
SetSlim.Hat = Set.Hat;
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 2.1375f; }
}
public override float NameYOffset { get { return 2.1375f; } }
public override float GetEyeY( Player player ) {
return 26/16f;
}
public override float GetEyeY( Entity entity ) { return 26/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 8/16f + 0.6f/16f, 28.1f/16f, 8/16f + 0.6f/16f ); }

View File

@ -44,17 +44,11 @@ namespace ClassicalSharp.Model {
FurRightLegBack = BuildBox( legDesc.SetModelBounds( 0.5f, 5.5f, 4.5f, 5.5f, 12.5f, 9.5f ) );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return Fur ? 1.48125f: 1.075f; }
}
public override float NameYOffset { get { return Fur ? 1.48125f: 1.075f; } }
public override float GetEyeY( Player player ) {
return 20/16f;
}
public override float GetEyeY( Entity entity ) { return 20/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 14/16f, 20/16f, 14/16f ); }

View File

@ -22,17 +22,11 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 40, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 2.075f; }
}
public override float NameYOffset { get { return 2.075f; } }
public override float GetEyeY( Player player ) {
return 26/16f;
}
public override float GetEyeY( Entity entity ) { return 26/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 8/16f, 30/16f, 8/16f ); }

View File

@ -20,17 +20,11 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 18, 0 ) );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 1.0125f; }
}
public override float NameYOffset { get { return 1.0125f; } }
public override float GetEyeY( Player player ) {
return 8/16f;
}
public override float GetEyeY( Entity entity ) { return 8/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 15/16f, 12/16f, 15/16f ); }

View File

@ -22,17 +22,11 @@ namespace ClassicalSharp.Model {
.SetTexOrigin( 40, 16 ) );
}
public override bool Bobbing {
get { return true; }
}
public override bool Bobbing { get { return true; } }
public override float NameYOffset {
get { return 2.075f; }
}
public override float NameYOffset { get { return 2.075f; } }
public override float GetEyeY( Player player ) {
return 26/16f;
}
public override float GetEyeY( Entity entity ) { return 26/16f; }
public override Vector3 CollisionSize {
get { return new Vector3( 8/16f, 30/16f, 8/16f ); }