eliminate fixed* char usage, fixes crash on a few mono versions

This commit is contained in:
UnknownShadow200 2018-06-16 11:44:00 +10:00
parent c08e2e9094
commit 8490f17943
15 changed files with 73 additions and 77 deletions

View File

@ -164,15 +164,11 @@ namespace ClassicalSharp.Gui.Widgets {
unsafe void MeasureContentSizes(SpecialInputTab e, Font font, Size* sizes) { unsafe void MeasureContentSizes(SpecialInputTab e, Font font, Size* sizes) {
string s = new String('\0', e.CharsPerItem); DrawTextArgs args = new DrawTextArgs(null, font, false);
DrawTextArgs args = new DrawTextArgs(s, font, false);
// avoid allocating temporary strings here for (int i = 0; i < e.Contents.Length; i += e.CharsPerItem) {
fixed(char* ptr = s) { args.Text = e.Contents.Substring(i, e.CharsPerItem);
for (int i = 0; i < e.Contents.Length; i += e.CharsPerItem) { sizes[i / e.CharsPerItem] = game.Drawer2D.MeasureSize(ref args);
for (int j = 0; j < e.CharsPerItem; j++)
ptr[j] = e.Contents[i + j];
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) { void DrawContent(IDrawer2D drawer, Font font, SpecialInputTab e, int yOffset) {
string s = new String('\0', e.CharsPerItem);
int wrap = e.ItemsPerRow; 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 i = 0; i < e.Contents.Length; i += e.CharsPerItem) { args.Text = e.Contents.Substring(i, e.CharsPerItem);
for (int j = 0; j < e.CharsPerItem; j++) int item = i / e.CharsPerItem;
ptr[j] = e.Contents[i + j];
int item = i / e.CharsPerItem; int x = (item % wrap) * elementSize.Width, y = (item / wrap) * elementSize.Height;
y += yOffset;
int x = (item % wrap) * elementSize.Width, y = (item / wrap) * elementSize.Height; drawer.DrawText(ref args, x, y);
y += yOffset;
drawer.DrawText(ref args, x, y);
}
} }
} }
} }

View File

@ -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; mouseX -= inputTex.X1; mouseY -= inputTex.Y1;
DrawTextArgs args = new DrawTextArgs(null, font, true); DrawTextArgs args = new DrawTextArgs(null, font, true);
IDrawer2D drawer = game.Drawer2D; IDrawer2D drawer = game.Drawer2D;
int offset = 0, charHeight = caretTex.Height; int offset = 0, charHeight = caretTex.Height;
string oneChar = new String('A', 1);
for (int y = 0; y < lines.Length; y++) { for (int y = 0; y < lines.Length; y++) {
string line = lines[y]; string line = lines[y];
@ -452,11 +451,7 @@ namespace ClassicalSharp.Gui.Widgets {
int charOffset = drawer.MeasureSize(ref args).Width; int charOffset = drawer.MeasureSize(ref args).Width;
if (y == 0) charOffset += prefixWidth; if (y == 0) charOffset += prefixWidth;
// avoid allocating an unnecessary string args.Text = new string(line[x], 1);
fixed(char* ptr = oneChar)
ptr[0] = line[x];
args.Text = oneChar;
int charWidth = drawer.MeasureSize(ref args).Width; int charWidth = drawer.MeasureSize(ref args).Width;
if (GuiElement.Contains(charOffset, y * charHeight, charWidth, charHeight, mouseX, mouseY)) { if (GuiElement.Contains(charOffset, y * charHeight, charWidth, charHeight, mouseX, mouseY)) {

View File

@ -27,7 +27,7 @@ namespace ClassicalSharp.Audio {
if (!Utils.CaselessStarts(name, sndGroup)) continue; if (!Utils.CaselessStarts(name, sndGroup)) continue;
// Convert dig_grass1.wav to grass // 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); name = name.Substring(0, name.Length - 1);
SoundGroup group = Find(name); SoundGroup group = Find(name);
@ -49,7 +49,7 @@ namespace ClassicalSharp.Audio {
SoundGroup Find(string name) { SoundGroup Find(string name) {
for (int i = 0; i < groups.Count; i++) { 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; return null;
} }

View File

@ -18,16 +18,16 @@ namespace ClassicalSharp {
name = name.Substring(0, dirIndex); name = name.Substring(0, dirIndex);
Vector3 offset = game.SelectedPos.Intersect - (Vector3)game.SelectedPos.TranslatedPos; Vector3 offset = game.SelectedPos.Intersect - (Vector3)game.SelectedPos.TranslatedPos;
if (Utils.CaselessEquals(dir, "nw") || Utils.CaselessEquals(dir, "ne") || if (Utils.CaselessEq(dir, "nw") || Utils.CaselessEq(dir, "ne") ||
Utils.CaselessEquals(dir, "sw") || Utils.CaselessEquals(dir, "se")) { Utils.CaselessEq(dir, "sw") || Utils.CaselessEq(dir, "se")) {
return RotateCorner(game, block, name, offset); 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); return RotateVertical(game, block, name, offset);
} else if (Utils.CaselessEquals(dir, "n") || Utils.CaselessEquals(dir, "w") || } else if (Utils.CaselessEq(dir, "n") || Utils.CaselessEq(dir, "w") ||
Utils.CaselessEquals(dir, "s") || Utils.CaselessEquals(dir, "e")) { Utils.CaselessEq(dir, "s") || Utils.CaselessEq(dir, "e")) {
return RotateDirection(game, block, name, offset); return RotateDirection(game, block, name, offset);
} else if (Utils.CaselessEquals(dir, "UD") || Utils.CaselessEquals(dir, "WE") || } else if (Utils.CaselessEq(dir, "UD") || Utils.CaselessEq(dir, "WE") ||
Utils.CaselessEquals(dir, "NS")) { Utils.CaselessEq(dir, "NS")) {
return RotateOther(game, block, name, offset); return RotateOther(game, block, name, offset);
} }
return block; return block;

View File

@ -238,7 +238,7 @@ namespace ClassicalSharp {
public static int FindID(string name) { public static int FindID(string name) {
for (int b = 0; b < Count; b++) { 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; return -1;
} }

View File

@ -22,7 +22,7 @@ namespace ClassicalSharp.Commands {
return true; return true;
return Utils.CaselessStarts(input, prefixSpace) return Utils.CaselessStarts(input, prefixSpace)
|| Utils.CaselessEquals(input, prefix); || Utils.CaselessEq(input, prefix);
} }
protected Game game; protected Game game;

View File

@ -131,7 +131,7 @@ namespace ClassicalSharp.Commands {
if (args.Length == 1) { if (args.Length == 1) {
game.Chat.Add("&e/client model: &cYou didn't specify a model name."); game.Chat.Add("&e/client model: &cYou didn't specify a model name.");
} else { } else {
game.LocalPlayer.SetModel(Utils.ToLower(args[1])); game.LocalPlayer.SetModel(args[1]);
} }
} }
} }
@ -161,7 +161,7 @@ namespace ClassicalSharp.Commands {
persist = false; persist = false;
if (!ParseBlock(args)) return; if (!ParseBlock(args)) return;
if (args.Length > 2 && Utils.CaselessEquals(args[2], "yes")) if (args.Length > 2 && Utils.CaselessEq(args[2], "yes"))
persist = true; persist = true;
game.Chat.Add("&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus1); game.Chat.Add("&eCuboid: &fPlace or delete a block.", MessageType.ClientStatus1);
@ -170,7 +170,7 @@ namespace ClassicalSharp.Commands {
bool ParseBlock(string[] args) { bool ParseBlock(string[] args) {
if (args.Length == 1) return true; 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]); int temp = BlockInfo.FindID(args[1]);
BlockID block = 0; BlockID block = 0;

View File

@ -116,7 +116,7 @@ namespace ClassicalSharp.Entities {
string scale = sep == -1 ? null : model.Substring(sep + 1); string scale = sep == -1 ? null : model.Substring(sep + 1);
ModelName = sep == -1 ? model : model.Substring(0, sep); ModelName = sep == -1 ? model : model.Substring(0, sep);
if (Utils.CaselessEquals(model, "giant")) { if (Utils.CaselessEq(model, "giant")) {
ModelName = "humanoid"; ModelName = "humanoid";
ModelScale *= 2; ModelScale *= 2;
} }

View File

@ -25,7 +25,7 @@ namespace ClassicalSharp.Entities.Mobs {
physics.hacks = hacks; physics.hacks = hacks;
physics.collisions = collisions; 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); ai = new FleeAI(game, this);
} else { } else {
ai = new HostileAI(game, this); ai = new HostileAI(game, this);

View File

@ -49,7 +49,7 @@ namespace ClassicalSharp.Model {
public int GetTextureIndex(string texName) { public int GetTextureIndex(string texName) {
for (int i = 0; i < Textures.Count; i++) { 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; return -1;
} }
@ -58,7 +58,8 @@ namespace ClassicalSharp.Model {
public IModel Get(string modelName) { public IModel Get(string modelName) {
for (int i = 0; i < Models.Count; i++) { for (int i = 0; i < Models.Count; i++) {
CachedModel m = Models[i]; CachedModel m = Models[i];
if (m.Name != modelName) continue; if (!Utils.CaselessEq(m.Name, modelName)) continue;
if (!m.Instance.initalised) InitModel(m); if (!m.Instance.initalised) InitModel(m);
return m.Instance; return m.Instance;
} }

View File

@ -89,7 +89,7 @@ namespace ClassicalSharp.Model {
DrawRotate(p.anim.leftLegX, 0, 0, RightLegBack, false); DrawRotate(p.anim.leftLegX, 0, 0, RightLegBack, false);
UpdateVB(); UpdateVB();
if (Utils.CaselessEquals(p.ModelName, "sheep_nofur")) return; if (Utils.CaselessEq(p.ModelName, "sheep_nofur")) return;
ModelCache cache = game.ModelCache; ModelCache cache = game.ModelCache;
gfx.BindTexture(cache.Textures[furIndex].TexID); gfx.BindTexture(cache.Textures[furIndex].TexID);
DrawRotate(-p.HeadXRadians, 0, 0, FurHead, true); DrawRotate(-p.HeadXRadians, 0, 0, FurHead, true);

View File

@ -199,13 +199,13 @@ namespace ClassicalSharp {
} }
public int CalcRenderType(string type) { public int CalcRenderType(string type) {
if (Utils.CaselessEquals(type, "legacyfast")) { if (Utils.CaselessEq(type, "legacyfast")) {
return 0x03; return 0x03;
} else if (Utils.CaselessEquals(type, "legacy")) { } else if (Utils.CaselessEq(type, "legacy")) {
return 0x01; return 0x01;
} else if (Utils.CaselessEquals(type, "normal")) { } else if (Utils.CaselessEq(type, "normal")) {
return 0x00; return 0x00;
} else if (Utils.CaselessEquals(type, "normalfast")) { } else if (Utils.CaselessEq(type, "normalfast")) {
return 0x02; return 0x02;
} }
return -1; return -1;

View File

@ -211,7 +211,7 @@ namespace ClassicalSharp.Network.Protocols {
void HandleChangeModel() { void HandleChangeModel() {
byte id = reader.ReadUInt8(); byte id = reader.ReadUInt8();
string modelName = Utils.ToLower(reader.ReadString()); string modelName = reader.ReadString();
Entity entity = game.Entities.List[id]; Entity entity = game.Entities.List[id];
if (entity != null) entity.SetModel(modelName); if (entity != null) entity.SetModel(modelName);
} }

View File

@ -88,7 +88,7 @@ namespace ClassicalSharp {
static bool IsChangedOption(string key) { static bool IsChangedOption(string key) {
for (int i = 0; i < OptionsChanged.Count; i++) { 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; return false;
} }
@ -155,7 +155,7 @@ namespace ClassicalSharp {
static int FindOption(string key) { static int FindOption(string key) {
for (int i = 0; i < OptionsKeys.Count; i++) { 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; return -1;
} }

View File

@ -19,7 +19,7 @@ namespace ClassicalSharp {
public delegate void Action(); public delegate void Action();
// ################################################################ // ################################################################
public enum Anchor { public enum Anchor {
Min, // left or top Min, // left or top
Centre, // middle Centre, // middle
Max, // right or bottom Max, // right or bottom
@ -46,7 +46,7 @@ namespace ClassicalSharp {
return new String(output, 0, usedChars); return new String(output, 0, usedChars);
} }
#if !LAUNCHER #if !LAUNCHER
public static string RemoveEndPlus(string value) { public static string RemoveEndPlus(string value) {
// Workaround for MCDzienny (and others) use a '+' at the end to distinguish classicube.net accounts // 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. // from minecraft.net accounts. Unfortunately they also send this ending + to the client.
@ -55,13 +55,14 @@ namespace ClassicalSharp {
return value[value.Length - 1] == '+' ? return value[value.Length - 1] == '+' ?
value.Substring(0, value.Length - 1) : value; value.Substring(0, value.Length - 1) : value;
} }
#endif #endif
const StringComparison comp = StringComparison.OrdinalIgnoreCase; 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 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 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) { public static void LogDebug(string text) {
try { Console.WriteLine(text); } catch { } try { Console.WriteLine(text); } catch { }
} }
@ -79,7 +80,7 @@ namespace ClassicalSharp {
return steps; return steps;
} }
#if !LAUNCHER #if !LAUNCHER
/// <summary> Attempts to caselessly parse the given string as a Key enum member, /// <summary> Attempts to caselessly parse the given string as a Key enum member,
/// returning defValue if there was an error parsing. </summary> /// returning defValue if there was an error parsing. </summary>
public static bool TryParseEnum<T>(string value, T defValue, out T result) { public static bool TryParseEnum<T>(string value, T defValue, out T result) {
@ -93,7 +94,7 @@ namespace ClassicalSharp {
result = mapping; result = mapping;
return true; return true;
} }
public static int AdjViewDist(float value) { public static int AdjViewDist(float value) {
return (int)(1.4142135 * value); return (int)(1.4142135 * value);
} }
@ -108,7 +109,7 @@ namespace ClassicalSharp {
adjCol *= tint; adjCol *= tint;
return adjCol.Pack(); return adjCol.Pack();
} }
/// <summary> Determines the skin type of the specified bitmap. </summary> /// <summary> Determines the skin type of the specified bitmap. </summary>
public static SkinType GetSkinType(Bitmap bmp) { public static SkinType GetSkinType(Bitmap bmp) {
if (bmp.Width == bmp.Height * 2) { if (bmp.Width == bmp.Height * 2) {
@ -133,7 +134,7 @@ namespace ClassicalSharp {
int https = value.IndexOf("https://", index); int https = value.IndexOf("https://", index);
return http == index || https == index; return http == index || https == index;
} }
#endif #endif
/// <summary> Conversion for code page 437 characters from index 0 to 31 to unicode. </summary> /// <summary> Conversion for code page 437 characters from index 0 to 31 to unicode. </summary>
const string ControlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼"; const string ControlCharReplacements = "\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼";
@ -167,15 +168,22 @@ namespace ClassicalSharp {
return ExtendedCharReplacements[c - 0x7F]; return ExtendedCharReplacements[c - 0x7F];
} }
public unsafe static string ToLower(string value) { public static string ToLower(string src) {
fixed(char* ptr = value) { bool hasUpper = false;
for (int i = 0; i < value.Length; i++) { for (int i = 0; i < src.Length; i++) {
char c = ptr[i]; char c = src[i];
if (c < 'A' || c > 'Z') continue; if (c >= 'A' && c <= 'Z') { hasUpper = true; break; }
c += ' '; ptr[i] = c;
}
} }
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) { public static uint CRC32(byte[] data, int length) {
@ -188,14 +196,14 @@ namespace ClassicalSharp {
return crc ^ 0xffffffffU; return crc ^ 0xffffffffU;
} }
#if !LAUNCHER #if !LAUNCHER
// Not all languages use . as their decimal point separator // Not all languages use . as their decimal point separator
public static bool TryParseDecimal(string s, out float result) { public static bool TryParseDecimal(string s, out float result) {
if (s.IndexOf(',') >= 0) if (s.IndexOf(',') >= 0)
s = s.Replace(',', '.'); s = s.Replace(',', '.');
float temp; float temp;
result = 0; result = 0;
if (!Single.TryParse(s, style, NumberFormatInfo.InvariantInfo, out temp)) return false; if (!Single.TryParse(s, style, NumberFormatInfo.InvariantInfo, out temp)) return false;
if (Single.IsInfinity(temp) || Single.IsNaN(temp)) return false; if (Single.IsInfinity(temp) || Single.IsNaN(temp)) return false;
result = temp; result = temp;
@ -203,7 +211,7 @@ namespace ClassicalSharp {
} }
public static float ParseDecimal(string s) { public static float ParseDecimal(string s) {
if (s.IndexOf(',') >= 0) if (s.IndexOf(',') >= 0)
s = s.Replace(',', '.'); s = s.Replace(',', '.');
return Single.Parse(s, style, NumberFormatInfo.InvariantInfo); return Single.Parse(s, style, NumberFormatInfo.InvariantInfo);
} }
@ -211,6 +219,6 @@ namespace ClassicalSharp {
const NumberStyles style = NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite const NumberStyles style = NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite
| NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint; | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint;
#endif #endif
} }
} }