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