From a6f90acf0008648964ff00bc0534d05e0ff7fcce Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 24 Oct 2015 15:31:57 +1100 Subject: [PATCH] More comments. --- .../Blocks/BlockInfo.BoundingBox.cs | 40 ++++++++++--------- ClassicalSharp/Blocks/BlockInfo.cs | 3 ++ ClassicalSharp/Entities/Entity.cs | 31 +++++++++++--- ClassicalSharp/Entities/LocalPlayer.cs | 15 ++++++- ClassicalSharp/Entities/LocationUpdate.cs | 8 ++++ ClassicalSharp/Entities/PhysicsEntity.cs | 6 ++- ClassicalSharp/Game/ChatLog.cs | 2 +- ClassicalSharp/Game/Inventory.cs | 5 +++ .../Network/NetworkProcessor.CPE.cs | 8 ++++ .../Network/Utils/AsyncDownloader.cs | 35 ++++++++++++++-- .../Rendering/StandardEnvRenderer.cs | 2 - 11 files changed, 120 insertions(+), 35 deletions(-) diff --git a/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs b/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs index ac3b7a4c8..3de7c0f65 100644 --- a/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs +++ b/ClassicalSharp/Blocks/BlockInfo.BoundingBox.cs @@ -23,29 +23,31 @@ namespace ClassicalSharp { } public void RecalculateSpriteBB( FastBitmap fastBmp ) { - int elemSize = fastBmp.Width / 16; for( int i = 0; i < 256; i++ ) { - if( IsSprite[i] ) { - int texId = GetTextureLoc( (byte)i, TileSide.Top ); - float topY = GetSpriteBB_TopY( elemSize, texId & 0x0F, texId >> 4, fastBmp ); - float bottomY = GetSpriteBB_BottomY( elemSize, texId & 0x0F, texId >> 4, fastBmp ); - float leftX = GetSpriteBB_LeftX( elemSize, texId & 0x0F, texId >> 4, fastBmp ); - float rightX = GetSpriteBB_RightX( elemSize, texId & 0x0F, texId >> 4, fastBmp ); - - MinBB[i] = Utils.RotateY( leftX - 0.5f, bottomY, 0, 45f * Utils.Deg2Rad ) - + new Vector3( 0.5f, 0, 0.5f ); - MaxBB[i] = Utils.RotateY( rightX - 0.5f, topY, 0, 45f * Utils.Deg2Rad ) - + new Vector3( 0.5f, 0, 0.5f ); - } + if( IsSprite[i] ) RecalculateBB( i, fastBmp ); } } + internal void RecalculateBB( int block, FastBitmap fastBmp ) { + int elemSize = fastBmp.Width / 16; + int texId = GetTextureLoc( (byte)block, TileSide.Top ); + float topY = GetSpriteBB_TopY( elemSize, texId & 0x0F, texId >> 4, fastBmp ); + float bottomY = GetSpriteBB_BottomY( elemSize, texId & 0x0F, texId >> 4, fastBmp ); + float leftX = GetSpriteBB_LeftX( elemSize, texId & 0x0F, texId >> 4, fastBmp ); + float rightX = GetSpriteBB_RightX( elemSize, texId & 0x0F, texId >> 4, fastBmp ); + + MinBB[block] = Utils.RotateY( leftX - 0.5f, bottomY, 0, 45f * Utils.Deg2Rad ) + + new Vector3( 0.5f, 0, 0.5f ); + MaxBB[block] = Utils.RotateY( rightX - 0.5f, topY, 0, 45f * Utils.Deg2Rad ) + + new Vector3( 0.5f, 0, 0.5f ); + } + const int alphaTest = unchecked( (int)0x80000000 ); unsafe float GetSpriteBB_TopY( int size, int tileX, int tileY, FastBitmap fastBmp ) { for( int y = 0; y < size; y++ ) { int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size); for( int x = 0; x < size; x++ ) { - if( (row[x] & alphaTest) != 0 ) + if( (row[x] & alphaTest) != 0 ) return 1 - (float)y / size; } } @@ -56,7 +58,7 @@ namespace ClassicalSharp { for( int y = size - 1; y >= 0; y-- ) { int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size); for( int x = 0; x < size; x++ ) { - if( (row[x] & alphaTest) != 0 ) + if( (row[x] & alphaTest) != 0 ) return 1 - (float)(y + 1) / size; } } @@ -64,10 +66,10 @@ namespace ClassicalSharp { } unsafe float GetSpriteBB_LeftX( int size, int tileX, int tileY, FastBitmap fastBmp ) { - for( int x = 0; x < size; x++ ) { + for( int x = 0; x < size; x++ ) { for( int y = 0; y < size; y++ ) { int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size); - if( (row[x] & alphaTest) != 0 ) + if( (row[x] & alphaTest) != 0 ) return (float)x / size; } } @@ -75,10 +77,10 @@ namespace ClassicalSharp { } unsafe float GetSpriteBB_RightX( int size, int tileX, int tileY, FastBitmap fastBmp ) { - for( int x = size - 1; x >= 0; x-- ) { + for( int x = size - 1; x >= 0; x-- ) { for( int y = 0; y < size; y++ ) { int* row = fastBmp.GetRowPtr( tileY * size + y ) + (tileX * size); - if( (row[x] & alphaTest) != 0 ) + if( (row[x] & alphaTest) != 0 ) return (float)(x + 1) / size; } } diff --git a/ClassicalSharp/Blocks/BlockInfo.cs b/ClassicalSharp/Blocks/BlockInfo.cs index 43bd83782..20317fcbd 100644 --- a/ClassicalSharp/Blocks/BlockInfo.cs +++ b/ClassicalSharp/Blocks/BlockInfo.cs @@ -1,4 +1,5 @@ using System; +using OpenTK; namespace ClassicalSharp { @@ -180,6 +181,8 @@ namespace ClassicalSharp { SpeedMultiplier[id] = 1; SetAll( 0, (Block)id ); SetupCullingCache(); + MinBB[id] = Vector3.Zero; + MaxBB[id] = Vector3.One; } } diff --git a/ClassicalSharp/Entities/Entity.cs b/ClassicalSharp/Entities/Entity.cs index 034621525..ddaeffc2e 100644 --- a/ClassicalSharp/Entities/Entity.cs +++ b/ClassicalSharp/Entities/Entity.cs @@ -4,6 +4,8 @@ using OpenTK; namespace ClassicalSharp { + /// Contains a model, along with position, velocity, and rotation. + /// May also contain other fields and properties. public abstract class Entity { public Entity( Game game ) { @@ -18,26 +20,31 @@ namespace ClassicalSharp { public Vector3 Position; public Vector3 Velocity; public float YawDegrees, PitchDegrees; - protected float StepSize; + protected Game game; protected BlockInfo info; + /// Rotation of the entity horizontally (i.e. looking north or east) public float YawRadians { get { return YawDegrees * Utils.Deg2Rad; } set { YawDegrees = value * Utils.Rad2Deg; } } + /// Rotation of the entity vertically. (i.e. looking up or down) public float PitchRadians { get { return PitchDegrees * Utils.Deg2Rad; } set { PitchDegrees = value * Utils.Rad2Deg; } } + /// Returns the size of the model that is used for collision detection. public virtual Vector3 CollisionSize { get { return new Vector3( 8/16f, 28.5f/16f, 8/16f ); //Model.CollisionSize; TODO: for non humanoid models } } + /// Bounding box of the model that collision detection + /// is performed with, in world coordinates. public virtual BoundingBox CollisionBounds { get { Vector3 pos = Position; @@ -49,12 +56,17 @@ namespace ClassicalSharp { public abstract void Despawn(); + /// Renders the entity's model, interpolating between the previous and next state. public abstract void Render( double deltaTime, float t ); + /// Determines whether any of the blocks that intersect the + /// bounding box of this entity satisfy the given condition. public bool TouchesAny( Predicate condition ) { return TouchesAny( CollisionBounds, condition ); } + /// Determines whether any of the blocks that intersect the + /// given bounding box satisfy the given condition. public bool TouchesAny( BoundingBox bounds, Predicate condition ) { Vector3I bbMin = Vector3I.Floor( bounds.Min ); Vector3I bbMax = Vector3I.Floor( bounds.Max ); @@ -64,6 +76,7 @@ namespace ClassicalSharp { for( int z = bbMin.Z; z <= bbMax.Z; z++ ) { if( !game.Map.IsValidPos( x, y, z ) ) continue; byte block = game.Map.GetBlock( x, y, z ); + if( condition( block ) ) { float blockHeight = info.Height[block]; Vector3 min = new Vector3( x, y, z ) + info.MinBB[block]; @@ -77,19 +90,27 @@ namespace ClassicalSharp { return false; } - public const float Adjustment = 0.001f; + /// Constant offset used to avoid floating point roundoff errors. + public const float Adjustment = 0.001f; + + /// Determines whether any of the blocks that intersect the + /// bounding box of this entity are lava or still lava. protected bool TouchesAnyLava() { - return TouchesAny( CollisionBounds, + return TouchesAny( CollisionBounds, b => b == (byte)Block.Lava || b == (byte)Block.StillLava ); } + /// Determines whether any of the blocks that intersect the + /// bounding box of this entity are rope. protected bool TouchesAnyRope() { - return TouchesAny( CollisionBounds, + return TouchesAny( CollisionBounds, b => b == (byte)Block.Rope ); } + /// Determines whether any of the blocks that intersect the + /// bounding box of this entity are water or still water. protected bool TouchesAnyWater() { - return TouchesAny( CollisionBounds, + return TouchesAny( CollisionBounds, b => b == (byte)Block.Water || b == (byte)Block.StillWater ); } } diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs index 87a025881..f80a91ea9 100644 --- a/ClassicalSharp/Entities/LocalPlayer.cs +++ b/ClassicalSharp/Entities/LocalPlayer.cs @@ -16,6 +16,7 @@ namespace ClassicalSharp { public byte UserType; bool canSpeed = true, canFly = true, canRespawn = true, canNoclip = true; + /// Whether the player has permission to increase its speed beyond the normal walking speed. public bool CanSpeed { get { return canSpeed; } set { canSpeed = value; } @@ -37,6 +38,8 @@ namespace ClassicalSharp { } float jumpVel = 0.42f; + /// Returns the height that the client can currently jump up to.
+ /// Note that when speeding is enabled the client is able to jump much further.
public float JumpHeight { get { return (float)GetMaxHeight( jumpVel ); } } @@ -200,6 +203,9 @@ namespace ClassicalSharp { } internal bool jumping, speeding, flying, noClip, flyingDown, flyingUp; + + /// Parses hack flags specified in the motd and/or name of the server. + /// Recognises +/-hax, +/-fly, +/-noclip, +/-speed, +/-respawn, +/-ophax public void ParseHackFlags( string name, string motd ) { string joined = name + motd; if( joined.Contains( "-hax" ) ) { @@ -216,9 +222,8 @@ namespace ClassicalSharp { ParseFlag( b => CanSpeed = b, joined, "speed" ); ParseFlag( b => CanRespawn = b, joined, "respawn" ); - if( UserType == 0x64 ) { + if( UserType == 0x64 ) ParseFlag( b => CanFly = CanNoclip = CanRespawn = CanSpeed = b, joined, "ophax" ); - } } static void ParseFlag( Action action, string joined, string flag ) { @@ -229,6 +234,8 @@ namespace ClassicalSharp { } } + /// Sets the user type of this user. This is used to control permissions for grass, + /// bedrock, water and lava blocks on servers that don't support CPE block permissions. public void SetUserType( byte value ) { UserType = value; Inventory inv = game.Inventory; @@ -244,6 +251,8 @@ namespace ClassicalSharp { internal Vector3 lastPos, nextPos; internal float lastYaw, nextYaw, lastPitch, nextPitch; + + /// Linearly interpolates position and rotation between the previous and next state. public void SetInterpPosition( float t ) { Position = Vector3.Lerp( lastPos, nextPos, t ); YawDegrees = Utils.LerpAngle( lastYaw, nextYaw, t ); @@ -278,6 +287,8 @@ namespace ClassicalSharp { } } + /// Calculates the jump velocity required such that when a client presses + /// the jump binding they will be able to jump up to the given height. internal void CalculateJumpVelocity( float jumpHeight ) { jumpVel = 0; if( jumpHeight >= 256 ) jumpVel = 10.0f; diff --git a/ClassicalSharp/Entities/LocationUpdate.cs b/ClassicalSharp/Entities/LocationUpdate.cs index 7fa674e1c..d2afd3bce 100644 --- a/ClassicalSharp/Entities/LocationUpdate.cs +++ b/ClassicalSharp/Entities/LocationUpdate.cs @@ -10,17 +10,25 @@ namespace ClassicalSharp { public Vector3 Pos; public float Yaw, Pitch; + /// Whether this update includes an absolute or relative position. public bool IncludesPosition; + + /// Whether the positon is specified as absolute (world coordinates), + /// or relative to the last position that was received from the server. public bool RelativePosition; + + /// Whether this update includes absolute yaw and pitch. public bool IncludesOrientation; public LocationUpdate( float x, float y, float z, float yaw, float pitch, bool incPos, bool relPos, bool incOri ) { Pos = new Vector3( x, y, z ); + // Make sure yaw and pitch are in [0, 360) Yaw = yaw % 360; if( Yaw < 0 ) Yaw += 360; Pitch = pitch % 360; if( Pitch < 0 ) Pitch += 360; + IncludesPosition = incPos; RelativePosition = relPos; IncludesOrientation = incOri; diff --git a/ClassicalSharp/Entities/PhysicsEntity.cs b/ClassicalSharp/Entities/PhysicsEntity.cs index 6f5f024df..19a0f79e3 100644 --- a/ClassicalSharp/Entities/PhysicsEntity.cs +++ b/ClassicalSharp/Entities/PhysicsEntity.cs @@ -6,10 +6,12 @@ namespace ClassicalSharp { /// Entity that performs collision detection. public abstract class PhysicsEntity : Entity { - + public PhysicsEntity( Game game ) : base( game ) { } - protected bool onGround, collideX, collideY, collideZ; + + protected bool onGround, collideX, collideY, collideZ; + protected float StepSize; protected byte GetPhysicsBlockId( int x, int y, int z ) { if( x < 0 || x >= game.Map.Width || z < 0 || diff --git a/ClassicalSharp/Game/ChatLog.cs b/ClassicalSharp/Game/ChatLog.cs index 29bf5fb80..bef651bb6 100644 --- a/ClassicalSharp/Game/ChatLog.cs +++ b/ClassicalSharp/Game/ChatLog.cs @@ -70,7 +70,7 @@ namespace ClassicalSharp { } } - DateTime last = new DateTime( 1, 1, 1 ); + DateTime last; StreamWriter writer = null; void LogChatToFile( string text ) { DateTime now = DateTime.Now; diff --git a/ClassicalSharp/Game/Inventory.cs b/ClassicalSharp/Game/Inventory.cs index 966ddb3d7..f848ec57d 100644 --- a/ClassicalSharp/Game/Inventory.cs +++ b/ClassicalSharp/Game/Inventory.cs @@ -2,6 +2,7 @@ namespace ClassicalSharp { + /// Contains the hotbar of blocks, as well as the permissions for placing and deleting all blocks. public sealed class Inventory { public Inventory( Game game ) { @@ -29,6 +30,8 @@ namespace ClassicalSharp { public InventoryPermissions CanPlace = new InventoryPermissions(); public InventoryPermissions CanDelete = new InventoryPermissions(); + /// Gets or sets the index of the held block. + /// Fails if the server has forbidden up from changing the held block. public int HeldBlockIndex { get { return hotbarIndex; } set { @@ -41,6 +44,8 @@ namespace ClassicalSharp { } } + /// Gets or sets the block currently held by the player. + /// Fails if the server has forbidden up from changing the held block. public Block HeldBlock { get { return Hotbar[hotbarIndex]; } set { diff --git a/ClassicalSharp/Network/NetworkProcessor.CPE.cs b/ClassicalSharp/Network/NetworkProcessor.CPE.cs index ba13e35e1..48101ff29 100644 --- a/ClassicalSharp/Network/NetworkProcessor.CPE.cs +++ b/ClassicalSharp/Network/NetworkProcessor.CPE.cs @@ -336,6 +336,14 @@ namespace ClassicalSharp { info.FogColour[block] = new FastColour( reader.ReadUInt8(), reader.ReadUInt8(), reader.ReadUInt8() ); info.SetupCullingCache(); + + // Update sprite BoundingBox if necessary + if( info.IsSprite[block] ) { + using( FastBitmap fastBmp = + new FastBitmap( game.TerrainAtlas.AtlasBitmap, true ) ) { + info.RecalculateBB( block, fastBmp ); + } + } } void HandleCpeRemoveBlockDefinition() { diff --git a/ClassicalSharp/Network/Utils/AsyncDownloader.cs b/ClassicalSharp/Network/Utils/AsyncDownloader.cs index 1da815c3e..46a22b9cb 100644 --- a/ClassicalSharp/Network/Utils/AsyncDownloader.cs +++ b/ClassicalSharp/Network/Utils/AsyncDownloader.cs @@ -29,6 +29,9 @@ namespace ClassicalSharp.Network { worker.Start(); } + /// Asynchronously downloads a skin. If 'skinName' points to the url then the skin is + /// downloaded from that url, otherwise it is downloaded from the url 'defaultSkinServer'/'skinName'.png + /// Identifier is skin_'skinName'. public void DownloadSkin( string skinName ) { string strippedSkinName = Utils.StripColours( skinName ); string url = Utils.IsUrl( skinName ) ? skinName : @@ -36,14 +39,17 @@ namespace ClassicalSharp.Network { AddRequest( url, true, "skin_" + strippedSkinName, 0 ); } + /// Asynchronously downloads a bitmap image from the specified url. public void DownloadImage( string url, bool priority, string identifier ) { AddRequest( url, priority, identifier, 0 ); } + /// Asynchronously downloads a string from the specified url. public void DownloadPage( string url, bool priority, string identifier ) { AddRequest( url, priority, identifier, 1 ); } + /// Asynchronously downloads a byte array from the specified url. public void DownloadData( string url, bool priority, string identifier ) { AddRequest( url, priority, identifier, 2 ); } @@ -60,6 +66,10 @@ namespace ClassicalSharp.Network { handle.Set(); } + /// Informs the asynchronous thread that it should stop processing further requests + /// and can consequentially exit the for loop.
+ /// Note that this will *block** the calling thread as the method waits until the asynchronous + /// thread has exited the for loop.
public void Dispose() { lock( requestLocker ) { requests.Insert( 0, null ); @@ -71,6 +81,8 @@ namespace ClassicalSharp.Network { client.Dispose(); } + /// Removes older entries that were downloaded a certain time ago + /// but were never removed from the downloaded queue. public void PurgeOldEntries( int seconds ) { lock( downloadedLocker ) { DateTime now = DateTime.UtcNow; @@ -95,6 +107,10 @@ namespace ClassicalSharp.Network { } } + /// Returns whether the requested item exists in the downloaded queue. + /// If it does, it removes the item from the queue and outputs it. + /// If the asynchronous thread failed to download the item, this method + /// will return 'true' and 'item' will be set. However, the contents of the 'item' object will be null. public bool TryGetItem( string identifier, out DownloadedItem item ) { bool success = false; lock( downloadedLocker ) { @@ -167,8 +183,8 @@ namespace ClassicalSharp.Network { downloaded[request.Identifier] = newItem; } } - - class GZipWebClient : WebClient { + + sealed class GZipWebClient : WebClient { protected override WebRequest GetWebRequest( Uri address ) { HttpWebRequest request = (HttpWebRequest)base.GetWebRequest( address ); @@ -177,7 +193,7 @@ namespace ClassicalSharp.Network { } } - class Request { + sealed class Request { public string Url; public string Identifier; @@ -193,10 +209,21 @@ namespace ClassicalSharp.Network { } } + /// Represents an item that was asynchronously downloaded. public class DownloadedItem { + /// Contents that were downloaded. Can be a bitmap, string or byte array. public object Data; - public DateTime TimeAdded, TimeDownloaded; + + /// Instant in time the item was originally added to the download queue. + public DateTime TimeAdded; + + /// Instant in time the item was fully downloaded. + public DateTime TimeDownloaded; + + /// + /// + /// public string Url; public DownloadedItem( object data, DateTime timeAdded, string url ) { diff --git a/ClassicalSharp/Rendering/StandardEnvRenderer.cs b/ClassicalSharp/Rendering/StandardEnvRenderer.cs index 07d827e3e..1810db83b 100644 --- a/ClassicalSharp/Rendering/StandardEnvRenderer.cs +++ b/ClassicalSharp/Rendering/StandardEnvRenderer.cs @@ -1,8 +1,6 @@ using System; -using System.Drawing; using ClassicalSharp.GraphicsAPI; using OpenTK; -using OpenTK; namespace ClassicalSharp.Renderers {