From 8490f1794301e621283319794131f17034cfd6c9 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 16 Jun 2018 11:44:00 +1000 Subject: [PATCH] eliminate fixed* char usage, fixes crash on a few mono versions --- .../2D/Widgets/Chat/SpecialInputWidget.cs | 36 +++++-------- ClassicalSharp/2D/Widgets/InputWidget.cs | 9 +--- ClassicalSharp/Audio/Soundboard.cs | 4 +- ClassicalSharp/Blocks/AutoRotate.cs | 14 ++--- ClassicalSharp/Blocks/BlockInfo.cs | 2 +- ClassicalSharp/Commands/CommandList.cs | 2 +- ClassicalSharp/Commands/Commands.cs | 6 +-- ClassicalSharp/Entities/Entity.cs | 2 +- ClassicalSharp/Entities/Mobs/MobEntity.cs | 2 +- ClassicalSharp/Entities/Model/ModelCache.cs | 5 +- ClassicalSharp/Entities/Model/SheepModel.cs | 2 +- ClassicalSharp/Game/Game.cs | 8 +-- ClassicalSharp/Network/Protocols/CPE.cs | 2 +- ClassicalSharp/Utils/Options.cs | 4 +- ClassicalSharp/Utils/Utils.cs | 52 +++++++++++-------- 15 files changed, 73 insertions(+), 77 deletions(-) diff --git a/ClassicalSharp/2D/Widgets/Chat/SpecialInputWidget.cs b/ClassicalSharp/2D/Widgets/Chat/SpecialInputWidget.cs index 5b839bbdc..a63775063 100644 --- a/ClassicalSharp/2D/Widgets/Chat/SpecialInputWidget.cs +++ b/ClassicalSharp/2D/Widgets/Chat/SpecialInputWidget.cs @@ -164,15 +164,11 @@ namespace ClassicalSharp.Gui.Widgets { unsafe void MeasureContentSizes(SpecialInputTab e, Font font, Size* sizes) { - string s = new String('\0', e.CharsPerItem); - DrawTextArgs args = new DrawTextArgs(s, font, false); - // avoid allocating temporary strings here - fixed(char* ptr = s) { - for (int i = 0; i < e.Contents.Length; i += e.CharsPerItem) { - for (int j = 0; j < e.CharsPerItem; j++) - ptr[j] = e.Contents[i + j]; - sizes[i / e.CharsPerItem] = game.Drawer2D.MeasureSize(ref args); - } + DrawTextArgs args = new DrawTextArgs(null, font, false); + + for (int i = 0; i < e.Contents.Length; i += e.CharsPerItem) { + args.Text = e.Contents.Substring(i, e.CharsPerItem); + sizes[i / e.CharsPerItem] = game.Drawer2D.MeasureSize(ref args); } } @@ -215,21 +211,17 @@ namespace ClassicalSharp.Gui.Widgets { } } - unsafe void DrawContent(IDrawer2D drawer, Font font, SpecialInputTab e, int yOffset) { - string s = new String('\0', e.CharsPerItem); + void DrawContent(IDrawer2D drawer, Font font, SpecialInputTab e, int yOffset) { int wrap = e.ItemsPerRow; - DrawTextArgs args = new DrawTextArgs(s, font, false); + DrawTextArgs args = new DrawTextArgs(null, font, false); - fixed(char* ptr = s) { - for (int i = 0; i < e.Contents.Length; i += e.CharsPerItem) { - for (int j = 0; j < e.CharsPerItem; j++) - ptr[j] = e.Contents[i + j]; - int item = i / e.CharsPerItem; - - int x = (item % wrap) * elementSize.Width, y = (item / wrap) * elementSize.Height; - y += yOffset; - drawer.DrawText(ref args, x, y); - } + for (int i = 0; i < e.Contents.Length; i += e.CharsPerItem) { + args.Text = e.Contents.Substring(i, e.CharsPerItem); + int item = i / e.CharsPerItem; + + int x = (item % wrap) * elementSize.Width, y = (item / wrap) * elementSize.Height; + y += yOffset; + drawer.DrawText(ref args, x, y); } } } diff --git a/ClassicalSharp/2D/Widgets/InputWidget.cs b/ClassicalSharp/2D/Widgets/InputWidget.cs index 5583f4d4e..063b5d1c3 100644 --- a/ClassicalSharp/2D/Widgets/InputWidget.cs +++ b/ClassicalSharp/2D/Widgets/InputWidget.cs @@ -436,12 +436,11 @@ namespace ClassicalSharp.Gui.Widgets { } - protected unsafe void SetCaretToCursor(int mouseX, int mouseY) { + protected void SetCaretToCursor(int mouseX, int mouseY) { mouseX -= inputTex.X1; mouseY -= inputTex.Y1; DrawTextArgs args = new DrawTextArgs(null, font, true); IDrawer2D drawer = game.Drawer2D; int offset = 0, charHeight = caretTex.Height; - string oneChar = new String('A', 1); for (int y = 0; y < lines.Length; y++) { string line = lines[y]; @@ -452,11 +451,7 @@ namespace ClassicalSharp.Gui.Widgets { int charOffset = drawer.MeasureSize(ref args).Width; if (y == 0) charOffset += prefixWidth; - // avoid allocating an unnecessary string - fixed(char* ptr = oneChar) - ptr[0] = line[x]; - - args.Text = oneChar; + args.Text = new string(line[x], 1); int charWidth = drawer.MeasureSize(ref args).Width; if (GuiElement.Contains(charOffset, y * charHeight, charWidth, charHeight, mouseX, mouseY)) { diff --git a/ClassicalSharp/Audio/Soundboard.cs b/ClassicalSharp/Audio/Soundboard.cs index 9014f26af..9cce30060 100644 --- a/ClassicalSharp/Audio/Soundboard.cs +++ b/ClassicalSharp/Audio/Soundboard.cs @@ -27,7 +27,7 @@ namespace ClassicalSharp.Audio { if (!Utils.CaselessStarts(name, sndGroup)) continue; // Convert dig_grass1.wav to grass - name = Utils.ToLower(name.Substring(sndGroup.Length)); + name = name.Substring(sndGroup.Length); name = name.Substring(0, name.Length - 1); SoundGroup group = Find(name); @@ -49,7 +49,7 @@ namespace ClassicalSharp.Audio { SoundGroup Find(string name) { for (int i = 0; i < groups.Count; i++) { - if (groups[i].Name == name) return groups[i]; + if (Utils.CaselessEq(groups[i].Name, name)) return groups[i]; } return null; } diff --git a/ClassicalSharp/Blocks/AutoRotate.cs b/ClassicalSharp/Blocks/AutoRotate.cs index 006fefce2..951d6ab9b 100644 --- a/ClassicalSharp/Blocks/AutoRotate.cs +++ b/ClassicalSharp/Blocks/AutoRotate.cs @@ -18,16 +18,16 @@ namespace ClassicalSharp { name = name.Substring(0, dirIndex); Vector3 offset = game.SelectedPos.Intersect - (Vector3)game.SelectedPos.TranslatedPos; - if (Utils.CaselessEquals(dir, "nw") || Utils.CaselessEquals(dir, "ne") || - Utils.CaselessEquals(dir, "sw") || Utils.CaselessEquals(dir, "se")) { + if (Utils.CaselessEq(dir, "nw") || Utils.CaselessEq(dir, "ne") || + Utils.CaselessEq(dir, "sw") || Utils.CaselessEq(dir, "se")) { return RotateCorner(game, block, name, offset); - } else if (Utils.CaselessEquals(dir, "u") || Utils.CaselessEquals(dir, "d")) { + } else if (Utils.CaselessEq(dir, "u") || Utils.CaselessEq(dir, "d")) { return RotateVertical(game, block, name, offset); - } else if (Utils.CaselessEquals(dir, "n") || Utils.CaselessEquals(dir, "w") || - Utils.CaselessEquals(dir, "s") || Utils.CaselessEquals(dir, "e")) { + } else if (Utils.CaselessEq(dir, "n") || Utils.CaselessEq(dir, "w") || + Utils.CaselessEq(dir, "s") || Utils.CaselessEq(dir, "e")) { return RotateDirection(game, block, name, offset); - } else if (Utils.CaselessEquals(dir, "UD") || Utils.CaselessEquals(dir, "WE") || - Utils.CaselessEquals(dir, "NS")) { + } else if (Utils.CaselessEq(dir, "UD") || Utils.CaselessEq(dir, "WE") || + Utils.CaselessEq(dir, "NS")) { return RotateOther(game, block, name, offset); } return block; diff --git a/ClassicalSharp/Blocks/BlockInfo.cs b/ClassicalSharp/Blocks/BlockInfo.cs index 95f3b3ae3..ca245e7fe 100644 --- a/ClassicalSharp/Blocks/BlockInfo.cs +++ b/ClassicalSharp/Blocks/BlockInfo.cs @@ -238,7 +238,7 @@ namespace ClassicalSharp { public static int FindID(string name) { for (int b = 0; b < Count; b++) { - if (Utils.CaselessEquals(Name[b], name)) return b; + if (Utils.CaselessEq(Name[b], name)) return b; } return -1; } diff --git a/ClassicalSharp/Commands/CommandList.cs b/ClassicalSharp/Commands/CommandList.cs index 56045c5f1..a65ec82bf 100644 --- a/ClassicalSharp/Commands/CommandList.cs +++ b/ClassicalSharp/Commands/CommandList.cs @@ -22,7 +22,7 @@ namespace ClassicalSharp.Commands { return true; return Utils.CaselessStarts(input, prefixSpace) - || Utils.CaselessEquals(input, prefix); + || Utils.CaselessEq(input, prefix); } protected Game game; diff --git a/ClassicalSharp/Commands/Commands.cs b/ClassicalSharp/Commands/Commands.cs index 3a5f76c27..01f22b63e 100644 --- a/ClassicalSharp/Commands/Commands.cs +++ b/ClassicalSharp/Commands/Commands.cs @@ -131,7 +131,7 @@ namespace ClassicalSharp.Commands { if (args.Length == 1) { game.Chat.Add("&e/client model: &cYou didn't specify a model name."); } else { - game.LocalPlayer.SetModel(Utils.ToLower(args[1])); + game.LocalPlayer.SetModel(args[1]); } } } @@ -161,7 +161,7 @@ namespace ClassicalSharp.Commands { persist = false; if (!ParseBlock(args)) return; - if (args.Length > 2 && Utils.CaselessEquals(args[2], "yes")) + if (args.Length > 2 && Utils.CaselessEq(args[2], "yes")) persist = true; game.Chat.Add("&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus1); @@ -170,7 +170,7 @@ namespace ClassicalSharp.Commands { bool ParseBlock(string[] args) { if (args.Length == 1) return true; - if (Utils.CaselessEquals(args[1], "yes")) { persist = true; return true; } + if (Utils.CaselessEq(args[1], "yes")) { persist = true; return true; } int temp = BlockInfo.FindID(args[1]); BlockID block = 0; diff --git a/ClassicalSharp/Entities/Entity.cs b/ClassicalSharp/Entities/Entity.cs index a0f70ff6a..26a193297 100644 --- a/ClassicalSharp/Entities/Entity.cs +++ b/ClassicalSharp/Entities/Entity.cs @@ -116,7 +116,7 @@ namespace ClassicalSharp.Entities { string scale = sep == -1 ? null : model.Substring(sep + 1); ModelName = sep == -1 ? model : model.Substring(0, sep); - if (Utils.CaselessEquals(model, "giant")) { + if (Utils.CaselessEq(model, "giant")) { ModelName = "humanoid"; ModelScale *= 2; } diff --git a/ClassicalSharp/Entities/Mobs/MobEntity.cs b/ClassicalSharp/Entities/Mobs/MobEntity.cs index 9cf1427b0..fe62cb5ce 100644 --- a/ClassicalSharp/Entities/Mobs/MobEntity.cs +++ b/ClassicalSharp/Entities/Mobs/MobEntity.cs @@ -25,7 +25,7 @@ namespace ClassicalSharp.Entities.Mobs { physics.hacks = hacks; physics.collisions = collisions; - if (Utils.CaselessEquals(model, "pig") || Utils.CaselessEquals(model, "sheep")) { + if (Utils.CaselessEq(model, "pig") || Utils.CaselessEq(model, "sheep")) { ai = new FleeAI(game, this); } else { ai = new HostileAI(game, this); diff --git a/ClassicalSharp/Entities/Model/ModelCache.cs b/ClassicalSharp/Entities/Model/ModelCache.cs index acc4efb10..5827717a8 100644 --- a/ClassicalSharp/Entities/Model/ModelCache.cs +++ b/ClassicalSharp/Entities/Model/ModelCache.cs @@ -49,7 +49,7 @@ namespace ClassicalSharp.Model { public int GetTextureIndex(string texName) { for (int i = 0; i < Textures.Count; i++) { - if (Textures[i].Name == texName) return i; + if (Utils.CaselessEq(Textures[i].Name, texName)) return i; } return -1; } @@ -58,7 +58,8 @@ namespace ClassicalSharp.Model { public IModel Get(string modelName) { for (int i = 0; i < Models.Count; i++) { CachedModel m = Models[i]; - if (m.Name != modelName) continue; + if (!Utils.CaselessEq(m.Name, modelName)) continue; + if (!m.Instance.initalised) InitModel(m); return m.Instance; } diff --git a/ClassicalSharp/Entities/Model/SheepModel.cs b/ClassicalSharp/Entities/Model/SheepModel.cs index d834fbaca..1bd4c90e6 100644 --- a/ClassicalSharp/Entities/Model/SheepModel.cs +++ b/ClassicalSharp/Entities/Model/SheepModel.cs @@ -89,7 +89,7 @@ namespace ClassicalSharp.Model { DrawRotate(p.anim.leftLegX, 0, 0, RightLegBack, false); UpdateVB(); - if (Utils.CaselessEquals(p.ModelName, "sheep_nofur")) return; + if (Utils.CaselessEq(p.ModelName, "sheep_nofur")) return; ModelCache cache = game.ModelCache; gfx.BindTexture(cache.Textures[furIndex].TexID); DrawRotate(-p.HeadXRadians, 0, 0, FurHead, true); diff --git a/ClassicalSharp/Game/Game.cs b/ClassicalSharp/Game/Game.cs index f5bfb4601..73ff9f307 100644 --- a/ClassicalSharp/Game/Game.cs +++ b/ClassicalSharp/Game/Game.cs @@ -199,13 +199,13 @@ namespace ClassicalSharp { } public int CalcRenderType(string type) { - if (Utils.CaselessEquals(type, "legacyfast")) { + if (Utils.CaselessEq(type, "legacyfast")) { return 0x03; - } else if (Utils.CaselessEquals(type, "legacy")) { + } else if (Utils.CaselessEq(type, "legacy")) { return 0x01; - } else if (Utils.CaselessEquals(type, "normal")) { + } else if (Utils.CaselessEq(type, "normal")) { return 0x00; - } else if (Utils.CaselessEquals(type, "normalfast")) { + } else if (Utils.CaselessEq(type, "normalfast")) { return 0x02; } return -1; diff --git a/ClassicalSharp/Network/Protocols/CPE.cs b/ClassicalSharp/Network/Protocols/CPE.cs index a5ac158bc..9d4a29a63 100644 --- a/ClassicalSharp/Network/Protocols/CPE.cs +++ b/ClassicalSharp/Network/Protocols/CPE.cs @@ -211,7 +211,7 @@ namespace ClassicalSharp.Network.Protocols { void HandleChangeModel() { byte id = reader.ReadUInt8(); - string modelName = Utils.ToLower(reader.ReadString()); + string modelName = reader.ReadString(); Entity entity = game.Entities.List[id]; if (entity != null) entity.SetModel(modelName); } diff --git a/ClassicalSharp/Utils/Options.cs b/ClassicalSharp/Utils/Options.cs index e53e3f764..0c4b658ba 100644 --- a/ClassicalSharp/Utils/Options.cs +++ b/ClassicalSharp/Utils/Options.cs @@ -88,7 +88,7 @@ namespace ClassicalSharp { static bool IsChangedOption(string key) { for (int i = 0; i < OptionsChanged.Count; i++) { - if (Utils.CaselessEquals(key, OptionsChanged[i])) return true; + if (Utils.CaselessEq(key, OptionsChanged[i])) return true; } return false; } @@ -155,7 +155,7 @@ namespace ClassicalSharp { static int FindOption(string key) { for (int i = 0; i < OptionsKeys.Count; i++) { - if (Utils.CaselessEquals(OptionsKeys[i], key)) return i; + if (Utils.CaselessEq(OptionsKeys[i], key)) return i; } return -1; } diff --git a/ClassicalSharp/Utils/Utils.cs b/ClassicalSharp/Utils/Utils.cs index 5536630b7..deb0f724e 100644 --- a/ClassicalSharp/Utils/Utils.cs +++ b/ClassicalSharp/Utils/Utils.cs @@ -19,7 +19,7 @@ namespace ClassicalSharp { public delegate void Action(); // ################################################################ - public enum Anchor { + public enum Anchor { Min, // left or top Centre, // middle Max, // right or bottom @@ -46,7 +46,7 @@ namespace ClassicalSharp { return new String(output, 0, usedChars); } -#if !LAUNCHER + #if !LAUNCHER public static string RemoveEndPlus(string value) { // Workaround for MCDzienny (and others) use a '+' at the end to distinguish classicube.net accounts // from minecraft.net accounts. Unfortunately they also send this ending + to the client. @@ -55,13 +55,14 @@ namespace ClassicalSharp { return value[value.Length - 1] == '+' ? value.Substring(0, value.Length - 1) : value; } -#endif + #endif const StringComparison comp = StringComparison.OrdinalIgnoreCase; + public static bool CaselessEq(string a, string b) { return a.Equals(b, comp); } public static bool CaselessEquals(string a, string b) { return a.Equals(b, comp); } public static bool CaselessStarts(string a, string b) { return a.StartsWith(b, comp); } - public static bool CaselessEnds(string a, string b) { return a.EndsWith(b, comp); } - + public static bool CaselessEnds(string a, string b) { return a.EndsWith(b, comp); } + public static void LogDebug(string text) { try { Console.WriteLine(text); } catch { } } @@ -79,7 +80,7 @@ namespace ClassicalSharp { return steps; } -#if !LAUNCHER + #if !LAUNCHER /// Attempts to caselessly parse the given string as a Key enum member, /// returning defValue if there was an error parsing. public static bool TryParseEnum(string value, T defValue, out T result) { @@ -93,7 +94,7 @@ namespace ClassicalSharp { result = mapping; return true; } - + public static int AdjViewDist(float value) { return (int)(1.4142135 * value); } @@ -108,7 +109,7 @@ namespace ClassicalSharp { adjCol *= tint; return adjCol.Pack(); } - + /// Determines the skin type of the specified bitmap. public static SkinType GetSkinType(Bitmap bmp) { if (bmp.Width == bmp.Height * 2) { @@ -133,7 +134,7 @@ namespace ClassicalSharp { int https = value.IndexOf("https://", index); return http == index || https == index; } -#endif + #endif /// Conversion for code page 437 characters from index 0 to 31 to unicode. const string ControlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼"; @@ -167,15 +168,22 @@ namespace ClassicalSharp { return ExtendedCharReplacements[c - 0x7F]; } - public unsafe static string ToLower(string value) { - fixed(char* ptr = value) { - for (int i = 0; i < value.Length; i++) { - char c = ptr[i]; - if (c < 'A' || c > 'Z') continue; - c += ' '; ptr[i] = c; - } + public static string ToLower(string src) { + bool hasUpper = false; + for (int i = 0; i < src.Length; i++) { + char c = src[i]; + if (c >= 'A' && c <= 'Z') { hasUpper = true; break; } } - return value; + + if (!hasUpper) return src; + char[] dst = new char[src.Length]; + + for (int i = 0; i < src.Length; i++) { + char c = src[i]; + if (c >= 'A' && c <= 'Z') { c += ' '; } + dst[i] = c; + } + return new string(dst); } public static uint CRC32(byte[] data, int length) { @@ -188,14 +196,14 @@ namespace ClassicalSharp { return crc ^ 0xffffffffU; } -#if !LAUNCHER + #if !LAUNCHER // Not all languages use . as their decimal point separator public static bool TryParseDecimal(string s, out float result) { - if (s.IndexOf(',') >= 0) + if (s.IndexOf(',') >= 0) s = s.Replace(',', '.'); float temp; - result = 0; + result = 0; if (!Single.TryParse(s, style, NumberFormatInfo.InvariantInfo, out temp)) return false; if (Single.IsInfinity(temp) || Single.IsNaN(temp)) return false; result = temp; @@ -203,7 +211,7 @@ namespace ClassicalSharp { } public static float ParseDecimal(string s) { - if (s.IndexOf(',') >= 0) + if (s.IndexOf(',') >= 0) s = s.Replace(',', '.'); return Single.Parse(s, style, NumberFormatInfo.InvariantInfo); } @@ -211,6 +219,6 @@ namespace ClassicalSharp { const NumberStyles style = NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint; -#endif + #endif } } \ No newline at end of file