diff --git a/ClassicalSharp.sln b/ClassicalSharp.sln index f812403c2..06c6fef8c 100644 --- a/ClassicalSharp.sln +++ b/ClassicalSharp.sln @@ -1,6 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 # SharpDevelop 4.4 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassicalSharp", "ClassicalSharp\ClassicalSharp.csproj", "{BEB1C785-5CAD-48FF-A886-876BF0A318D4}" EndProject diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index 5750af17b..93eb1b6f4 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -33,8 +33,8 @@ False DEBUG;TRACE Project - wwwf null 127.0.0.1 25566 obj\ + wwwf null 127.0.0.1 25566 ..\output\release\ @@ -129,7 +129,6 @@ - @@ -156,6 +155,8 @@ + + @@ -187,6 +188,7 @@ + diff --git a/ClassicalSharp/Commands/CommandManager.cs b/ClassicalSharp/Commands/CommandManager.cs index e0b0f07c2..b5698774e 100644 --- a/ClassicalSharp/Commands/CommandManager.cs +++ b/ClassicalSharp/Commands/CommandManager.cs @@ -23,7 +23,7 @@ namespace ClassicalSharp.Commands { RegisterCommand( new ViewDistanceCommand() ); } - void RegisterCommand( Command command ) { + public void RegisterCommand( Command command ) { command.Window = Window; foreach( Command cmd in RegisteredCommands ) { if( Utils.CaselessEquals( cmd.Name, command.Name ) ) { diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 16a4b0e7d..c48cc6d1b 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -139,7 +139,11 @@ namespace ClassicalSharp { MapRenderer = new MapRenderer( this ); MapEnvRenderer = new MapEnvRenderer( this ); EnvRenderer = new StandardEnvRenderer( this ); - Network = new NetworkProcessor( this ); + if( IPAddress == null ) { + Network = new Singleplayer.SinglePlayerServer( this ); + } else { + Network = new NetworkProcessor( this ); + } firstPersonCam = new FirstPersonCamera( this ); thirdPersonCam = new ThirdPersonCamera( this ); Camera = firstPersonCam; diff --git a/ClassicalSharp/Program.cs b/ClassicalSharp/Program.cs index f78bc48cb..38ac9d72e 100644 --- a/ClassicalSharp/Program.cs +++ b/ClassicalSharp/Program.cs @@ -18,31 +18,41 @@ namespace ClassicalSharp { if( !AllResourcesExist( "terrain.png", "char.png", "clouds.png" ) ) { return; } - if( args.Length < 4 ) { + if( args.Length == 0 ) { + Utils.Log( "Starting singleplayer mode." ); + using( Game game = new Game() ) { + game.Username = "LocalPlayer"; + game.skinServer = "http://s3.amazonaws.com/MinecraftSkins/"; + game.Run(); + } + } else if( args.Length < 4 ) { Fail( "ClassicalSharp.exe is only the raw client. You must either use the launcher or" + " provide command line arguments to start the client." ); - return; + } else { + RunMultiplayer( args ); + } + } + + static void RunMultiplayer( string[] args ) { + IPAddress ip = null; + if( !IPAddress.TryParse( args[2], out ip ) ) { + Fail( "Invalid IP \"" + args[2] + '"' ); } - IPAddress ip = null; - if( !IPAddress.TryParse( args[2], out ip ) ) { - Fail( "Invalid IP \"" + args[2] + '"' ); - } + int port = 0; + if( !Int32.TryParse( args[3], out port ) ) { + Fail( "Invalid port \"" + args[3] + '"' ); + return; + } else if( port < ushort.MinValue || port > ushort.MaxValue ) { + Fail( "Specified port " + port + " is out of valid range." ); + } - int port = 0; - if( !Int32.TryParse( args[3], out port ) ) { - Fail( "Invalid port \"" + args[3] + '"' ); - return; - } else if( port < ushort.MinValue || port > ushort.MaxValue ) { - Fail( "Specified port " + port + " is out of valid range." ); - } - - string skinServer = args.Length >= 5 ? args[4] : "http://s3.amazonaws.com/MinecraftSkins/"; + string skinServer = args.Length >= 5 ? args[4] : "http://s3.amazonaws.com/MinecraftSkins/"; using( Game game = new Game() ) { game.Username = args[0]; game.Mppass = args[1]; game.IPAddress = ip; - game.Port = port; + game.Port = port; game.skinServer = skinServer; game.Run(); } @@ -87,7 +97,7 @@ namespace ClassicalSharp { "(and the circumstances that caused it) to github.com/UnknownShadow200/ClassicalSharp/issues" + Environment.NewLine + Environment.NewLine + error; - MessageBox.Show( "Oh dear. ClassicalSharp has crashed." + Environment.NewLine + Environment.NewLine + message, "ClassicalSharp has crashed" ); + MessageBox.Show( "Oh dear. ClassicalSharp has crashed." + Environment.NewLine + Environment.NewLine + message, "ClassicalSharp has crashed" ); Environment.Exit( 1 ); } } diff --git a/ClassicalSharp/Singleplayer/Commands.cs b/ClassicalSharp/Singleplayer/Commands.cs new file mode 100644 index 000000000..d6751565c --- /dev/null +++ b/ClassicalSharp/Singleplayer/Commands.cs @@ -0,0 +1,43 @@ +using System; +using ClassicalSharp.Commands; + +namespace ClassicalSharp.Singleplayer { + + /// Command that modifies the font size of chat in the normal gui screen. + public sealed class GenerateCommand : Command { + + public GenerateCommand() { + Name = "Generate"; + Help = new [] { + "&a/client generate [width height length]", + "&bwidth: &eSpecifies X-axis/width of the new map.", + "&bheight: &eSpecifies Y-axis/height of the new map.", + "&blength: &eSpecifies Z-axis/length of the new map.", + }; + } + + public override void Execute( CommandReader reader ) { + int width, height, length; + if( !reader.NextInt( out width ) || !reader.NextInt( out height ) || !reader.NextInt( out length ) ) { + Window.AddChat( "&e/client generate: &cInvalid dimensions." ); + } else { + if( width < 16 || height < 16 || length < 16 ) { + Window.AddChat( "&e/client generate: &cDimensions too small." ); + return; + } + if( width > 1024 || height > 1024 || length > 1024 ) { + Window.AddChat( "&e/client generate: &cDimensions too large." ); + return; + } + if( !( Window.Network is SinglePlayerServer ) ) { + Window.AddChat( "&e/client generate: &cThis command only works in singleplayer mode." ); + return; + } + SinglePlayerServer server = (SinglePlayerServer)Window.Network; + server.NewMap(); + Window.chatInInputBuffer = ""; + server.MakeMap( width, height, length ); + } + } + } +} diff --git a/ClassicalSharp/Network/SinglePlayerServer.cs b/ClassicalSharp/Singleplayer/Server.cs similarity index 73% rename from ClassicalSharp/Network/SinglePlayerServer.cs rename to ClassicalSharp/Singleplayer/Server.cs index 1153aa6b2..8b7e7cd84 100644 --- a/ClassicalSharp/Network/SinglePlayerServer.cs +++ b/ClassicalSharp/Singleplayer/Server.cs @@ -3,7 +3,7 @@ using System.Net; using OpenTK; using OpenTK.Input; -namespace ClassicalSharp { +namespace ClassicalSharp.Singleplayer { public sealed class SinglePlayerServer : INetworkProcessor { @@ -23,7 +23,8 @@ namespace ClassicalSharp { } game.RaiseBlockPermissionsChanged(); NewMap(); - MapLoaded(); + MakeMap( 128, 128, 128 ); + game.CommandManager.RegisterCommand( new GenerateCommand() ); } public override void SendChat( string text ) { @@ -48,7 +49,7 @@ namespace ClassicalSharp { if( Disconnected ) return; } - void NewMap() { + internal void NewMap() { ServerName = "Single player"; ServerMotd = "Generating a map.."; game.LocalPlayer.UserType = 0x64; @@ -58,25 +59,25 @@ namespace ClassicalSharp { game.SetNewScreen( new LoadingMapScreen( game, ServerName, ServerMotd ) ); } - void MapLoaded() { - game.SetNewScreen( new NormalScreen( game ) ); - int width = 16, height = 16, length = 16; + internal unsafe void MakeMap( int width, int height, int length ) { byte[] map = new byte[width * height * length]; - MapSet( width, length, map, 0, height / 2 - 2, (byte)Block.Dirt ); - MapSet( width, length, map, height / 2 - 1, height / 2 - 1, (byte)Block.Grass ); + var sw = System.Diagnostics.Stopwatch.StartNew(); + fixed( byte* ptr = map ) { + MapSet( width, length, ptr, 0, height / 2 - 2, (byte)Block.Dirt ); + MapSet( width, length, ptr, height / 2 - 1, height / 2 - 1, (byte)Block.Grass ); + } game.Map.UseRawMap( map, width, height, length ); game.RaiseOnNewMapLoaded(); + game.SetNewScreen( new NormalScreen( game ) ); ResetPlayerPosition(); game.AddChat( "&ePlaying single player", CpeMessage.Status1 ); GC.Collect(); } - void MapSet( int width, int length, byte[] map, int yStart, int yEnd, byte block ) { + unsafe void MapSet( int width, int length, byte* ptr, int yStart, int yEnd, byte block ) { int startIndex = yStart * length * width; int endIndex = ( yEnd * length + (length - 1) ) * width + (width - 1); - for( int i = startIndex; i <= endIndex; i++ ) { - map[i] = block; - } + MemUtils.memset( (IntPtr)ptr, block, startIndex, endIndex - startIndex + 1 ); } void ResetPlayerPosition() { diff --git a/OpenTK/MemUtils.cs b/OpenTK/MemUtils.cs new file mode 100644 index 000000000..90032e0eb --- /dev/null +++ b/OpenTK/MemUtils.cs @@ -0,0 +1,67 @@ +using System; + +namespace OpenTK { + + public static class MemUtils { + + static MemUtils() { + use64Bit = IntPtr.Size == 8; + } + static bool use64Bit; + + public static unsafe void memcpy( IntPtr srcPtr, IntPtr dstPtr, int bytes ) { + byte* srcByte, dstByte; + if( use64Bit ) { + ulong* srcLong = (ulong*)srcPtr, dstLong = (ulong*)dstPtr; + while( bytes >= 8 ) { + *dstLong++ = *srcLong++; + bytes -= 8; + } + srcByte = (byte*)srcLong; dstByte = (byte*)dstLong; + } else { + uint* srcInt = (uint*)srcPtr, dstInt = (uint*)dstPtr; + while( bytes >= 4 ) { + *dstInt++ = *srcInt++; + bytes -= 4; + } + srcByte = (byte*)srcInt; dstByte = (byte*)dstInt; + } + + for( int i = 0; i < bytes; i++ ) { + *dstByte++ = *srcByte++; + } + } + + public static unsafe void memset( IntPtr srcPtr, byte value, int startIndex, int bytes ) { + byte* srcByte = (byte*)srcPtr + startIndex; + // Make sure we do an aligned write/read for the bulk copy + while( bytes > 0 && ( startIndex & 0x7 ) != 0 ) { + *srcByte++ = value; + startIndex++; + bytes--; + } + uint valueInt = (uint)( ( value << 24 ) | ( value << 16 ) | ( value << 8 ) | value ); + + if( use64Bit ) { + ulong valueLong = ( (ulong)valueInt << 32 ) | valueInt; + ulong* srcLong = (ulong*)srcByte; + while( bytes >= 8 ) { + *srcLong++ = valueLong; + bytes -= 8; + } + srcByte = (byte*)srcLong; + } else { + uint* srcInt = (uint*)srcByte; + while( bytes >= 4 ) { + *srcInt++ = valueInt; + bytes -= 4; + } + srcByte = (byte*)srcInt; + } + + for( int i = 0; i < bytes; i++ ) { + *srcByte++ = value; + } + } + } +} diff --git a/OpenTK/OpenTK.csproj b/OpenTK/OpenTK.csproj index 74b55b2e3..96d48cce1 100644 --- a/OpenTK/OpenTK.csproj +++ b/OpenTK/OpenTK.csproj @@ -51,7 +51,6 @@ - @@ -62,6 +61,7 @@ + @@ -80,6 +80,7 @@ + diff --git a/OpenTK/Configuration.cs b/OpenTK/Platform/Configuration.cs similarity index 100% rename from OpenTK/Configuration.cs rename to OpenTK/Platform/Configuration.cs diff --git a/OpenTK/SharpDX.Direct3D/Direct3D.cs b/OpenTK/SharpDX.Direct3D/Direct3D.cs index d5da9b49b..be8f42bad 100644 --- a/OpenTK/SharpDX.Direct3D/Direct3D.cs +++ b/OpenTK/SharpDX.Direct3D/Direct3D.cs @@ -34,7 +34,6 @@ namespace SharpDX.Direct3D9 { Adapters = new List( count ); for( int i = 0; i < count; i++ ) Adapters.Add( new AdapterInformation( this, i ) ); - memcpy64Bit = IntPtr.Size == 8; } public List Adapters; @@ -104,29 +103,5 @@ namespace SharpDX.Direct3D9 { if( res < 0 ) { throw new SharpDXException( res ); } return new Device( devicePtr ); } - - // TODO: Place this in a utilities class. - static bool memcpy64Bit; - internal static unsafe void memcpy( IntPtr srcPtr, IntPtr dstPtr, int bytes ) { - byte* srcByte, dstByte; - if( memcpy64Bit ) { - long* srcLong = (long*)srcPtr, dstLong = (long*)dstPtr; - while( bytes >= 8 ) { - *dstLong++ = *srcLong++; - bytes -= 8; - } - srcByte = (byte*)srcLong; dstByte = (byte*)dstLong; - } else { - int* srcInt = (int*)srcPtr, dstInt = (int*)dstPtr; - while( bytes >= 4 ) { - *dstInt++ = *srcInt++; - bytes -= 4; - } - srcByte = (byte*)srcInt; dstByte = (byte*)dstInt; - } - for( int i = 0; i < bytes; i++ ) { - *dstByte++ = *srcByte++; - } - } } } diff --git a/OpenTK/SharpDX.Direct3D/Resources.cs b/OpenTK/SharpDX.Direct3D/Resources.cs index b725b1c6a..63fb0dadf 100644 --- a/OpenTK/SharpDX.Direct3D/Resources.cs +++ b/OpenTK/SharpDX.Direct3D/Resources.cs @@ -57,14 +57,14 @@ namespace SharpDX.Direct3D9 { public void SetData( IntPtr data, int bytes, LockFlags flags ) { IntPtr dst = Lock( 0, bytes, flags ); - Direct3D.memcpy( data, dst, bytes ); + MemUtils.memcpy( data, dst, bytes ); Unlock(); } public void SetData( T[] data, int bytes, LockFlags flags ) where T : struct { IntPtr src = Interop.Fixed( ref data[0] ); IntPtr dst = Lock( 0, bytes, flags ); - Direct3D.memcpy( src, dst, bytes ); + MemUtils.memcpy( src, dst, bytes ); Unlock(); } @@ -108,7 +108,7 @@ namespace SharpDX.Direct3D9 { public void SetData( IntPtr data, int bytes, int level, LockFlags flags ) { LockedRectangle rect = LockRectangle( level, flags ); - Direct3D.memcpy( data, rect.DataPointer, bytes ); + MemUtils.memcpy( data, rect.DataPointer, bytes ); UnlockRectangle( level ); }