mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-29 08:32:46 -04:00
198 lines
6.3 KiB
C#
198 lines
6.3 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using System.Drawing;
|
|
using ClassicalSharp.GraphicsAPI;
|
|
using ClassicalSharp.Model;
|
|
using ClassicalSharp.Network;
|
|
using OpenTK;
|
|
#if ANDROID
|
|
using Android.Graphics;
|
|
#endif
|
|
|
|
namespace ClassicalSharp.Entities {
|
|
|
|
public abstract partial class Player : Entity {
|
|
|
|
public string DisplayName, SkinName, SkinIdentifier;
|
|
public SkinType SkinType;
|
|
internal AnimatedComponent anim;
|
|
internal ShadowComponent shadow;
|
|
internal float uScale = 1, vScale = 1;
|
|
|
|
public Player( Game game ) : base( game ) {
|
|
this.game = game;
|
|
StepSize = 0.5f;
|
|
SkinType = game.DefaultPlayerSkinType;
|
|
anim = new AnimatedComponent( game, this );
|
|
shadow = new ShadowComponent( game, this );
|
|
SetModel( "humanoid" );
|
|
}
|
|
|
|
DateTime lastModelChange = new DateTime( 1, 1, 1 );
|
|
public void SetModel( string model ) {
|
|
ModelScale = 1;
|
|
int sep = model.IndexOf( '|' );
|
|
string scale = sep == -1 ? null : model.Substring( sep + 1 );
|
|
ModelName = sep == -1 ? model : model.Substring( 0, sep );
|
|
|
|
Model = game.ModelCache.Get( ModelName );
|
|
lastModelChange = DateTime.UtcNow;
|
|
MobTextureId = -1;
|
|
ParseScale( scale );
|
|
}
|
|
|
|
void ParseScale( string scale ) {
|
|
if( scale == null ) return;
|
|
float value;
|
|
if( !Utils.TryParseDecimal( scale, out value ) )
|
|
return;
|
|
|
|
Utils.Clamp( ref value, 0.25f, Model.MaxScale );
|
|
ModelScale = value;
|
|
}
|
|
|
|
protected Texture nameTex;
|
|
protected internal int TextureId = -1, MobTextureId = -1;
|
|
|
|
public override void Despawn() {
|
|
game.Graphics.DeleteTexture( ref TextureId );
|
|
game.Graphics.DeleteTexture( ref nameTex.ID );
|
|
}
|
|
|
|
protected void MakeNameTexture() {
|
|
using( Font font = new Font( game.FontName, 24 ) ) {
|
|
DrawTextArgs args = new DrawTextArgs( DisplayName, font, false );
|
|
Size size = game.Drawer2D.MeasureBitmappedSize( ref args );
|
|
if( size.Width == 0 ) { nameTex = new Texture( -1, 0, 0, 0, 0, 1, 1 ); return; }
|
|
size.Width += 3; size.Height += 3;
|
|
|
|
using( IDrawer2D drawer = game.Drawer2D )
|
|
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) )
|
|
{
|
|
drawer.SetBitmap( bmp );
|
|
args.Text = "&\xFF" + Utils.StripColours( args.Text );
|
|
game.Drawer2D.Colours['\xFF'] = new FastColour( 80, 80, 80 );
|
|
game.Drawer2D.DrawBitmappedText( ref args, 3, 3 );
|
|
game.Drawer2D.Colours['\xFF'] = default(FastColour);
|
|
|
|
args.Text = DisplayName;
|
|
game.Drawer2D.DrawBitmappedText( ref args, 0, 0 );
|
|
nameTex = game.Drawer2D.Make2DTexture( bmp, size, 0, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdateName() {
|
|
game.Graphics.DeleteTexture( ref nameTex );
|
|
MakeNameTexture();
|
|
}
|
|
|
|
protected void DrawName() {
|
|
if( nameTex.ID == 0 ) MakeNameTexture();
|
|
if( nameTex.ID == -1 ) return;
|
|
|
|
IGraphicsApi gfx = game.Graphics;
|
|
gfx.BindTexture( nameTex.ID );
|
|
Vector3 pos = Position; pos.Y += Model.NameYOffset * ModelScale;
|
|
float scale = Math.Min( 1, Model.NameScale * ModelScale ) / 70f;
|
|
|
|
Vector3 p111, p121, p212, p222;
|
|
int col = FastColour.WhitePacked;
|
|
Vector2 size = new Vector2( nameTex.Width * scale, nameTex.Height * scale );
|
|
Utils.CalcBillboardPoints( size, pos, ref game.View, out p111, out p121, out p212, out p222 );
|
|
gfx.texVerts[0] = new VertexP3fT2fC4b( ref p111, nameTex.U1, nameTex.V2, col );
|
|
gfx.texVerts[1] = new VertexP3fT2fC4b( ref p121, nameTex.U1, nameTex.V1, col );
|
|
gfx.texVerts[2] = new VertexP3fT2fC4b( ref p222, nameTex.U2, nameTex.V1, col );
|
|
gfx.texVerts[3] = new VertexP3fT2fC4b( ref p212, nameTex.U2, nameTex.V2, col );
|
|
|
|
gfx.SetBatchFormat( VertexFormat.P3fT2fC4b );
|
|
gfx.UpdateDynamicIndexedVb( DrawMode.Triangles, gfx.texVb, gfx.texVerts, 4 );
|
|
}
|
|
|
|
protected void CheckSkin() {
|
|
DownloadedItem item;
|
|
game.AsyncDownloader.TryGetItem( SkinIdentifier, out item );
|
|
if( item == null || item.Data == null ) return;
|
|
|
|
Bitmap bmp = (Bitmap)item.Data;
|
|
game.Graphics.DeleteTexture( ref TextureId );
|
|
if( !Platform.Is32Bpp( bmp ) )
|
|
game.Drawer2D.ConvertTo32Bpp( ref bmp );
|
|
uScale = 1; vScale = 1;
|
|
EnsurePow2( ref bmp );
|
|
|
|
SkinType = Utils.GetSkinType( bmp );
|
|
if( SkinType == SkinType.Invalid ) {
|
|
ResetSkin( bmp ); return;
|
|
}
|
|
|
|
if( Model is HumanoidModel )
|
|
ClearHat( bmp, SkinType );
|
|
TextureId = game.Graphics.CreateTexture( bmp, true );
|
|
MobTextureId = -1;
|
|
|
|
// Custom mob textures.
|
|
if( Utils.IsUrlPrefix( SkinName, 0 ) && item.TimeAdded > lastModelChange )
|
|
MobTextureId = TextureId;
|
|
bmp.Dispose();
|
|
}
|
|
|
|
void ResetSkin( Bitmap bmp ) {
|
|
string formatString = "Skin {0} has unsupported dimensions({1}, {2}), reverting to default.";
|
|
Utils.LogDebug( formatString, SkinName, bmp.Width, bmp.Height );
|
|
MobTextureId = -1;
|
|
TextureId = -1;
|
|
SkinType = game.DefaultPlayerSkinType;
|
|
bmp.Dispose();
|
|
}
|
|
|
|
unsafe static void ClearHat( Bitmap bmp, SkinType skinType ) {
|
|
using( FastBitmap fastBmp = new FastBitmap( bmp, true, false ) ) {
|
|
int sizeX = (bmp.Width / 64) * 32;
|
|
int yScale = skinType == SkinType.Type64x32 ? 32 : 64;
|
|
int sizeY = (bmp.Height / yScale) * 16;
|
|
|
|
// determine if we actually need filtering
|
|
for( int y = 0; y < sizeY; y++ ) {
|
|
int* row = fastBmp.GetRowPtr( y );
|
|
row += sizeX;
|
|
for( int x = 0; x < sizeX; x++ ) {
|
|
byte alpha = (byte)(row[x] >> 24);
|
|
if( alpha != 255 ) return;
|
|
}
|
|
}
|
|
|
|
// only perform filtering when the entire hat is opaque
|
|
int fullWhite = FastColour.White.ToArgb();
|
|
int fullBlack = FastColour.Black.ToArgb();
|
|
for( int y = 0; y < sizeY; y++ ) {
|
|
int* row = fastBmp.GetRowPtr( y );
|
|
row += sizeX;
|
|
for( int x = 0; x < sizeX; x++ ) {
|
|
int pixel = row[x];
|
|
if( pixel == fullWhite || pixel == fullBlack ) row[x] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnsurePow2( ref Bitmap bmp ) {
|
|
int width = Utils.NextPowerOf2( bmp.Width );
|
|
int height = Utils.NextPowerOf2( bmp.Height );
|
|
if( width == bmp.Width && height == bmp.Height ) return;
|
|
|
|
Bitmap scaled = Platform.CreateBmp( width, height );
|
|
using( FastBitmap src = new FastBitmap( bmp, true, true ) )
|
|
using( FastBitmap dst = new FastBitmap( scaled, true, false ) )
|
|
{
|
|
for( int y = 0; y < src.Height; y++ )
|
|
FastBitmap.CopyRow( y, y, src, dst, src.Width );
|
|
}
|
|
|
|
uScale = (float)bmp.Width / width;
|
|
vScale = (float)bmp.Height / height;
|
|
bmp.Dispose();
|
|
bmp = scaled;
|
|
}
|
|
}
|
|
} |