mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 03:25:14 -04:00
Merge branch 'master' of github.com:UnknownShadow200/ClassicalSharp
This commit is contained in:
commit
7271985f13
@ -246,7 +246,7 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
public override void Dispose() {
|
||||
if( HandlesAllInput ) {
|
||||
game.chatInInputBuffer = textInput.chatInputText.ToString();
|
||||
game.chatInInputBuffer = textInput.buffer.ToString();
|
||||
game.CursorVisible = false;
|
||||
} else {
|
||||
game.chatInInputBuffer = null;
|
||||
@ -321,8 +321,8 @@ namespace ClassicalSharp.Gui {
|
||||
HandlesAllInput = true;
|
||||
game.Keyboard.KeyRepeat = true;
|
||||
|
||||
textInput.chatInputText.Clear();
|
||||
textInput.chatInputText.Append( 0, initialText );
|
||||
textInput.buffer.Clear();
|
||||
textInput.buffer.Append( 0, initialText );
|
||||
textInput.Init();
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ namespace ClassicalSharp.Gui {
|
||||
string connectString = "Connecting to " + game.IPAddress + ":" + game.Port + "..";
|
||||
foreach( IGameComponent comp in game.Components )
|
||||
comp.Reset( game );
|
||||
game.BlockInfo.Reset( game );
|
||||
|
||||
game.SetNewScreen( new LoadingMapScreen( game, connectString, "Waiting for handshake" ) );
|
||||
game.Network.Connect( game.IPAddress, game.Port );
|
||||
|
@ -22,18 +22,18 @@ namespace ClassicalSharp.Gui {
|
||||
textFont = new Font( game.FontName, 16, FontStyle.Bold );
|
||||
arrowFont = new Font( game.FontName, 18, FontStyle.Bold );
|
||||
titleFont = new Font( game.FontName, 16, FontStyle.Bold );
|
||||
title = ChatTextWidget.Create( game, 0, -130, titleText,
|
||||
title = ChatTextWidget.Create( game, 0, -155, titleText,
|
||||
Anchor.Centre, Anchor.Centre, titleFont );
|
||||
|
||||
buttons = new ButtonWidget[] {
|
||||
MakeText( 0, -80, Get( 0 ) ),
|
||||
MakeText( 0, -40, Get( 1 ) ),
|
||||
MakeText( 0, -100, Get( 0 ) ),
|
||||
MakeText( 0, -50, Get( 1 ) ),
|
||||
MakeText( 0, 0, Get( 2 ) ),
|
||||
MakeText( 0, 40, Get( 3 ) ),
|
||||
MakeText( 0, 80, Get( 4 ) ),
|
||||
MakeText( 0, 50, Get( 3 ) ),
|
||||
MakeText( 0, 100, Get( 4 ) ),
|
||||
|
||||
Make( -160, 0, "<", (g, w) => PageClick( false ) ),
|
||||
Make( 160, 0, ">", (g, w) => PageClick( true ) ),
|
||||
Make( -220, 0, "<", (g, w) => PageClick( false ) ),
|
||||
Make( 220, 0, ">", (g, w) => PageClick( true ) ),
|
||||
null,
|
||||
};
|
||||
}
|
||||
@ -52,12 +52,12 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
ButtonWidget MakeText( int x, int y, string text ) {
|
||||
return ButtonWidget.Create( game, x, y, 240, 30, text,
|
||||
return ButtonWidget.Create( game, x, y, 301, 40, text,
|
||||
Anchor.Centre, Anchor.Centre, textFont, TextButtonClick );
|
||||
}
|
||||
|
||||
ButtonWidget Make( int x, int y, string text, Action<Game, Widget> onClick ) {
|
||||
return ButtonWidget.Create( game, x, y, 40, 40, text,
|
||||
return ButtonWidget.Create( game, x, y, 41, 40, text,
|
||||
Anchor.Centre, Anchor.Centre, arrowFont, LeftOnly( onClick ) );
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ using ClassicalSharp.GraphicsAPI;
|
||||
|
||||
namespace ClassicalSharp.Gui {
|
||||
|
||||
public class FpsScreen : Screen {
|
||||
public class FpsScreen : Screen, IGameComponent {
|
||||
|
||||
Font font, posFont;
|
||||
StringBuffer text;
|
||||
@ -15,6 +15,12 @@ namespace ClassicalSharp.Gui {
|
||||
text = new StringBuffer( 128 );
|
||||
}
|
||||
|
||||
public void Init( Game game ) { }
|
||||
public void Ready( Game game) { Init(); }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
||||
TextWidget fpsText, hackStates;
|
||||
Texture posTex;
|
||||
public override void Render( double delta ) {
|
||||
@ -158,7 +164,9 @@ namespace ClassicalSharp.Gui {
|
||||
if( game.Fov != game.DefaultFov ) text.Append( ref index, "Zoom fov " )
|
||||
.AppendNum( ref index, lastFov ).Append( ref index, " " );
|
||||
if( fly ) text.Append( ref index, "Fly ON " );
|
||||
if( speeding || halfSpeeding ) text.Append( ref index, "Speed ON " );
|
||||
|
||||
bool showSpeedMsg = (speeding || halfSpeeding) && hacks.MaxSpeedMultiplier > 1;
|
||||
if( showSpeedMsg ) text.Append( ref index, "Speed ON " );
|
||||
if( noclip ) text.Append( ref index, "Noclip ON " );
|
||||
hackStates.SetText( text.GetString() );
|
||||
}
|
||||
@ -166,7 +174,7 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
const string possibleChars = "0123456789-, ()";
|
||||
int[] widths = new int[possibleChars.Length];
|
||||
int baseWidth, curX, posHeight;
|
||||
int baseWidth, curX;
|
||||
float texWidth;
|
||||
void MakePosTextWidget() {
|
||||
DrawTextArgs args = new DrawTextArgs( "", posFont, true );
|
||||
|
@ -15,7 +15,8 @@ namespace ClassicalSharp.Gui {
|
||||
PlayerListWidget playerList;
|
||||
Font playerFont;
|
||||
|
||||
public void Init( Game game ) { Init(); }
|
||||
public void Init( Game game ) { }
|
||||
public void Ready( Game game) { Init(); }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
@ -35,7 +36,7 @@ namespace ClassicalSharp.Gui {
|
||||
//graphicsApi.BindTexture( game.TerrainAtlas.TexId );
|
||||
//IsometricBlockDrawer.Draw( game, (byte)Block.Brick, 30, game.Width - 50, game.Height - 20 );
|
||||
|
||||
if( playerList != null ) {
|
||||
if( playerList != null && game.ActiveScreen == this ) {
|
||||
playerList.Render( delta );
|
||||
// NOTE: Should usually be caught by KeyUp, but just in case.
|
||||
if( !game.IsKeyDown( KeyBinding.PlayerList ) ) {
|
||||
@ -76,8 +77,6 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
public void LoseFocus() {
|
||||
if( playerList != null )
|
||||
playerList.Dispose();
|
||||
game.CursorVisible = true;
|
||||
}
|
||||
|
||||
|
@ -132,20 +132,12 @@ namespace ClassicalSharp.Gui {
|
||||
RecreateBlockInfoTexture();
|
||||
}
|
||||
|
||||
static string[] normalNames = null;
|
||||
void UpdateBlockInfoString( Block block ) {
|
||||
if( normalNames == null )
|
||||
MakeNormalNames();
|
||||
|
||||
int index = 0;
|
||||
buffer.Clear();
|
||||
buffer.Append( ref index, "&f" );
|
||||
string value = game.BlockInfo.Name[(byte)block];
|
||||
if( (byte)block < BlockInfo.CpeBlocksCount && value == "Invalid" ) {
|
||||
buffer.Append( ref index, normalNames[(byte)block] );
|
||||
} else {
|
||||
string value = game.BlockInfo.GetBlockName( (byte)block );
|
||||
buffer.Append( ref index, value );
|
||||
}
|
||||
if( game.ClassicMode ) return;
|
||||
|
||||
buffer.Append( ref index, " (ID: " );
|
||||
@ -157,32 +149,6 @@ namespace ClassicalSharp.Gui {
|
||||
buffer.Append( ref index, "&f)" );
|
||||
}
|
||||
|
||||
void MakeNormalNames() {
|
||||
normalNames = new string[BlockInfo.CpeBlocksCount];
|
||||
for( int i = 0; i < normalNames.Length; i++ ) {
|
||||
string origName = Enum.GetName( typeof(Block), (byte)i );
|
||||
buffer.Clear();
|
||||
int index = 0;
|
||||
SplitUppercase( origName, ref index );
|
||||
normalNames[i] = buffer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
void SplitUppercase( string value, ref int index ) {
|
||||
for( int i = 0; i < value.Length; i++ ) {
|
||||
char c = value[i];
|
||||
bool upper = Char.IsUpper( c ) && i > 0;
|
||||
bool nextLower = i < value.Length - 1 && !Char.IsUpper( value[i + 1] );
|
||||
|
||||
if( upper && nextLower ) {
|
||||
buffer.Append( ref index, ' ' );
|
||||
buffer.Append( ref index, Char.ToLower( c ) );
|
||||
} else {
|
||||
buffer.Append( ref index, c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int lastCreatedIndex = -1000;
|
||||
void RecreateBlockInfoTexture() {
|
||||
if( selIndex == lastCreatedIndex ) return;
|
||||
|
@ -14,29 +14,31 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
MenuInputWidget inputWidget;
|
||||
TextWidget descWidget;
|
||||
const int overwriteIndex = 2;
|
||||
FastColour grey = new FastColour( 150, 150, 150 );
|
||||
|
||||
public override void Render( double delta ) {
|
||||
RenderMenuBounds();
|
||||
api.Texturing = true;
|
||||
RenderMenuWidgets( delta );
|
||||
inputWidget.Render( delta );
|
||||
if( descWidget != null )
|
||||
descWidget.Render( delta );
|
||||
if( descWidget != null ) descWidget.Render( delta );
|
||||
api.Texturing = false;
|
||||
|
||||
if( textPath != null ) {
|
||||
float cX = game.Width / 2, cY = game.Height / 2;
|
||||
api.Draw2DQuad( cX - 250, cY + 90, 500, 2, grey );
|
||||
if( textPath == null ) return;
|
||||
SaveMap( textPath );
|
||||
textPath = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HandlesKeyPress( char key ) {
|
||||
RemoveOverwriteButton();
|
||||
RemoveOverwrites();
|
||||
return inputWidget.HandlesKeyPress( key );
|
||||
}
|
||||
|
||||
public override bool HandlesKeyDown( Key key ) {
|
||||
RemoveOverwriteButton();
|
||||
RemoveOverwrites();
|
||||
if( key == Key.Escape ) {
|
||||
game.SetNewScreen( null );
|
||||
return true;
|
||||
@ -54,12 +56,16 @@ namespace ClassicalSharp.Gui {
|
||||
regularFont = new Font( game.FontName, 16, FontStyle.Regular );
|
||||
|
||||
inputWidget = MenuInputWidget.Create(
|
||||
game, -30, 50, 500, 30, "", Anchor.Centre, Anchor.Centre,
|
||||
game, 0, -30, 500, 30, "", Anchor.Centre, Anchor.Centre,
|
||||
regularFont, titleFont, new PathValidator() );
|
||||
|
||||
widgets = new [] {
|
||||
ButtonWidget.Create( game, 260, 50, 60, 30, "Save", Anchor.Centre,
|
||||
Anchor.Centre, titleFont, OkButtonClick ),
|
||||
widgets = new Widget[] {
|
||||
ButtonWidget.Create( game, 0, 20, 301, 40, "Save", Anchor.Centre,
|
||||
Anchor.Centre, titleFont, SaveClassic ),
|
||||
ButtonWidget.Create( game, -150, 120, 201, 40, "Save schematic", Anchor.Centre,
|
||||
Anchor.Centre, titleFont, SaveSchematic ),
|
||||
ChatTextWidget.Create( game, 110, 120, "&eCan be imported into MCedit", Anchor.Centre,
|
||||
Anchor.Centre, regularFont ),
|
||||
null,
|
||||
MakeBack( false, titleFont,
|
||||
(g, w) => g.SetNewScreen( new PauseScreen( g ) ) ),
|
||||
@ -79,54 +85,58 @@ namespace ClassicalSharp.Gui {
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
void OkButtonClick( Game game, Widget widget, MouseButton mouseBtn ) {
|
||||
void SaveClassic( Game game, Widget widget, MouseButton mouseBtn ) {
|
||||
DoSave( widget, mouseBtn, ".cw" );
|
||||
}
|
||||
|
||||
void SaveSchematic( Game game, Widget widget, MouseButton mouseBtn ) {
|
||||
DoSave( widget, mouseBtn, ".schematic" );
|
||||
}
|
||||
|
||||
void DoSave( Widget widget, MouseButton mouseBtn, string ext ) {
|
||||
if( mouseBtn != MouseButton.Left ) return;
|
||||
|
||||
string text = inputWidget.GetText();
|
||||
if( text.Length == 0 ) {
|
||||
MakeDescWidget( "Please enter a filename" );
|
||||
return;
|
||||
MakeDescWidget( "&ePlease enter a filename" ); return;
|
||||
}
|
||||
string file = Path.ChangeExtension( text, ".cw" );
|
||||
string file = Path.ChangeExtension( text, ext );
|
||||
text = Path.Combine( Program.AppDirectory, "maps" );
|
||||
text = Path.Combine( text, file );
|
||||
|
||||
if( File.Exists( text ) ) {
|
||||
widgets[1] = ButtonWidget.Create( game, 0, 90, 260, 30, "Overwrite existing?",
|
||||
Anchor.Centre, Anchor.Centre, titleFont, OverwriteButtonClick );
|
||||
if( File.Exists( text ) && widget.Metadata == null ) {
|
||||
((ButtonWidget)widget).SetText( "&cOverwrite existing?" );
|
||||
((ButtonWidget)widget).Metadata = true;
|
||||
} else {
|
||||
// NOTE: We don't immediately save here, because otherwise the 'saving...'
|
||||
// will not be rendered in time because saving is done on the main thread.
|
||||
MakeDescWidget( "Saving.." );
|
||||
textPath = text;
|
||||
RemoveOverwriteButton();
|
||||
RemoveOverwrites();
|
||||
}
|
||||
}
|
||||
|
||||
void OverwriteButtonClick( Game game, Widget widget, MouseButton mouseBtn ) {
|
||||
if( mouseBtn != MouseButton.Left ) return;
|
||||
string text = inputWidget.GetText();
|
||||
string file = Path.ChangeExtension( text, ".cw" );
|
||||
text = Path.Combine( Program.AppDirectory, "maps" );
|
||||
text = Path.Combine( text, file );
|
||||
|
||||
MakeDescWidget( "Saving.." );
|
||||
textPath = text;
|
||||
RemoveOverwriteButton();
|
||||
void RemoveOverwrites() {
|
||||
RemoveOverwrite( widgets[0] ); RemoveOverwrite( widgets[1] );
|
||||
}
|
||||
|
||||
void RemoveOverwriteButton() {
|
||||
if( widgets[1] == null ) return;
|
||||
widgets[1].Dispose();
|
||||
widgets[1] = null;
|
||||
void RemoveOverwrite( Widget widget ) {
|
||||
ButtonWidget button = (ButtonWidget)widget;
|
||||
if( button.Metadata == null ) return;
|
||||
button.Metadata = null;
|
||||
button.SetText( "Save" );
|
||||
}
|
||||
|
||||
string textPath;
|
||||
void SaveMap( string path ) {
|
||||
bool classic = path.EndsWith( ".cw" );
|
||||
try {
|
||||
if( File.Exists( path ) )
|
||||
File.Delete( path );
|
||||
using( FileStream fs = new FileStream( path, FileMode.CreateNew, FileAccess.Write ) ) {
|
||||
IMapFormatExporter exporter = new MapCwExporter();
|
||||
IMapFormatExporter exporter = null;
|
||||
if( classic ) exporter = new MapCwExporter();
|
||||
else exporter = new MapSchematicExporter();
|
||||
exporter.Save( fs, game );
|
||||
}
|
||||
} catch( Exception ex ) {
|
||||
@ -140,7 +150,7 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
void MakeDescWidget( string text ) {
|
||||
DisposeDescWidget();
|
||||
descWidget = ChatTextWidget.Create( game, 0, 90, text,
|
||||
descWidget = ChatTextWidget.Create( game, 0, 65, text,
|
||||
Anchor.Centre, Anchor.Centre, regularFont );
|
||||
}
|
||||
|
||||
|
@ -90,15 +90,11 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
public int GetUsedHeight() {
|
||||
int sum = 0, max = Textures.Length;
|
||||
int sum = 0;
|
||||
for( int i = 0; i < Textures.Length; i++ ) {
|
||||
if( Textures[i].IsValid ) {
|
||||
max = i; break;
|
||||
}
|
||||
}
|
||||
|
||||
for( int i = max; i < Textures.Length; i++ )
|
||||
if( !Textures[i].IsValid ) continue;
|
||||
sum += Textures[i].Height;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
@ -44,9 +44,9 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
void TabKey() {
|
||||
int pos = caretPos == -1 ? chatInputText.Length - 1 : caretPos;
|
||||
int pos = caretPos == -1 ? buffer.Length - 1 : caretPos;
|
||||
int start = pos;
|
||||
char[] value = chatInputText.value;
|
||||
char[] value = buffer.value;
|
||||
|
||||
while( start >= 0 && IsNameChar( value[start] ) )
|
||||
start--;
|
||||
@ -74,22 +74,22 @@ namespace ClassicalSharp.Gui {
|
||||
if( caretPos == -1 ) pos++;
|
||||
int len = pos - start;
|
||||
for( int i = 0; i < len; i++ )
|
||||
chatInputText.DeleteAt( start );
|
||||
buffer.DeleteAt( start );
|
||||
if( caretPos != -1 ) caretPos -= len;
|
||||
AppendText( matches[0] );
|
||||
} else if( matches.Count > 1 ) {
|
||||
StringBuffer buffer = new StringBuffer( 64 );
|
||||
StringBuffer sb = new StringBuffer( 64 );
|
||||
int index = 0;
|
||||
buffer.Append( ref index, "&e" );
|
||||
buffer.AppendNum( ref index, matches.Count );
|
||||
buffer.Append( ref index, " matching names: " );
|
||||
sb.Append( ref index, "&e" );
|
||||
sb.AppendNum( ref index, matches.Count );
|
||||
sb.Append( ref index, " matching names: " );
|
||||
|
||||
foreach( string match in matches ) {
|
||||
if( (match.Length + 1 + buffer.Length) > LineLength ) break;
|
||||
buffer.Append( ref index, match );
|
||||
buffer.Append( ref index, ' ' );
|
||||
if( (match.Length + 1 + sb.Length) > LineLength ) break;
|
||||
sb.Append( ref index, match );
|
||||
sb.Append( ref index, ' ' );
|
||||
}
|
||||
game.Chat.Add( buffer.ToString(), MessageType.ClientStatus5 );
|
||||
game.Chat.Add( sb.ToString(), MessageType.ClientStatus5 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,36 +101,49 @@ namespace ClassicalSharp.Gui {
|
||||
void BackspaceKey( bool controlDown ) {
|
||||
if( controlDown ) {
|
||||
if( caretPos == -1 )
|
||||
caretPos = chatInputText.Length - 1;
|
||||
int len = chatInputText.GetBackLength( caretPos );
|
||||
caretPos = buffer.Length - 1;
|
||||
int len = buffer.GetBackLength( caretPos );
|
||||
caretPos -= len;
|
||||
|
||||
if( caretPos < 0 ) caretPos = 0;
|
||||
if( caretPos != 0 ) caretPos++; // Don't remove space.
|
||||
for( int i = 0; i <= len; i++ )
|
||||
chatInputText.DeleteAt( caretPos );
|
||||
buffer.DeleteAt( caretPos );
|
||||
|
||||
Dispose();
|
||||
Init();
|
||||
return;
|
||||
} else if( !buffer.Empty && caretPos != 0 ) {
|
||||
DeleteChar();
|
||||
BackspaceColourCode();
|
||||
Dispose();
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
if( !chatInputText.Empty && caretPos != 0 ) {
|
||||
void BackspaceColourCode() {
|
||||
// If text is XYZ%eH, backspaces to XYZ.
|
||||
int index = caretPos == -1 ? buffer.Length - 1 : caretPos;
|
||||
if( index <= 0 ) return;
|
||||
|
||||
if( index == 0 || buffer.value[index - 1] != '%'
|
||||
|| !game.Drawer2D.ValidColour( buffer.value[index] ) )
|
||||
return;
|
||||
DeleteChar(); DeleteChar();
|
||||
}
|
||||
|
||||
void DeleteChar() {
|
||||
if( caretPos == -1 ) {
|
||||
chatInputText.DeleteAt( chatInputText.Length - 1 );
|
||||
buffer.DeleteAt( buffer.Length - 1 );
|
||||
} else {
|
||||
caretPos--;
|
||||
chatInputText.DeleteAt( caretPos );
|
||||
}
|
||||
Dispose();
|
||||
Init();
|
||||
buffer.DeleteAt( caretPos );
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteKey() {
|
||||
if( !chatInputText.Empty && caretPos != -1 ) {
|
||||
chatInputText.DeleteAt( caretPos );
|
||||
if( caretPos >= chatInputText.Length ) caretPos = -1;
|
||||
if( !buffer.Empty && caretPos != -1 ) {
|
||||
buffer.DeleteAt( caretPos );
|
||||
if( caretPos >= buffer.Length ) caretPos = -1;
|
||||
Dispose();
|
||||
Init();
|
||||
}
|
||||
@ -139,14 +152,14 @@ namespace ClassicalSharp.Gui {
|
||||
void LeftKey( bool controlDown ) {
|
||||
if( controlDown ) {
|
||||
if( caretPos == -1 )
|
||||
caretPos = chatInputText.Length - 1;
|
||||
caretPos -= chatInputText.GetBackLength( caretPos );
|
||||
caretPos = buffer.Length - 1;
|
||||
caretPos -= buffer.GetBackLength( caretPos );
|
||||
CalculateCaretData();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !chatInputText.Empty ) {
|
||||
if( caretPos == -1 ) caretPos = chatInputText.Length;
|
||||
if( !buffer.Empty ) {
|
||||
if( caretPos == -1 ) caretPos = buffer.Length;
|
||||
caretPos--;
|
||||
if( caretPos < 0 ) caretPos = 0;
|
||||
CalculateCaretData();
|
||||
@ -155,15 +168,15 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
void RightKey( bool controlDown ) {
|
||||
if( controlDown ) {
|
||||
caretPos += chatInputText.GetForwardLength( caretPos );
|
||||
if( caretPos >= chatInputText.Length ) caretPos = -1;
|
||||
caretPos += buffer.GetForwardLength( caretPos );
|
||||
if( caretPos >= buffer.Length ) caretPos = -1;
|
||||
CalculateCaretData();
|
||||
return;
|
||||
}
|
||||
|
||||
if( !chatInputText.Empty && caretPos != -1 ) {
|
||||
if( !buffer.Empty && caretPos != -1 ) {
|
||||
caretPos++;
|
||||
if( caretPos >= chatInputText.Length ) caretPos = -1;
|
||||
if( caretPos >= buffer.Length ) caretPos = -1;
|
||||
CalculateCaretData();
|
||||
}
|
||||
}
|
||||
@ -171,7 +184,7 @@ namespace ClassicalSharp.Gui {
|
||||
string originalText;
|
||||
void UpKey( bool controlDown ) {
|
||||
if( controlDown ) {
|
||||
int pos = caretPos == -1 ? chatInputText.Length : caretPos;
|
||||
int pos = caretPos == -1 ? buffer.Length : caretPos;
|
||||
if( pos < LineLength ) return;
|
||||
|
||||
caretPos = pos - LineLength;
|
||||
@ -180,12 +193,12 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
if( typingLogPos == game.Chat.InputLog.Count )
|
||||
originalText = chatInputText.ToString();
|
||||
originalText = buffer.ToString();
|
||||
if( game.Chat.InputLog.Count > 0 ) {
|
||||
typingLogPos--;
|
||||
if( typingLogPos < 0 ) typingLogPos = 0;
|
||||
chatInputText.Clear();
|
||||
chatInputText.Append( 0, game.Chat.InputLog[typingLogPos] );
|
||||
buffer.Clear();
|
||||
buffer.Append( 0, game.Chat.InputLog[typingLogPos] );
|
||||
caretPos = -1;
|
||||
Dispose();
|
||||
Init();
|
||||
@ -202,13 +215,13 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
if( game.Chat.InputLog.Count > 0 ) {
|
||||
typingLogPos++;
|
||||
chatInputText.Clear();
|
||||
buffer.Clear();
|
||||
if( typingLogPos >= game.Chat.InputLog.Count ) {
|
||||
typingLogPos = game.Chat.InputLog.Count;
|
||||
if( originalText != null )
|
||||
chatInputText.Append( 0, originalText );
|
||||
buffer.Append( 0, originalText );
|
||||
} else {
|
||||
chatInputText.Append( 0, game.Chat.InputLog[typingLogPos] );
|
||||
buffer.Append( 0, game.Chat.InputLog[typingLogPos] );
|
||||
}
|
||||
caretPos = -1;
|
||||
Dispose();
|
||||
@ -217,7 +230,7 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
void HomeKey() {
|
||||
if( chatInputText.Empty ) return;
|
||||
if( buffer.Empty ) return;
|
||||
caretPos = 0;
|
||||
CalculateCaretData();
|
||||
}
|
||||
@ -228,7 +241,7 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
bool OtherKey( Key key ) {
|
||||
if( key == Key.V && chatInputText.Length < TotalChars ) {
|
||||
if( key == Key.V && buffer.Length < TotalChars ) {
|
||||
string text = null;
|
||||
try {
|
||||
text = game.window.ClipboardText;
|
||||
@ -252,9 +265,9 @@ namespace ClassicalSharp.Gui {
|
||||
AppendText( text );
|
||||
return true;
|
||||
} else if( key == Key.C ) {
|
||||
if( chatInputText.Empty ) return true;
|
||||
if( buffer.Empty ) return true;
|
||||
try {
|
||||
game.window.ClipboardText = chatInputText.ToString();
|
||||
game.window.ClipboardText = buffer.ToString();
|
||||
} catch( Exception ex ) {
|
||||
ErrorHandler.LogError( "Copy to clipboard", ex );
|
||||
const string warning = "&cError while trying to copy to clipboard.";
|
||||
|
@ -12,7 +12,7 @@ namespace ClassicalSharp.Gui {
|
||||
HorizontalAnchor = Anchor.LeftOrTop;
|
||||
VerticalAnchor = Anchor.BottomOrRight;
|
||||
typingLogPos = game.Chat.InputLog.Count; // Index of newest entry + 1.
|
||||
chatInputText = new WrappableStringBuffer( 64 * lines );
|
||||
buffer = new WrappableStringBuffer( 64 * lines );
|
||||
|
||||
DrawTextArgs args = new DrawTextArgs( "_", boldFont, true );
|
||||
caretTex = game.Drawer2D.MakeChatTextTexture( ref args, 0, 0 );
|
||||
@ -35,7 +35,7 @@ namespace ClassicalSharp.Gui {
|
||||
int caretPos = -1, typingLogPos = 0;
|
||||
public int YOffset;
|
||||
int defaultCaretWidth, defaultWidth, defaultHeight;
|
||||
internal WrappableStringBuffer chatInputText;
|
||||
internal WrappableStringBuffer buffer;
|
||||
readonly Font font;
|
||||
|
||||
FastColour caretCol;
|
||||
@ -72,7 +72,7 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
public override void Init() {
|
||||
X = 5;
|
||||
chatInputText.WordWrap( game.Drawer2D, ref parts, ref partLens,
|
||||
buffer.WordWrap( game.Drawer2D, ref parts, ref partLens,
|
||||
LineLength, TotalChars );
|
||||
|
||||
for( int y = 0; y < sizes.Length; y++ )
|
||||
@ -89,10 +89,10 @@ namespace ClassicalSharp.Gui {
|
||||
if( sizes[0].Height == 0 ) sizes[0].Height = defaultHeight;
|
||||
|
||||
bool supports = game.Network.ServerSupportsPartialMessages;
|
||||
if( chatInputText.Length > LineLength && !shownWarning && !supports ) {
|
||||
if( buffer.Length > LineLength && !shownWarning && !supports ) {
|
||||
game.Chat.Add( "&eNote: Each line will be sent as a separate packet.", MessageType.ClientStatus6 );
|
||||
shownWarning = true;
|
||||
} else if( chatInputText.Length <= LineLength && shownWarning ) {
|
||||
} else if( buffer.Length <= LineLength && shownWarning ) {
|
||||
game.Chat.Add( null, MessageType.ClientStatus6 );
|
||||
shownWarning = false;
|
||||
}
|
||||
@ -104,8 +104,8 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
void CalculateCaretData() {
|
||||
if( caretPos >= chatInputText.Length ) caretPos = -1;
|
||||
chatInputText.MakeCoords( caretPos, partLens, out indexX, out indexY );
|
||||
if( caretPos >= buffer.Length ) caretPos = -1;
|
||||
buffer.MakeCoords( caretPos, partLens, out indexX, out indexY );
|
||||
DrawTextArgs args = new DrawTextArgs( null, font, true );
|
||||
|
||||
if( indexX == LineLength ) {
|
||||
@ -204,7 +204,7 @@ namespace ClassicalSharp.Gui {
|
||||
public void SendTextInBufferAndReset() {
|
||||
SendInBuffer();
|
||||
typingLogPos = game.Chat.InputLog.Count; // Index of newest entry + 1.
|
||||
chatInputText.Clear();
|
||||
buffer.Clear();
|
||||
caretPos = -1;
|
||||
Dispose();
|
||||
Height = defaultHeight;
|
||||
@ -216,8 +216,8 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
void SendInBuffer() {
|
||||
if( chatInputText.Empty ) return;
|
||||
string allText = chatInputText.GetString();
|
||||
if( buffer.Empty ) return;
|
||||
string allText = buffer.GetString();
|
||||
game.Chat.InputLog.Add( allText );
|
||||
|
||||
if( game.Network.ServerSupportsPartialMessages )
|
||||
@ -257,38 +257,38 @@ namespace ClassicalSharp.Gui {
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
chatInputText.Clear();
|
||||
buffer.Clear();
|
||||
for( int i = 0; i < parts.Length; i++ ) {
|
||||
parts[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AppendText( string text ) {
|
||||
if( chatInputText.Length + text.Length > TotalChars ) {
|
||||
text = text.Substring( 0, TotalChars - chatInputText.Length );
|
||||
if( buffer.Length + text.Length > TotalChars ) {
|
||||
text = text.Substring( 0, TotalChars - buffer.Length );
|
||||
}
|
||||
if( text == "" ) return;
|
||||
|
||||
if( caretPos == -1 ) {
|
||||
chatInputText.InsertAt( chatInputText.Length, text );
|
||||
buffer.InsertAt( buffer.Length, text );
|
||||
} else {
|
||||
chatInputText.InsertAt( caretPos, text );
|
||||
buffer.InsertAt( caretPos, text );
|
||||
caretPos += text.Length;
|
||||
if( caretPos >= chatInputText.Length ) caretPos = -1;
|
||||
if( caretPos >= buffer.Length ) caretPos = -1;
|
||||
}
|
||||
Dispose();
|
||||
Init();
|
||||
}
|
||||
|
||||
public void AppendChar( char c ) {
|
||||
if( chatInputText.Length == TotalChars ) return;
|
||||
if( buffer.Length == TotalChars ) return;
|
||||
|
||||
if( caretPos == -1 ) {
|
||||
chatInputText.InsertAt( chatInputText.Length, c );
|
||||
buffer.InsertAt( buffer.Length, c );
|
||||
} else {
|
||||
chatInputText.InsertAt( caretPos, c );
|
||||
buffer.InsertAt( caretPos, c );
|
||||
caretPos++;
|
||||
if( caretPos >= chatInputText.Length ) caretPos = -1;
|
||||
if( caretPos >= buffer.Length ) caretPos = -1;
|
||||
}
|
||||
Dispose();
|
||||
Init();
|
||||
|
@ -109,12 +109,12 @@ namespace ClassicalSharp.Gui {
|
||||
public sealed class PathValidator : MenuInputValidator {
|
||||
|
||||
public PathValidator() {
|
||||
Range = "&7(Enter filename)";
|
||||
Range = "&7(Enter name)";
|
||||
}
|
||||
|
||||
public override bool IsValidChar( char c ) {
|
||||
return !(c == '/' || c == '\\' || c == '?' || c == '*' || c == ':'
|
||||
|| c == '<' || c == '>' || c == '|' || c == '"');
|
||||
|| c == '<' || c == '>' || c == '|' || c == '"' || c == '.');
|
||||
}
|
||||
|
||||
public override bool IsValidString( string s ) { return true; }
|
||||
|
@ -89,8 +89,8 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
base.Init();
|
||||
if( !extList ) {
|
||||
game.EntityEvents.EntityAdded += PlayerSpawned;
|
||||
game.EntityEvents.EntityRemoved += PlayerDespawned;
|
||||
game.EntityEvents.Added += PlayerSpawned;
|
||||
game.EntityEvents.Removed += PlayerDespawned;
|
||||
} else {
|
||||
game.EntityEvents.CpeListInfoAdded += PlayerListInfoAdded;
|
||||
game.EntityEvents.CpeListInfoRemoved += PlayerDespawned;
|
||||
@ -102,8 +102,8 @@ namespace ClassicalSharp.Gui {
|
||||
base.Dispose();
|
||||
overview.Dispose();
|
||||
if( !extList ) {
|
||||
game.EntityEvents.EntityAdded -= PlayerSpawned;
|
||||
game.EntityEvents.EntityRemoved -= PlayerDespawned;
|
||||
game.EntityEvents.Added -= PlayerSpawned;
|
||||
game.EntityEvents.Removed -= PlayerDespawned;
|
||||
} else {
|
||||
game.EntityEvents.CpeListInfoAdded -= PlayerListInfoAdded;
|
||||
game.EntityEvents.CpeListInfoChanged -= PlayerListInfoChanged;
|
||||
|
@ -27,14 +27,14 @@ namespace ClassicalSharp.Gui {
|
||||
|
||||
public override void Init() {
|
||||
base.Init();
|
||||
game.EntityEvents.EntityAdded += PlayerSpawned;
|
||||
game.EntityEvents.EntityRemoved += PlayerDespawned;
|
||||
game.EntityEvents.Added += PlayerSpawned;
|
||||
game.EntityEvents.Removed += PlayerDespawned;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
base.Dispose();
|
||||
game.EntityEvents.EntityAdded -= PlayerSpawned;
|
||||
game.EntityEvents.EntityRemoved -= PlayerDespawned;
|
||||
game.EntityEvents.Added -= PlayerSpawned;
|
||||
game.EntityEvents.Removed -= PlayerDespawned;
|
||||
}
|
||||
|
||||
void PlayerSpawned( object sender, IdEventArgs e ) {
|
||||
|
@ -26,6 +26,7 @@ namespace ClassicalSharp.Audio {
|
||||
SetSound( game.UseSound );
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -58,6 +58,40 @@ namespace ClassicalSharp {
|
||||
public const byte MaxDefinedBlock = byte.MaxValue;
|
||||
public const int BlocksCount = MaxDefinedBlock + 1;
|
||||
|
||||
public void Reset( Game game ) {
|
||||
// Reset properties
|
||||
for( int i = 0; i < IsTransparent.Length; i++ ) IsTransparent[i] = false;
|
||||
for( int i = 0; i < IsTranslucent.Length; i++ ) IsTranslucent[i] = false;
|
||||
for( int i = 0; i < IsOpaque.Length; i++ ) IsOpaque[i] = false;
|
||||
for( int i = 0; i < IsOpaqueY.Length; i++ ) IsOpaqueY[i] = false;
|
||||
for( int i = 0; i < IsSprite.Length; i++ ) IsSprite[i] = false;
|
||||
for( int i = 0; i < IsLiquid.Length; i++ ) IsLiquid[i] = false;
|
||||
for( int i = 0; i < BlocksLight.Length; i++ ) BlocksLight[i] = false;
|
||||
for( int i = 0; i < FullBright.Length; i++ ) FullBright[i] = false;
|
||||
for( int i = 0; i < Name.Length; i++ ) Name[i] = "Invalid";
|
||||
for( int i = 0; i < FogColour.Length; i++ ) FogColour[i] = default(FastColour);
|
||||
for( int i = 0; i < FogDensity.Length; i++ ) FogDensity[i] = 0;
|
||||
for( int i = 0; i < Collide.Length; i++ ) Collide[i] = CollideType.WalkThrough;
|
||||
for( int i = 0; i < SpeedMultiplier.Length; i++ ) SpeedMultiplier[i] = 0;
|
||||
for( int i = 0; i < CullWithNeighbours.Length; i++ ) CullWithNeighbours[i] = false;
|
||||
for( int i = 0; i < LightOffset.Length; i++ ) LightOffset[i] = 0;
|
||||
for( int i = 0; i < DefinedCustomBlocks.Length; i++ ) DefinedCustomBlocks[i] = 0;
|
||||
// Reset textures
|
||||
texId = 0;
|
||||
for( int i = 0; i < textures.Length; i++ ) textures[i] = 0;
|
||||
// Reset culling
|
||||
for( int i = 0; i < hidden.Length; i++ ) hidden[i] = 0;
|
||||
for( int i = 0; i < CanStretch.Length; i++ ) CanStretch[i] = false;
|
||||
for( int i = 0; i < IsAir.Length; i++ ) IsAir[i] = false;
|
||||
// Reset bounds
|
||||
for( int i = 0; i < MinBB.Length; i++ ) MinBB[i] = Vector3.Zero;
|
||||
for( int i = 0; i < MaxBB.Length; i++ ) MaxBB[i] = Vector3.One;
|
||||
// Reset sounds
|
||||
for( int i = 0; i < DigSounds.Length; i++ ) DigSounds[i] = SoundType.None;
|
||||
for( int i = 0; i < StepSounds.Length; i++ ) StepSounds[i] = SoundType.None;
|
||||
Init();
|
||||
}
|
||||
|
||||
public void Init() {
|
||||
for( int tile = 1; tile < BlocksCount; tile++ ) {
|
||||
MaxBB[tile].Y = 1;
|
||||
@ -189,6 +223,45 @@ namespace ClassicalSharp {
|
||||
StepSounds[id] = SoundType.None;
|
||||
DigSounds[id] = SoundType.None;
|
||||
}
|
||||
|
||||
internal static string[] normalNames = null;
|
||||
public string GetBlockName( byte block ) {
|
||||
if( normalNames == null )
|
||||
MakeNormalNames();
|
||||
|
||||
string value = Name[block];
|
||||
if( block < CpeBlocksCount && value == "Invalid" )
|
||||
return normalNames[block];
|
||||
return value;
|
||||
}
|
||||
|
||||
static void MakeNormalNames() {
|
||||
StringBuffer buffer = new StringBuffer( 64 );
|
||||
normalNames = new string[CpeBlocksCount];
|
||||
|
||||
for( int i = 0; i < normalNames.Length; i++ ) {
|
||||
string origName = Enum.GetName( typeof(Block), (byte)i );
|
||||
buffer.Clear();
|
||||
int index = 0;
|
||||
SplitUppercase( buffer, origName, ref index );
|
||||
normalNames[i] = buffer.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
static void SplitUppercase( StringBuffer buffer, string value, ref int index ) {
|
||||
for( int i = 0; i < value.Length; i++ ) {
|
||||
char c = value[i];
|
||||
bool upper = Char.IsUpper( c ) && i > 0;
|
||||
bool nextLower = i < value.Length - 1 && !Char.IsUpper( value[i + 1] );
|
||||
|
||||
if( upper && nextLower ) {
|
||||
buffer.Append( ref index, ' ' );
|
||||
buffer.Append( ref index, Char.ToLower( c ) );
|
||||
} else {
|
||||
buffer.Append( ref index, c );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum CollideType : byte {
|
||||
|
@ -145,6 +145,7 @@
|
||||
<Compile Include="Blocks\BlockInfo.Culling.cs" />
|
||||
<Compile Include="Blocks\BlockInfo.Atlas.cs" />
|
||||
<Compile Include="Blocks\BlockInfo.Sounds.cs" />
|
||||
<Compile Include="Commands\SinglePlayerCommands.cs" />
|
||||
<Compile Include="Entities\AI\AI.cs" />
|
||||
<Compile Include="Entities\AI\FleeAI.cs" />
|
||||
<Compile Include="Entities\AI\HostileAI.cs" />
|
||||
@ -165,6 +166,7 @@
|
||||
<Compile Include="Entities\NetPlayer.cs" />
|
||||
<Compile Include="Events\EntityEvents.cs" />
|
||||
<Compile Include="Events\Events.cs" />
|
||||
<Compile Include="Events\UserEvents.cs" />
|
||||
<Compile Include="Events\WorldEvents.cs" />
|
||||
<Compile Include="Game\Game.Properties.cs" />
|
||||
<Compile Include="Game\PickingHandler.cs" />
|
||||
@ -174,6 +176,7 @@
|
||||
<Compile Include="Generator\NotchyGenerator.cs" />
|
||||
<Compile Include="Generator\NotchyGenerator.Utils.cs" />
|
||||
<Compile Include="GraphicsAPI\OpenGLESApi.cs" />
|
||||
<Compile Include="Map\Formats\MapSchematic.Exporter.cs" />
|
||||
<Compile Include="Map\Formats\MapLvl.Importer.cs" />
|
||||
<Compile Include="Map\Formats\NbtFile.cs" />
|
||||
<Compile Include="Math\RayTracer.cs" />
|
||||
@ -208,7 +211,7 @@
|
||||
<Compile Include="Map\ChunkMeshBuilder.cs" />
|
||||
<Compile Include="Map\ChunkMeshBuilder.FloodFill.cs" />
|
||||
<Compile Include="Map\ChunkMeshBuilderTex2Col4.cs" />
|
||||
<Compile Include="Map\Formats\IMapFileFormat.cs" />
|
||||
<Compile Include="Map\Formats\IMapFormat.cs" />
|
||||
<Compile Include="Map\Formats\MapCw.Exporter.cs" />
|
||||
<Compile Include="Map\Formats\MapCw.Importer.cs" />
|
||||
<Compile Include="Map\Formats\MapDat.Importer.cs" />
|
||||
|
@ -21,10 +21,14 @@ namespace ClassicalSharp.Commands {
|
||||
Register( new HelpCommand() );
|
||||
Register( new InfoCommand() );
|
||||
Register( new RenderTypeCommand() );
|
||||
if( game.Network.IsSinglePlayer )
|
||||
|
||||
if( game.Network.IsSinglePlayer ) {
|
||||
Register( new ModelCommand() );
|
||||
Register( new CuboidCommand() );
|
||||
}
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -150,25 +150,4 @@ namespace ClassicalSharp.Commands {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ModelCommand : Command {
|
||||
|
||||
public ModelCommand() {
|
||||
Name = "Model";
|
||||
Help = new [] {
|
||||
"&a/client model [name]",
|
||||
"&bnames: &echibi, chicken, creeper, human, pig, sheep",
|
||||
"&e skeleton, spider, zombie, <numerical block id>",
|
||||
};
|
||||
}
|
||||
|
||||
public override void Execute( CommandReader reader ) {
|
||||
string name = reader.Next();
|
||||
if( String.IsNullOrEmpty( name ) ) {
|
||||
game.Chat.Add( "&e/client model: &cYou didn't specify a model name." );
|
||||
} else {
|
||||
game.LocalPlayer.SetModel( name );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
115
ClassicalSharp/Commands/SinglePlayerCommands.cs
Normal file
115
ClassicalSharp/Commands/SinglePlayerCommands.cs
Normal file
@ -0,0 +1,115 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using ClassicalSharp.Events;
|
||||
using ClassicalSharp.Renderers;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace ClassicalSharp.Commands {
|
||||
|
||||
public sealed class ModelCommand : Command {
|
||||
|
||||
public ModelCommand() {
|
||||
Name = "Model";
|
||||
Help = new [] {
|
||||
"&a/client model [name]",
|
||||
"&bnames: &echibi, chicken, creeper, human, pig, sheep",
|
||||
"&e skeleton, spider, zombie, <numerical block id>",
|
||||
};
|
||||
}
|
||||
|
||||
public override void Execute( CommandReader reader ) {
|
||||
string name = reader.Next();
|
||||
if( String.IsNullOrEmpty( name ) ) {
|
||||
game.Chat.Add( "&e/client model: &cYou didn't specify a model name." );
|
||||
} else {
|
||||
game.LocalPlayer.SetModel( name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CuboidCommand : Command {
|
||||
|
||||
public CuboidCommand() {
|
||||
Name = "Cuboid";
|
||||
Help = new [] {
|
||||
"&a/client cuboid [block] [persist]",
|
||||
"&eFills the 3D rectangle between two points with [block].",
|
||||
"&eIf no block is given, uses your currently held block.",
|
||||
"&e If persist is given and is \"yes\", then the command",
|
||||
"&e will repeatedly cuboid, without needing to be typed in again.",
|
||||
};
|
||||
}
|
||||
byte block = 0xFF;
|
||||
Vector3I mark1, mark2;
|
||||
bool persist = false;
|
||||
|
||||
public override void Execute( CommandReader reader ) {
|
||||
game.UserEvents.BlockChanged -= BlockChanged;
|
||||
block = 0xFF;
|
||||
mark1 = new Vector3I( int.MaxValue );
|
||||
mark2 = new Vector3I( int.MaxValue );
|
||||
persist = false;
|
||||
|
||||
if( !ParseBlock( reader ) ) return;
|
||||
string arg = reader.Next();
|
||||
if( arg != null && Utils.CaselessEquals( arg, "yes" ) )
|
||||
persist = true;
|
||||
|
||||
game.Chat.Add( "&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus3 );
|
||||
game.UserEvents.BlockChanged += BlockChanged;
|
||||
}
|
||||
|
||||
bool ParseBlock( CommandReader reader ) {
|
||||
string id = reader.Next();
|
||||
if( id == null ) return true;
|
||||
if( Utils.CaselessEquals( id, "yes" ) ) { persist = true; return true; }
|
||||
|
||||
byte blockID = 0;
|
||||
if( !byte.TryParse( id, out blockID ) ) {
|
||||
game.Chat.Add( "&eCuboid: &c\"" + id + "\" is not a valid block id." ); return false;
|
||||
}
|
||||
if( blockID >= BlockInfo.CpeBlocksCount && game.BlockInfo.Name[blockID] == "Invalid" ) {
|
||||
game.Chat.Add( "&eCuboid: &cThere is no block with id \"" + id + "\"." ); return false;
|
||||
}
|
||||
block = blockID;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BlockChanged( object sender, BlockChangedEventArgs e ) {
|
||||
if( mark1.X == int.MaxValue ) {
|
||||
mark1 = e.Coords;
|
||||
game.UpdateBlock( mark1.X, mark1.Y, mark1.Z, e.OldBlock );
|
||||
game.Chat.Add( "&eCuboid: &fMark 1 placed at (" + e.Coords + "), place mark 2.",
|
||||
MessageType.ClientStatus3 );
|
||||
} else {
|
||||
mark2 = e.Coords;
|
||||
DoCuboid();
|
||||
game.Chat.Add( null, MessageType.ClientStatus3 );
|
||||
|
||||
if( !persist ) {
|
||||
game.UserEvents.BlockChanged -= BlockChanged;
|
||||
} else {
|
||||
mark1 = new Vector3I( int.MaxValue );
|
||||
game.Chat.Add( "&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus3 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoCuboid() {
|
||||
Vector3I min = Vector3I.Min( mark1, mark2 );
|
||||
Vector3I max = Vector3I.Max( mark1, mark2 );
|
||||
if( !game.World.IsValidPos( min ) || !game.World.IsValidPos( max ) ) return;
|
||||
byte id = block;
|
||||
|
||||
if( id == 0xFF ) id = (byte)game.Inventory.HeldBlock;
|
||||
for( int y = min.Y; y <= max.Y; y++ )
|
||||
for( int z = min.Z; z <= max.Z; z++ )
|
||||
for( int x = min.X; x <= max.X; x++ )
|
||||
{
|
||||
game.UpdateBlock( x, y, z, id );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -98,7 +98,7 @@ namespace ClassicalSharp.Entities {
|
||||
}
|
||||
|
||||
void TextureChanged( object sender, TextureEventArgs e ) {
|
||||
if( e.Texture != "char" ) return;
|
||||
if( e.Name != "char.png" ) return;
|
||||
for( int i = 0; i < Players.Length; i++ ) {
|
||||
if( Players[i] == null || Players[i].TextureId != -1 ) continue;
|
||||
Players[i].SkinType = game.DefaultPlayerSkinType;
|
||||
|
@ -52,8 +52,6 @@ namespace ClassicalSharp.Entities {
|
||||
Hacks.DoubleJump = !game.ClassicMode && Options.GetBool( OptionsKey.DoubleJump, false );
|
||||
Hacks.Enabled = !game.ClassicMode && Options.GetBool( OptionsKey.HacksEnabled, true );
|
||||
if( game.ClassicMode && game.ClassicHacks ) Hacks.Enabled = true;
|
||||
|
||||
InitRenderingData();
|
||||
}
|
||||
|
||||
Vector3 lastSoundPos = new Vector3( float.PositiveInfinity );
|
||||
|
@ -13,7 +13,6 @@ namespace ClassicalSharp.Entities {
|
||||
SkinName = skinName;
|
||||
SkinIdentifier = "skin_" + id;
|
||||
interp = new InterpolatedComponent( game, this );
|
||||
InitRenderingData();
|
||||
}
|
||||
|
||||
public override void SetLocation( LocationUpdate update, bool interpolate ) {
|
||||
|
@ -59,7 +59,7 @@ namespace ClassicalSharp.Entities {
|
||||
game.Graphics.DeleteTexture( ref nameTex.ID );
|
||||
}
|
||||
|
||||
protected void InitRenderingData() {
|
||||
protected void MakeNameTexture() {
|
||||
using( Font font = new Font( game.FontName, 24 ) ) {
|
||||
DrawTextArgs args = new DrawTextArgs( DisplayName, font, true );
|
||||
nameTex = game.Drawer2D.MakeBitmappedTextTexture( ref args, 0, 0 );
|
||||
@ -68,11 +68,13 @@ namespace ClassicalSharp.Entities {
|
||||
|
||||
public void UpdateName() {
|
||||
game.Graphics.DeleteTexture( ref nameTex );
|
||||
InitRenderingData();
|
||||
MakeNameTexture();
|
||||
}
|
||||
|
||||
protected void DrawName() {
|
||||
if( nameTex.ID == 0 ) MakeNameTexture();
|
||||
if( nameTex.ID == -1 ) return;
|
||||
|
||||
IGraphicsApi api = game.Graphics;
|
||||
api.BindTexture( nameTex.ID );
|
||||
Vector3 pos = Position; pos.Y += Model.NameYOffset;
|
||||
|
@ -10,12 +10,12 @@ namespace ClassicalSharp.Events {
|
||||
IdEventArgs idArgs = new IdEventArgs();
|
||||
|
||||
/// <summary> Raised when an entity is spawned in the current world. </summary>
|
||||
public event EventHandler<IdEventArgs> EntityAdded;
|
||||
internal void RaiseEntityAdded( byte id ) { idArgs.Id = id; Raise( EntityAdded, idArgs ); }
|
||||
public event EventHandler<IdEventArgs> Added;
|
||||
internal void RaiseAdded( byte id ) { idArgs.Id = id; Raise( Added, idArgs ); }
|
||||
|
||||
/// <summary> Raised when an entity is despawned from the current world. </summary>
|
||||
public event EventHandler<IdEventArgs> EntityRemoved;
|
||||
internal void RaiseEntityRemoved( byte id ) { idArgs.Id = id; Raise( EntityRemoved, idArgs ); }
|
||||
public event EventHandler<IdEventArgs> Removed;
|
||||
internal void RaiseRemoved( byte id ) { idArgs.Id = id; Raise( Removed, idArgs ); }
|
||||
|
||||
/// <summary> Raised when a new CPE player list entry is created. </summary>
|
||||
public event EventHandler<IdEventArgs> CpeListInfoAdded;
|
||||
|
@ -11,8 +11,8 @@ namespace ClassicalSharp.Events {
|
||||
|
||||
/// <summary> Raised when a texture is changed. (such as "terrain", "rain") </summary>
|
||||
public event EventHandler<TextureEventArgs> TextureChanged;
|
||||
internal void RaiseTextureChanged( string texture ) {
|
||||
texArgs.Texture = texture; Raise( TextureChanged, texArgs ); }
|
||||
internal void RaiseTextureChanged( string name, byte[] data ) {
|
||||
texArgs.Name = name; texArgs.Data = data; Raise( TextureChanged, texArgs ); }
|
||||
|
||||
/// <summary> Raised when the user changed their view/fog distance. </summary>
|
||||
public event EventHandler ViewDistanceChanged;
|
||||
@ -78,8 +78,10 @@ namespace ClassicalSharp.Events {
|
||||
|
||||
public sealed class TextureEventArgs : EventArgs {
|
||||
|
||||
/// <summary> Location of the texture within a texture pack. (e.g. "snow", "default", "char") </summary>
|
||||
/// <remarks> See TexturePackExtractor for a list of supported textures. </remarks>
|
||||
public string Texture;
|
||||
/// <summary> Location of the file within a texture pack, without a directory. (e.g. "snow.png") </summary>
|
||||
public string Name;
|
||||
|
||||
/// <summary> Raw data of the file. </summary>
|
||||
public byte[] Data;
|
||||
}
|
||||
}
|
||||
|
38
ClassicalSharp/Events/UserEvents.cs
Normal file
38
ClassicalSharp/Events/UserEvents.cs
Normal file
@ -0,0 +1,38 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
|
||||
namespace ClassicalSharp.Events {
|
||||
|
||||
public class UserEvents {
|
||||
|
||||
/// <summary> Raised when the user changes a block in the world. </summary>
|
||||
public event EventHandler<BlockChangedEventArgs> BlockChanged;
|
||||
internal void RaiseBlockChanged( Vector3I coords, byte old, byte block ) {
|
||||
blockArgs.Coords = coords; blockArgs.OldBlock = old; blockArgs.Block = block;
|
||||
Raise( BlockChanged, blockArgs );
|
||||
}
|
||||
|
||||
BlockChangedEventArgs blockArgs = new BlockChangedEventArgs();
|
||||
protected void Raise( EventHandler handler ) {
|
||||
if( handler != null )
|
||||
handler( this, EventArgs.Empty );
|
||||
}
|
||||
|
||||
protected void Raise<T>( EventHandler<T> handler, T args ) where T : EventArgs {
|
||||
if( handler != null )
|
||||
handler( this, args );
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class BlockChangedEventArgs : EventArgs {
|
||||
|
||||
/// <summary> Location within the world the block was updated at. </summary>
|
||||
public Vector3I Coords;
|
||||
|
||||
/// <summary> Block ID that was at the given location before. </summary>
|
||||
public byte OldBlock;
|
||||
|
||||
/// <summary> Block ID that is now at the given location. </summary>
|
||||
public byte Block;
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ namespace ClassicalSharp {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -25,9 +25,12 @@ namespace ClassicalSharp {
|
||||
/// <summary> Represents a game component. </summary>
|
||||
public interface IGameComponent : IDisposable {
|
||||
|
||||
/// <summary> Called when the game has loaded. </summary>
|
||||
/// <summary> Called when the game is being loaded. </summary>
|
||||
void Init( Game game );
|
||||
|
||||
/// <summary> Called when the texture pack has been loaded and all components have been initalised. </summary>
|
||||
void Ready( Game game );
|
||||
|
||||
/// <summary> Called to reset the component's state when the user is reconnecting to a server. </summary>
|
||||
void Reset( Game game );
|
||||
|
||||
@ -102,6 +105,7 @@ namespace ClassicalSharp {
|
||||
public OtherEvents Events = new OtherEvents();
|
||||
public EntityEvents EntityEvents = new EntityEvents();
|
||||
public WorldEvents WorldEvents = new WorldEvents();
|
||||
public UserEvents UserEvents = new UserEvents();
|
||||
public InputHandler InputHandler;
|
||||
public Chat Chat;
|
||||
public BlockHandRenderer BlockHandRenderer;
|
||||
@ -170,7 +174,7 @@ namespace ClassicalSharp {
|
||||
public Vector3 CurrentCameraPos;
|
||||
|
||||
public Animations Animations;
|
||||
internal int CloudsTexId, RainTexId, SnowTexId, GuiTexId, GuiClassicTexId;
|
||||
internal int CloudsTexId, GuiTexId, GuiClassicTexId;
|
||||
internal bool screenshotRequested;
|
||||
internal EntryList AcceptedUrls = new EntryList( "acceptedurls.txt" );
|
||||
internal EntryList DeniedUrls = new EntryList( "deniedurls.txt" );
|
||||
|
@ -84,13 +84,7 @@ namespace ClassicalSharp {
|
||||
|
||||
TerrainAtlas1D = new TerrainAtlas1D( Graphics );
|
||||
TerrainAtlas = new TerrainAtlas2D( Graphics, Drawer2D );
|
||||
Animations = new Animations( this );
|
||||
defTexturePack = Options.Get( OptionsKey.DefaultTexturePack ) ?? "default.zip";
|
||||
TexturePackExtractor extractor = new TexturePackExtractor();
|
||||
extractor.Extract( "default.zip", this );
|
||||
// in case the user's default texture pack doesn't have all required textures
|
||||
if( defTexturePack != "default.zip" )
|
||||
extractor.Extract( DefaultTexturePack, this );
|
||||
Animations = AddComponent( new Animations() );
|
||||
Inventory = AddComponent( new Inventory() );
|
||||
|
||||
BlockInfo.SetDefaultBlockPermissions( Inventory.CanPlace, Inventory.CanDelete );
|
||||
@ -124,8 +118,7 @@ namespace ClassicalSharp {
|
||||
//Graphics.DepthWrite = true;
|
||||
Graphics.AlphaBlendFunc( BlendFunc.SourceAlpha, BlendFunc.InvSourceAlpha );
|
||||
Graphics.AlphaTestFunc( CompareFunc.Greater, 0.5f );
|
||||
fpsScreen = new FpsScreen( this );
|
||||
fpsScreen.Init();
|
||||
fpsScreen = AddComponent( new FpsScreen( this ) );
|
||||
hudScreen = AddComponent( new HudScreen( this ) );
|
||||
Culling = new FrustumCulling();
|
||||
Picking = AddComponent( new PickedPosRenderer() );
|
||||
@ -134,6 +127,9 @@ namespace ClassicalSharp {
|
||||
|
||||
foreach( IGameComponent comp in Components )
|
||||
comp.Init( this );
|
||||
ExtractInitialTexturePack();
|
||||
foreach( IGameComponent comp in Components )
|
||||
comp.Ready( this );
|
||||
|
||||
LoadIcon();
|
||||
string connectString = "Connecting to " + IPAddress + ":" + Port + "..";
|
||||
@ -145,6 +141,15 @@ namespace ClassicalSharp {
|
||||
Network.Connect( IPAddress, Port );
|
||||
}
|
||||
|
||||
void ExtractInitialTexturePack() {
|
||||
defTexturePack = Options.Get( OptionsKey.DefaultTexturePack ) ?? "default.zip";
|
||||
TexturePackExtractor extractor = new TexturePackExtractor();
|
||||
extractor.Extract( "default.zip", this );
|
||||
// in case the user's default texture pack doesn't have all required textures
|
||||
if( defTexturePack != "default.zip" )
|
||||
extractor.Extract( DefaultTexturePack, this );
|
||||
}
|
||||
|
||||
void LoadOptions() {
|
||||
ClassicMode = Options.GetBool( "mode-classic", false );
|
||||
ClassicHacks = Options.GetBool( OptionsKey.AllowClassicHacks, false );
|
||||
@ -531,10 +536,7 @@ namespace ClassicalSharp {
|
||||
Graphics.DeleteIb( defaultIb );
|
||||
Graphics.Dispose();
|
||||
Drawer2D.DisposeInstance();
|
||||
Animations.Dispose();
|
||||
Graphics.DeleteTexture( ref CloudsTexId );
|
||||
Graphics.DeleteTexture( ref RainTexId );
|
||||
Graphics.DeleteTexture( ref SnowTexId );
|
||||
Graphics.DeleteTexture( ref GuiTexId );
|
||||
Graphics.DeleteTexture( ref GuiClassicTexId );
|
||||
foreach( WarningScreen screen in WarningOverlays )
|
||||
@ -555,6 +557,26 @@ namespace ClassicalSharp {
|
||||
Inventory.CanPlace[block] && Inventory.CanDelete[block];
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Reads a bitmap from the stream (converting it to 32 bits per pixel if necessary),
|
||||
/// and updates the native texture for it. </summary>
|
||||
public void UpdateTexture( ref int texId, byte[] data, bool setSkinType ) {
|
||||
MemoryStream stream = new MemoryStream( data );
|
||||
Graphics.DeleteTexture( ref texId );
|
||||
|
||||
using( Bitmap bmp = Platform.ReadBmp( stream ) ) {
|
||||
if( setSkinType )
|
||||
DefaultPlayerSkinType = Utils.GetSkinType( bmp );
|
||||
|
||||
if( !FastBitmap.CheckFormat( bmp.PixelFormat ) ) {
|
||||
using( Bitmap bmp32 = Drawer2D.ConvertTo32Bpp( bmp ) )
|
||||
texId = Graphics.CreateTexture( bmp32 );
|
||||
} else {
|
||||
texId = Graphics.CreateTexture( bmp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Game( string username, string mppass, string skinServer,
|
||||
bool nullContext, int width, int height ) {
|
||||
window = new DesktopWindow( this, username, nullContext, width, height );
|
||||
|
@ -22,6 +22,7 @@ namespace ClassicalSharp {
|
||||
Hotbar[8] = Block.Slab;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -38,41 +38,45 @@ namespace ClassicalSharp {
|
||||
// always play delete animations, even if we aren't picking a block.
|
||||
if( left ) game.BlockHandRenderer.SetAnimationClick( true );
|
||||
if( !game.SelectedPos.Valid ) return;
|
||||
BlockInfo info = game.BlockInfo;
|
||||
|
||||
if( middle ) {
|
||||
Vector3I pos = game.SelectedPos.BlockPos;
|
||||
byte block = 0;
|
||||
if( game.World.IsValidPos( pos ) && (block = game.World.GetBlock( pos )) != 0
|
||||
&& (inv.CanPlace[block] || inv.CanDelete[block]) ) {
|
||||
if( !game.World.IsValidPos( pos ) ) return;
|
||||
byte old = game.World.GetBlock( pos );
|
||||
|
||||
if( !info.IsAir[old] && (inv.CanPlace[old] || inv.CanDelete[old]) ) {
|
||||
for( int i = 0; i < inv.Hotbar.Length; i++ ) {
|
||||
if( inv.Hotbar[i] == (Block)block ) {
|
||||
if( inv.Hotbar[i] == (Block)old ) {
|
||||
inv.HeldBlockIndex = i; return;
|
||||
}
|
||||
}
|
||||
inv.HeldBlock = (Block)block;
|
||||
inv.HeldBlock = (Block)old;
|
||||
}
|
||||
} else if( left ) {
|
||||
Vector3I pos = game.SelectedPos.BlockPos;
|
||||
byte block = 0;
|
||||
if( game.World.IsValidPos( pos ) && (block = game.World.GetBlock( pos )) != 0
|
||||
&& inv.CanDelete[block] ) {
|
||||
game.ParticleManager.BreakBlockEffect( pos, block );
|
||||
game.AudioPlayer.PlayDigSound( game.BlockInfo.DigSounds[block] );
|
||||
if( !game.World.IsValidPos( pos ) ) return;
|
||||
byte old = game.World.GetBlock( pos );
|
||||
|
||||
if( !info.IsAir[old] && inv.CanDelete[old] ) {
|
||||
game.ParticleManager.BreakBlockEffect( pos, old );
|
||||
game.AudioPlayer.PlayDigSound( game.BlockInfo.DigSounds[old] );
|
||||
game.UpdateBlock( pos.X, pos.Y, pos.Z, 0 );
|
||||
game.Network.SendSetBlock( pos.X, pos.Y, pos.Z, false, (byte)inv.HeldBlock );
|
||||
game.UserEvents.RaiseBlockChanged( pos, old, 0 );
|
||||
}
|
||||
} else if( right ) {
|
||||
Vector3I pos = game.SelectedPos.TranslatedPos;
|
||||
if( !game.World.IsValidPos( pos ) ) return;
|
||||
|
||||
byte old = game.World.GetBlock( pos );
|
||||
byte block = (byte)inv.HeldBlock;
|
||||
if( !game.CanPick( game.World.GetBlock( pos ) ) && inv.CanPlace[block]
|
||||
&& CheckIsFree( game.SelectedPos, block ) ) {
|
||||
|
||||
if( !game.CanPick( old ) && inv.CanPlace[block] && CheckIsFree( game.SelectedPos, block ) ) {
|
||||
game.UpdateBlock( pos.X, pos.Y, pos.Z, block );
|
||||
game.AudioPlayer.PlayDigSound( game.BlockInfo.StepSounds[block] );
|
||||
game.Network.SendSetBlock( pos.X, pos.Y, pos.Z, true, block );
|
||||
game.BlockHandRenderer.SetAnimationClick( false );
|
||||
game.UserEvents.RaiseBlockChanged( pos, old, block );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,8 +131,6 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
}
|
||||
|
||||
public override void SetFogStart( float value ) {
|
||||
if( value == fogStart ) return;
|
||||
fogStart = value;
|
||||
device.SetRenderState( RenderState.FogStart, value );
|
||||
}
|
||||
|
||||
|
@ -81,13 +81,13 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
}
|
||||
}
|
||||
|
||||
float lastFogStart = -1, lastFogEnd = -1, lastFogDensity = -1;
|
||||
float lastFogEnd = -1, lastFogDensity = -1;
|
||||
public override void SetFogDensity( float value ) {
|
||||
FogParam( FogParameter.FogDensity, value, ref lastFogDensity );
|
||||
}
|
||||
|
||||
public override void SetFogStart( float value ) {
|
||||
FogParam( FogParameter.FogStart, value, ref lastFogStart );
|
||||
GL.Fogf( FogParameter.FogStart, value );
|
||||
}
|
||||
|
||||
public override void SetFogEnd( float value ) {
|
||||
@ -95,11 +95,10 @@ namespace ClassicalSharp.GraphicsAPI {
|
||||
}
|
||||
|
||||
static void FogParam( FogParameter param, float value, ref float last ) {
|
||||
if( value != last ) {
|
||||
if( value == last ) return;
|
||||
GL.Fogf( param, value );
|
||||
last = value;
|
||||
}
|
||||
}
|
||||
|
||||
Fog lastFogMode = (Fog)999;
|
||||
FogMode[] fogModes;
|
||||
|
@ -67,11 +67,11 @@ namespace ClassicalSharp.Map {
|
||||
|
||||
nbt.Write( NbtTagType.Int8 );
|
||||
nbt.Write( "H" );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnYaw, 256 ) );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnYaw ) );
|
||||
|
||||
nbt.Write( NbtTagType.Int8 );
|
||||
nbt.Write( "P" );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnPitch, 256 ) );
|
||||
nbt.WriteUInt8( (byte)Utils.DegreesToPacked( p.SpawnPitch ) );
|
||||
|
||||
nbt.Write( NbtTagType.End );
|
||||
}
|
||||
|
@ -75,9 +75,13 @@ namespace ClassicalSharp.Map {
|
||||
map.SetShadowlight( GetColour( "Ambient", World.DefaultShadowlight ) );
|
||||
}
|
||||
if( CheckKey( "EnvMapAppearance", 1, metadata ) ) {
|
||||
string url = null;
|
||||
if( curCpeExt.ContainsKey( "TextureURL" ) )
|
||||
map.TextureUrl = (string)curCpeExt["TextureURL"].Value;
|
||||
if( map.TextureUrl.Length == 0 ) map.TextureUrl = null;
|
||||
url = (string)curCpeExt["TextureURL"].Value;
|
||||
if( url.Length == 0 ) url = null;
|
||||
if( game.AllowServerTextures && url != null )
|
||||
game.Network.RetrieveTexturePack( url );
|
||||
|
||||
byte sidesBlock = (byte)curCpeExt["SideBlock"].Value;
|
||||
byte edgeBlock = (byte)curCpeExt["EdgeBlock"].Value;
|
||||
map.SetSidesBlock( (Block)sidesBlock );
|
||||
|
@ -15,34 +15,33 @@ namespace ClassicalSharp.Map {
|
||||
const byte Revision = 13;
|
||||
|
||||
public byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {
|
||||
BinaryReader reader = new BinaryReader( stream );
|
||||
if( reader.ReadInt32() != Identifier || reader.ReadByte() != Revision ) {
|
||||
BinaryReader r = new BinaryReader( stream );
|
||||
if( r.ReadInt32() != Identifier || r.ReadByte() != Revision )
|
||||
throw new InvalidDataException( "Unexpected constant in .fcm file" );
|
||||
}
|
||||
|
||||
width = reader.ReadInt16();
|
||||
height = reader.ReadInt16();
|
||||
length = reader.ReadInt16();
|
||||
width = r.ReadInt16();
|
||||
height = r.ReadInt16();
|
||||
length = r.ReadInt16();
|
||||
|
||||
LocalPlayer p = game.LocalPlayer;
|
||||
p.Spawn.X = reader.ReadInt32() / 32f;
|
||||
p.Spawn.Y = reader.ReadInt32() / 32f;
|
||||
p.Spawn.Z = reader.ReadInt32() / 32f;
|
||||
p.SpawnYaw = (float)Utils.PackedToDegrees( reader.ReadByte() );
|
||||
p.SpawnPitch = (float)Utils.PackedToDegrees( reader.ReadByte() );
|
||||
p.Spawn.X = r.ReadInt32() / 32f;
|
||||
p.Spawn.Y = r.ReadInt32() / 32f;
|
||||
p.Spawn.Z = r.ReadInt32() / 32f;
|
||||
p.SpawnYaw = (float)Utils.PackedToDegrees( r.ReadByte() );
|
||||
p.SpawnPitch = (float)Utils.PackedToDegrees( r.ReadByte() );
|
||||
|
||||
reader.ReadUInt32(); // date modified
|
||||
reader.ReadUInt32(); // date created
|
||||
game.World.Uuid = new Guid( reader.ReadBytes( 16 ) );
|
||||
reader.ReadBytes( 26 ); // layer index
|
||||
int metaSize = reader.ReadInt32();
|
||||
r.ReadUInt32(); // date modified
|
||||
r.ReadUInt32(); // date created
|
||||
game.World.Uuid = new Guid( r.ReadBytes( 16 ) );
|
||||
r.ReadBytes( 26 ); // layer index
|
||||
int metaSize = r.ReadInt32();
|
||||
|
||||
using( DeflateStream ds = new DeflateStream( stream, CompressionMode.Decompress ) ) {
|
||||
reader = new BinaryReader( ds );
|
||||
r = new BinaryReader( ds );
|
||||
for( int i = 0; i < metaSize; i++ ) {
|
||||
string group = ReadString( reader );
|
||||
string key = ReadString( reader );
|
||||
string value = ReadString( reader );
|
||||
string group = ReadString( r );
|
||||
string key = ReadString( r );
|
||||
string value = ReadString( r );
|
||||
}
|
||||
|
||||
byte[] blocks = new byte[width * height * length];
|
||||
|
@ -13,27 +13,29 @@ namespace ClassicalSharp.Map {
|
||||
public sealed class MapLvlImporter : IMapFormatImporter {
|
||||
|
||||
const int Version = 1874;
|
||||
const byte customTile = 163;
|
||||
|
||||
public byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) {
|
||||
GZipHeaderReader gsHeader = new GZipHeaderReader();
|
||||
while( !gsHeader.ReadHeader( stream ) ) { }
|
||||
|
||||
using( DeflateStream gs = new DeflateStream( stream, CompressionMode.Decompress ) ) {
|
||||
BinaryReader reader = new BinaryReader( gs );
|
||||
ushort header = reader.ReadUInt16();
|
||||
BinaryReader r = new BinaryReader( gs );
|
||||
ushort header = r.ReadUInt16();
|
||||
|
||||
width = header == Version ? reader.ReadUInt16() : header;
|
||||
length = reader.ReadUInt16();
|
||||
height = reader.ReadUInt16();
|
||||
width = header == Version ? r.ReadUInt16() : header;
|
||||
length = r.ReadUInt16();
|
||||
height = r.ReadUInt16();
|
||||
|
||||
LocalPlayer p = game.LocalPlayer;
|
||||
p.Spawn.X = reader.ReadUInt16();
|
||||
p.Spawn.Z = reader.ReadUInt16();
|
||||
p.Spawn.Y = reader.ReadUInt16();
|
||||
p.SpawnYaw = (float)Utils.PackedToDegrees( reader.ReadByte() );
|
||||
p.SpawnPitch = (float)Utils.PackedToDegrees( reader.ReadByte() );
|
||||
p.Spawn.X = r.ReadUInt16();
|
||||
p.Spawn.Z = r.ReadUInt16();
|
||||
p.Spawn.Y = r.ReadUInt16();
|
||||
p.SpawnYaw = (float)Utils.PackedToDegrees( r.ReadByte() );
|
||||
p.SpawnPitch = (float)Utils.PackedToDegrees( r.ReadByte() );
|
||||
|
||||
if( header == Version )
|
||||
reader.ReadUInt16(); // pervisit and perbuild perms
|
||||
r.ReadUInt16(); // pervisit and perbuild perms
|
||||
byte[] blocks = new byte[width * height * length];
|
||||
int read = gs.Read( blocks, 0, blocks.Length );
|
||||
ConvertPhysicsBlocks( blocks );
|
||||
@ -59,7 +61,7 @@ namespace ClassicalSharp.Map {
|
||||
int bx = i & 0xF, by = (i >> 8) & 0xF, bz = (i >> 4) & 0xF;
|
||||
int index = baseIndex + (by * length + bz) * width + bx;
|
||||
|
||||
if( blocks[index] == 163 ) // custom block id
|
||||
if( blocks[index] == customTile )
|
||||
blocks[index] = chunk[i];
|
||||
}
|
||||
}
|
||||
@ -82,8 +84,8 @@ namespace ClassicalSharp.Map {
|
||||
34, 35, 36, 22, 20, 49, 45, 1, 4, 0, 9, 11, 4, 19, 5, 17, 10, 49, 20, 1,
|
||||
18, 12, 5, 25, 46, 44, 17, 49, 20, 1, 18, 12, 5, 25, 36, 34, 0, 9, 11, 46,
|
||||
44, 0, 9, 11, 8, 10, 22, 27, 22, 8, 10, 28, 17, 49, 20, 1, 18, 12, 5, 25, 46,
|
||||
44, 11, 9, 0, 9, 11, 163, 0, 0, 9, 11, 0, 0, 0, 0, 0, 0, 0, 28, 22, 21, 11,
|
||||
0, 0, 0, 46, 46, 10, 10, 46, 20, 41, 42, 11, 9, 0, 8, 10, 10, 8, 0, 22, 22,
|
||||
44, 11, 9, 0, 9, 11, customTile, 0, 0, 9, 11, 0, 0, 0, 0, 0, 0, 0, 28, 22, 21,
|
||||
11, 0, 0, 0, 46, 46, 10, 10, 46, 20, 41, 42, 11, 9, 0, 8, 10, 10, 8, 0, 22, 22,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 22, 22, 42, 3, 2, 29,
|
||||
47, 0, 0, 0, 0, 0, 27, 46, 48, 24, 22, 36, 34, 8, 10, 21, 29, 22, 10, 22, 22,
|
||||
41, 19, 35, 21, 29, 49, 34, 16, 41, 0, 22 };
|
||||
|
73
ClassicalSharp/Map/Formats/MapSchematic.Exporter.cs
Normal file
73
ClassicalSharp/Map/Formats/MapSchematic.Exporter.cs
Normal file
@ -0,0 +1,73 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace ClassicalSharp.Map {
|
||||
|
||||
public sealed class MapSchematicExporter : IMapFormatExporter {
|
||||
|
||||
public void Save( Stream stream, Game game ) {
|
||||
using( GZipStream wrapper = new GZipStream( stream, CompressionMode.Compress ) ) {
|
||||
BinaryWriter writer = new BinaryWriter( wrapper );
|
||||
NbtFile nbt = new NbtFile( writer );
|
||||
World map = game.World;
|
||||
|
||||
nbt.Write( NbtTagType.Compound ); nbt.Write( "Schematic" );
|
||||
|
||||
nbt.Write( NbtTagType.String );
|
||||
nbt.Write( "Materials" ); nbt.Write( "Classic" );
|
||||
|
||||
nbt.Write( NbtTagType.Int16 );
|
||||
nbt.Write( "Width" ); nbt.WriteInt16( (short)map.Width );
|
||||
|
||||
nbt.Write( NbtTagType.Int16 );
|
||||
nbt.Write( "Height" ); nbt.WriteInt16( (short)map.Height );
|
||||
|
||||
nbt.Write( NbtTagType.Int16 );
|
||||
nbt.Write( "Length" ); nbt.WriteInt16( (short)map.Length );
|
||||
|
||||
WriteBlocks( nbt, map.mapData );
|
||||
|
||||
WriteBlockData( nbt, map.mapData );
|
||||
|
||||
nbt.Write( NbtTagType.List );
|
||||
nbt.Write( "Entities" );
|
||||
nbt.Write( NbtTagType.Compound ); nbt.WriteInt32( 0 );
|
||||
|
||||
nbt.Write( NbtTagType.List );
|
||||
nbt.Write( "TileEntities" );
|
||||
nbt.Write( NbtTagType.Compound ); nbt.WriteInt32( 0 );
|
||||
|
||||
nbt.Write( NbtTagType.End );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WriteBlocks( NbtFile nbt, byte[] blocks ) {
|
||||
const int chunkSize = 64 * 1024 * 32;
|
||||
nbt.Write( NbtTagType.Int8Array );
|
||||
nbt.Write( "Blocks" );
|
||||
nbt.WriteInt32( blocks.Length );
|
||||
|
||||
for( int i = 0; i < blocks.Length; i += chunkSize ) {
|
||||
int count = Math.Min( chunkSize, blocks.Length - i );
|
||||
nbt.WriteBytes( blocks, i, count );
|
||||
}
|
||||
}
|
||||
|
||||
void WriteBlockData( NbtFile nbt, byte[] blocks ) {
|
||||
const int chunkSize = 64 * 1024;
|
||||
byte[] chunk = new byte[chunkSize];
|
||||
nbt.Write( NbtTagType.Int8Array );
|
||||
nbt.Write( "Data" );
|
||||
nbt.WriteInt32( blocks.Length );
|
||||
|
||||
for( int i = 0; i < blocks.Length; i += chunkSize ) {
|
||||
// All 0 so we can skip this.
|
||||
int count = Math.Min( chunkSize, blocks.Length - i );
|
||||
nbt.WriteBytes( chunk, 0, count );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -55,6 +55,8 @@ namespace ClassicalSharp.Map {
|
||||
|
||||
public void WriteBytes( byte[] v ) { writer.Write( v ); }
|
||||
|
||||
public void WriteBytes( byte[] v, int index, int count ) { writer.Write( v, index, count ); }
|
||||
|
||||
public void Write( string value ) {
|
||||
ushort len = (ushort)value.Length;
|
||||
byte[] data = Encoding.UTF8.GetBytes( value );
|
||||
|
@ -56,6 +56,13 @@ namespace ClassicalSharp {
|
||||
other.Max.X <= Max.X && other.Max.Y <= Max.Y && other.Max.Z <= Max.Z;
|
||||
}
|
||||
|
||||
/// <summary> Determines whether this bounding box entirely contains
|
||||
/// the coordinates on all axes. </summary>
|
||||
public bool Contains( Vector3 P ) {
|
||||
return P.X >= Min.X && P.Y >= Min.Y && P.Z >= Min.Z &&
|
||||
P.X <= Max.X && P.Y <= Max.Y && P.Z <= Max.Z;
|
||||
}
|
||||
|
||||
/// <summary> Determines whether this bounding box intersects
|
||||
/// the given bounding box on the X axis. </summary>
|
||||
public bool XIntersects( BoundingBox box ) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ClassicalSharp.Events;
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
|
||||
namespace ClassicalSharp.Model {
|
||||
@ -23,6 +24,7 @@ namespace ClassicalSharp.Model {
|
||||
model.CreateParts();
|
||||
cache["humanoid"] = model;
|
||||
cache["human"] = cache["humanoid"];
|
||||
game.Events.TextureChanged += TextureChanged;
|
||||
}
|
||||
|
||||
internal int vb;
|
||||
@ -62,10 +64,11 @@ namespace ClassicalSharp.Model {
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
foreach( var entry in cache ) {
|
||||
foreach( var entry in cache )
|
||||
entry.Value.Dispose();
|
||||
}
|
||||
api.DeleteDynamicVb( vb );
|
||||
game.Events.TextureChanged -= TextureChanged;
|
||||
|
||||
api.DeleteTexture( ref ChickenTexId );
|
||||
api.DeleteTexture( ref CreeperTexId );
|
||||
api.DeleteTexture( ref PigTexId );
|
||||
@ -76,5 +79,28 @@ namespace ClassicalSharp.Model {
|
||||
api.DeleteTexture( ref SheepFurTexId );
|
||||
api.DeleteTexture( ref HumanoidTexId );
|
||||
}
|
||||
|
||||
void TextureChanged( object sender, TextureEventArgs e ) {
|
||||
switch( e.Name ) {
|
||||
case "chicken.png":
|
||||
game.UpdateTexture( ref ChickenTexId, e.Data, false ); break;
|
||||
case "creeper.png":
|
||||
game.UpdateTexture( ref CreeperTexId, e.Data, false ); break;
|
||||
case "pig.png":
|
||||
game.UpdateTexture( ref PigTexId, e.Data, false ); break;
|
||||
case "sheep.png":
|
||||
game.UpdateTexture( ref SheepTexId, e.Data, false ); break;
|
||||
case "skeleton.png":
|
||||
game.UpdateTexture( ref SkeletonTexId, e.Data, false ); break;
|
||||
case "spider.png":
|
||||
game.UpdateTexture( ref SpiderTexId, e.Data, false ); break;
|
||||
case "zombie.png":
|
||||
game.UpdateTexture( ref ZombieTexId, e.Data, false ); break;
|
||||
case "sheep_fur.png":
|
||||
game.UpdateTexture( ref SheepFurTexId, e.Data, false ); break;
|
||||
case "char.png":
|
||||
game.UpdateTexture( ref HumanoidTexId, e.Data, true ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ namespace ClassicalSharp {
|
||||
if( item.Data != null ) {
|
||||
Bitmap bmp = (Bitmap)item.Data;
|
||||
game.World.TextureUrl = item.Url;
|
||||
game.Animations.Dispose();
|
||||
game.Animations.Clear();
|
||||
|
||||
if( !FastBitmap.CheckFormat( bmp.PixelFormat ) ) {
|
||||
Utils.LogDebug( "Converting terrain atlas to 32bpp image" );
|
||||
@ -142,7 +142,7 @@ namespace ClassicalSharp {
|
||||
if( bmp == null ) {// Should never happen, but handle anyways.
|
||||
ExtractDefault();
|
||||
} else if( item.Url != game.World.TextureUrl ) {
|
||||
game.Animations.Dispose();
|
||||
game.Animations.Clear();
|
||||
if( !game.ChangeTerrainAtlas( bmp ) ) { bmp.Dispose(); return; }
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ namespace ClassicalSharp {
|
||||
if( game.AsyncDownloader.TryGetItem( "texturePack", out item ) ) {
|
||||
if( item.Data != null ) {
|
||||
game.World.TextureUrl = item.Url;
|
||||
game.Animations.Dispose();
|
||||
game.Animations.Clear();
|
||||
|
||||
TexturePackExtractor extractor = new TexturePackExtractor();
|
||||
extractor.Extract( (byte[])item.Data, game );
|
||||
@ -166,7 +166,7 @@ namespace ClassicalSharp {
|
||||
if( data == null ) { // Should never happen, but handle anyways.
|
||||
ExtractDefault();
|
||||
} else if( item.Url != game.World.TextureUrl ) {
|
||||
game.Animations.Dispose();
|
||||
game.Animations.Clear();
|
||||
TexturePackExtractor extractor = new TexturePackExtractor();
|
||||
extractor.Extract( data, game );
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ namespace ClassicalSharp.Net {
|
||||
writer.WriteInt16( (short)(pos.X * 32) );
|
||||
writer.WriteInt16( (short)((int)(pos.Y * 32) + 51) );
|
||||
writer.WriteInt16( (short)(pos.Z * 32) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( yaw, 256 ) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( pitch, 256 ) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( yaw ) );
|
||||
writer.WriteUInt8( (byte)Utils.DegreesToPacked( pitch ) );
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -172,8 +172,6 @@ namespace ClassicalSharp.Net {
|
||||
sentWomId = true;
|
||||
}
|
||||
gzipStream = null;
|
||||
ServerName = null;
|
||||
ServerMotd = null;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
@ -277,11 +275,11 @@ namespace ClassicalSharp.Net {
|
||||
if( entityId != 0xFF ) {
|
||||
Player oldPlayer = game.Players[entityId];
|
||||
if( oldPlayer != null ) {
|
||||
game.EntityEvents.RaiseEntityRemoved( entityId );
|
||||
game.EntityEvents.RaiseRemoved( entityId );
|
||||
oldPlayer.Despawn();
|
||||
}
|
||||
game.Players[entityId] = new NetPlayer( displayName, skinName, game, entityId );
|
||||
game.EntityEvents.RaiseEntityAdded( entityId );
|
||||
game.EntityEvents.RaiseAdded( entityId );
|
||||
} else {
|
||||
// Server is only allowed to change our own name colours.
|
||||
if( Utils.StripColours( displayName ) != game.Username )
|
||||
@ -309,7 +307,7 @@ namespace ClassicalSharp.Net {
|
||||
if( player == null ) return;
|
||||
|
||||
if( entityId != 0xFF ) {
|
||||
game.EntityEvents.RaiseEntityRemoved( entityId );
|
||||
game.EntityEvents.RaiseRemoved( entityId );
|
||||
player.Despawn();
|
||||
game.Players[entityId] = null;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ namespace ClassicalSharp.Network {
|
||||
worker.Start();
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) {
|
||||
lock( requestLocker )
|
||||
requests.Clear();
|
||||
|
@ -13,13 +13,12 @@ namespace ClassicalSharp.Particles {
|
||||
int[] terrain1DCount, terrain1DIndices;
|
||||
|
||||
Game game;
|
||||
Random rnd;
|
||||
Random rnd = new Random();
|
||||
int vb;
|
||||
const int maxParticles = 600;
|
||||
|
||||
public ParticleManager( Game game ) {
|
||||
this.game = game;
|
||||
rnd = new Random();
|
||||
vb = game.Graphics.CreateDynamicVb( VertexFormat.P3fT2fC4b, maxParticles * 4 );
|
||||
game.Events.TerrainAtlasChanged += TerrainAtlasChanged;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ namespace ClassicalSharp.Renderers {
|
||||
game.Events.HeldBlockChanged += HeldBlockChanged;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -27,13 +27,8 @@ namespace ClassicalSharp.Renderers {
|
||||
this.renderer = renderer;
|
||||
info = game.BlockInfo;
|
||||
|
||||
renderer._1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, info );
|
||||
renderer.totalUsed = new int[game.TerrainAtlas1D.TexIds.Length];
|
||||
RecalcBooleans( true );
|
||||
|
||||
builder = new ChunkMeshBuilder( game );
|
||||
api = game.Graphics;
|
||||
elementsPerBitmap = game.TerrainAtlas1D.elementsPerBitmap;
|
||||
|
||||
game.Events.TerrainAtlasChanged += TerrainAtlasChanged;
|
||||
game.WorldEvents.OnNewMap += OnNewMap;
|
||||
@ -93,11 +88,15 @@ namespace ClassicalSharp.Renderers {
|
||||
}
|
||||
|
||||
void TerrainAtlasChanged( object sender, EventArgs e ) {
|
||||
if( renderer._1DUsed == -1 ) {
|
||||
renderer.totalUsed = new int[game.TerrainAtlas1D.TexIds.Length];
|
||||
} else {
|
||||
bool refreshRequired = elementsPerBitmap != game.TerrainAtlas1D.elementsPerBitmap;
|
||||
elementsPerBitmap = game.TerrainAtlas1D.elementsPerBitmap;
|
||||
renderer._1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, info );
|
||||
|
||||
if( refreshRequired ) Refresh();
|
||||
}
|
||||
|
||||
renderer._1DUsed = game.TerrainAtlas1D.CalcMaxUsedRow( game.TerrainAtlas, info );
|
||||
elementsPerBitmap = game.TerrainAtlas1D.elementsPerBitmap;
|
||||
RecalcBooleans( true );
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ namespace ClassicalSharp.Renderers {
|
||||
game.WorldEvents.EnvVariableChanged += EnvVariableChanged;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public virtual void Reset( Game game ) { OnNewMap( game ); }
|
||||
|
||||
public abstract void OnNewMap( Game game );
|
||||
|
@ -33,10 +33,6 @@ namespace ClassicalSharp.Renderers {
|
||||
game.WorldEvents.EnvVariableChanged += EnvVariableChanged;
|
||||
game.Events.ViewDistanceChanged += ResetSidesAndEdges;
|
||||
game.Events.TerrainAtlasChanged += ResetTextures;
|
||||
|
||||
MakeTexture( ref edgeTexId, ref lastEdgeTexLoc, map.EdgeBlock );
|
||||
MakeTexture( ref sideTexId, ref lastSideTexLoc, map.SidesBlock );
|
||||
ResetSidesAndEdges( null, null );
|
||||
}
|
||||
|
||||
public void Render( double deltaTime ) {
|
||||
@ -81,6 +77,7 @@ namespace ClassicalSharp.Renderers {
|
||||
sidesVb = edgesVb = -1;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { OnNewMap( game ); }
|
||||
|
||||
public void OnNewMap( Game game ) {
|
||||
|
@ -42,7 +42,7 @@ namespace ClassicalSharp.Renderers {
|
||||
Game game;
|
||||
IGraphicsApi api;
|
||||
|
||||
internal int _1DUsed = 1;
|
||||
internal int _1DUsed = -1;
|
||||
internal ChunkInfo[] chunks, unsortedChunks;
|
||||
internal bool[] usedTranslucent, usedNormal;
|
||||
internal bool[] pendingTranslucent, pendingNormal;
|
||||
|
@ -37,14 +37,14 @@ namespace ClassicalSharp.Renderers {
|
||||
}
|
||||
|
||||
RenderClouds( deltaTime );
|
||||
ResetFog();
|
||||
UpdateFog();
|
||||
}
|
||||
|
||||
protected override void EnvVariableChanged( object sender, EnvVarEventArgs e ) {
|
||||
if( e.Var == EnvVar.SkyColour ) {
|
||||
ResetSky();
|
||||
} else if( e.Var == EnvVar.FogColour ) {
|
||||
ResetFog();
|
||||
UpdateFog();
|
||||
} else if( e.Var == EnvVar.CloudsColour ) {
|
||||
ResetClouds();
|
||||
} else if( e.Var == EnvVar.CloudsLevel ) {
|
||||
@ -55,6 +55,7 @@ namespace ClassicalSharp.Renderers {
|
||||
|
||||
public override void Init( Game game ) {
|
||||
base.Init( game );
|
||||
graphics.SetFogStart( 0 );
|
||||
graphics.Fog = true;
|
||||
ResetAllEnv( null, null );
|
||||
game.Events.ViewDistanceChanged += ResetAllEnv;
|
||||
@ -73,7 +74,7 @@ namespace ClassicalSharp.Renderers {
|
||||
}
|
||||
|
||||
void ResetAllEnv( object sender, EventArgs e ) {
|
||||
ResetFog();
|
||||
UpdateFog();
|
||||
ResetSky();
|
||||
ResetClouds();
|
||||
}
|
||||
@ -116,30 +117,27 @@ namespace ClassicalSharp.Renderers {
|
||||
return blend;
|
||||
}
|
||||
|
||||
void ResetFog() {
|
||||
void UpdateFog() {
|
||||
if( map.IsNotLoaded ) return;
|
||||
FastColour adjFogCol = FastColour.White;
|
||||
BlockInfo info = game.BlockInfo;
|
||||
BoundingBox pBounds = game.LocalPlayer.CollisionBounds;
|
||||
|
||||
Vector3I headCoords = Vector3I.Floor( game.LocalPlayer.EyePosition );
|
||||
Vector3 pos = (Vector3)headCoords;
|
||||
byte headBlock = game.World.SafeGetBlock( headCoords );
|
||||
BoundingBox blockBB = new BoundingBox( pos + game.BlockInfo.MinBB[headBlock],
|
||||
pos + game.BlockInfo.MaxBB[headBlock] );
|
||||
BoundingBox localBB = game.LocalPlayer.CollisionBounds;
|
||||
bool intersecting = blockBB.Intersects( localBB );
|
||||
Vector3 pos = game.CurrentCameraPos;
|
||||
Vector3I coords = Vector3I.Floor( pos );
|
||||
byte block = game.World.SafeGetBlock( coords );
|
||||
BoundingBox blockBB = new BoundingBox(
|
||||
(Vector3)coords + info.MinBB[block],
|
||||
(Vector3)coords + info.MaxBB[block] );
|
||||
|
||||
if( intersecting && info.FogDensity[headBlock] != 0 ) {
|
||||
if( blockBB.Contains( pos ) && info.FogDensity[block] != 0 ) {
|
||||
graphics.SetFogMode( Fog.Exp );
|
||||
graphics.SetFogDensity( info.FogDensity[headBlock] );
|
||||
adjFogCol = info.FogColour[headBlock];
|
||||
graphics.SetFogDensity( info.FogDensity[block] );
|
||||
adjFogCol = info.FogColour[block];
|
||||
} else {
|
||||
// Blend fog and sky together
|
||||
float blend = (float)BlendFactor( game.ViewDistance );
|
||||
adjFogCol = FastColour.Lerp( map.FogCol, map.SkyCol, blend );
|
||||
graphics.SetFogMode( Fog.Linear );
|
||||
graphics.SetFogStart( 0 );
|
||||
graphics.SetFogEnd( game.ViewDistance );
|
||||
}
|
||||
graphics.ClearColour( adjFogCol );
|
||||
|
@ -1,5 +1,7 @@
|
||||
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
||||
using System;
|
||||
using System.IO;
|
||||
using ClassicalSharp.Events;
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
using ClassicalSharp.Map;
|
||||
using OpenTK;
|
||||
@ -12,6 +14,7 @@ namespace ClassicalSharp.Renderers {
|
||||
World map;
|
||||
IGraphicsApi graphics;
|
||||
BlockInfo info;
|
||||
public int RainTexId, SnowTexId;
|
||||
|
||||
public void Init( Game game ) {
|
||||
this.game = game;
|
||||
@ -19,6 +22,7 @@ namespace ClassicalSharp.Renderers {
|
||||
graphics = game.Graphics;
|
||||
info = game.BlockInfo;
|
||||
weatherVb = graphics.CreateDynamicVb( VertexFormat.P3fT2fC4b, vertices.Length );
|
||||
game.Events.TextureChanged += TextureChanged;
|
||||
}
|
||||
|
||||
int weatherVb;
|
||||
@ -34,7 +38,7 @@ namespace ClassicalSharp.Renderers {
|
||||
if( weather == Weather.Sunny ) return;
|
||||
if( heightmap == null ) InitHeightmap();
|
||||
|
||||
graphics.BindTexture( weather == Weather.Rainy ? game.RainTexId : game.SnowTexId );
|
||||
graphics.BindTexture( weather == Weather.Rainy ? RainTexId : SnowTexId );
|
||||
Vector3 camPos = game.CurrentCameraPos;
|
||||
Vector3I pos = Vector3I.Floor( camPos );
|
||||
bool moved = pos != lastPos;
|
||||
@ -94,6 +98,7 @@ namespace ClassicalSharp.Renderers {
|
||||
}
|
||||
|
||||
int length, width, maxY, oneY;
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { OnNewMap( game ); }
|
||||
|
||||
public void OnNewMap( Game game ) {
|
||||
@ -108,6 +113,21 @@ namespace ClassicalSharp.Renderers {
|
||||
oneY = length * width;
|
||||
}
|
||||
|
||||
void TextureChanged( object sender, TextureEventArgs e ) {
|
||||
if( e.Name == "snow.png" ) {
|
||||
game.UpdateTexture( ref SnowTexId, e.Data, false );
|
||||
} else if( e.Name == "rain.png" ) {
|
||||
game.UpdateTexture( ref RainTexId, e.Data, false );
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
game.Graphics.DeleteTexture( ref RainTexId );
|
||||
game.Graphics.DeleteTexture( ref SnowTexId );
|
||||
graphics.DeleteDynamicVb( weatherVb );
|
||||
game.Events.TextureChanged -= TextureChanged;
|
||||
}
|
||||
|
||||
void InitHeightmap() {
|
||||
heightmap = new short[map.Width * map.Length];
|
||||
for( int i = 0; i < heightmap.Length; i++ ) {
|
||||
@ -115,10 +135,6 @@ namespace ClassicalSharp.Renderers {
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
graphics.DeleteDynamicVb( weatherVb );
|
||||
}
|
||||
|
||||
float GetRainHeight( int x, int z ) {
|
||||
if( x < 0 || z < 0 || x >= width || z >= length ) return map.EdgeHeight;
|
||||
int index = (x * length) + z;
|
||||
|
@ -15,6 +15,7 @@ namespace ClassicalSharp.Selections {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -17,6 +17,7 @@ namespace ClassicalSharp.Renderers {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -18,6 +18,7 @@ namespace ClassicalSharp.Selections {
|
||||
Graphics = game.Graphics;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { selections.Clear(); }
|
||||
public void OnNewMap( Game game ) { selections.Clear(); }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
@ -36,8 +36,8 @@ namespace ClassicalSharp.Singleplayer {
|
||||
game.LocalPlayer.SkinName );
|
||||
|
||||
game.Events.RaiseBlockPermissionsChanged();
|
||||
int seed = 500;//new Random().Next();
|
||||
GenMap( 256, 256, 256, seed, new NotchyGenerator() );
|
||||
int seed = new Random().Next();
|
||||
GenMap( 128, 64, 128, seed, new NotchyGenerator() );
|
||||
}
|
||||
|
||||
char lastCol = '\0';
|
||||
@ -102,9 +102,8 @@ namespace ClassicalSharp.Singleplayer {
|
||||
IMapGenerator gen = generator;
|
||||
game.World.SetData( generatedMap, gen.Width, gen.Height, gen.Length );
|
||||
generatedMap = null;
|
||||
|
||||
game.WorldEvents.RaiseOnNewMapLoaded();
|
||||
ResetPlayerPosition();
|
||||
game.WorldEvents.RaiseOnNewMapLoaded();
|
||||
}
|
||||
|
||||
generator = null;
|
||||
@ -133,6 +132,7 @@ namespace ClassicalSharp.Singleplayer {
|
||||
LocationUpdate update = LocationUpdate.MakePosAndOri( x, y, z, 0, 0, false );
|
||||
game.LocalPlayer.SetLocation( update, false );
|
||||
game.LocalPlayer.Spawn = new Vector3( x, y, z );
|
||||
game.CurrentCameraPos = game.Camera.GetCameraPos( game.LocalPlayer.EyePosition );
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using ClassicalSharp.Events;
|
||||
using ClassicalSharp.GraphicsAPI;
|
||||
#if ANDROID
|
||||
using Android.Graphics;
|
||||
@ -11,7 +12,7 @@ using Android.Graphics;
|
||||
namespace ClassicalSharp.TexturePack {
|
||||
|
||||
/// <summary> Contains and describes the various animations applied to the terrain atlas. </summary>
|
||||
public class Animations {
|
||||
public class Animations : IGameComponent {
|
||||
|
||||
Game game;
|
||||
IGraphicsApi api;
|
||||
@ -19,14 +20,34 @@ namespace ClassicalSharp.TexturePack {
|
||||
FastBitmap fastBmp;
|
||||
List<AnimationData> animations = new List<AnimationData>();
|
||||
|
||||
public Animations( Game game ) {
|
||||
public void Init( Game game ) {
|
||||
this.game = game;
|
||||
api = game.Graphics;
|
||||
game.Events.TextureChanged += TextureChanged;
|
||||
}
|
||||
|
||||
public void Ready( Game game ) { }
|
||||
public void Reset( Game game ) { }
|
||||
public void OnNewMap( Game game ) { }
|
||||
public void OnNewMapLoaded( Game game ) { }
|
||||
|
||||
void TextureChanged( object sender, TextureEventArgs e ) {
|
||||
if( e.Name == "animations.png" || e.Name == "animation.png" ) {
|
||||
MemoryStream stream = new MemoryStream( e.Data );
|
||||
SetAtlas( Platform.ReadBmp( stream ) );
|
||||
} else if( e.Name == "animations.txt" || e.Name == "animation.txt" ) {
|
||||
MemoryStream stream = new MemoryStream( e.Data );
|
||||
StreamReader reader = new StreamReader( stream );
|
||||
ReadAnimationsDescription( reader );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Sets the atlas bitmap that animation frames are contained within. </summary>
|
||||
public void SetAtlas( Bitmap bmp ) {
|
||||
Dispose();
|
||||
if( !FastBitmap.CheckFormat( bmp.PixelFormat ) )
|
||||
game.Drawer2D.ConvertTo32Bpp( ref bmp );
|
||||
|
||||
Clear();
|
||||
this.bmp = bmp;
|
||||
fastBmp = new FastBitmap( bmp, true, true );
|
||||
}
|
||||
@ -124,12 +145,17 @@ namespace ClassicalSharp.TexturePack {
|
||||
|
||||
/// <summary> Disposes the atlas bitmap that contains animation frames, and clears
|
||||
/// the list of defined animations. </summary>
|
||||
public void Dispose() {
|
||||
public void Clear() {
|
||||
animations.Clear();
|
||||
|
||||
if( bmp == null ) return;
|
||||
fastBmp.Dispose(); fastBmp = null;
|
||||
bmp.Dispose(); bmp = null;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
Clear();
|
||||
game.Events.TextureChanged -= TextureChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace ClassicalSharp.TexturePack {
|
||||
|
||||
void Extract( Stream stream, Game game ) {
|
||||
this.game = game;
|
||||
game.Animations.Dispose();
|
||||
game.Animations.Clear();
|
||||
ZipReader reader = new ZipReader();
|
||||
|
||||
reader.ShouldProcessZipEntry = (f) => true;
|
||||
@ -50,53 +50,20 @@ namespace ClassicalSharp.TexturePack {
|
||||
Bitmap atlas = Platform.ReadBmp( stream );
|
||||
if( !game.ChangeTerrainAtlas( atlas ) ) atlas.Dispose();
|
||||
break;
|
||||
case "chicken.png":
|
||||
UpdateTexture( ref cache.ChickenTexId, stream, false ); break;
|
||||
case "creeper.png":
|
||||
UpdateTexture( ref cache.CreeperTexId, stream, false ); break;
|
||||
case "pig.png":
|
||||
UpdateTexture( ref cache.PigTexId, stream, false ); break;
|
||||
case "sheep.png":
|
||||
UpdateTexture( ref cache.SheepTexId, stream, false ); break;
|
||||
case "skeleton.png":
|
||||
UpdateTexture( ref cache.SkeletonTexId, stream, false ); break;
|
||||
case "spider.png":
|
||||
UpdateTexture( ref cache.SpiderTexId, stream, false ); break;
|
||||
case "zombie.png":
|
||||
UpdateTexture( ref cache.ZombieTexId, stream, false ); break;
|
||||
case "sheep_fur.png":
|
||||
UpdateTexture( ref cache.SheepFurTexId, stream, false ); break;
|
||||
case "char.png":
|
||||
UpdateTexture( ref cache.HumanoidTexId, stream, true ); break;
|
||||
case "clouds.png":
|
||||
case "cloud.png":
|
||||
UpdateTexture( ref game.CloudsTexId, stream, false ); break;
|
||||
case "rain.png":
|
||||
UpdateTexture( ref game.RainTexId, stream, false ); break;
|
||||
case "snow.png":
|
||||
UpdateTexture( ref game.SnowTexId, stream, false ); break;
|
||||
game.UpdateTexture( ref game.CloudsTexId, data, false ); break;
|
||||
case "gui.png":
|
||||
UpdateTexture( ref game.GuiTexId, stream, false ); break;
|
||||
game.UpdateTexture( ref game.GuiTexId, data, false ); break;
|
||||
case "gui_classic.png":
|
||||
UpdateTexture( ref game.GuiClassicTexId, stream, false ); break;
|
||||
case "animations.png":
|
||||
case "animation.png":
|
||||
game.Animations.SetAtlas( Platform.ReadBmp( stream ) ); break;
|
||||
case "animations.txt":
|
||||
case "animation.txt":
|
||||
StreamReader reader = new StreamReader( stream );
|
||||
game.Animations.ReadAnimationsDescription( reader );
|
||||
break;
|
||||
game.UpdateTexture( ref game.GuiClassicTexId, data, false ); break;
|
||||
case "particles.png":
|
||||
UpdateTexture( ref game.ParticleManager.ParticlesTexId,
|
||||
stream, false ); break;
|
||||
game.UpdateTexture( ref game.ParticleManager.ParticlesTexId,
|
||||
data, false ); break;
|
||||
case "default.png":
|
||||
SetFontBitmap( game, stream ); break;
|
||||
}
|
||||
|
||||
if( !name.EndsWith( ".png" ) ) return;
|
||||
string tex = name.Substring( 0, name.Length - 4 );
|
||||
game.Events.RaiseTextureChanged( tex );
|
||||
game.Events.RaiseTextureChanged( name, data );
|
||||
}
|
||||
|
||||
void SetFontBitmap( Game game, Stream stream ) {
|
||||
@ -106,20 +73,5 @@ namespace ClassicalSharp.TexturePack {
|
||||
game.Drawer2D.SetFontBitmap( bmp );
|
||||
game.Events.RaiseChatFontChanged();
|
||||
}
|
||||
|
||||
void UpdateTexture( ref int texId, Stream stream, bool setSkinType ) {
|
||||
game.Graphics.DeleteTexture( ref texId );
|
||||
using( Bitmap bmp = Platform.ReadBmp( stream ) ) {
|
||||
if( setSkinType )
|
||||
game.DefaultPlayerSkinType = Utils.GetSkinType( bmp );
|
||||
|
||||
if( !FastBitmap.CheckFormat( bmp.PixelFormat ) ) {
|
||||
using( Bitmap bmp32 = game.Drawer2D.ConvertTo32Bpp( bmp ) )
|
||||
texId = game.Graphics.CreateTexture( bmp32 );
|
||||
} else {
|
||||
texId = game.Graphics.CreateTexture( bmp );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,15 +110,28 @@ namespace ClassicalSharp {
|
||||
UpdateMouseRotation();
|
||||
}
|
||||
|
||||
protected float bobYOffset = 0;
|
||||
protected float bobYOffset = 0, tilt = 0;
|
||||
bool finishedTilt = true;
|
||||
protected void CalcViewBobbing( double delta ) {
|
||||
LocalPlayer p = game.LocalPlayer;
|
||||
if( !game.ViewBobbing || !game.LocalPlayer.onGround ) {
|
||||
// When player leaves the ground, still want to finish the current bob cycle.
|
||||
if( finishedTilt || FinishTilt() ) return;
|
||||
}
|
||||
|
||||
tilt = p.anim.tilt;
|
||||
tiltMatrix = Matrix4.RotateZ( tilt );
|
||||
bobYOffset = p.anim.bobYOffset * (2.0f/2.5f);
|
||||
finishedTilt = false;
|
||||
}
|
||||
|
||||
bool FinishTilt() {
|
||||
LocalPlayer p = game.LocalPlayer;
|
||||
if( Math.Sign( tilt ) == Math.Sign( p.anim.tilt ) ) return false;
|
||||
tiltMatrix = Matrix4.Identity;
|
||||
bobYOffset = 0;
|
||||
} else {
|
||||
tiltMatrix = Matrix4.RotateZ( game.LocalPlayer.anim.tilt );
|
||||
bobYOffset = game.LocalPlayer.anim.bobYOffset * (2.0f/2.5f);
|
||||
}
|
||||
finishedTilt = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,10 @@ namespace ClassicalSharp {
|
||||
return (int)(degrees * period / 360.0) % period;
|
||||
}
|
||||
|
||||
public static int DegreesToPacked( double degrees ) {
|
||||
return (int)(degrees * 256 / 360.0) & 0xFF;
|
||||
}
|
||||
|
||||
public static double PackedToDegrees( byte packed ) {
|
||||
return packed * 360.0 / 256.0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user