From 00945a609581d706425c868cfd3b41a99b44c1c2 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 10 Oct 2015 20:29:29 +1100 Subject: [PATCH] More comments, more refactoring. Remove WoM terrain atlas support because WoM's file server has been down for quite a long time now. --- ClassicalSharp/2D/Drawing/IDrawer2D.cs | 32 ++++++--- .../2D/Widgets/NormalPlayerListWidget.cs | 2 +- ClassicalSharp/ClassicalSharp.csproj | 1 + ClassicalSharp/Entities/AnimatedEntity.cs | 54 +++++++++++++++ ClassicalSharp/Entities/Entity.cs | 8 +-- ClassicalSharp/Entities/EntityList.cs | 8 ++- ClassicalSharp/Entities/LocalPlayer.cs | 4 +- ClassicalSharp/Entities/NetPlayer.cs | 2 +- ClassicalSharp/Entities/PhysicsEntity.cs | 9 ++- ClassicalSharp/Entities/Player.cs | 65 ++++--------------- .../Network/NetworkProcessor.WoM.cs | 22 +------ 11 files changed, 112 insertions(+), 95 deletions(-) create mode 100644 ClassicalSharp/Entities/AnimatedEntity.cs diff --git a/ClassicalSharp/2D/Drawing/IDrawer2D.cs b/ClassicalSharp/2D/Drawing/IDrawer2D.cs index 71c3af7b1..f1d816330 100644 --- a/ClassicalSharp/2D/Drawing/IDrawer2D.cs +++ b/ClassicalSharp/2D/Drawing/IDrawer2D.cs @@ -13,31 +13,44 @@ namespace ClassicalSharp { /// Sets the underlying bitmap that drawing operations will be performed on. public abstract void SetBitmap( Bitmap bmp ); + /// Draws a string using the specified arguments and fonts at the + /// specified coordinates in the currently bound bitmap. public abstract void DrawText( Font font, ref DrawTextArgs args, float x, float y ); + /// Draws a 2D flat rectangle of the specified dimensions at the + /// specified coordinates in the currently bound bitmap. public abstract void DrawRect( Color colour, int x, int y, int width, int height ); + /// Draws the outline of a 2D flat rectangle of the specified dimensions + /// at the specified coordinates in the currently bound bitmap. public abstract void DrawRectBounds( Color colour, float lineWidth, int x, int y, int width, int height ); + /// Draws a 2D rectangle with rounded borders of the specified dimensions + /// at the specified coordinates in the currently bound bitmap. public abstract void DrawRoundedRect( Color colour, float radius, float x, float y, float width, float height ); + /// Clears the entire bound bitmap to the specified colour. public abstract void Clear( Color colour ); /// Disposes of any resources used by this class that are associated with the underlying bitmap. public abstract void Dispose(); + /// Returns a new bitmap that has 32-bpp pixel format. public abstract Bitmap ConvertTo32Bpp( Bitmap src ); + /// Returns the size of a bitmap needed to contain the specified text with the given arguments. public abstract Size MeasureSize( string text, Font font, bool shadow ); /// Disposes of all native resources used by this class. /// You will no longer be able to perform measuring or drawing calls after this. public abstract void DisposeInstance(); - public Texture MakeTextTexture( Font font, int screenX, int screenY, ref DrawTextArgs args ) { + /// Draws the specified string from the arguments into a new bitmap, + /// them creates a 2D texture with origin at the specified window coordinates. + public Texture MakeTextTexture( Font font, int windowX, int windowY, ref DrawTextArgs args ) { Size size = MeasureSize( args.Text, font, args.UseShadow ); if( parts.Count == 0 ) - return new Texture( -1, screenX, screenY, 0, 0, 1, 1 ); + return new Texture( -1, windowX, windowY, 0, 0, 1, 1 ); using( Bitmap bmp = CreatePow2Bitmap( size ) ) { SetBitmap( bmp ); @@ -45,17 +58,18 @@ namespace ClassicalSharp { DrawText( font, ref args, 0, 0 ); Dispose(); - return Make2DTexture( bmp, size, screenX, screenY ); + return Make2DTexture( bmp, size, windowX, windowY ); } } - public Texture Make2DTexture( Bitmap bmp, Size used, int screenX, int screenY ) { + /// Creates a 2D texture with origin at the specified window coordinates. + public Texture Make2DTexture( Bitmap bmp, Size used, int windowX, int windowY ) { int texId = graphics.CreateTexture( bmp ); - return new Texture( texId, screenX, screenY, used.Width, used.Height, + return new Texture( texId, windowX, windowY, used.Width, used.Height, (float)used.Width / bmp.Width, (float)used.Height / bmp.Height ); } - + /// Creates a power-of-2 sized bitmap larger or equal to to the given size. public static Bitmap CreatePow2Bitmap( Size size ) { return new Bitmap( Utils.NextPowerOf2( size.Width ), Utils.NextPowerOf2( size.Height ) ); } @@ -91,9 +105,9 @@ namespace ClassicalSharp { if( partLength > 0 ) { string part = value.Substring( i, partLength ); Color col = Color.FromArgb( - 191 * ( ( code >> 2 ) & 0x1 ) + 64 * ( code >> 3 ), - 191 * ( ( code >> 1 ) & 0x1 ) + 64 * ( code >> 3 ), - 191 * ( ( code >> 0 ) & 0x1 ) + 64 * ( code >> 3 ) ); + 191 * ((code >> 2) & 1) + 64 * (code >> 3), + 191 * ((code >> 1) & 1) + 64 * (code >> 3), + 191 * ((code >> 0) & 1) + 64 * (code >> 3) ); parts.Add( new TextPart( part, col ) ); } i += partLength + 1; diff --git a/ClassicalSharp/2D/Widgets/NormalPlayerListWidget.cs b/ClassicalSharp/2D/Widgets/NormalPlayerListWidget.cs index 33606ec3a..a63352b46 100644 --- a/ClassicalSharp/2D/Widgets/NormalPlayerListWidget.cs +++ b/ClassicalSharp/2D/Widgets/NormalPlayerListWidget.cs @@ -41,7 +41,7 @@ namespace ClassicalSharp { } protected override void CreateInitialPlayerInfo() { - for( int i = 0; i < game.Players.MaxCount; i++ ) { + for( int i = 0; i < EntityList.MaxCount; i++ ) { Player player = game.Players[i]; if( player != null ) { AddPlayerInfo( player ); diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index f996b77d8..b9063cbbf 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -103,6 +103,7 @@ + diff --git a/ClassicalSharp/Entities/AnimatedEntity.cs b/ClassicalSharp/Entities/AnimatedEntity.cs new file mode 100644 index 000000000..f7a0ba413 --- /dev/null +++ b/ClassicalSharp/Entities/AnimatedEntity.cs @@ -0,0 +1,54 @@ +using System; +using OpenTK; + +namespace ClassicalSharp { + + /// Entity that is animated depending on movement speed and time. + public abstract class AnimatedEntity : PhysicsEntity { + + public AnimatedEntity( Game game ) : base( game ) { + } + public float leftLegXRot, leftArmXRot, leftArmZRot; + public float rightLegXRot, rightArmXRot, rightArmZRot; + protected float walkTimeO, walkTimeN, swingO, swingN; + + /// Calculates the next animation state based on old and new position. + protected void UpdateAnimState( Vector3 oldPos, Vector3 newPos, double delta ) { + walkTimeO = walkTimeN; + swingO = swingN; + float dx = newPos.X - oldPos.X; + float dz = newPos.Z - oldPos.Z; + double distance = Math.Sqrt( dx * dx + dz * dz ); + + if( distance > 0.05 ) { + walkTimeN += (float)distance * 2 * (float)(20 * delta); + swingN += (float)delta * 3; + } else { + swingN -= (float)delta * 3; + } + Utils.Clamp( ref swingN, 0, 1 ); + } + + const float armMax = 60 * Utils.Deg2Rad; + const float legMax = 80 * Utils.Deg2Rad; + const float idleMax = 3 * Utils.Deg2Rad; + const float idleXPeriod = (float)(2 * Math.PI / 5.0f); + const float idleZPeriod = (float)(2 * Math.PI / 3.5f); + + /// Calculates the interpolated state between the last and next animation state. + protected void GetCurrentAnimState( float t ) { + float swing = Utils.Lerp( swingO, swingN, t ); + float walkTime = Utils.Lerp( walkTimeO, walkTimeN, t ); + float idleTime = (float)game.accumulator; + float idleXRot = (float)(Math.Sin( idleTime * idleXPeriod ) * idleMax); + float idleZRot = (float)(idleMax + Math.Cos(idleTime * idleZPeriod) * idleMax); + + leftArmXRot = (float)(Math.Cos( walkTime ) * swing * armMax) - idleXRot; + rightArmXRot = -leftArmXRot; + rightLegXRot = (float)(Math.Cos( walkTime ) * swing * legMax); + leftLegXRot = -rightLegXRot; + rightArmZRot = idleZRot; + leftArmZRot = -idleZRot; + } + } +} \ No newline at end of file diff --git a/ClassicalSharp/Entities/Entity.cs b/ClassicalSharp/Entities/Entity.cs index d4c4f0c12..58e0b22e9 100644 --- a/ClassicalSharp/Entities/Entity.cs +++ b/ClassicalSharp/Entities/Entity.cs @@ -7,7 +7,7 @@ namespace ClassicalSharp { public abstract class Entity { public Entity( Game game ) { - map = game.Map; + this.game = game; info = game.BlockInfo; } @@ -19,7 +19,7 @@ namespace ClassicalSharp { public Vector3 Velocity; public float YawDegrees, PitchDegrees; protected float StepSize; - protected Map map; + protected Game game; protected BlockInfo info; public float YawRadians { @@ -75,8 +75,8 @@ namespace ClassicalSharp { for( int x = bbMin.X; x <= bbMax.X; x++ ) { for( int y = bbMin.Y; y <= bbMax.Y; y++ ) { for( int z = bbMin.Z; z <= bbMax.Z; z++ ) { - if( !map.IsValidPos( x, y, z ) ) continue; - byte block = map.GetBlock( x, y, 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 ); diff --git a/ClassicalSharp/Entities/EntityList.cs b/ClassicalSharp/Entities/EntityList.cs index d9dc76b99..cfd854bff 100644 --- a/ClassicalSharp/Entities/EntityList.cs +++ b/ClassicalSharp/Entities/EntityList.cs @@ -5,9 +5,10 @@ namespace ClassicalSharp { public class EntityList : IDisposable { - public int MaxCount = 256; - public Player[] Players = new Player[256]; + public const int MaxCount = 256; + public Player[] Players = new Player[MaxCount]; + /// Performs a tick call for all player entities contained in this list. public void Tick( double delta ) { for( int i = 0; i < Players.Length; i++ ) { if( Players[i] != null ) { @@ -16,6 +17,7 @@ namespace ClassicalSharp { } } + /// Renders all player entities contained in this list. public void Render( double delta, float t ) { for( int i = 0; i < Players.Length; i++ ) { if( Players[i] != null ) { @@ -24,6 +26,7 @@ namespace ClassicalSharp { } } + /// Disposes of all player entities contained in this list. public void Dispose() { for( int i = 0; i < Players.Length; i++ ) { if( Players[i] != null ) { @@ -52,6 +55,7 @@ namespace ClassicalSharp { return targetId; } + /// Gets or sets the player entity for the specified id. public Player this[int id] { get { return Players[id]; } set { diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs index 6761d4e76..bbf795440 100644 --- a/ClassicalSharp/Entities/LocalPlayer.cs +++ b/ClassicalSharp/Entities/LocalPlayer.cs @@ -87,7 +87,7 @@ namespace ClassicalSharp { InitRenderingData(); game.AsyncDownloader.DownloadSkin( SkinName ); } - SetCurrentAnimState( t ); + GetCurrentAnimState( t ); RenderModel( deltaTime ); } @@ -291,7 +291,7 @@ namespace ClassicalSharp { for( int x = bbMin.X; x <= bbMax.X; x++ ) { for( int y = bbMin.Y; y <= bbMax.Y; y++ ) { for( int z = bbMin.Z; z <= bbMax.Z; z++ ) { - byte block = map.SafeGetBlock( x, y, z ); + byte block = game.Map.SafeGetBlock( x, y, z ); if( block == 0 ) continue; modifier = Math.Min( modifier, info.SpeedMultiplier[block] ); diff --git a/ClassicalSharp/Entities/NetPlayer.cs b/ClassicalSharp/Entities/NetPlayer.cs index de91b6605..02d0fe164 100644 --- a/ClassicalSharp/Entities/NetPlayer.cs +++ b/ClassicalSharp/Entities/NetPlayer.cs @@ -91,7 +91,7 @@ namespace ClassicalSharp { YawDegrees = Utils.InterpAngle( oldState.yaw, newState.yaw, t ); PitchDegrees = Utils.InterpAngle( oldState.pitch, newState.pitch, t ); - SetCurrentAnimState( t ); + GetCurrentAnimState( t ); RenderModel( deltaTime ); } } diff --git a/ClassicalSharp/Entities/PhysicsEntity.cs b/ClassicalSharp/Entities/PhysicsEntity.cs index cfb75e3a8..d925c3943 100644 --- a/ClassicalSharp/Entities/PhysicsEntity.cs +++ b/ClassicalSharp/Entities/PhysicsEntity.cs @@ -4,6 +4,7 @@ using OpenTK; namespace ClassicalSharp { + /// Entity that performs collision detection. public abstract class PhysicsEntity : Entity { public PhysicsEntity( Game game ) : base( game ) { @@ -11,9 +12,11 @@ namespace ClassicalSharp { protected bool onGround, collideX, collideY, collideZ; protected byte GetPhysicsBlockId( int x, int y, int z ) { - if( x < 0 || x >= map.Width || z < 0 || z >= map.Length || y < 0 ) return (byte)Block.Bedrock; - if( y >= map.Height ) return (byte)Block.Air; - return map.GetBlock( x, y, z ); + if( x < 0 || x >= game.Map.Width || z < 0 || + z >= game.Map.Length || y < 0 ) return (byte)Block.Bedrock; + + if( y >= game.Map.Height ) return (byte)Block.Air; + return game.Map.GetBlock( x, y, z ); } bool GetBoundingBox( byte block, int x, int y, int z, out BoundingBox box ) { diff --git a/ClassicalSharp/Entities/Player.cs b/ClassicalSharp/Entities/Player.cs index 2e4d1d800..1d21e285b 100644 --- a/ClassicalSharp/Entities/Player.cs +++ b/ClassicalSharp/Entities/Player.cs @@ -5,14 +5,13 @@ using OpenTK; namespace ClassicalSharp { - public abstract partial class Player : PhysicsEntity { + public abstract partial class Player : AnimatedEntity { /// Gets the position of the player's eye in the world. public Vector3 EyePosition { get { return new Vector3( Position.X, Position.Y + Model.GetEyeY( this ), Position.Z ); } } - protected Game game; public string DisplayName, SkinName; public SkinType SkinType; @@ -33,55 +32,15 @@ namespace ClassicalSharp { get { return GetBlock( EyePosition ); } } - Block GetBlock( Vector3 coords ) { + protected Block GetBlock( Vector3 coords ) { Vector3I p = Vector3I.Floor( coords ); - return (Block)map.SafeGetBlock( p.X, p.Y, p.Z ); + return (Block)game.Map.SafeGetBlock( p.X, p.Y, p.Z ); } public abstract void Tick( double delta ); public abstract void SetLocation( LocationUpdate update, bool interpolate ); - public float leftLegXRot, leftArmXRot, leftArmZRot; - public float rightLegXRot, rightArmXRot, rightArmZRot; - protected float walkTimeO, walkTimeN, swingO, swingN; - - protected void UpdateAnimState( Vector3 oldPos, Vector3 newPos, double delta ) { - walkTimeO = walkTimeN; - swingO = swingN; - float dx = newPos.X - oldPos.X; - float dz = newPos.Z - oldPos.Z; - double distance = Math.Sqrt( dx * dx + dz * dz ); - - if( distance > 0.05 ) { - walkTimeN += (float)distance * 2 * (float)( 20 * delta ); - swingN += (float)delta * 3; - } else { - swingN -= (float)delta * 3; - } - Utils.Clamp( ref swingN, 0, 1 ); - } - - const float armMax = 60 * Utils.Deg2Rad; - const float legMax = 80 * Utils.Deg2Rad; - const float idleMax = 3 * Utils.Deg2Rad; - const float idleXPeriod = (float)(2 * Math.PI / 5.0f); - const float idleZPeriod = (float)(2 * Math.PI / 3.5f); - protected void SetCurrentAnimState( float t ) { - float swing = Utils.Lerp( swingO, swingN, t ); - float walkTime = Utils.Lerp( walkTimeO, walkTimeN, t ); - float idleTime = (float)game.accumulator; - float idleXRot = (float)(Math.Sin( idleTime * idleXPeriod ) * idleMax); - float idleZRot = (float)(idleMax + Math.Cos(idleTime * idleZPeriod) * idleMax); - - leftArmXRot = (float)(Math.Cos( walkTime ) * swing * armMax) - idleXRot; - rightArmXRot = -leftArmXRot; - rightLegXRot = (float)(Math.Cos( walkTime ) * swing * legMax); - leftLegXRot = -rightLegXRot; - rightArmZRot = idleZRot; - leftArmZRot = -idleZRot; - } - protected void CheckSkin() { DownloadedItem item; game.AsyncDownloader.TryGetItem( "skin_" + SkinName, out item ); @@ -117,7 +76,15 @@ namespace ClassicalSharp { } - unsafe bool HasHat( Bitmap bmp, SkinType skinType ) { + DateTime lastModelChange = new DateTime( 1, 1, 1 ); + public void SetModel( string modelName ) { + ModelName = modelName; + Model = game.ModelCache.GetModel( ModelName ); + lastModelChange = DateTime.UtcNow; + MobTextureId = -1; + } + + unsafe static bool HasHat( Bitmap bmp, SkinType skinType ) { using( FastBitmap fastBmp = new FastBitmap( bmp, true ) ) { int sizeX = (bmp.Width / 64) * 32; int yScale = skinType == SkinType.Type64x32 ? 32 : 64; @@ -138,13 +105,5 @@ namespace ClassicalSharp { } return false; } - - DateTime lastModelChange = new DateTime( 1, 1, 1 ); - public void SetModel( string modelName ) { - ModelName = modelName; - Model = game.ModelCache.GetModel( ModelName ); - lastModelChange = DateTime.UtcNow; - MobTextureId = -1; - } } } \ No newline at end of file diff --git a/ClassicalSharp/Network/NetworkProcessor.WoM.cs b/ClassicalSharp/Network/NetworkProcessor.WoM.cs index da0116a55..01b8d428d 100644 --- a/ClassicalSharp/Network/NetworkProcessor.WoM.cs +++ b/ClassicalSharp/Network/NetworkProcessor.WoM.cs @@ -1,4 +1,5 @@ // This class was partially based on information from http://files.worldofminecraft.com/texturing/ +// NOTE: http://files.worldofminecraft.com/ has been down for quite a while, so support was removed on Oct 10, 2015 using System; using System.Drawing; using System.IO; @@ -8,7 +9,7 @@ namespace ClassicalSharp { public partial class NetworkProcessor { - string womEnvIdentifier = "womenv_0", womTerrainIdentifier = "womterrain_0"; + string womEnvIdentifier = "womenv_0"; int womCounter = 0; bool sendWomId = false, sentWomId = false; @@ -18,11 +19,6 @@ namespace ClassicalSharp { if( item != null && item.Data != null ) { ParseWomConfig( (string)item.Data ); } - - game.AsyncDownloader.TryGetItem( womTerrainIdentifier, out item ); - if( item != null && item.Data != null ) { - game.ChangeTerrainAtlas( (Bitmap)item.Data ); - } } void ParseWomConfig( string page ) { @@ -48,12 +44,6 @@ namespace ClassicalSharp { int waterLevel = 0; if( Int32.TryParse( value, out waterLevel ) ) game.Map.SetWaterLevel( waterLevel ); - } else if( key == "environment.terrain" ) { - GetWomImageAsync( "terrain", value ); - } else if( key == "environment.edge" ) { // TODO: custom edges and sides - //GetWomImageAsync( "edge", value ); - } else if( key == "environment.side" ) { - //GetWomImageAsync( "side", value ); } else if( key == "user.detail" && !useMessageTypes ) { game.Chat.Add( value, CpeMessage.Status2 ); } @@ -61,13 +51,6 @@ namespace ClassicalSharp { } } - void GetWomImageAsync( string type, string id ) { - const string hostFormat = "http://files.worldofminecraft.com/skin.php?type={0}&id={1}"; - string url = String.Format( hostFormat, type, Uri.EscapeDataString( id ) ); - string identifier = "wom" + type + "_" + womCounter; - game.AsyncDownloader.DownloadImage( url, true, identifier ); - } - void ReadWomConfigurationAsync() { string host = ServerMotd.Substring( ServerMotd.IndexOf( "cfg=" ) + 4 ); string url = "http://" + host; @@ -77,7 +60,6 @@ namespace ClassicalSharp { // new world if the async 'get request' didn't complete before the new world was loaded. womCounter++; womEnvIdentifier = "womenv_" + womCounter; - womTerrainIdentifier = "womterrain_" + womCounter; game.AsyncDownloader.DownloadPage( url, true, womEnvIdentifier ); sendWomId = true; }