diff --git a/ClassicalSharp/2D/Screens/BlockSelectScreen.cs b/ClassicalSharp/2D/Screens/BlockSelectScreen.cs index d60033cda..5cfb907a1 100644 --- a/ClassicalSharp/2D/Screens/BlockSelectScreen.cs +++ b/ClassicalSharp/2D/Screens/BlockSelectScreen.cs @@ -187,8 +187,8 @@ namespace ClassicalSharp { } public override bool HandlesKeyDown( Key key ) { - if( key == game.Mapping( KeyMapping.PauseOrExit ) || - key == game.Mapping( KeyMapping.OpenInventory ) ) { + if( key == game.Mapping( KeyBinding.PauseOrExit ) || + key == game.Mapping( KeyBinding.OpenInventory ) ) { game.SetNewScreen( new NormalScreen( game ) ); } return true; diff --git a/ClassicalSharp/2D/Screens/ChatScreen.cs b/ClassicalSharp/2D/Screens/ChatScreen.cs index 1ae840b67..f564ae3fa 100644 --- a/ClassicalSharp/2D/Screens/ChatScreen.cs +++ b/ClassicalSharp/2D/Screens/ChatScreen.cs @@ -216,15 +216,15 @@ namespace ClassicalSharp { suppressNextPress = false; if( HandlesAllInput ) { // text input bar - if( key == game.Mapping( KeyMapping.SendChat ) - || key == game.Mapping( KeyMapping.PauseOrExit ) ) { + if( key == game.Mapping( KeyBinding.SendChat ) + || key == game.Mapping( KeyBinding.PauseOrExit ) ) { HandlesAllInput = false; if( game.CursorVisible ) game.CursorVisible = false; game.Camera.RegrabMouse(); game.Keyboard.KeyRepeat = false; - if( key == game.Mapping( KeyMapping.PauseOrExit ) ) + if( key == game.Mapping( KeyBinding.PauseOrExit ) ) textInput.Clear(); textInput.SendTextInBufferAndReset(); } else if( key == Key.PageUp ) { @@ -238,7 +238,7 @@ namespace ClassicalSharp { if( chatIndex > game.Chat.Log.Count - chatLines ) chatIndex = game.Chat.Log.Count - chatLines; ResetChat(); - } else if( key == game.Mapping( KeyMapping.HideGui ) ) { + } else if( key == game.Mapping( KeyBinding.HideGui ) ) { game.HideGui = !game.HideGui; } else { textInput.HandlesKeyDown( key ); @@ -246,7 +246,7 @@ namespace ClassicalSharp { return true; } - if( key == game.Mapping( KeyMapping.OpenChat ) ) { + if( key == game.Mapping( KeyBinding.OpenChat ) ) { OpenTextInputBar( "" ); } else if( key == Key.Slash ) { OpenTextInputBar( "/" ); diff --git a/ClassicalSharp/2D/Screens/Menu/KeyMappingsScreen.cs b/ClassicalSharp/2D/Screens/Menu/KeyBindingsScreen.cs similarity index 90% rename from ClassicalSharp/2D/Screens/Menu/KeyMappingsScreen.cs rename to ClassicalSharp/2D/Screens/Menu/KeyBindingsScreen.cs index 0efde820f..3a94dba46 100644 --- a/ClassicalSharp/2D/Screens/Menu/KeyMappingsScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/KeyBindingsScreen.cs @@ -4,9 +4,9 @@ using OpenTK.Input; namespace ClassicalSharp { - public class KeyMappingsScreen : MenuScreen { + public class KeyBindingsScreen : MenuScreen { - public KeyMappingsScreen( Game game ) : base( game ) { + public KeyBindingsScreen( Game game ) : base( game ) { } public override void Render( double delta ) { @@ -43,9 +43,9 @@ namespace ClassicalSharp { void MakeKeys( int start, int len, int x ) { int y = -180; for( int i = 0; i < len; i++ ) { - KeyMapping mapping = (KeyMapping)( (int)start + i ); + KeyBinding binding = (KeyBinding)((int)start + i); string text = descriptions[start + i] + ": " - + keyNames[(int)game.Mapping( mapping )]; + + keyNames[(int)game.Mapping( binding )]; buttons[index++] = ButtonWidget.Create( game, x, y, 240, 25, text, Anchor.Centre, Anchor.Centre, keyFont, OnWidgetClick ); @@ -68,7 +68,7 @@ namespace ClassicalSharp { game.SetNewScreen( new NormalScreen( game ) ); } else if( widget != null ) { int index = Array.IndexOf( buttons, widget ); - KeyMapping mapping = (KeyMapping)index; + KeyBinding mapping = (KeyBinding)index; KeyMap map = game.InputHandler.Keys; Key oldKey = map[mapping]; string reason; diff --git a/ClassicalSharp/2D/Screens/Menu/LoadLevelScreen.cs b/ClassicalSharp/2D/Screens/Menu/LoadLevelScreen.cs index 5d808a3f6..46049e729 100644 --- a/ClassicalSharp/2D/Screens/Menu/LoadLevelScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/LoadLevelScreen.cs @@ -62,7 +62,7 @@ namespace ClassicalSharp { p.SetLocation( update, false ); } } catch( Exception ex ) { - Utils.LogError( "Error while trying to load map: {0}{1}", Environment.NewLine, ex ); + ErrorHandler.LogError( "loading map", ex ); game.Chat.Add( "&e/client loadmap: Failed to load map \"" + path + "\"" ); } } diff --git a/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs b/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs index 211bb9762..6a0050395 100644 --- a/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/OptionsScreen.cs @@ -47,8 +47,8 @@ namespace ClassicalSharp { (g, v) => { g.MouseSensitivity = Int32.Parse( v ); Options.Set( OptionsKey.Sensitivity, v ); } ), - Make( 140, 50, "Key mappings", Anchor.Centre, - (g, w) => g.SetNewScreen( new KeyMappingsScreen( g ) ), null, null ), + Make( 140, 50, "Key bindings", Anchor.Centre, + (g, w) => g.SetNewScreen( new KeyBindingsScreen( g ) ), null, null ), // Extra stuff !network.IsSinglePlayer ? null : Make( -140, -150, "Singleplayer physics", Anchor.Centre, OnWidgetClick, diff --git a/ClassicalSharp/2D/Screens/Menu/SaveLevelScreen.cs b/ClassicalSharp/2D/Screens/Menu/SaveLevelScreen.cs index 312b7f223..9e63ecf63 100644 --- a/ClassicalSharp/2D/Screens/Menu/SaveLevelScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/SaveLevelScreen.cs @@ -103,8 +103,8 @@ namespace ClassicalSharp { map.Save( fs, game ); } } catch( Exception ex ) { - Utils.LogError( "Error while trying to save map: {0}{1}", Environment.NewLine, ex ); - MakeDescWidget( "&cFailed to save map" ); + ErrorHandler.LogError( "saving map", ex ); + MakeDescWidget( "&cError while trying to save map" ); return; } game.SetNewScreen( new PauseScreen( game ) ); diff --git a/ClassicalSharp/2D/Screens/NormalScreen.cs b/ClassicalSharp/2D/Screens/NormalScreen.cs index 8f95e4f1f..ec5f58c8e 100644 --- a/ClassicalSharp/2D/Screens/NormalScreen.cs +++ b/ClassicalSharp/2D/Screens/NormalScreen.cs @@ -31,7 +31,7 @@ namespace ClassicalSharp { if( playerList != null ) { playerList.Render( delta ); // NOTE: Should usually be caught by KeyUp, but just in case. - if( !game.IsKeyDown( KeyMapping.PlayerList ) ) { + if( !game.IsKeyDown( KeyBinding.PlayerList ) ) { playerList.Dispose(); playerList = null; } @@ -93,7 +93,7 @@ namespace ClassicalSharp { } public override bool HandlesKeyDown( Key key ) { - if( key == game.Mapping( KeyMapping.PlayerList ) ) { + if( key == game.Mapping( KeyBinding.PlayerList ) ) { if( playerList == null ) { if( game.Network.UsingExtPlayerList ) { playerList = new ExtPlayerListWidget( game, playerFont ); @@ -111,7 +111,7 @@ namespace ClassicalSharp { } public override bool HandlesKeyUp( Key key ) { - if( key == game.Mapping( KeyMapping.PlayerList ) ) { + if( key == game.Mapping( KeyBinding.PlayerList ) ) { if( playerList != null ) { playerList.Dispose(); playerList = null; diff --git a/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs b/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs index ac5acfc3e..485d046a5 100644 --- a/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs +++ b/ClassicalSharp/2D/Widgets/BlockHotbarWidget.cs @@ -1,7 +1,7 @@ -using System; -using System.Drawing; -using ClassicalSharp.GraphicsAPI; -using OpenTK.Input; +using System; +using System.Drawing; +using ClassicalSharp.GraphicsAPI; +using OpenTK.Input; namespace ClassicalSharp { @@ -41,7 +41,6 @@ namespace ClassicalSharp { public override void Render( double delta ) { graphicsApi.Texturing = true; background.Render( graphicsApi ); - // TODO: Maybe redesign this so we don't have to bind the whole atlas. Not cheap. graphicsApi.BindTexture( game.TerrainAtlas.TexId ); graphicsApi.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b ); diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index 8bdcdc851..6ba4fbaa1 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -87,7 +87,7 @@ - + diff --git a/ClassicalSharp/Entities/LocalPlayer.cs b/ClassicalSharp/Entities/LocalPlayer.cs index e213a5a28..63913bb94 100644 --- a/ClassicalSharp/Entities/LocalPlayer.cs +++ b/ClassicalSharp/Entities/LocalPlayer.cs @@ -99,15 +99,15 @@ namespace ClassicalSharp { if( game.ScreenLockedInput ) { jumping = speeding = flyingUp = flyingDown = false; } else { - if( game.IsKeyDown( KeyMapping.Forward ) ) xMoving -= 0.98f; - if( game.IsKeyDown( KeyMapping.Back ) ) xMoving += 0.98f; - if( game.IsKeyDown( KeyMapping.Left ) ) zMoving -= 0.98f; - if( game.IsKeyDown( KeyMapping.Right ) ) zMoving += 0.98f; + if( game.IsKeyDown( KeyBinding.Forward ) ) xMoving -= 0.98f; + if( game.IsKeyDown( KeyBinding.Back ) ) xMoving += 0.98f; + if( game.IsKeyDown( KeyBinding.Left ) ) zMoving -= 0.98f; + if( game.IsKeyDown( KeyBinding.Right ) ) zMoving += 0.98f; - jumping = game.IsKeyDown( KeyMapping.Jump ); - speeding = canSpeed && game.IsKeyDown( KeyMapping.Speed ); - flyingUp = game.IsKeyDown( KeyMapping.FlyUp ); - flyingDown = game.IsKeyDown( KeyMapping.FlyDown ); + jumping = game.IsKeyDown( KeyBinding.Jump ); + speeding = canSpeed && game.IsKeyDown( KeyBinding.Speed ); + flyingUp = game.IsKeyDown( KeyBinding.FlyUp ); + flyingDown = game.IsKeyDown( KeyBinding.FlyDown ); } } @@ -266,7 +266,7 @@ namespace ClassicalSharp { internal bool HandleKeyDown( Key key ) { KeyMap keys = game.InputHandler.Keys; - if( key == keys[KeyMapping.Respawn] && canRespawn ) { + if( key == keys[KeyBinding.Respawn] && canRespawn ) { Vector3I p = Vector3I.Floor( SpawnPoint ); if( game.Map.IsValidPos( p ) ) { // Spawn player at highest valid position. @@ -283,11 +283,11 @@ namespace ClassicalSharp { Vector3 spawn = (Vector3)p + new Vector3( 0.5f, 0.01f, 0.5f ); LocationUpdate update = LocationUpdate.MakePos( spawn, false ); SetLocation( update, false ); - } else if( key == keys[KeyMapping.SetSpawn] && canRespawn ) { + } else if( key == keys[KeyBinding.SetSpawn] && canRespawn ) { SpawnPoint = Position; - } else if( key == keys[KeyMapping.Fly] && canFly ) { + } else if( key == keys[KeyBinding.Fly] && canFly ) { flying = !flying; - } else if( key == keys[KeyMapping.NoClip] && canNoclip ) { + } else if( key == keys[KeyBinding.NoClip] && canNoclip ) { noClip = !noClip; } else { return false; diff --git a/ClassicalSharp/Entities/Player.cs b/ClassicalSharp/Entities/Player.cs index 1ae5d01e6..36ee1096d 100644 --- a/ClassicalSharp/Entities/Player.cs +++ b/ClassicalSharp/Entities/Player.cs @@ -55,7 +55,7 @@ namespace ClassicalSharp { MobTextureId = -1; // Custom mob textures. - if( Utils.IsUrl( item.Url ) && item.TimeAdded > lastModelChange ) { + if( Utils.IsUrlPrefix( item.Url ) && item.TimeAdded > lastModelChange ) { MobTextureId = PlayerTextureId; } RenderHat = HasHat( bmp, SkinType ); diff --git a/ClassicalSharp/Game/ChatLog.cs b/ClassicalSharp/Game/ChatLog.cs index bef651bb6..399a059ac 100644 --- a/ClassicalSharp/Game/ChatLog.cs +++ b/ClassicalSharp/Game/ChatLog.cs @@ -92,11 +92,12 @@ namespace ClassicalSharp { Directory.CreateDirectory( "logs" ); string date = now.ToString( "yyyy-MM-dd" ); - // Cheap way of ensuring multiple instances do not end up overwriting each other's log entries. + // Ensure multiple instances do not end up overwriting each other's log entries. for( int i = 0; i < 20; i++ ) { string id = i == 0 ? "" : " _" + i; string fileName = "chat-" + date + id + ".log"; string path = Path.Combine( "logs", fileName ); + FileStream stream = null; try { stream = File.Open( path, FileMode.Append, FileAccess.Write, FileShare.Read ); @@ -105,12 +106,13 @@ namespace ClassicalSharp { throw; continue; } - Utils.LogDebug( "opening chat with id:" + id ); + writer = new StreamWriter( stream ); writer.AutoFlush = true; return; } - Utils.LogError( "Failed to open or create a chat log file after 20 tries, giving up." ); + ErrorHandler.LogError( "creating chat log", + "Failed to open or create a chat log file after 20 tries, giving up." ); } } diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index 12a7f5954..8c46116e3 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -261,15 +261,15 @@ namespace ClassicalSharp { cameraAccumulator -= cameraPeriod; } - if( ticksThisFrame > ticksFrequency / 3 ) { + if( ticksThisFrame > ticksFrequency / 3 ) Utils.LogWarning( "Falling behind (did {0} ticks this frame)", ticksThisFrame ); - } } void TakeScreenshot() { if( !Directory.Exists( "screenshots" ) ) { Directory.CreateDirectory( "screenshots" ); } + string timestamp = DateTime.Now.ToString( "dd-MM-yyyy-HH-mm-ss" ); string path = Path.Combine( "screenshots", "screenshot_" + timestamp + ".png" ); Graphics.TakeScreenshot( path, ClientSize ); @@ -333,11 +333,11 @@ namespace ClassicalSharp { public bool IsKeyDown( Key key ) { return InputHandler.IsKeyDown( key ); } - public bool IsKeyDown( KeyMapping mapping ) { return InputHandler.IsKeyDown( mapping ); } + public bool IsKeyDown( KeyBinding binding ) { return InputHandler.IsKeyDown( binding ); } public bool IsMousePressed( MouseButton button ) { return InputHandler.IsMousePressed( button ); } - public Key Mapping( KeyMapping mapping ) { return InputHandler.Keys[mapping]; } + public Key Mapping( KeyBinding mapping ) { return InputHandler.Keys[mapping]; } public override void Dispose() { MapRenderer.Dispose(); diff --git a/ClassicalSharp/Game/InputHandler.cs b/ClassicalSharp/Game/InputHandler.cs index e19f14eb3..f32be26fc 100644 --- a/ClassicalSharp/Game/InputHandler.cs +++ b/ClassicalSharp/Game/InputHandler.cs @@ -38,8 +38,9 @@ namespace ClassicalSharp { return game.Keyboard[key]; } - public bool IsKeyDown( KeyMapping mapping ) { - Key key = Keys[mapping]; + /// Returns whether the key associated with the given key binding is currently held down. + public bool IsKeyDown( KeyBinding binding ) { + Key key = Keys[binding]; return game.Keyboard[key]; } @@ -267,7 +268,7 @@ namespace ClassicalSharp { if( key == Key.F4 && (game.IsKeyDown( Key.AltLeft ) || game.IsKeyDown( Key.AltRight )) ) { game.Exit(); - } else if( key == Keys[KeyMapping.Screenshot] ) { + } else if( key == Keys[KeyBinding.Screenshot] ) { game.screenshotRequested = true; } else if( game.activeScreen == null || !game.activeScreen.HandlesKeyDown( key ) ) { @@ -308,26 +309,26 @@ namespace ClassicalSharp { } bool HandleBuiltinKey( Key key ) { - if( key == Keys[KeyMapping.HideGui] ) { + if( key == Keys[KeyBinding.HideGui] ) { game.HideGui = !game.HideGui; - } else if( key == Keys[KeyMapping.Fullscreen] ) { + } else if( key == Keys[KeyBinding.Fullscreen] ) { WindowState state = game.WindowState; if( state != WindowState.Minimized ) { game.WindowState = state == WindowState.Fullscreen ? WindowState.Normal : WindowState.Fullscreen; } - } else if( key == Keys[KeyMapping.ThirdPersonCamera] ) { + } else if( key == Keys[KeyBinding.ThirdPersonCamera] ) { bool useThirdPerson = !(game.Camera is ForwardThirdPersonCamera); game.SetCamera( useThirdPerson ); - } else if( key == Keys[KeyMapping.ViewDistance] ) { + } else if( key == Keys[KeyBinding.ViewDistance] ) { if( game.IsKeyDown( Key.ShiftLeft ) || game.IsKeyDown( Key.ShiftRight ) ) { CycleDistanceBackwards(); } else { CycleDistanceForwards(); } - } else if( key == Keys[KeyMapping.PauseOrExit] && !game.Map.IsNotLoaded ) { + } else if( key == Keys[KeyBinding.PauseOrExit] && !game.Map.IsNotLoaded ) { game.SetNewScreen( new PauseScreen( game ) ); - } else if( key == Keys[KeyMapping.OpenInventory] ) { + } else if( key == Keys[KeyBinding.OpenInventory] ) { game.SetNewScreen( new BlockSelectScreen( game ) ); } else { return false; diff --git a/ClassicalSharp/Game/KeyMap.cs b/ClassicalSharp/Game/KeyMap.cs index 6f1db15e6..e4720630f 100644 --- a/ClassicalSharp/Game/KeyMap.cs +++ b/ClassicalSharp/Game/KeyMap.cs @@ -3,7 +3,7 @@ using OpenTK.Input; namespace ClassicalSharp { - public enum KeyMapping { + public enum KeyBinding { Forward, Back, Left, Right, Jump, Respawn, SetSpawn, OpenChat, SendChat, PauseOrExit, OpenInventory, Screenshot, Fullscreen, ThirdPersonCamera, ViewDistance, Fly, Speed, NoClip, FlyUp, @@ -12,7 +12,7 @@ namespace ClassicalSharp { public class KeyMap { - public Key this[KeyMapping key] { + public Key this[KeyBinding key] { get { return Keys[(int)key]; } set { Keys[(int)key] = value; SaveKeyBindings(); } } @@ -27,7 +27,7 @@ namespace ClassicalSharp { public bool IsKeyOkay( Key oldKey, Key key, out string reason ) { if( oldKey == Key.Escape || oldKey == Key.F12 ) { - reason = "This mapping is locked"; + reason = "This binding is locked"; return false; } @@ -61,7 +61,7 @@ namespace ClassicalSharp { } void LoadKeyBindings() { - string[] names = KeyMapping.GetNames( typeof( KeyMapping ) ); + string[] names = KeyBinding.GetNames( typeof( KeyBinding ) ); for( int i = 0; i < names.Length; i++ ) { string key = "key-" + names[i]; Key mapping = Options.GetKey( key, Keys[i] ); @@ -71,7 +71,7 @@ namespace ClassicalSharp { } void SaveKeyBindings() { - string[] names = KeyMapping.GetNames( typeof( KeyMapping ) ); + string[] names = KeyBinding.GetNames( typeof( KeyBinding ) ); for( int i = 0; i < names.Length; i++ ) { Options.Set( "key-" + names[i], Keys[i] ); } diff --git a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs index a0904822a..61bbf4483 100644 --- a/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs +++ b/ClassicalSharp/GraphicsAPI/Direct3D9Api.cs @@ -11,6 +11,7 @@ using WinWindowInfo = OpenTK.Platform.Windows.WinWindowInfo; namespace ClassicalSharp.GraphicsAPI { + /// Implemented IGraphicsAPI using Direct3D 9. public class Direct3D9Api : IGraphicsApi { Device device; diff --git a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs index 4a9047d75..9ab5d4f82 100644 --- a/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs +++ b/ClassicalSharp/GraphicsAPI/IGraphicsApi.cs @@ -9,7 +9,6 @@ using OpenTK.Graphics.OpenGL; namespace ClassicalSharp.GraphicsAPI { /// Abstracts a 3D graphics rendering API. - /// Only Direct3D9 and OpenGL support are implemented. public abstract class IGraphicsApi { /// Maximum supported length of a dimension (width and height) of a 2D texture. @@ -292,13 +291,13 @@ namespace ClassicalSharp.GraphicsAPI { IntPtr ptr = (IntPtr)indices; for( int i = 0; i < maxIndices; i += 6 ) { - *indices++ = (ushort)( element + 0 ); - *indices++ = (ushort)( element + 1 ); - *indices++ = (ushort)( element + 2 ); + *indices++ = (ushort)(element + 0); + *indices++ = (ushort)(element + 1); + *indices++ = (ushort)(element + 2); - *indices++ = (ushort)( element + 2 ); - *indices++ = (ushort)( element + 3 ); - *indices++ = (ushort)( element + 0 ); + *indices++ = (ushort)(element + 2); + *indices++ = (ushort)(element + 3); + *indices++ = (ushort)(element + 0); element += 4; } return CreateIb( ptr, maxIndices ); diff --git a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs index 3f156bb6f..1aad09ecc 100644 --- a/ClassicalSharp/GraphicsAPI/OpenGLApi.cs +++ b/ClassicalSharp/GraphicsAPI/OpenGLApi.cs @@ -9,6 +9,8 @@ using GlPixelFormat = OpenTK.Graphics.OpenGL.PixelFormat; namespace ClassicalSharp.GraphicsAPI { + /// Implemented IGraphicsAPI using OpenGL 1.5, + /// or 1.2 with the GL_ARB_vertex_buffer_object extension. public class OpenGLApi : IGraphicsApi { BeginMode[] modeMappings; @@ -29,15 +31,19 @@ namespace ClassicalSharp.GraphicsAPI { unsafe void CheckVboSupport() { string extensions = new String( (sbyte*)GL.GetString( StringName.Extensions ) ); string version = new String( (sbyte*)GL.GetString( StringName.Version ) ); - int major = (int)( version[0] - '0' ); // x.y. (and so forth) - int minor = (int)( version[2] - '0' ); + int major = (int)(version[0] - '0'); // x.y. (and so forth) + int minor = (int)(version[2] - '0'); if( (major > 1) || (major == 1 && minor >= 5) ) return; // Supported in core since 1.5 Utils.LogDebug( "Using ARB vertex buffer objects" ); if( !extensions.Contains( "GL_ARB_vertex_buffer_object" ) ) { - Utils.LogError( "ClassicalSharp post 0.6 version requires OpenGL VBOs." ); + Utils.LogWarning( "ClassicalSharp post 0.6 version requires OpenGL VBOs." ); Utils.LogWarning( "You may need to install and/or update your video card drivers." ); Utils.LogWarning( "Alternatively, you can download the Direct3D9 build." ); + + ErrorHandler.LogError( "OpenGL vbo check", + "Driver does not support OpenGL VBOs, which are required for the OpenGL build." + + Environment.NewLine + "you may need to install and/or update video card drivers" ); throw new InvalidOperationException( "VBO support required for OpenGL build" ); } GL.UseArbVboAddresses(); diff --git a/ClassicalSharp/Model/ModelCache.cs b/ClassicalSharp/Model/ModelCache.cs index f01569656..a7af49180 100644 --- a/ClassicalSharp/Model/ModelCache.cs +++ b/ClassicalSharp/Model/ModelCache.cs @@ -36,14 +36,8 @@ namespace ClassicalSharp.Model { } if( !cache.TryGetValue( modelName, out model ) ) { - try { - model = InitModel( modelName ); - } catch( FileNotFoundException ) { - model = null; - Utils.LogWarning( modelName + " not found, falling back to human default." ); - } - if( model == null ) - model = cache["humanoid"]; // fallback to default + model = InitModel( modelName ); + if( model == null ) model = cache["humanoid"]; // fallback to default cache[modelName] = model; } return model; diff --git a/ClassicalSharp/Network/NetworkProcessor.cs b/ClassicalSharp/Network/NetworkProcessor.cs index 09df91b0d..97afe9b8c 100644 --- a/ClassicalSharp/Network/NetworkProcessor.cs +++ b/ClassicalSharp/Network/NetworkProcessor.cs @@ -1,11 +1,11 @@ -using System; -using System.Drawing; -using System.IO; -using System.Net; -using System.Net.Sockets; -using ClassicalSharp.Network; -using ClassicalSharp.TexturePack; -using OpenTK; +using System; +using System.Drawing; +using System.IO; +using System.Net; +using System.Net.Sockets; +using ClassicalSharp.Network; +using ClassicalSharp.TexturePack; +using OpenTK; #if __MonoCS__ using Ionic.Zlib; #else @@ -35,7 +35,7 @@ namespace ClassicalSharp { try { socket.Connect( address, port ); } catch( SocketException ex ) { - Utils.LogError( "Error while trying to connect: {0}{1}", Environment.NewLine, ex ); + ErrorHandler.LogError( "connecting to server", ex ); game.Disconnect( "&eUnable to reach " + address + ":" + port, "Unable to establish an underlying connection" ); Dispose(); @@ -84,7 +84,7 @@ namespace ClassicalSharp { if( game.AsyncDownloader.TryGetItem( "texturePack", out item ) ) { TexturePackExtractor extractor = new TexturePackExtractor(); - if( item.Data != null ) { + if( item.Data != null ) { extractor.Extract( (byte[])item.Data, game ); } else { extractor.Extract( game.defaultTexPack, game ); @@ -98,8 +98,8 @@ namespace ClassicalSharp { try { reader.ReadPendingData(); } catch( IOException ex ) { - Utils.LogError( "Error while reading packets: {0}{1}", Environment.NewLine, ex ); - game.Disconnect( "&eLost connection to the server", "Underlying connection was closed" ); + ErrorHandler.LogError( "reading packets", ex ); + game.Disconnect( "&eLost connection to the server", "IO error when reading packets" ); Dispose(); return; } @@ -204,8 +204,8 @@ namespace ClassicalSharp { try { stream.Write( outBuffer, 0, packetLength ); } catch( IOException ex ) { - Utils.LogError( "Error while writing packets: {0}{1}", Environment.NewLine, ex ); - game.Disconnect( "&eLost connection to the server", "Underlying connection was closed" ); + ErrorHandler.LogError( "wrting packets", ex ); + game.Disconnect( "&eLost connection to the server", "IO Error while writing packets" ); Dispose(); } } @@ -254,6 +254,7 @@ namespace ClassicalSharp { } receivedFirstPosition = false; gzipHeader = new GZipHeaderReader(); + // Workaround because built in mono stream assumes that the end of stream // has been reached the first time a read call returns 0. (MS.NET doesn't) #if __MonoCS__ @@ -261,10 +262,8 @@ namespace ClassicalSharp { #else gzipStream = new DeflateStream( gzippedMap, CompressionMode.Decompress ); if( OpenTK.Configuration.RunningOnMono ) { - Utils.LogWarning( "You are running on Mono, but this build does not support the Mono workaround." ); - Utils.LogWarning( "You should either download the Mono compatible build or define '__MonoCS__' when targeting Mono. " + - "(The Mono compiler already defines this by default)" ); - Utils.LogWarning( "You will likely experience an 'Internal error (no progress possible) ReadInternal' exception when decompressing the map." ); + throw new InvalidOperationException( "You must compile ClassicalSharp with the mono compiler " + + "to run on Mono, due to a limitation in Mono." ); } #endif diff --git a/ClassicalSharp/Network/Utils/AsyncDownloader.cs b/ClassicalSharp/Network/Utils/AsyncDownloader.cs index 46a22b9cb..294f108c5 100644 --- a/ClassicalSharp/Network/Utils/AsyncDownloader.cs +++ b/ClassicalSharp/Network/Utils/AsyncDownloader.cs @@ -34,7 +34,7 @@ namespace ClassicalSharp.Network { /// Identifier is skin_'skinName'. public void DownloadSkin( string skinName ) { string strippedSkinName = Utils.StripColours( skinName ); - string url = Utils.IsUrl( skinName ) ? skinName : + string url = Utils.IsUrlPrefix( skinName ) ? skinName : skinServer + strippedSkinName + ".png"; AddRequest( url, true, "skin_" + strippedSkinName, 0 ); } diff --git a/ClassicalSharp/Utils/ErrorHandler.cs b/ClassicalSharp/Utils/ErrorHandler.cs index ebd815aaa..f1c1e7bad 100644 --- a/ClassicalSharp/Utils/ErrorHandler.cs +++ b/ClassicalSharp/Utils/ErrorHandler.cs @@ -11,7 +11,7 @@ namespace ClassicalSharp { static string crashFile = "crash.log"; - /// Adds a handler for when a unhandled exception occurs, unless + /// Adds a handler for when a unhandled exception occurs, unless /// a debugger is attached to the process in which case this does nothing. public static void InstallHandler( string logFile ) { crashFile = logFile; @@ -48,13 +48,20 @@ namespace ClassicalSharp { Environment.Exit( 1 ); } - public static bool LogHandledException( Exception ex ) { - string error = ex.GetType().FullName + ": " + ex.Message + Environment.NewLine + ex.StackTrace; - + /// Logs a handled exception that occured at the specified location to the log file. + public static bool LogError( string location, Exception ex ) { + string error = ex.GetType().FullName + ": " + ex.Message + + Environment.NewLine + ex.StackTrace; + return LogError( location, error ); + } + + /// Logs an error that occured at the specified location to the log file. + public static bool LogError( string location, string text ) { try { using( StreamWriter writer = new StreamWriter( crashFile, true ) ) { writer.WriteLine( "--- handled error ---" ); - writer.WriteLine( error ); + writer.WriteLine( "Occured when: " + location ); + writer.WriteLine( text ); writer.WriteLine(); } } catch( Exception ) { diff --git a/ClassicalSharp/Utils/Utils.cs b/ClassicalSharp/Utils/Utils.cs index 89652adda..f74f4d8c8 100644 --- a/ClassicalSharp/Utils/Utils.cs +++ b/ClassicalSharp/Utils/Utils.cs @@ -1,6 +1,6 @@ -using System; -using System.Drawing; -using OpenTK; +using System; +using System.Drawing; +using OpenTK; namespace ClassicalSharp { @@ -19,8 +19,6 @@ namespace ClassicalSharp { public static class Utils { - - /// Clamps that specified value such that min ≤ value ≤ max public static void Clamp( ref float value, float min, float max ) { if( value < min ) value = min; @@ -67,14 +65,17 @@ namespace ClassicalSharp { return new String( output, 0, usedChars ); } + /// Returns whether a equals b, ignoring any case differences. public static bool CaselessEquals( string a, string b ) { return a.Equals( b, StringComparison.OrdinalIgnoreCase ); } + /// Returns whether a starts with b, ignoring any case differences. public static bool CaselessStarts( string a, string b ) { return a.StartsWith( b, StringComparison.OrdinalIgnoreCase ); } + /// Converts the given byte array of length N to a hex string of length 2N. public static string ToHexString( byte[] array ) { int len = array.Length; char[] hexadecimal = new char[len * 2]; @@ -117,38 +118,46 @@ namespace ClassicalSharp { return packed * 360.0 / 256.0; } + /// Rotates the given 3D coordinates around the y axis. public static Vector3 RotateY( Vector3 v, float angle ) { float cosA = (float)Math.Cos( angle ); float sinA = (float)Math.Sin( angle ); return new Vector3( cosA * v.X - sinA * v.Z, v.Y, sinA * v.X + cosA * v.Z ); } + /// Rotates the given 3D coordinates around the y axis. public static Vector3 RotateY( float x, float y, float z, float angle ) { float cosA = (float)Math.Cos( angle ); float sinA = (float)Math.Sin( angle ); return new Vector3( cosA * x - sinA * z, y, sinA * x + cosA * z ); } + /// Rotates the given 3D coordinates around the x axis. public static Vector3 RotateX( Vector3 p, float cosA, float sinA ) { return new Vector3( p.X, cosA * p.Y + sinA * p.Z, -sinA * p.Y + cosA * p.Z ); } - public static Vector3 RotateY( Vector3 p, float cosA, float sinA ) { - return new Vector3( cosA * p.X - sinA * p.Z, p.Y, sinA * p.X + cosA * p.Z ); - } - - public static Vector3 RotateZ( Vector3 p, float cosA, float sinA ) { - return new Vector3( cosA * p.X + sinA * p.Y, -sinA * p.X + cosA * p.Y, p.Z ); - } - + /// Rotates the given 3D coordinates around the x axis. public static Vector3 RotateX( float x, float y, float z, float cosA, float sinA ) { return new Vector3( x, cosA * y + sinA * z, -sinA * y + cosA * z ); } + /// Rotates the given 3D coordinates around the y axis. + public static Vector3 RotateY( Vector3 p, float cosA, float sinA ) { + return new Vector3( cosA * p.X - sinA * p.Z, p.Y, sinA * p.X + cosA * p.Z ); + } + + /// Rotates the given 3D coordinates around the y axis. public static Vector3 RotateY( float x, float y, float z, float cosA, float sinA ) { return new Vector3( cosA * x - sinA * z, y, sinA * x + cosA * z ); } + /// Rotates the given 3D coordinates around the z axis. + public static Vector3 RotateZ( Vector3 p, float cosA, float sinA ) { + return new Vector3( cosA * p.X + sinA * p.Y, -sinA * p.X + cosA * p.Y, p.Z ); + } + + /// Rotates the given 3D coordinates around the z axis. public static Vector3 RotateZ( float x, float y, float z, float cosA, float sinA ) { return new Vector3( cosA * x + sinA * y, -sinA * x + cosA * y, z ); } @@ -177,6 +186,8 @@ namespace ClassicalSharp { return dx * dx + dy * dy + dz * dz; } + /// Returns a normalised vector that faces in the direction + /// described by the given yaw and pitch. public static Vector3 GetDirVector( double yawRad, double pitchRad ) { double x = -Math.Cos( pitchRad ) * -Math.Sin( yawRad ); double y = -Math.Sin( pitchRad ); @@ -202,16 +213,6 @@ namespace ClassicalSharp { LogWarning( String.Format( text, args ) ); } - public static void LogError( string text ) { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine( text ); - Console.ResetColor(); - } - - public static void LogError( string text, params object[] args ) { - LogError( String.Format( text, args ) ); - } - public static void LogDebug( string text ) { #if DEBUG Console.ForegroundColor = ConsoleColor.DarkGray; @@ -275,7 +276,8 @@ namespace ClassicalSharp { } } - public static bool IsUrl( string value ) { + /// Returns whether the specified string starts with http:// or https:// + public static bool IsUrlPrefix( string value ) { return value.StartsWith( "http://" ) || value.StartsWith( "https://" ); } } diff --git a/Launcher2/Gui/Screens/ClassiCubeScreen.cs b/Launcher2/Gui/Screens/ClassiCubeScreen.cs index 7543dcf31..87e97ea3f 100644 --- a/Launcher2/Gui/Screens/ClassiCubeScreen.cs +++ b/Launcher2/Gui/Screens/ClassiCubeScreen.cs @@ -152,7 +152,7 @@ namespace Launcher2 { } void DisplayWebException( WebException ex, string action ) { - Program.LogException( ex ); + ErrorHandler.LogError( action, ex ); if( ex.Status == WebExceptionStatus.Timeout ) { string text = "&eFailed to " + action + ":" + Environment.NewLine + "Timed out while connecting to classicube.net."; diff --git a/Launcher2/LauncherWindow.cs b/Launcher2/LauncherWindow.cs index 2e9756ba8..81d78cfde 100644 --- a/Launcher2/LauncherWindow.cs +++ b/Launcher2/LauncherWindow.cs @@ -65,7 +65,7 @@ namespace Launcher2 { try { data = Session.GetConnectInfo( hash ); } catch( WebException ex ) { - Program.LogException( ex ); + ErrorHandler.LogError( "retrieving server information", ex ); return false; } Client.Start( data, true ); diff --git a/Launcher2/Program.cs b/Launcher2/Program.cs index c93d1c842..e1987b44f 100644 --- a/Launcher2/Program.cs +++ b/Launcher2/Program.cs @@ -13,9 +13,5 @@ namespace Launcher2 { LauncherWindow window = new LauncherWindow(); window.Run(); } - - internal static bool LogException( Exception ex ) { - return ErrorHandler.LogHandledException( ex ); - } } }