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"; return tile < BlockInfo.CpeBlocksCount || game.BlockInfo.Name[tile] != "Invalid";
} }
public override bool HandlesAllInput { public override bool HandlesAllInput { get { return true; } }
get { return true; }
}
public override bool HandlesMouseMove( int mouseX, int mouseY ) { public override bool HandlesMouseMove( int mouseX, int mouseY ) {
if( draggingMouse ) { if( draggingMouse ) {

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using ClassicalSharp.Network;
using OpenTK.Input; using OpenTK.Input;
namespace ClassicalSharp { namespace ClassicalSharp {
@ -13,7 +14,7 @@ namespace ClassicalSharp {
} }
int chatLines; int chatLines;
ChatTextWidget announcement, clock; ChatTextWidget announcement;
TextInputWidget textInput; TextInputWidget textInput;
TextGroupWidget status, bottomRight, normalChat, clientStatus; TextGroupWidget status, bottomRight, normalChat, clientStatus;
bool suppressNextPress = true; bool suppressNextPress = true;
@ -49,9 +50,11 @@ namespace ClassicalSharp {
void ConstructWidgets() { void ConstructWidgets() {
textInput = new TextInputWidget( game, chatFont, chatBoldFont ); textInput = new TextInputWidget( game, chatFont, chatBoldFont );
textInput.YOffset = blockSize + 5; textInput.YOffset = blockSize + 5;
status = new TextGroupWidget( game, 4, chatFont, chatUnderlineFont, status = new TextGroupWidget( game, 5, chatFont, chatUnderlineFont,
Anchor.BottomOrRight, Anchor.LeftOrTop ); Anchor.BottomOrRight, Anchor.LeftOrTop );
status.Init(); status.Init();
status.SetUsePlaceHolder( 0, false );
status.SetUsePlaceHolder( 1, false );
bottomRight = new TextGroupWidget( game, 3, chatFont, chatUnderlineFont, bottomRight = new TextGroupWidget( game, 3, chatFont, chatUnderlineFont,
Anchor.BottomOrRight, Anchor.BottomOrRight ); Anchor.BottomOrRight, Anchor.BottomOrRight );
bottomRight.YOffset = blockSize * 3 / 2; bottomRight.YOffset = blockSize * 3 / 2;
@ -69,18 +72,16 @@ namespace ClassicalSharp {
announcement = ChatTextWidget.Create( game, 0, 0, null, announcement = ChatTextWidget.Create( game, 0, 0, null,
Anchor.Centre, Anchor.Centre, announcementFont ); Anchor.Centre, Anchor.Centre, announcementFont );
announcement.YOffset = -game.Height / 4; announcement.YOffset = -game.Height / 4;
clock = ChatTextWidget.Create( game, 0, 0, null,
Anchor.BottomOrRight, Anchor.LeftOrTop, chatItalicFont );
} }
void SetInitialMessages() { void SetInitialMessages() {
Chat chat = game.Chat; Chat chat = game.Chat;
chatIndex = chat.Log.Count - chatLines; chatIndex = chat.Log.Count - chatLines;
ResetChat(); ResetChat();
status.SetText( 0, chat.Status1.Text ); status.SetText( 2, chat.Status1.Text );
status.SetText( 1, chat.Status2.Text ); status.SetText( 3, chat.Status2.Text );
status.SetText( 2, chat.Status3.Text ); status.SetText( 4, chat.Status3.Text );
if( game.ShowClock ) clock.SetText( chat.ClientClock.Text ); if( game.ShowClock ) status.SetText( 0, chat.ClientClock.Text );
bottomRight.SetText( 2, chat.BottomRight1.Text ); bottomRight.SetText( 2, chat.BottomRight1.Text );
bottomRight.SetText( 1, chat.BottomRight2.Text ); bottomRight.SetText( 1, chat.BottomRight2.Text );
@ -100,18 +101,7 @@ namespace ClassicalSharp {
status.Render( delta ); status.Render( delta );
bottomRight.Render( delta ); bottomRight.Render( delta );
} }
CheckOtherStatuses();
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 );
}
UpdateChatYOffset( false ); UpdateChatYOffset( false );
RenderClientStatus(); RenderClientStatus();
@ -130,6 +120,42 @@ namespace ClassicalSharp {
announcement.Dispose(); 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 ) { void RenderRecentChat( DateTime now, double delta ) {
int[] metadata = (int[])Metadata; int[] metadata = (int[])Metadata;
for( int i = 0; i < normalChat.Textures.Length; i++ ) { for( int i = 0; i < normalChat.Textures.Length; i++ ) {
@ -156,7 +182,9 @@ namespace ClassicalSharp {
static FastColour backColour = new FastColour( 60, 60, 60, 180 ); static FastColour backColour = new FastColour( 60, 60, 60, 180 );
public void RenderBackground() { 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 y = normalChat.Y + normalChat.Height - height - 5;
int x = normalChat.X - 5; int x = normalChat.X - 5;
int width = Math.Max( clientStatus.Width, normalChat.Width ) + 10; int width = Math.Max( clientStatus.Width, normalChat.Width ) + 10;
@ -166,7 +194,7 @@ namespace ClassicalSharp {
graphicsApi.Draw2DQuad( x, y, width, boxHeight + 10, backColour ); graphicsApi.Draw2DQuad( x, y, width, boxHeight + 10, backColour );
} }
int inputOldHeight = -1, oldStatusOffset = -1; int inputOldHeight = -1;
void UpdateChatYOffset( bool force ) { void UpdateChatYOffset( bool force ) {
int height = textInput.RealHeight; int height = textInput.RealHeight;
if( force || height != inputOldHeight ) { if( force || height != inputOldHeight ) {
@ -200,7 +228,7 @@ namespace ClassicalSharp {
metadata[i] = metadata[i + 1]; metadata[i] = metadata[i + 1];
metadata[chatLines - 1] = chatIndex + chatLines - 1; metadata[chatLines - 1] = chatIndex + chatLines - 1;
} else if( type >= MessageType.Status1 && type <= MessageType.Status3 ) { } 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 ) { } else if( type >= MessageType.BottomRight1 && type <= MessageType.BottomRight3 ) {
bottomRight.SetText( 2 - (int)(type - MessageType.BottomRight1), e.Text ); bottomRight.SetText( 2 - (int)(type - MessageType.BottomRight1), e.Text );
} else if( type == MessageType.Announcement ) { } else if( type == MessageType.Announcement ) {
@ -209,7 +237,7 @@ namespace ClassicalSharp {
clientStatus.SetText( (int)(type - MessageType.ClientStatus1), e.Text ); clientStatus.SetText( (int)(type - MessageType.ClientStatus1), e.Text );
UpdateChatYOffset( true ); UpdateChatYOffset( true );
} else if( type == MessageType.ClientClock && game.ShowClock ) { } else if( type == MessageType.ClientClock && game.ShowClock ) {
clock.SetText( e.Text ); status.SetText( 0, e.Text );
} }
} }
@ -319,13 +347,13 @@ namespace ClassicalSharp {
textInput.SendTextInBufferAndReset(); textInput.SendTextInBufferAndReset();
chatIndex = game.Chat.Log.Count - chatLines; chatIndex = game.Chat.Log.Count - chatLines;
ResetIndex(); ScrollHistory();
} else if( key == Key.PageUp ) { } else if( key == Key.PageUp ) {
chatIndex -= chatLines; chatIndex -= chatLines;
ResetIndex(); ScrollHistory();
} else if( key == Key.PageDown ) { } else if( key == Key.PageDown ) {
chatIndex += chatLines; chatIndex += chatLines;
ResetIndex(); ScrollHistory();
} else { } else {
textInput.HandlesKeyDown( key ); textInput.HandlesKeyDown( key );
} }
@ -345,40 +373,43 @@ namespace ClassicalSharp {
public override bool HandlesMouseScroll( int delta ) { public override bool HandlesMouseScroll( int delta ) {
if( !HandlesAllInput ) return false; if( !HandlesAllInput ) return false;
chatIndex -= delta; chatIndex -= delta;
ResetIndex(); ScrollHistory();
return true; return true;
} }
public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) { public override bool HandlesMouseClick( int mouseX, int mouseY, MouseButton button ) {
if( !HandlesAllInput || game.HideGui ) return false; if( !HandlesAllInput || game.HideGui ) return false;
if( normalChat.Bounds.Contains( mouseX, mouseY ) ) { if( !normalChat.Bounds.Contains( mouseX, mouseY ) )
int height = normalChat.GetUsedHeight(); return textInput.HandlesMouseClick( mouseX, mouseY, button );
int y = normalChat.Y + normalChat.Height - height;
if( new Rectangle( normalChat.X, y, normalChat.Width, height ).Contains( mouseX, mouseY ) ) {
string text = normalChat.GetSelected( mouseX, mouseY );
if( text == null ) return false;
if( Utils.IsUrlPrefix( text ) ) { int height = normalChat.GetUsedHeight();
game.ShowWarning( new WarningScreen( int y = normalChat.Y + normalChat.Height - height;
game, text, false, "Are you sure you want to go to this url?", if( new Rectangle( normalChat.X, y, normalChat.Width, height ).Contains( mouseX, mouseY ) )
OpenUrl, AppendUrl, null, text, return HandlesChatClick( mouseX, mouseY );
"Be careful - urls from strangers may link to websites that", return false;
" may have viruses, or things you may not want to open/see." }
) );
} else if( game.ClickableChat ) { bool HandlesChatClick( int mouseX, int mouseY ) {
for( int i = 0; i < text.Length; i++ ) { string text = normalChat.GetSelected( mouseX, mouseY );
if( !IsValidInputChar( text[i] ) ) { if( text == null ) return false;
game.Chat.Add( "&eChatline contained characters that can't be sent on this server." );
return true; if( Utils.IsUrlPrefix( text ) ) {
} game.ShowWarning( new WarningScreen(
} game, text, false, "Are you sure you want to go to this url?",
textInput.AppendText( text ); OpenUrl, AppendUrl, null, text,
"Be careful - urls from strangers may link to websites that",
" may have viruses, or things you may not want to open/see."
) );
} else if( game.ClickableChat ) {
for( int i = 0; i < text.Length; i++ ) {
if( !IsValidInputChar( text[i] ) ) {
game.Chat.Add( "&eChatline contained characters that can't be sent on this server." );
return true;
} }
return true;
} }
return false; textInput.AppendText( text );
} }
return textInput.HandlesMouseClick( mouseX, mouseY, button ); return true;
} }
void OpenUrl( WarningScreen screen ) { void OpenUrl( WarningScreen screen ) {
@ -394,7 +425,7 @@ namespace ClassicalSharp {
textInput.AppendText( (string)screen.Metadata ); textInput.AppendText( (string)screen.Metadata );
} }
void ResetIndex() { void ScrollHistory() {
int maxIndex = game.Chat.Log.Count - chatLines; int maxIndex = game.Chat.Log.Count - chatLines;
int minIndex = Math.Min( 0, maxIndex ); int minIndex = Math.Min( 0, maxIndex );
Utils.Clamp( ref chatIndex, minIndex, maxIndex ); Utils.Clamp( ref chatIndex, minIndex, maxIndex );

View File

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

View File

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

View File

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

View File

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

View File

@ -19,7 +19,9 @@ namespace ClassicalSharp {
Textures[index] = tex; Textures[index] = tex;
lines[index] = text; lines[index] = text;
} else { } 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; lines[index] = null;
} }
UpdateDimensions(); UpdateDimensions();

View File

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

View File

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

View File

@ -44,7 +44,7 @@ namespace ClassicalSharp {
public bool CanRespawn = true; public bool CanRespawn = true;
/// <summary> Whether the player is allowed to pass through all blocks. </summary> /// <summary> Whether the player is allowed to pass through all blocks. </summary>
public bool CanNoclip = true; public bool CanNoclip = true;
/// <summary> Whether the player is allowed to use pushback block placing. </summary> /// <summary> Whether the player is allowed to use pushback block placing. </summary>
public bool CanPushbackBlocks = true; public bool CanPushbackBlocks = true;
@ -61,14 +61,17 @@ namespace ClassicalSharp {
/// <summary> Whether the player is allowed to double jump. </summary> /// <summary> Whether the player is allowed to double jump. </summary>
public bool CanDoubleJump = true; 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> /// <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 ) { public void ParseHackFlags( string name, string motd ) {
string joined = name + motd; string joined = name + motd;
SetAllHacks( true ); SetAllHacks( true );
MaxSpeedMultiplier = 1;
// By default (this is also the case with WoM), we can use hacks. // By default (this is also the case with WoM), we can use hacks.
if( joined.Contains( "-hax" ) ) if( joined.Contains( "-hax" ) ) SetAllHacks( false );
SetAllHacks( false );
ParseFlag( b => CanFly = b, joined, "fly" ); ParseFlag( b => CanFly = b, joined, "fly" );
ParseFlag( b => CanNoclip = b, joined, "noclip" ); ParseFlag( b => CanNoclip = b, joined, "noclip" );
@ -77,6 +80,21 @@ namespace ClassicalSharp {
if( UserType == 0x64 ) if( UserType == 0x64 )
ParseFlag( b => SetAllHacks( b ), joined, "ophax" ); 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 ) { void SetAllHacks( bool allowed ) {

View File

@ -23,37 +23,38 @@ namespace ClassicalSharp {
int index = 0, vb = 0; int index = 0, vb = 0;
VertexPos3fTex2fCol4b[] verts = null; VertexPos3fTex2fCol4b[] verts = null;
ShadowData data = new ShadowData(); int posCount = 0, dataCount = 0;
int coordsCount = 0;
Vector3I* coords = stackalloc Vector3I[4]; 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 ); coords[i] = new Vector3I( int.MinValue );
data[i] = new ShadowData();
}
if( mode == EntityShadow.SnapToBlock ) { if( mode == EntityShadow.SnapToBlock ) {
vb = game.Graphics.texVb; verts = game.Graphics.texVerts; 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 ); 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 { } else {
vb = game.ModelCache.vb; verts = game.ModelCache.vertices; vb = game.ModelCache.vb; verts = game.ModelCache.vertices;
float x1 = posX - 7/16f, x2 = Math.Min( posX + 7/16f, Utils.Floor( x1 ) + 1 ); float x = posX - 7/16f, z = posZ - 7/16f;
float z1 = posZ - 7/16f, z2 = Math.Min( posZ + 7/16f, Utils.Floor( z1 ) + 1 ); if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 ) DrawCircle( verts, ref index, data, dataCount, x, z );
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position );
x2 = posX + 7/16f; x1 = Math.Max( posX - 7/16f, Utils.Floor( x2 ) ); x = Math.Max( posX - 7/16f, Utils.Floor( posX + 7/16f ) );
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 ) if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position ); DrawCircle( verts, ref index, data, dataCount, x, z );
z2 = posZ + 7/16f; z1 = Math.Max( posZ - 7/16f, Utils.Floor( z2 ) ); z = Math.Max( posZ - 7/16f, Utils.Floor( posZ + 7/16f ) );
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 ) if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position ); DrawCircle( verts, ref index, data, dataCount, x, z );
x1 = posX - 7/16f; x2 = Math.Min( posX + 7/16f, Utils.Floor( x1 ) + 1 ); x = posX - 7/16f;
if( CalculateShadow( coords, ref coordsCount, x1, z1, posY, ref data ) && data.A > 0 ) if( GetBlocks( coords, ref posCount, x, z, posY, data, ref dataCount ) && data[0].A > 0 )
DrawCoords( verts, ref index, data, new Vector2( x1, z1 ), new Vector2( x2, z2 ), Position ); DrawCircle( verts, ref index, data, dataCount, x, z );
} }
if( index == 0 ) return; if( index == 0 ) return;
@ -66,47 +67,6 @@ namespace ClassicalSharp {
game.Graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, verts, index, index * 6 / 4 ); 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();
int blockX = Utils.Floor( x ), blockZ = Utils.Floor( z );
Vector3I p = new Vector3I( blockX, 0, blockZ );
BlockInfo info = game.BlockInfo;
Vector3 Position = entity.Position;
if( Position.Y < 0 ) return false;
for( int i = 0; i < 4; i++ )
if( coords[i] == p ) return false;
while( posY >= 0 ) {
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;
coords[coordsCount] = p; coordsCount++;
CalcAlpha( Position.Y, ref data.Y, ref data.A );
return true;
}
byte GetShadowBlock( int x, int y, int z ) {
if( x < 0 || z < 0 || x >= game.Map.Width || z >= game.Map.Length ) {
if (y == game.Map.EdgeHeight - 1)
return (byte)(game.BlockInfo.IsAir[(byte)game.Map.EdgeBlock] ? 0 : Block.Bedrock);
if (y == game.Map.SidesHeight - 1)
return (byte)(game.BlockInfo.IsAir[(byte)game.Map.SidesBlock] ? 0 : Block.Bedrock);
return (byte)Block.Air;
}
return game.Map.GetBlock( x, y, z );
}
void DraqSquareShadow( VertexPos3fTex2fCol4b[] verts, ref int index, float y, byte alpha, float x, float z ) { void DraqSquareShadow( VertexPos3fTex2fCol4b[] verts, ref int index, float y, byte alpha, float x, float z ) {
FastColour col = FastColour.White; col.A = alpha; FastColour col = FastColour.White; col.A = alpha;
TextureRec rec = new TextureRec( 63/128f, 63/128f, 1/128f, 1/128f ); TextureRec rec = new TextureRec( 63/128f, 63/128f, 1/128f, 1/128f );
@ -116,24 +76,95 @@ namespace ClassicalSharp {
verts[index++] = new VertexPos3fTex2fCol4b( x, y, z + 1, rec.U1, 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 ) { void DrawCircle( VertexPos3fTex2fCol4b[] verts, ref int index,
if( lequal( p2.X, p1.X ) || lequal( p2.Y, p1.Y ) ) return; ShadowData* data, int dataCount, float x, float z ) {
float u1 = (p1.X - centre.X) * 16/14f + 0.5f; x = Utils.Floor( x ); z = Utils.Floor( z );
float v1 = (p1.Y - centre.Z) * 16/14f + 0.5f; BlockInfo info = game.BlockInfo;
float u2 = (p2.X - centre.X) * 16/14f + 0.5f; Vector3 min = info.MinBB[data[0].Block], max = info.MaxBB[data[0].Block];
float v2 = (p2.Y - centre.Z) * 16/14f + 0.5f;
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; 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 ); x1 = Math.Max( x1, centre.X - 7/16f ); u1 = Math.Max( u1, 0 );
p1.Y = Math.Max( p1.Y, centre.Z - 14/16f ); v1 = Math.Max( v1, 0 ); z1 = Math.Max( z1, centre.Z - 7/16f ); v1 = Math.Max( v1, 0 );
p2.X = Math.Min( p2.X, centre.X + 14/16f ); u2 = Math.Min( u2, 1 ); x2 = Math.Min( x2, centre.X + 7/16f ); u2 = Math.Min( u2, 1 );
p2.Y = Math.Min( p2.Y, centre.Z + 14/16f ); v2 = Math.Min( v2, 1 ); z2 = Math.Min( z2, centre.Z + 7/16f ); v2 = Math.Min( v2, 1 );
FastColour col = FastColour.White; col.A = data.A; 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( x1, data.Y, z1, u1, v1, col );
verts[index++] = new VertexPos3fTex2fCol4b( p2.X, data.Y, p1.Y, u2, v1, col ); verts[index++] = new VertexPos3fTex2fCol4b( x2, data.Y, z1, u2, v1, col );
verts[index++] = new VertexPos3fTex2fCol4b( p2.X, data.Y, p2.Y, u2, v2, col ); verts[index++] = new VertexPos3fTex2fCol4b( x2, data.Y, z2, u2, v2, col );
verts[index++] = new VertexPos3fTex2fCol4b( p1.X, data.Y, p2.Y, u1, 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++ ) {
if( coords[i] == p ) return false;
data[i] = new ShadowData();
}
coords[posCount] = p; posCount++;
while( posY >= 0 && index < 4 ) {
byte block = GetShadowBlock( blockX, posY, blockZ );
posY--;
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;
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;
}
byte GetShadowBlock( int x, int y, int z ) {
if( x < 0 || z < 0 || x >= game.Map.Width || z >= game.Map.Length ) {
if( y == game.Map.EdgeHeight - 1 )
return (byte)(game.BlockInfo.IsAir[(byte)game.Map.EdgeBlock] ? 0 : Block.Bedrock);
if( y == game.Map.SidesHeight - 1 )
return (byte)(game.BlockInfo.IsAir[(byte)game.Map.SidesBlock] ? 0 : Block.Bedrock);
return (byte)Block.Air;
}
return game.Map.GetBlock( x, y, z );
} }
struct ShadowData { struct ShadowData {
@ -142,19 +173,24 @@ namespace ClassicalSharp {
public byte A; public byte A;
} }
static void CalcAlpha( float playerY, ref float y, ref byte alpha ) { static void CalcAlpha( float playerY, ref ShadowData data ) {
if( (playerY - y) <= 6 ) { y += 1/64f; alpha = (byte)(190 - 190 * (playerY - y) / 6); } float y = data.Y;
else if( (playerY - y) <= 16 ) { y += 1/64f; alpha = 0; } if( (playerY - y) <= 6 ) {
else if( (playerY - y) <= 32 ) { y += 1/16f; alpha = 0; } data.A = (byte)(190 - 190 * (playerY - y) / 6);
else if( (playerY - y) <= 96 ) { y += 1/8f; alpha = 0; } data.Y += 1/64f; return;
else { y += 1/4f; alpha = 0; } }
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) { static bool lequal(float a, float b) {
return a < b || Math.Abs(a - b) < 0.001f; return a < b || Math.Abs(a - b) < 0.001f;
} }
internal static bool boundShadowTex = false; internal static bool boundShadowTex = false;
internal static int shadowTex = -1; internal static int shadowTex = -1;
static void CheckShadowTexture( IGraphicsApi graphics ) { static void CheckShadowTexture( IGraphicsApi graphics ) {

View File

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

View File

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

View File

@ -152,8 +152,8 @@ namespace ClassicalSharp {
if( game.IsKeyDown( KeyBinding.Right ) ) zMoving += 0.98f; if( game.IsKeyDown( KeyBinding.Right ) ) zMoving += 0.98f;
jumping = game.IsKeyDown( KeyBinding.Jump ); jumping = game.IsKeyDown( KeyBinding.Jump );
speeding = Hacks.CanSpeed && Hacks.Enabled && game.IsKeyDown( KeyBinding.Speed ); speeding = Hacks.Enabled && game.IsKeyDown( KeyBinding.Speed );
halfSpeeding = Hacks.CanSpeed && Hacks.Enabled && game.IsKeyDown( KeyBinding.HalfSpeed ); halfSpeeding = Hacks.Enabled && game.IsKeyDown( KeyBinding.HalfSpeed );
flyingUp = game.IsKeyDown( KeyBinding.FlyUp ); flyingUp = game.IsKeyDown( KeyBinding.FlyUp );
flyingDown = game.IsKeyDown( KeyBinding.FlyDown ); 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> /// <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 /// <remarks> Affected by both the current resolution of the window, as well as the
/// scaling specified by the user (field HotbarScale). </remarks> /// scaling specified by the user (field HotbarScale). </remarks>
public float GuiHotbarScale { public float GuiHotbarScale { get { return MinWindowScale * HotbarScale; } }
get { return MinWindowScale * HotbarScale; }
}
/// <summary> Calculates the amount that the block inventory menu should be scaled by when rendered. </summary> /// <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 /// <remarks> Affected by both the current resolution of the window, as well as the
/// scaling specified by the user (field InventoryScale). </remarks> /// scaling specified by the user (field InventoryScale). </remarks>
public float GuiInventoryScale { public float GuiInventoryScale { get { return MinWindowScale * InventoryScale; } }
get { return MinWindowScale * InventoryScale; }
}
/// <summary> Calculates the amount that 2D chat widgets should be scaled by when rendered. </summary> /// <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 /// <remarks> Affected by both the current resolution of the window, as well as the
/// scaling specified by the user (field ChatScale). </remarks> /// scaling specified by the user (field ChatScale). </remarks>
public float GuiChatScale { public float GuiChatScale { get { return (Height / 480f) * ChatScale; } }
get { return (Height / 480f) * ChatScale; }
}
float MinWindowScale { get { return Math.Min( Width / 640f, Height / 480f ); } } 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 unsafe sealed class FlatGrassGenerator : IMapGenerator {
public override string GeneratorName { public override string GeneratorName { get { return "Flatgrass"; } }
get { return "Flatgrass generator"; }
}
int width, length; int width, length;
public override byte[] Generate( int width, int height, int length, int seed ) { 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 { namespace ClassicalSharp.Generator {
// TODO: figure out how noise functions differ, probably based on rnd.
public sealed partial class NotchyGenerator : IMapGenerator { public sealed partial class NotchyGenerator : IMapGenerator {
int width, height, length; int width, height, length;
@ -16,9 +15,7 @@ namespace ClassicalSharp.Generator {
short[] heightmap; short[] heightmap;
Random rnd; Random rnd;
public override string GeneratorName { public override string GeneratorName { get { return "Vanilla classic"; } }
get { return "Vanilla classic generator"; }
}
public override byte[] Generate( int width, int height, int length, int seed ) { public override byte[] Generate( int width, int height, int length, int seed ) {
this.width = width; this.width = width;

View File

@ -8,14 +8,10 @@ namespace ClassicalSharp {
public abstract class IMapFileFormat { public abstract class IMapFileFormat {
/// <summary> Whether a map can be exported to a file in this format. </summary> /// <summary> Whether a map can be exported to a file in this format. </summary>
public virtual bool SupportsLoading { public virtual bool SupportsLoading { get { return false; } }
get { return false; }
}
/// <summary> Whether a map can be imported from a file in this format. </summary> /// <summary> Whether a map can be imported from a file in this format. </summary>
public virtual bool SupportsSaving { public virtual bool SupportsSaving { get { return false; } }
get { return false; }
}
/// <summary> Replaces the current map from a stream that contains a map in this format. </summary> /// <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 ) { 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 sealed partial class MapCw : IMapFileFormat {
public override bool SupportsSaving { public override bool SupportsSaving { get { return true; } }
get { return true; }
}
BinaryWriter writer; BinaryWriter writer;
public override void Save( Stream stream, Game game ) { public override void Save( Stream stream, Game game ) {

View File

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

View File

@ -15,9 +15,7 @@ namespace ClassicalSharp {
const byte TC_STRING = 0x74, TC_ARRAY = 0x75; const byte TC_STRING = 0x74, TC_ARRAY = 0x75;
const byte TC_ENDBLOCKDATA = 0x78; const byte TC_ENDBLOCKDATA = 0x78;
public override bool SupportsLoading { public override bool SupportsLoading { get { return true; } }
get { return true; }
}
BinaryReader reader; BinaryReader reader;
public override byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) { 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 uint Identifier = 0x0FC2AF40;
const byte Revision = 13; const byte Revision = 13;
public override bool SupportsLoading { public override bool SupportsLoading { get { return true; } }
get { return true; }
}
public override byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) { public override byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {
BinaryReader reader = new BinaryReader( stream ); BinaryReader reader = new BinaryReader( stream );

View File

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

View File

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

View File

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

View File

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

View File

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