mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 19:45:23 -04:00
More comments, more refactoring. Remove WoM terrain atlas support because WoM's file server has been down for quite a long time now.
This commit is contained in:
parent
448ec55e6e
commit
00945a6095
@ -13,31 +13,44 @@ namespace ClassicalSharp {
|
||||
/// <summary> Sets the underlying bitmap that drawing operations will be performed on. </summary>
|
||||
public abstract void SetBitmap( Bitmap bmp );
|
||||
|
||||
/// <summary> Draws a string using the specified arguments and fonts at the
|
||||
/// specified coordinates in the currently bound bitmap. </summary>
|
||||
public abstract void DrawText( Font font, ref DrawTextArgs args, float x, float y );
|
||||
|
||||
/// <summary> Draws a 2D flat rectangle of the specified dimensions at the
|
||||
/// specified coordinates in the currently bound bitmap. </summary>
|
||||
public abstract void DrawRect( Color colour, int x, int y, int width, int height );
|
||||
|
||||
/// <summary> Draws the outline of a 2D flat rectangle of the specified dimensions
|
||||
/// at the specified coordinates in the currently bound bitmap. </summary>
|
||||
public abstract void DrawRectBounds( Color colour, float lineWidth, int x, int y, int width, int height );
|
||||
|
||||
/// <summary> Draws a 2D rectangle with rounded borders of the specified dimensions
|
||||
/// at the specified coordinates in the currently bound bitmap. </summary>
|
||||
public abstract void DrawRoundedRect( Color colour, float radius, float x, float y, float width, float height );
|
||||
|
||||
/// <summary> Clears the entire bound bitmap to the specified colour. </summary>
|
||||
public abstract void Clear( Color colour );
|
||||
|
||||
/// <summary> Disposes of any resources used by this class that are associated with the underlying bitmap. </summary>
|
||||
public abstract void Dispose();
|
||||
|
||||
/// <summary> Returns a new bitmap that has 32-bpp pixel format. </summary>
|
||||
public abstract Bitmap ConvertTo32Bpp( Bitmap src );
|
||||
|
||||
/// <summary> Returns the size of a bitmap needed to contain the specified text with the given arguments. </summary>
|
||||
public abstract Size MeasureSize( string text, Font font, bool shadow );
|
||||
|
||||
/// <summary> Disposes of all native resources used by this class. </summary>
|
||||
/// <remarks> You will no longer be able to perform measuring or drawing calls after this. </remarks>
|
||||
public abstract void DisposeInstance();
|
||||
|
||||
public Texture MakeTextTexture( Font font, int screenX, int screenY, ref DrawTextArgs args ) {
|
||||
/// <summary> Draws the specified string from the arguments into a new bitmap,
|
||||
/// them creates a 2D texture with origin at the specified window coordinates. </summary>
|
||||
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 ) {
|
||||
/// <summary> Creates a 2D texture with origin at the specified window coordinates. </summary>
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Creates a power-of-2 sized bitmap larger or equal to to the given size. </summary>
|
||||
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;
|
||||
|
@ -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 );
|
||||
|
@ -103,6 +103,7 @@
|
||||
<Compile Include="Blocks\BlockInfo.cs" />
|
||||
<Compile Include="Blocks\BlockInfo.Culling.cs" />
|
||||
<Compile Include="Blocks\BlockInfo.Atlas.cs" />
|
||||
<Compile Include="Entities\AnimatedEntity.cs" />
|
||||
<Compile Include="Entities\Entity.cs" />
|
||||
<Compile Include="Entities\EntityList.cs" />
|
||||
<Compile Include="Entities\LocalPlayer.cs" />
|
||||
|
54
ClassicalSharp/Entities/AnimatedEntity.cs
Normal file
54
ClassicalSharp/Entities/AnimatedEntity.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
/// <summary> Entity that is animated depending on movement speed and time. </summary>
|
||||
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;
|
||||
|
||||
/// <summary> Calculates the next animation state based on old and new position. </summary>
|
||||
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);
|
||||
|
||||
/// <summary> Calculates the interpolated state between the last and next animation state. </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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 );
|
||||
|
@ -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];
|
||||
|
||||
/// <summary> Performs a tick call for all player entities contained in this list. </summary>
|
||||
public void Tick( double delta ) {
|
||||
for( int i = 0; i < Players.Length; i++ ) {
|
||||
if( Players[i] != null ) {
|
||||
@ -16,6 +17,7 @@ namespace ClassicalSharp {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Renders all player entities contained in this list. </summary>
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Disposes of all player entities contained in this list. </summary>
|
||||
public void Dispose() {
|
||||
for( int i = 0; i < Players.Length; i++ ) {
|
||||
if( Players[i] != null ) {
|
||||
@ -52,6 +55,7 @@ namespace ClassicalSharp {
|
||||
return targetId;
|
||||
}
|
||||
|
||||
/// <summary> Gets or sets the player entity for the specified id. </summary>
|
||||
public Player this[int id] {
|
||||
get { return Players[id]; }
|
||||
set {
|
||||
|
@ -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] );
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
/// <summary> Entity that performs collision detection. </summary>
|
||||
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 ) {
|
||||
|
@ -5,14 +5,13 @@ using OpenTK;
|
||||
|
||||
namespace ClassicalSharp {
|
||||
|
||||
public abstract partial class Player : PhysicsEntity {
|
||||
public abstract partial class Player : AnimatedEntity {
|
||||
|
||||
/// <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 ); }
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user