Merge branch 'master' of github.com:UnknownShadow200/ClassicalSharp

This commit is contained in:
UnknownShadow200 2016-03-03 07:11:42 +11:00
commit 76361f440d
27 changed files with 347 additions and 310 deletions

View File

@ -221,9 +221,7 @@ namespace ClassicalSharp {
return tile < BlockInfo.CpeBlocksCount || game.BlockInfo.Name[tile] != "Invalid";
}
public override bool HandlesAllInput {
get { return true; }
}
public override bool HandlesAllInput { get { return true; } }
public override bool HandlesMouseMove( int mouseX, int mouseY ) {
if( draggingMouse ) {

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using ClassicalSharp.Network;
using OpenTK.Input;
namespace ClassicalSharp {
@ -13,7 +14,7 @@ namespace ClassicalSharp {
}
int chatLines;
ChatTextWidget announcement, clock;
ChatTextWidget announcement;
TextInputWidget textInput;
TextGroupWidget status, bottomRight, normalChat, clientStatus;
bool suppressNextPress = true;
@ -49,9 +50,11 @@ namespace ClassicalSharp {
void ConstructWidgets() {
textInput = new TextInputWidget( game, chatFont, chatBoldFont );
textInput.YOffset = blockSize + 5;
status = new TextGroupWidget( game, 4, chatFont, chatUnderlineFont,
status = new TextGroupWidget( game, 5, chatFont, chatUnderlineFont,
Anchor.BottomOrRight, Anchor.LeftOrTop );
status.Init();
status.SetUsePlaceHolder( 0, false );
status.SetUsePlaceHolder( 1, false );
bottomRight = new TextGroupWidget( game, 3, chatFont, chatUnderlineFont,
Anchor.BottomOrRight, Anchor.BottomOrRight );
bottomRight.YOffset = blockSize * 3 / 2;
@ -69,18 +72,16 @@ namespace ClassicalSharp {
announcement = ChatTextWidget.Create( game, 0, 0, null,
Anchor.Centre, Anchor.Centre, announcementFont );
announcement.YOffset = -game.Height / 4;
clock = ChatTextWidget.Create( game, 0, 0, null,
Anchor.BottomOrRight, Anchor.LeftOrTop, chatItalicFont );
}
void SetInitialMessages() {
Chat chat = game.Chat;
chatIndex = chat.Log.Count - chatLines;
ResetChat();
status.SetText( 0, chat.Status1.Text );
status.SetText( 1, chat.Status2.Text );
status.SetText( 2, chat.Status3.Text );
if( game.ShowClock ) clock.SetText( chat.ClientClock.Text );
status.SetText( 2, chat.Status1.Text );
status.SetText( 3, chat.Status2.Text );
status.SetText( 4, chat.Status3.Text );
if( game.ShowClock ) status.SetText( 0, chat.ClientClock.Text );
bottomRight.SetText( 2, chat.BottomRight1.Text );
bottomRight.SetText( 1, chat.BottomRight2.Text );
@ -100,18 +101,7 @@ namespace ClassicalSharp {
status.Render( delta );
bottomRight.Render( delta );
}
if( game.ShowClock ) {
if( !clock.IsValid ) clock.SetText( game.Chat.ClientClock.Text );
clock.Render( delta );
} else if( clock.IsValid ) {
clock.Dispose();
}
int statusOffset = clock.IsValid ? clock.Height : 0;
if( statusOffset != oldStatusOffset ) {
oldStatusOffset = statusOffset;
status.MoveTo( status.X, oldStatusOffset );
}
CheckOtherStatuses();
UpdateChatYOffset( false );
RenderClientStatus();
@ -130,6 +120,42 @@ namespace ClassicalSharp {
announcement.Dispose();
}
int lastDownloadStatus = int.MinValue;
StringBuffer lastDownload = new StringBuffer( 48 );
void CheckOtherStatuses() {
bool clockValid = status.Textures[0].IsValid;
if( game.ShowClock ) {
if( !clockValid ) status.SetText( 0, game.Chat.ClientClock.Text );
} else if( clockValid ) {
status.SetText( 0, null );
}
Request item = game.AsyncDownloader.CurrentItem;
if( item == null || !(item.Identifier == "terrain" || item.Identifier == "texturePack") ) {
if( status.Textures[1].IsValid ) status.SetText( 1, null );
lastDownloadStatus = int.MinValue;
return;
}
int progress = game.AsyncDownloader.CurrentItemProgress;
if( progress == lastDownloadStatus ) return;
lastDownloadStatus = progress;
SetTexturePackMessage( progress );
}
void SetTexturePackMessage( int progress ) {
lastDownload.Clear();
int index = 0;
if( progress == -2 )
lastDownload.Append( ref index, "&eRetrieving texture pack.." );
else if( progress == -1 )
lastDownload.Append( ref index, "&eDownloading texture pack" );
else if( progress >= 0 && progress <= 100 )
lastDownload.Append( ref index, "&eDownloading texture pack (&7" )
.AppendNum( ref index, progress ).Append( ref index, "&e%)" );
status.SetText( 1, lastDownload.ToString() );
}
void RenderRecentChat( DateTime now, double delta ) {
int[] metadata = (int[])Metadata;
for( int i = 0; i < normalChat.Textures.Length; i++ ) {
@ -156,7 +182,9 @@ namespace ClassicalSharp {
static FastColour backColour = new FastColour( 60, 60, 60, 180 );
public void RenderBackground() {
int height = normalChat.GetUsedHeight();
int minIndex = Math.Min( 0, game.Chat.Log.Count - chatLines );
int height = chatIndex == minIndex ? normalChat.GetUsedHeight() : normalChat.Height;
int y = normalChat.Y + normalChat.Height - height - 5;
int x = normalChat.X - 5;
int width = Math.Max( clientStatus.Width, normalChat.Width ) + 10;
@ -166,7 +194,7 @@ namespace ClassicalSharp {
graphicsApi.Draw2DQuad( x, y, width, boxHeight + 10, backColour );
}
int inputOldHeight = -1, oldStatusOffset = -1;
int inputOldHeight = -1;
void UpdateChatYOffset( bool force ) {
int height = textInput.RealHeight;
if( force || height != inputOldHeight ) {
@ -200,7 +228,7 @@ namespace ClassicalSharp {
metadata[i] = metadata[i + 1];
metadata[chatLines - 1] = chatIndex + chatLines - 1;
} else if( type >= MessageType.Status1 && type <= MessageType.Status3 ) {
status.SetText( (int)(type - MessageType.Status1), e.Text );
status.SetText( 2 + (int)(type - MessageType.Status1), e.Text );
} else if( type >= MessageType.BottomRight1 && type <= MessageType.BottomRight3 ) {
bottomRight.SetText( 2 - (int)(type - MessageType.BottomRight1), e.Text );
} else if( type == MessageType.Announcement ) {
@ -209,7 +237,7 @@ namespace ClassicalSharp {
clientStatus.SetText( (int)(type - MessageType.ClientStatus1), e.Text );
UpdateChatYOffset( true );
} else if( type == MessageType.ClientClock && game.ShowClock ) {
clock.SetText( e.Text );
status.SetText( 0, e.Text );
}
}
@ -319,13 +347,13 @@ namespace ClassicalSharp {
textInput.SendTextInBufferAndReset();
chatIndex = game.Chat.Log.Count - chatLines;
ResetIndex();
ScrollHistory();
} else if( key == Key.PageUp ) {
chatIndex -= chatLines;
ResetIndex();
ScrollHistory();
} else if( key == Key.PageDown ) {
chatIndex += chatLines;
ResetIndex();
ScrollHistory();
} else {
textInput.HandlesKeyDown( key );
}
@ -345,16 +373,23 @@ namespace ClassicalSharp {
public override bool HandlesMouseScroll( int delta ) {
if( !HandlesAllInput ) return false;
chatIndex -= delta;
ResetIndex();
ScrollHistory();
return true;
}
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
if( !HandlesAllInput || game.HideGui ) return false;
if( normalChat.Bounds.Contains( mouseX, mouseY ) ) {
if( !normalChat.Bounds.Contains( mouseX, mouseY ) )
return textInput.HandlesMouseClick( mouseX, mouseY, button );
int height = normalChat.GetUsedHeight();
int y = normalChat.Y + normalChat.Height - height;
if( new Rectangle( normalChat.X, y, normalChat.Width, height ).Contains( mouseX, mouseY ) ) {
if( new Rectangle( normalChat.X, y, normalChat.Width, height ).Contains( mouseX, mouseY ) )
return HandlesChatClick( mouseX, mouseY );
return false;
}
bool HandlesChatClick( int mouseX, int mouseY ) {
string text = normalChat.GetSelected( mouseX, mouseY );
if( text == null ) return false;
@ -376,10 +411,6 @@ namespace ClassicalSharp {
}
return true;
}
return false;
}
return textInput.HandlesMouseClick( mouseX, mouseY, button );
}
void OpenUrl( WarningScreen screen ) {
try {
@ -394,7 +425,7 @@ namespace ClassicalSharp {
textInput.AppendText( (string)screen.Metadata );
}
void ResetIndex() {
void ScrollHistory() {
int maxIndex = game.Chat.Log.Count - chatLines;
int minIndex = Math.Min( 0, maxIndex );
Utils.Clamp( ref chatIndex, minIndex, maxIndex );

View File

@ -96,9 +96,7 @@ namespace ClassicalSharp {
return HandleMouseClick( buttons, mouseX, mouseY, button );
}
public override bool HandlesAllInput {
get { return true; }
}
public override bool HandlesAllInput { get { return true; } }
public override void OnResize( int oldWidth, int oldHeight, int width, int height ) {
for( int i = 0; i < buttons.Length; i++ )

View File

@ -14,19 +14,13 @@ namespace ClassicalSharp {
public virtual bool HandlesAllInput { get; protected set; }
/// <summary> Whether this screen completely and opaquely covers the game world behind it. </summary>
public virtual bool BlocksWorld {
get { return false; }
}
public virtual bool BlocksWorld { get { return false; } }
/// <summary> Whether this screen hides the normal in-game hud. </summary>
public virtual bool HidesHud {
get { return false; }
}
public virtual bool HidesHud { get { return false; } }
/// <summary> Whether the normal in-game hud should be drawn over the top of this screen. </summary>
public virtual bool RenderHudAfter {
get { return false; }
}
public virtual bool RenderHudAfter { get { return false; } }
/// <summary> Causes the screen to recreate all of its contained widgets. </summary>
/// <remarks> Typically used when bitmap font changes. </remarks>

View File

@ -13,9 +13,7 @@ namespace ClassicalSharp {
public float U1, V1;
public float U2, V2;
public Rectangle Bounds {
get { return new Rectangle( X1, Y1, Width, Height ); }
}
public Rectangle Bounds { get { return new Rectangle( X1, Y1, Width, Height ); } }
public Texture( int id, int x, int y, int width, int height, float u2, float v2 )
: this( id, x, y, width, height, 0, u2, 0, v2 ) {
@ -33,9 +31,7 @@ namespace ClassicalSharp {
U2 = u2; V2 = v2;
}
public bool IsValid {
get { return ID > 0; }
}
public bool IsValid { get { return ID > 0; } }
public void Render( IGraphicsApi graphics ) {
graphics.BindTexture( ID );
@ -47,15 +43,9 @@ namespace ClassicalSharp {
graphics.Draw2DTexture( ref this, colour );
}
public int X2 {
get { return X1 + Width; }
//set { X1 = value - Width; }
}
public int X2 { get { return X1 + Width; } }
public int Y2 {
get { return Y1 + Height; }
//set { Y1 = value - Height; }
}
public int Y2 { get { return Y1 + Height; } }
public override string ToString() {
return ID + String.Format( "({0}, {1} -> {2},{3}", X1, Y1, Width, Height );

View File

@ -42,9 +42,7 @@ namespace ClassicalSharp {
BitmapData data;
byte* scan0Byte;
public bool IsLocked {
get { return data != null; }
}
public bool IsLocked { get { return data != null; } }
public IntPtr Scan0;
public int Stride;

View File

@ -19,7 +19,9 @@ namespace ClassicalSharp {
Textures[index] = tex;
lines[index] = text;
} else {
Textures[index] = new Texture( -1, 0, 0, 0, defaultHeight, 0, 0 );
int height = PlaceholderHeight[index] ? defaultHeight : 0;
int y = CalcY( index, height );
Textures[index] = new Texture( -1, 0, y, 0, height, 0, 0 );
lines[index] = null;
}
UpdateDimensions();

View File

@ -16,6 +16,7 @@ namespace ClassicalSharp {
}
public Texture[] Textures;
public bool[] PlaceholderHeight;
string[] lines;
Rectangle[][] urlBounds;
int ElementsCount, defaultHeight;
@ -24,16 +25,28 @@ namespace ClassicalSharp {
public override void Init() {
Textures = new Texture[ElementsCount];
PlaceholderHeight = new bool[ElementsCount];
lines = new string[ElementsCount];
urlBounds = new Rectangle[ElementsCount][];
DrawTextArgs args = new DrawTextArgs( "I", font, true );
defaultHeight = game.Drawer2D.MeasureChatSize( ref args ).Height;
for( int i = 0; i < Textures.Length; i++ )
for( int i = 0; i < Textures.Length; i++ ) {
Textures[i].Height = defaultHeight;
PlaceholderHeight[i] = true;
}
UpdateDimensions();
}
public void SetUsePlaceHolder( int index, bool placeHolder ) {
PlaceholderHeight[index] = placeHolder;
if( Textures[index].ID > 0 ) return;
int newHeight = placeHolder ? defaultHeight : 0;
Textures[index].Y1 = CalcY( index, newHeight );
Textures[index].Height = newHeight;
}
public void PushUpAndReplaceLast( string text ) {
int y = Y;
graphicsApi.DeleteTexture( ref Textures[0] );
@ -56,31 +69,32 @@ namespace ClassicalSharp {
if( VerticalAnchor == Anchor.LeftOrTop ) {
y = Y;
for( int i = 0; i < index; i++ ) {
for( int i = 0; i < index; i++ )
y += Textures[i].Height;
}
for( int i = index + 1; i < Textures.Length; i++ ) {
for( int i = index + 1; i < Textures.Length; i++ )
Textures[i].Y1 += deltaY;
}
} else {
y = game.Height - YOffset;
for( int i = index + 1; i < Textures.Length; i++ ) {
for( int i = index + 1; i < Textures.Length; i++ )
y -= Textures[i].Height;
}
y -= newHeight;
for( int i = 0; i < index; i++ ) {
for( int i = 0; i < index; i++ )
Textures[i].Y1 -= deltaY;
}
}
return y;
}
public int GetUsedHeight() {
int sum = 0;
int sum = 0, max = Textures.Length;
for( int i = 0; i < Textures.Length; i++ ) {
if( Textures[i].IsValid )
sum += Textures[i].Height;
if( Textures[i].IsValid ) {
max = i; break;
}
}
for( int i = max; i < Textures.Length; i++ )
sum += Textures[i].Height;
return sum;
}

View File

@ -40,24 +40,16 @@ namespace ClassicalSharp {
public Anchor VerticalAnchor;
/// <summary> Width and height of widget in window space. </summary>
public Size Size {
get { return new Size( Width, Height ); }
}
public Size Size { get { return new Size( Width, Height ); } }
/// <summary> Coordinate of top left corner of widget's bounds in window space. </summary>
public Point TopLeft {
get { return new Point( X, Y ); }
}
public Point TopLeft { get { return new Point( X, Y ); } }
/// <summary> Coordinate of bottom right corner of widget's bounds in window space. </summary>
public Point BottomRight {
get { return new Point( X + Width, Y + Height ); }
}
public Point BottomRight { get { return new Point( X + Width, Y + Height ); } }
/// <summary> Specifies the boundaries of the widget in window space. </summary>
public Rectangle Bounds {
get { return new Rectangle( X, Y, Width, Height ); }
}
public Rectangle Bounds { get { return new Rectangle( X, Y, Width, Height ); } }
/// <summary> Moves the widget to the specified window space coordinates. </summary>
public virtual void MoveTo( int newX, int newY ) {

View File

@ -61,14 +61,17 @@ namespace ClassicalSharp {
/// <summary> Whether the player is allowed to double jump. </summary>
public bool CanDoubleJump = true;
/// <summary> Maximum speed the entity can move at horizontally when CanSpeed is false. </summary>
public float MaxSpeedMultiplier = 1;
/// <summary> Parses hack flags specified in the motd and/or name of the server. </summary>
/// <remarks> Recognises +/-hax, +/-fly, +/-noclip, +/-speed, +/-respawn, +/-ophax </remarks>
/// <remarks> Recognises +/-hax, +/-fly, +/-noclip, +/-speed, +/-respawn, +/-ophax, and horspeed=xyz </remarks>
public void ParseHackFlags( string name, string motd ) {
string joined = name + motd;
SetAllHacks( true );
MaxSpeedMultiplier = 1;
// By default (this is also the case with WoM), we can use hacks.
if( joined.Contains( "-hax" ) )
SetAllHacks( false );
if( joined.Contains( "-hax" ) ) SetAllHacks( false );
ParseFlag( b => CanFly = b, joined, "fly" );
ParseFlag( b => CanNoclip = b, joined, "noclip" );
@ -77,6 +80,21 @@ namespace ClassicalSharp {
if( UserType == 0x64 )
ParseFlag( b => SetAllHacks( b ), joined, "ophax" );
ParseHorizontalSpeed( joined );
}
void ParseHorizontalSpeed( string joined ) {
int start = joined.IndexOf( "horspeed=", StringComparison.OrdinalIgnoreCase );
if( start < 0 ) return;
start += 9;
int end = joined.IndexOf(' ', start );
if( end < 0 ) end = joined.Length;
string num = joined.Substring( start, end - start );
float value = 0;
if( !Single.TryParse( num, out value ) || value <= 0 ) return;
MaxSpeedMultiplier = value;
}
void SetAllHacks( bool allowed ) {

View File

@ -23,37 +23,38 @@ namespace ClassicalSharp {
int index = 0, vb = 0;
VertexPos3fTex2fCol4b[] verts = null;
ShadowData data = new ShadowData();
int coordsCount = 0;
int posCount = 0, dataCount = 0;
Vector3I* coords = stackalloc Vector3I[4];
for( int i = 0; i < 4; i++ )
ShadowData* data = stackalloc ShadowData[4];
for( int i = 0; i < 4; i++ ) {
coords[i] = new Vector3I( int.MinValue );
data[i] = new ShadowData();
}
if( mode == EntityShadow.SnapToBlock ) {
vb = game.Graphics.texVb; verts = game.Graphics.texVerts;
if( !CalculateShadow( coords, ref coordsCount, posX, posZ, posY, ref data ) ) return;
if( !GetBlocks( coords, ref posCount, posX, posZ, posY, data, ref dataCount ) ) return;
float x1 = Utils.Floor( posX ), z1 = Utils.Floor( posZ );
DraqSquareShadow( verts, ref index, data.Y, 220, x1, z1 );
DraqSquareShadow( verts, ref index, data[0].Y, 220, x1, z1 );
} else {
vb = game.ModelCache.vb; verts = game.ModelCache.vertices;
float x1 = posX - 7/16f, x2 = Math.Min( posX + 7/16f, Utils.Floor( x1 ) + 1 );
float z1 = posZ - 7/16f, z2 = Math.Min( posZ + 7/16f, Utils.Floor( z1 ) + 1 );
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position );
float x = posX - 7/16f, z = posZ - 7/16f;
if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCircle( verts, ref index, data, dataCount, x, z );
x2 = posX + 7/16f; x1 = Math.Max( posX - 7/16f, Utils.Floor( x2 ) );
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position );
x = Math.Max( posX - 7/16f, Utils.Floor( posX + 7/16f ) );
if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCircle( verts, ref index, data, dataCount, x, z );
z2 = posZ + 7/16f; z1 = Math.Max( posZ - 7/16f, Utils.Floor( z2 ) );
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position );
z = Math.Max( posZ - 7/16f, Utils.Floor( posZ + 7/16f ) );
if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCircle( verts, ref index, data, dataCount, x, z );
x1 = posX - 7/16f; x2 = Math.Min( posX + 7/16f, Utils.Floor( x1 ) + 1 );
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position );
x = posX - 7/16f;
if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCircle( verts, ref index, data, dataCount, x, z );
}
if( index == 0 ) return;
@ -66,31 +67,92 @@ namespace ClassicalSharp {
game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, verts, index, index * 6 / 4 );
}
bool CalculateShadow( Vector3I* coords, ref int coordsCount, float x, float z, int posY, ref ShadowData data ) {
data = new ShadowData();
void DraqSquareShadow( VertexPos3fTex2fCol4b[] verts, ref int index, float y, byte alpha, float x, float z ) {
FastColour col = FastColour.White; col.A = alpha;
TextureRec rec = new TextureRec( 63/128f, 63/128f, 1/128f, 1/128f );
verts[index++] = new VertexPos3fTex2fCol4b( x, y, z, rec.U1, rec.V1, col );
verts[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z, rec.U2, rec.V1, col );
verts[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z + 1, rec.U2, rec.V2, col );
verts[index++] = new VertexPos3fTex2fCol4b( x, y, z + 1, rec.U1, rec.V2, col );
}
void DrawCircle( VertexPos3fTex2fCol4b[] verts, ref int index,
ShadowData* data, int dataCount, float x, float z ) {
x = Utils.Floor( x ); z = Utils.Floor( z );
BlockInfo info = game.BlockInfo;
Vector3 min = info.MinBB[data[0].Block], max = info.MaxBB[data[0].Block];
DrawCoords( verts, ref index, data[0], x + min.X, z + min.Z, x + max.X, z + max.Z );
for( int i = 1; i < dataCount; i++ ) {
Vector3 nMin = info.MinBB[data[i].Block], nMax = info.MaxBB[data[i].Block];
DrawCoords( verts, ref index, data[i], x + min.X, z + nMin.Z, x + max.X, z + min.Z );
DrawCoords( verts, ref index, data[i], x + min.X, z + max.Z, x + max.X, z + nMax.Z );
DrawCoords( verts, ref index, data[i], x + nMin.X, z + nMin.Z, x + min.X, z + nMax.Z );
DrawCoords( verts, ref index, data[i], x + max.X, z + nMin.Z, x + nMax.X, z + nMax.Z );
min = nMin; max = nMax;
}
}
void DrawCoords( VertexPos3fTex2fCol4b[] verts, ref int index, ShadowData data,
float x1, float z1, float x2, float z2 ) {
Vector3 centre = entity.Position;
BlockInfo info = game.BlockInfo;
if( lequal( x2, x1 ) || lequal( z2, z1 ) ) return;
float u1 = (x1 - centre.X) * 16/14f + 0.5f;
float v1 = (z1 - centre.Z) * 16/14f + 0.5f;
float u2 = (x2 - centre.X) * 16/14f + 0.5f;
float v2 = (z2 - centre.Z) * 16/14f + 0.5f;
if( u2 <= 0 || v2 <= 0 || u1 >= 1 || v1 >= 1 ) return;
x1 = Math.Max( x1, centre.X - 7/16f ); u1 = Math.Max( u1, 0 );
z1 = Math.Max( z1, centre.Z - 7/16f ); v1 = Math.Max( v1, 0 );
x2 = Math.Min( x2, centre.X + 7/16f ); u2 = Math.Min( u2, 1 );
z2 = Math.Min( z2, centre.Z + 7/16f ); v2 = Math.Min( v2, 1 );
FastColour col = FastColour.White; col.A = data.A;
verts[index++] = new VertexPos3fTex2fCol4b( x1, data.Y, z1, u1, v1, col );
verts[index++] = new VertexPos3fTex2fCol4b( x2, data.Y, z1, u2, v1, col );
verts[index++] = new VertexPos3fTex2fCol4b( x2, data.Y, z2, u2, v2, col );
verts[index++] = new VertexPos3fTex2fCol4b( x1, data.Y, z2, u1, v2, col );
}
bool GetBlocks( Vector3I* coords, ref int posCount, float x, float z,
int posY, ShadowData* data, ref int index ) {
int blockX = Utils.Floor( x ), blockZ = Utils.Floor( z );
Vector3I p = new Vector3I( blockX, 0, blockZ );
BlockInfo info = game.BlockInfo;
Vector3 Position = entity.Position;
index = 0;
// Check we have not processed this particular block already.
if( Position.Y < 0 ) return false;
for( int i = 0; i < 4; i++ )
for( int i = 0; i < 4; i++ ) {
if( coords[i] == p ) return false;
data[i] = new ShadowData();
}
coords[posCount] = p; posCount++;
while( posY >= 0 ) {
while( posY >= 0 && index < 4 ) {
byte block = GetShadowBlock( blockX, posY, blockZ );
if( !(info.IsAir[block] || info.IsSprite[block] || info.IsLiquid[block]) ) {
float blockY = posY + info.MaxBB[block].Y;
if( blockY < Position.Y + 0.01f ) {
data.Block = block; data.Y = blockY; break;
}
}
posY--;
}
if( posY == -1 ) data.Y = 0;
if( info.IsAir[block] || info.IsSprite[block] || info.IsLiquid[block] ) continue;
float blockY = posY + 1 + info.MaxBB[block].Y;
if( blockY >= Position.Y + 0.01f ) continue;
coords[coordsCount] = p; coordsCount++;
CalcAlpha( Position.Y, ref data.Y, ref data.A );
data[index].Block = block; data[index].Y = blockY;
CalcAlpha( Position.Y, ref data[index] );
index++;
// Check if the casted shadow will continue on further down.
if( info.MinBB[block].X == 0 && info.MaxBB[block].X == 1 &&
info.MinBB[block].Z == 0 && info.MaxBB[block].Z == 1 ) return true;
}
if( index < 4 ) {
data[index].Block = (byte)game.Map.EdgeBlock; data[index].Y = 0;
CalcAlpha( Position.Y, ref data[index] );
index++;
}
return true;
}
@ -105,56 +167,30 @@ namespace ClassicalSharp {
return game.Map.GetBlock( x, y, z );
}
void DraqSquareShadow( VertexPos3fTex2fCol4b[] verts, ref int index, float y, byte alpha, float x, float z ) {
FastColour col = FastColour.White; col.A = alpha;
TextureRec rec = new TextureRec( 63/128f, 63/128f, 1/128f, 1/128f );
verts[index++] = new VertexPos3fTex2fCol4b( x, y, z, rec.U1, rec.V1, col );
verts[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z, rec.U2, rec.V1, col );
verts[index++] = new VertexPos3fTex2fCol4b( x + 1, y, z + 1, rec.U2, rec.V2, col );
verts[index++] = new VertexPos3fTex2fCol4b( x, y, z + 1, rec.U1, rec.V2, col );
}
void DrawCoords( VertexPos3fTex2fCol4b[] verts, ref int index, ShadowData data, Vector2 p1, Vector2 p2, Vector3 centre ) {
if( lequal( p2.X, p1.X ) || lequal( p2.Y, p1.Y ) ) return;
float u1 = (p1.X - centre.X) * 16/14f + 0.5f;
float v1 = (p1.Y - centre.Z) * 16/14f + 0.5f;
float u2 = (p2.X - centre.X) * 16/14f + 0.5f;
float v2 = (p2.Y - centre.Z) * 16/14f + 0.5f;
if( u2 <= 0 || v2 <= 0 || u1 >= 1 || v1 >= 1 ) return;
p1.X = Math.Max( p1.X, centre.X - 14/16f ); u1 = Math.Max( u1, 0 );
p1.Y = Math.Max( p1.Y, centre.Z - 14/16f ); v1 = Math.Max( v1, 0 );
p2.X = Math.Min( p2.X, centre.X + 14/16f ); u2 = Math.Min( u2, 1 );
p2.Y = Math.Min( p2.Y, centre.Z + 14/16f ); v2 = Math.Min( v2, 1 );
FastColour col = FastColour.White; col.A = data.A;
verts[index++] = new VertexPos3fTex2fCol4b( p1.X, data.Y, p1.Y, u1, v1, col );
verts[index++] = new VertexPos3fTex2fCol4b( p2.X, data.Y, p1.Y, u2, v1, col );
verts[index++] = new VertexPos3fTex2fCol4b( p2.X, data.Y, p2.Y, u2, v2, col );
verts[index++] = new VertexPos3fTex2fCol4b( p1.X, data.Y, p2.Y, u1, v2, col );
}
struct ShadowData {
public byte Block;
public float Y;
public byte A;
}
static void CalcAlpha( float playerY, ref float y, ref byte alpha ) {
if( (playerY - y) <= 6 ) { y += 1/64f; alpha = (byte)(190 - 190 * (playerY - y) / 6); }
else if( (playerY - y) <= 16 ) { y += 1/64f; alpha = 0; }
else if( (playerY - y) <= 32 ) { y += 1/16f; alpha = 0; }
else if( (playerY - y) <= 96 ) { y += 1/8f; alpha = 0; }
else { y += 1/4f; alpha = 0; }
static void CalcAlpha( float playerY, ref ShadowData data ) {
float y = data.Y;
if( (playerY - y) <= 6 ) {
data.A = (byte)(190 - 190 * (playerY - y) / 6);
data.Y += 1/64f; return;
}
data.A = 0;
if( (playerY - y) <= 16 ) data.Y += 1/64f;
else if( (playerY - y) <= 32 ) data.Y += 1/16f;
else if( (playerY - y) <= 96 ) data.Y += 1/8f;
else data.Y += 1/4f;
}
static bool lequal(float a, float b) {
return a < b || Math.Abs(a - b) < 0.001f;
}
internal static bool boundShadowTex = false;
internal static int shadowTex = -1;
static void CheckShadowTexture( IGraphicsApi graphics ) {

View File

@ -146,6 +146,7 @@ namespace ClassicalSharp {
game.Graphics.AlphaArgBlend = true;
game.Graphics.DepthWrite = false;
game.Graphics.AlphaBlending = true;
game.Graphics.Texturing = true;
Players[255].shadow.Draw();
if( ShadowMode == EntityShadow.CircleAll )
@ -153,6 +154,7 @@ namespace ClassicalSharp {
game.Graphics.AlphaArgBlend = false;
game.Graphics.DepthWrite = true;
game.Graphics.AlphaBlending = false;
game.Graphics.Texturing = false;
}
void DrawOtherShadows() {

View File

@ -15,18 +15,13 @@ namespace ClassicalSharp {
void UpdateVelocityState( float xMoving, float zMoving ) {
if( !Hacks.NoclipSlide && (noClip && xMoving == 0 && zMoving == 0) )
Velocity = Vector3.Zero;
if( flying || noClip ) {
Velocity.Y = 0; // eliminate the effect of gravity
if( flyingUp || jumping ) {
Velocity.Y = 0.12f;
if( speeding ) Velocity.Y += 0.12f;
if( halfSpeeding ) Velocity.Y += 0.06f;
} else if( flyingDown ) {
Velocity.Y -= 0.12f;
if( speeding ) Velocity.Y -= 0.12f;
if( halfSpeeding ) Velocity.Y -= 0.06f;
}
int dir = (flyingUp || jumping) ? 1 : (flyingDown ? -1 : 0);
Velocity.Y += 0.12f * dir;
if( speeding && Hacks.CanSpeed ) Velocity.Y += 0.12f * dir;
if( halfSpeeding && Hacks.CanSpeed ) Velocity.Y += 0.06f * dir;
} else if( jumping && TouchesAnyRope() && Velocity.Y > 0.02f ) {
Velocity.Y = 0.02f;
}
@ -63,11 +58,11 @@ namespace ClassicalSharp {
}
} else if( useLiquidGravity ) {
Velocity.Y += 0.04f;
if( speeding ) Velocity.Y += 0.04f;
if( halfSpeeding ) Velocity.Y += 0.02f;
if( speeding && Hacks.CanSpeed ) Velocity.Y += 0.04f;
if( halfSpeeding && Hacks.CanSpeed ) Velocity.Y += 0.02f;
canLiquidJump = false;
} else if( TouchesAnyRope() ) {
Velocity.Y += speeding ? 0.15f : 0.10f;
Velocity.Y += (speeding && Hacks.CanSpeed) ? 0.15f : 0.10f;
canLiquidJump = false;
} else if( onGround ) {
DoNormalJump();
@ -75,10 +70,9 @@ namespace ClassicalSharp {
}
void DoNormalJump() {
Velocity.Y = 0;
Velocity.Y += jumpVel;
if( speeding ) Velocity.Y += jumpVel;
if( halfSpeeding ) Velocity.Y += jumpVel / 2;
Velocity.Y = jumpVel;
if( speeding && Hacks.CanSpeed ) Velocity.Y += jumpVel;
if( halfSpeeding && Hacks.CanSpeed ) Velocity.Y += jumpVel / 2;
canLiquidJump = false;
}
@ -95,10 +89,11 @@ namespace ClassicalSharp {
void PhysicsTick( float xMoving, float zMoving ) {
if( noClip ) onGround = false;
float multiply = GetBaseMultiply();
float multiply = GetBaseMultiply( true );
float yMultiply = GetBaseMultiply( Hacks.CanSpeed );
float modifier = LowestSpeedModifier();
float yMul = Math.Max( 1f, multiply / 5 ) * modifier;
float yMul = Math.Max( 1f, yMultiply / 5 ) * modifier;
float horMul = multiply * modifier;
if( !(flying || noClip) ) {
if( secondJump ) { horMul *= 93f; yMul *= 10f; }
@ -171,18 +166,18 @@ namespace ClassicalSharp {
Velocity.Y -= gravity;
}
float GetBaseMultiply() {
float GetBaseMultiply( bool canSpeed ) {
float multiply = 0;
if( flying || noClip ) {
if( speeding ) multiply += Hacks.SpeedMultiplier * 8;
if( halfSpeeding ) multiply += Hacks.SpeedMultiplier * 8 / 2;
if( speeding && canSpeed ) multiply += Hacks.SpeedMultiplier * 8;
if( halfSpeeding && canSpeed ) multiply += Hacks.SpeedMultiplier * 8 / 2;
if( multiply == 0 ) multiply = 8f;
} else {
if( speeding ) multiply += Hacks.SpeedMultiplier;
if( halfSpeeding ) multiply += Hacks.SpeedMultiplier / 2;
if( speeding && canSpeed ) multiply += Hacks.SpeedMultiplier;
if( halfSpeeding && canSpeed ) multiply += Hacks.SpeedMultiplier / 2;
if( multiply == 0 ) multiply = 1;
}
return multiply;
return Hacks.CanSpeed ? multiply : Math.Min( multiply, Hacks.MaxSpeedMultiplier );
}
const float inf = float.PositiveInfinity;

View File

@ -152,8 +152,8 @@ namespace ClassicalSharp {
if( game.IsKeyDown( KeyBinding.Right ) ) zMoving += 0.98f;
jumping = game.IsKeyDown( KeyBinding.Jump );
speeding = Hacks.CanSpeed && Hacks.Enabled && game.IsKeyDown( KeyBinding.Speed );
halfSpeeding = Hacks.CanSpeed && Hacks.Enabled && game.IsKeyDown( KeyBinding.HalfSpeed );
speeding = Hacks.Enabled && game.IsKeyDown( KeyBinding.Speed );
halfSpeeding = Hacks.Enabled && game.IsKeyDown( KeyBinding.HalfSpeed );
flyingUp = game.IsKeyDown( KeyBinding.FlyUp );
flyingDown = game.IsKeyDown( KeyBinding.FlyDown );
}

View File

@ -153,23 +153,17 @@ namespace ClassicalSharp {
/// <summary> Calculates the amount that the hotbar widget should be scaled by when rendered. </summary>
/// <remarks> Affected by both the current resolution of the window, as well as the
/// scaling specified by the user (field HotbarScale). </remarks>
public float GuiHotbarScale {
get { return MinWindowScale * HotbarScale; }
}
public float GuiHotbarScale { get { return MinWindowScale * HotbarScale; } }
/// <summary> Calculates the amount that the block inventory menu should be scaled by when rendered. </summary>
/// <remarks> Affected by both the current resolution of the window, as well as the
/// scaling specified by the user (field InventoryScale). </remarks>
public float GuiInventoryScale {
get { return MinWindowScale * InventoryScale; }
}
public float GuiInventoryScale { get { return MinWindowScale * InventoryScale; } }
/// <summary> Calculates the amount that 2D chat widgets should be scaled by when rendered. </summary>
/// <remarks> Affected by both the current resolution of the window, as well as the
/// scaling specified by the user (field ChatScale). </remarks>
public float GuiChatScale {
get { return (Height / 480f) * ChatScale; }
}
public float GuiChatScale { get { return (Height / 480f) * ChatScale; } }
float MinWindowScale { get { return Math.Min( Width / 640f, Height / 480f ); } }

View File

@ -5,9 +5,7 @@ namespace ClassicalSharp.Generator {
public unsafe sealed class FlatGrassGenerator : IMapGenerator {
public override string GeneratorName {
get { return "Flatgrass generator"; }
}
public override string GeneratorName { get { return "Flatgrass"; } }
int width, length;
public override byte[] Generate( int width, int height, int length, int seed ) {

View File

@ -7,7 +7,6 @@ using System.Collections.Generic;
namespace ClassicalSharp.Generator {
// TODO: figure out how noise functions differ, probably based on rnd.
public sealed partial class NotchyGenerator : IMapGenerator {
int width, height, length;
@ -16,9 +15,7 @@ namespace ClassicalSharp.Generator {
short[] heightmap;
Random rnd;
public override string GeneratorName {
get { return "Vanilla classic generator"; }
}
public override string GeneratorName { get { return "Vanilla classic"; } }
public override byte[] Generate( int width, int height, int length, int seed ) {
this.width = width;

View File

@ -8,14 +8,10 @@ namespace ClassicalSharp {
public abstract class IMapFileFormat {
/// <summary> Whether a map can be exported to a file in this format. </summary>
public virtual bool SupportsLoading {
get { return false; }
}
public virtual bool SupportsLoading { get { return false; } }
/// <summary> Whether a map can be imported from a file in this format. </summary>
public virtual bool SupportsSaving {
get { return false; }
}
public virtual bool SupportsSaving { get { return false; } }
/// <summary> Replaces the current map from a stream that contains a map in this format. </summary>
public virtual byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {

View File

@ -7,9 +7,7 @@ namespace ClassicalSharp {
public sealed partial class MapCw : IMapFileFormat {
public override bool SupportsSaving {
get { return true; }
}
public override bool SupportsSaving { get { return true; } }
BinaryWriter writer;
public override void Save( Stream stream, Game game ) {

View File

@ -8,9 +8,7 @@ namespace ClassicalSharp {
public sealed partial class MapCw : IMapFileFormat {
public override bool SupportsLoading {
get { return true; }
}
public override bool SupportsLoading { get { return true; } }
BinaryReader reader;
Game game;

View File

@ -15,9 +15,7 @@ namespace ClassicalSharp {
const byte TC_STRING = 0x74, TC_ARRAY = 0x75;
const byte TC_ENDBLOCKDATA = 0x78;
public override bool SupportsLoading {
get { return true; }
}
public override bool SupportsLoading { get { return true; } }
BinaryReader reader;
public override byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {

View File

@ -12,9 +12,7 @@ namespace ClassicalSharp {
const uint Identifier = 0x0FC2AF40;
const byte Revision = 13;
public override bool SupportsLoading {
get { return true; }
}
public override bool SupportsLoading { get { return true; } }
public override byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {
BinaryReader reader = new BinaryReader( stream );

View File

@ -59,14 +59,10 @@ namespace ClassicalSharp {
public Block SidesBlock = Block.Bedrock;
/// <summary> Maximum height of the various parts of the map sides, in world space. </summary>
public int SidesHeight {
get { return EdgeHeight - 2; }
}
public int SidesHeight { get { return EdgeHeight - 2; } }
/// <summary> Whether this map is empty. </summary>
public bool IsNotLoaded {
get { return Width == 0 && Height == 0 && Length == 0; }
}
public bool IsNotLoaded { get { return Width == 0 && Height == 0 && Length == 0; } }
/// <summary> Current terrain.png or texture pack url of this map. </summary>
public string TextureUrl = null;

View File

@ -15,9 +15,7 @@ namespace ClassicalSharp {
SetupHandlers();
}
public override bool IsSinglePlayer {
get { return false; }
}
public override bool IsSinglePlayer { get { return false; } }
Socket socket;
bool receivedFirstPosition;

View File

@ -19,6 +19,9 @@ namespace ClassicalSharp.Network {
Dictionary<string, DownloadedItem> downloaded = new Dictionary<string, DownloadedItem>();
string skinServer = null;
internal Request CurrentItem;
internal int CurrentItemProgress = -3;
public AsyncDownloader( string skinServer ) {
this.skinServer = skinServer;
WebRequest.DefaultWebProxy = null;
@ -148,7 +151,12 @@ namespace ClassicalSharp.Network {
}
}
if( request != null ) {
CurrentItem = request;
CurrentItemProgress = -2;
ProcessRequest( request );
CurrentItem = null;
CurrentItemProgress = -3;
} else {
handle.WaitOne();
}
@ -241,19 +249,25 @@ namespace ClassicalSharp.Network {
static byte[] buffer = new byte[4096 * 8];
MemoryStream DownloadBytes( HttpWebResponse response ) {
int length = (int)response.ContentLength;
MemoryStream dst = length >= 0 ?
MemoryStream dst = length > 0 ?
new MemoryStream( length ) : new MemoryStream();
CurrentItemProgress = length > 0 ? 0 : -1;
using( Stream src = response.GetResponseStream() ) {
int read = 0;
while( (read = src.Read( buffer, 0, buffer.Length )) > 0 ) {
dst.Write( buffer, 0, read );
if( length <= 0 ) continue;
CurrentItemProgress = (int)(100 * (float)dst.Length / length);
}
}
return dst;
}
}
sealed class Request {
public enum RequestType { Bitmap, String, ByteArray, ContentLength }
internal sealed class Request {
public string Url;
public string Identifier;
@ -269,14 +283,6 @@ namespace ClassicalSharp.Network {
LastModified = lastModified;
}
}
}
public enum RequestType {
Bitmap,
String,
ByteArray,
ContentLength,
}
/// <summary> Represents an item that was asynchronously downloaded. </summary>
public class DownloadedItem {

View File

@ -21,9 +21,7 @@ namespace ClassicalSharp.Singleplayer {
ServerSupportsPartialMessages = true;
}
public override bool IsSinglePlayer {
get { return true; }
}
public override bool IsSinglePlayer { get { return true; } }
public override void Connect( IPAddress address, int port ) {
int max = game.UseCPE ? BlockInfo.MaxDefinedCpeBlock : BlockInfo.MaxDefinedOriginalBlock;

View File

@ -148,9 +148,7 @@ namespace ClassicalSharp {
return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY ) * tiltMatrix;
}
public override bool IsThirdPerson {
get { return true; }
}
public override bool IsThirdPerson { get { return true; } }
public override Vector3 GetCameraPos( Vector3 eyePos ) {
Vector3 dir = -Utils.GetDirVector( player.HeadYawRadians,
@ -184,9 +182,7 @@ namespace ClassicalSharp {
return Matrix4.LookAt( cameraPos, eyePos, Vector3.UnitY ) * tiltMatrix;
}
public override bool IsThirdPerson {
get { return true; }
}
public override bool IsThirdPerson { get { return true; } }
public override Vector3 GetCameraPos( Vector3 eyePos ) {
Vector3 dir = Utils.GetDirVector( player.HeadYawRadians,
@ -210,9 +206,7 @@ namespace ClassicalSharp {
return Matrix4.LookAt( eyePos, eyePos + cameraDir, Vector3.UnitY ) * tiltMatrix;
}
public override bool IsThirdPerson {
get { return false; }
}
public override bool IsThirdPerson { get { return false; } }
public override Vector3 GetCameraPos( Vector3 eyePos ) {
return eyePos;