Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Signwright v1.1.18
Signwright.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Signwright")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.18.0")] [assembly: AssemblyInformationalVersion("1.1.18")] [assembly: AssemblyProduct("Signwright")] [assembly: AssemblyTitle("Signwright")] [assembly: AssemblyVersion("1.1.18.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Signwright { public static class Camp { public sealed class Ink { public string Name; public string Hex; } public sealed class Stamp { public string Name; public string Markup; } public static readonly Ink[] Inks = new Ink[15] { new Ink { Name = "Ink", Hex = "111111" }, new Ink { Name = "White", Hex = "ffffff" }, new Ink { Name = "Ash", Hex = "bbbbbb" }, new Ink { Name = "Iron", Hex = "889999" }, new Ink { Name = "Copper", Hex = "cc7744" }, new Ink { Name = "Bronze", Hex = "ddaa44" }, new Ink { Name = "Gold", Hex = "ffcc00" }, new Ink { Name = "Ember", Hex = "ff6622" }, new Ink { Name = "Blood", Hex = "cc3333" }, new Ink { Name = "Mead", Hex = "eeaa44" }, new Ink { Name = "Pine", Hex = "66aa33" }, new Ink { Name = "Sea", Hex = "3399cc" }, new Ink { Name = "Night", Hex = "223366" }, new Ink { Name = "Plum", Hex = "aa55cc" }, new Ink { Name = "Bone", Hex = "ffeecc" } }; public static readonly Stamp[] Stamps = new Stamp[16] { new Stamp { Name = "Stores", Markup = "<#c74>⛏ Ore\\n<#899>\ud83d\udd29 Bars" }, new Stamp { Name = "Coal", Markup = "<#bbb>\ud83d\udd25 Coal" }, new Stamp { Name = "Arms", Markup = "<#899>⚔ Arms" }, new Stamp { Name = "Kitchen", Markup = "<#f62>\ud83c\udf56 Kitchen" }, new Stamp { Name = "Mead", Markup = "<#ea4>\ud83c\udf7a Mead" }, new Stamp { Name = "Danger", Markup = "<#c33>⚠ Danger" }, new Stamp { Name = "Waymark", Markup = "<#6a3>→ Meadows" }, new Stamp { Name = "Portal", Markup = "<#a5c>Portal\\n<#fec>→ Plains" }, new Stamp { Name = "Dock", Markup = "<#39c>⚓ Dock" }, new Stamp { Name = "Private", Markup = "<#c33>\ud83d\udd12 Private" }, new Stamp { Name = "Farm", Markup = "<#6a3>\ud83e\udd55 Farm" }, new Stamp { Name = "Crypt", Markup = "<#899>☠ Crypt" }, new Stamp { Name = "Sold out", Markup = "<#c74><s>Copper" }, new Stamp { Name = "Way up", Markup = "<#fff><size=20>⬆" }, new Stamp { Name = "North", Markup = "<#39c>Deep North\\n<#fff>❄" }, new Stamp { Name = "Tavern", Markup = "<#fc0>The Raven\\n<#fec><i>Inn" } }; private static readonly Dictionary<char, char> Runes = new Dictionary<char, char> { { 'a', 'ᚨ' }, { 'b', 'ᛒ' }, { 'c', 'ᚲ' }, { 'd', 'ᛞ' }, { 'e', 'ᛖ' }, { 'f', 'ᚠ' }, { 'g', 'ᚷ' }, { 'h', 'ᚺ' }, { 'i', 'ᛁ' }, { 'j', 'ᛃ' }, { 'k', 'ᚲ' }, { 'l', 'ᛚ' }, { 'm', 'ᛗ' }, { 'n', 'ᚾ' }, { 'o', 'ᛟ' }, { 'p', 'ᛈ' }, { 'q', 'ᚲ' }, { 'r', 'ᚱ' }, { 's', 'ᛊ' }, { 't', 'ᛏ' }, { 'u', 'ᚢ' }, { 'v', 'ᚢ' }, { 'w', 'ᚹ' }, { 'x', 'ᛉ' }, { 'y', 'ᛃ' }, { 'z', 'ᛉ' } }; public static readonly string[] Portals = new string[10] { "Ravenwatch", "Ashgate", "Fjordhome", "Wolfden", "Stonepier", "Nightfen", "Pineholt", "Seaharrow", "Goldbarrow", "Meadhall" }; public static readonly string[] Taverns = new string[5] { "The Raven", "Broken Oar", "Last Mead", "Red Boar", "Ash Antler" }; public static readonly string[] Shops = new string[5] { "Iron and Oak", "Fine Blades", "The Smelter", "Honey Jar", "Copper Bin" }; public static readonly string[] Warnings = new string[5] { "Wolves", "Draugr", "Turn back", "Serpents", "Do not dig" }; public static string CarveRunes(string input) { if (string.IsNullOrEmpty(input)) { return ""; } string text = input.ToLowerInvariant(); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < text.Length; i++) { if (i + 1 < text.Length && text[i] == 't' && text[i + 1] == 'h') { stringBuilder.Append('ᚦ'); i++; continue; } char c = text[i]; char value; if (c >= 'ᚠ' && c <= '\u16ff') { stringBuilder.Append(c); } else if (c == ' ' || c == '·' || c == '-') { stringBuilder.Append(c); } else if (Runes.TryGetValue(c, out value)) { stringBuilder.Append(value); } else if (c >= '0' && c <= '9') { stringBuilder.Append(c); } } return stringBuilder.ToString(); } public static string Spin(string[] list, int pick) { if (list == null || list.Length == 0) { return ""; } int num = pick % list.Length; if (num < 0) { num += list.Length; } return list[num]; } } public sealed class Run { public string Text = ""; public string Color; public int Alpha = 255; public int? Size; public bool Italic; public bool Underline; public bool Strike; public bool Mark; public bool SmallCaps; public string Baseline; public int? VOffset; public int? CSpace; public int? Rotate; } public sealed class Line { public string Align = "center"; public List<Run> Runs = new List<Run>(); } public sealed class SignDoc { public List<Line> Lines = new List<Line>(); public static SignDoc Blank() { SignDoc signDoc = new SignDoc(); Line item = new Line { Runs = { new Run() } }; signDoc.Lines.Add(item); return signDoc; } } public static class Markup { private sealed class State { public string Align = "center"; public bool DefaultBlack = true; public string Ink; public int? Size; public bool Italic; public bool Underline; public bool Strike; public bool Mark; public bool SmallCaps; public string Baseline; public int? VOffset; public int? CSpace; public int? Rotate; public static State From(string align, Run run) { bool flag = IsDefaultBlack(run); return new State { Align = (string.IsNullOrEmpty(align) ? "center" : align), DefaultBlack = flag, Ink = (flag ? null : ColorTag(run)), Size = run.Size, Italic = run.Italic, Underline = run.Underline, Strike = run.Strike, Mark = run.Mark, SmallCaps = run.SmallCaps, Baseline = run.Baseline, VOffset = run.VOffset, CSpace = run.CSpace, Rotate = run.Rotate }; } } public static SignDoc Parse(string raw) { if (string.IsNullOrEmpty(raw)) { return SignDoc.Blank(); } SignDoc doc = new SignDoc(); List<Run> runs = new List<Run>(); StringBuilder buf = new StringBuilder(); Run style = new Run(); string align = "center"; Action flush = delegate { if (buf.Length != 0) { runs.Add(Copy(style, buf.ToString())); buf.Length = 0; } }; Action action = delegate { flush(); Line line2 = new Line { Align = align, Runs = runs }; if (line2.Runs.Count == 0) { line2.Runs.Add(new Run()); } doc.Lines.Add(line2); runs = new List<Run>(); }; for (int num = 0; num < raw.Length; num++) { char c = raw[num]; if (c == '\\' && num + 1 < raw.Length && raw[num + 1] == 'n') { action(); num++; continue; } switch (c) { case '\n': action(); continue; case '<': break; default: buf.Append(c); continue; } int num2 = raw.IndexOf('>', num); if (num2 < 0) { buf.Append(raw, num, raw.Length - num); break; } string literal; bool br; Run run = Apply(raw.Substring(num, num2 - num + 1), style, align, out literal, out br, out align); if (literal != null) { buf.Append(literal); } else if (br) { action(); } else { flush(); style = run; } num = num2; } flush(); Line line = new Line { Align = align, Runs = runs }; if (line.Runs.Count == 0) { line.Runs.Add(new Run()); } doc.Lines.Add(line); if (doc.Lines.Count == 0) { return SignDoc.Blank(); } return doc; } public static string Write(SignDoc doc) { if (doc == null || doc.Lines == null) { return ""; } bool flag = false; foreach (Line line2 in doc.Lines) { foreach (Run run in line2.Runs) { if (!string.IsNullOrEmpty(run.Text)) { flag = true; } } } if (!flag) { return ""; } StringBuilder stringBuilder = new StringBuilder(); State state = new State(); for (int i = 0; i < doc.Lines.Count; i++) { if (i > 0) { stringBuilder.Append("\\n"); } Line line = doc.Lines[i]; foreach (Run run2 in line.Runs) { if (!string.IsNullOrEmpty(run2.Text)) { State state2 = State.From(line.Align, run2); stringBuilder.Append(Transition(state, state2)); stringBuilder.Append(run2.Text); state = state2; } } } return stringBuilder.ToString(); } public static string RenderNewlines(string raw) { return (raw ?? "").Replace("\\n", "\n"); } public static string ColorTag(Run run) { if (IsDefaultBlack(run)) { return "<#000>"; } if (!HexChannels(run.Color ?? "000000", out var r, out var g, out var b)) { return "<#000>"; } int num = Clamp(run.Alpha); if (num >= 255 && Nibble(r) && Nibble(g) && Nibble(b)) { return "<#" + HexNibble(r) + HexNibble(g) + HexNibble(b) + ">"; } if (Nibble(r) && Nibble(g) && Nibble(b) && Nibble(num)) { return "<#" + HexNibble(r) + HexNibble(g) + HexNibble(b) + HexNibble(num) + ">"; } if (num >= 255) { return "<#" + Byte(r) + Byte(g) + Byte(b) + ">"; } return "<#" + Byte(r) + Byte(g) + Byte(b) + Byte(num) + ">"; } public static bool IsDefaultBlack(Run run) { if (Clamp(run.Alpha) < 255) { return false; } if (!string.IsNullOrEmpty(run.Color)) { return run.Color == "000000"; } return true; } private static string Transition(State from, State to) { StringBuilder stringBuilder = new StringBuilder(); if (from.Baseline != null && from.Baseline != to.Baseline) { stringBuilder.Append("</").Append(from.Baseline).Append('>'); } if (from.SmallCaps && !to.SmallCaps) { stringBuilder.Append("</smallcaps>"); } if (from.Mark && !to.Mark) { stringBuilder.Append("</mark>"); } if (from.Strike && !to.Strike) { stringBuilder.Append("</s>"); } if (from.Underline && !to.Underline) { stringBuilder.Append("</u>"); } if (from.Italic && !to.Italic) { stringBuilder.Append("</i>"); } if (from.Rotate.HasValue && from.Rotate != to.Rotate) { stringBuilder.Append("</rotate>"); } if (from.CSpace.HasValue && from.CSpace != to.CSpace) { stringBuilder.Append("</cspace>"); } if (from.VOffset.HasValue && from.VOffset != to.VOffset) { stringBuilder.Append("</voffset>"); } if (from.Size.HasValue && from.Size != to.Size) { stringBuilder.Append("</size>"); } if (from.Align != "center" && from.Align != to.Align) { stringBuilder.Append("</align>"); } if (to.Align != "center" && to.Align != from.Align) { stringBuilder.Append("<align=").Append(to.Align).Append('>'); } string obj = (from.DefaultBlack ? null : from.Ink); string text = (to.DefaultBlack ? null : to.Ink); if (obj != text) { if (to.DefaultBlack) { stringBuilder.Append("<#000>"); } else if (text != null) { stringBuilder.Append(text); } } if (to.Size.HasValue && to.Size != from.Size) { stringBuilder.Append("<size=").Append(to.Size.Value.ToString(CultureInfo.InvariantCulture)).Append('>'); } if (to.VOffset.HasValue && to.VOffset != from.VOffset) { stringBuilder.Append("<voffset=").Append(to.VOffset.Value.ToString(CultureInfo.InvariantCulture)).Append('>'); } if (to.CSpace.HasValue && to.CSpace != from.CSpace) { stringBuilder.Append("<cspace=").Append(to.CSpace.Value.ToString(CultureInfo.InvariantCulture)).Append('>'); } if (to.Rotate.HasValue && to.Rotate != from.Rotate) { stringBuilder.Append("<rotate=").Append(to.Rotate.Value.ToString(CultureInfo.InvariantCulture)).Append('>'); } if (to.Italic && !from.Italic) { stringBuilder.Append("<i>"); } if (to.Underline && !from.Underline) { stringBuilder.Append("<u>"); } if (to.Strike && !from.Strike) { stringBuilder.Append("<s>"); } if (to.Mark && !from.Mark) { stringBuilder.Append("<mark>"); } if (to.SmallCaps && !from.SmallCaps) { stringBuilder.Append("<smallcaps>"); } if (to.Baseline != null && to.Baseline != from.Baseline) { stringBuilder.Append('<').Append(to.Baseline).Append('>'); } return stringBuilder.ToString(); } private static Run Copy(Run style, string text) { return new Run { Text = text, Color = style.Color, Alpha = style.Alpha, Size = style.Size, Italic = style.Italic, Underline = style.Underline, Strike = style.Strike, Mark = style.Mark, SmallCaps = style.SmallCaps, Baseline = style.Baseline, VOffset = style.VOffset, CSpace = style.CSpace, Rotate = style.Rotate }; } private static Run Apply(string tag, Run style, string align, out string literal, out bool br, out string nextAlign) { literal = null; br = false; nextAlign = align; string text = tag.Substring(1, tag.Length - 2).Trim(); string text2 = text.ToLowerInvariant(); Run run = Copy(style, ""); switch (text2) { case "br": case "br/": br = true; return style; case "b": case "/b": return style; case "i": run.Italic = true; break; case "/i": run.Italic = false; break; case "u": run.Underline = true; break; case "/u": run.Underline = false; break; case "s": run.Strike = true; break; case "/s": run.Strike = false; break; case "mark": run.Mark = true; break; case "/mark": run.Mark = false; break; case "smallcaps": run.SmallCaps = true; break; case "/smallcaps": run.SmallCaps = false; break; case "sub": run.Baseline = "sub"; break; case "/sub": if (run.Baseline == "sub") { run.Baseline = null; } break; case "sup": run.Baseline = "sup"; break; case "/sup": if (run.Baseline == "sup") { run.Baseline = null; } break; case "/color": run.Color = null; run.Alpha = 255; break; case "/size": run.Size = null; break; case "/voffset": run.VOffset = null; break; case "/cspace": run.CSpace = null; break; case "/rotate": run.Rotate = null; break; case "/align": nextAlign = "center"; break; default: { if (text2.StartsWith("#")) { if (!ParseHex(text2.Substring(1), out var r, out var g, out var b, out var a)) { literal = tag; return style; } run.Color = Byte(r) + Byte(g) + Byte(b); run.Alpha = a; if (run.Color == "000000" && run.Alpha >= 255) { run.Color = null; run.Alpha = 255; } break; } int num = text2.IndexOf('='); if (num < 0) { literal = tag; return style; } string text3 = text2.Substring(0, num).Trim(); string text4 = text.Substring(num + 1).Trim().Trim('"', '\''); string text5 = text4.ToLowerInvariant(); switch (text3) { case "color": { if (!ParseHex(Named(text5) ?? text5.TrimStart(new char[1] { '#' }), out var r3, out var g3, out var b3, out var a3)) { literal = tag; return style; } run.Color = Byte(r3) + Byte(g3) + Byte(b3); run.Alpha = a3; break; } case "size": { if (text5.EndsWith("%") || !int.TryParse(text4, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2)) { literal = tag; return style; } run.Size = result2; break; } case "align": switch (text5) { case "left": case "center": case "right": break; default: literal = tag; return style; } nextAlign = text5; break; case "voffset": case "cspace": case "rotate": case "alpha": { string text6 = text5.Replace("em", "").Replace("px", "").TrimStart(new char[1] { '#' }); if (text3 == "alpha") { if (!ParseHex(text6, out var r2, out var _, out var _, out var _)) { literal = tag; return style; } run.Alpha = r2; break; } if (!int.TryParse(text6, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { literal = tag; return style; } if (text3 == "voffset") { run.VOffset = result; } else if (text3 == "cspace") { run.CSpace = result; } else { run.Rotate = result; } break; } default: literal = tag; return style; } break; } } return run; } private static string Named(string name) { switch (name) { case "black": return "000000"; case "white": return "ffffff"; case "red": return "ff0000"; case "green": return "00ff00"; case "blue": return "0000ff"; case "yellow": return "ffff00"; case "orange": return "ffa500"; case "purple": return "800080"; case "grey": case "gray": return "808080"; case "cyan": return "00ffff"; case "magenta": return "ff00ff"; default: return null; } } public static bool ParseHex(string raw, out int r, out int g, out int b, out int a) { r = (g = (b = 0)); a = 255; if (string.IsNullOrEmpty(raw)) { return false; } raw = raw.Trim().TrimStart(new char[1] { '#' }).ToLowerInvariant(); string text = raw; for (int i = 0; i < text.Length; i++) { if (!Uri.IsHexDigit(text[i])) { return false; } } if (raw.Length != 3 && raw.Length != 4 && raw.Length != 6 && raw.Length != 8) { return false; } if (raw.Length <= 4) { r = Expand(raw[0]); g = Expand(raw[1]); b = Expand(raw[2]); if (raw.Length == 4) { a = Expand(raw[3]); } return true; } r = Convert.ToInt32(raw.Substring(0, 2), 16); g = Convert.ToInt32(raw.Substring(2, 2), 16); b = Convert.ToInt32(raw.Substring(4, 2), 16); if (raw.Length == 8) { a = Convert.ToInt32(raw.Substring(6, 2), 16); } return true; } private static bool HexChannels(string raw, out int r, out int g, out int b) { int a; return ParseHex(raw, out r, out g, out b, out a); } private static int Expand(char c) { int num = Convert.ToInt32(c.ToString(), 16); return num * 16 + num; } private static bool Nibble(int n) { return n >> 4 == (n & 0xF); } private static string HexNibble(int n) { return (n >> 4).ToString("x"); } private static string Byte(int n) { return Clamp(n).ToString("x2"); } private static int Clamp(int n) { if (n < 0) { return 0; } if (n > 255) { return 255; } return n; } } internal static class ZdoAccess { private static readonly FieldInfo NviewField = AccessTools.Field(typeof(Sign), "m_nview"); public const int TextHash = -871206003; public static object Nview(Sign sign) { if (!(NviewField != null)) { return null; } return NviewField.GetValue(sign); } public static object Zdo(Sign sign) { object obj = Nview(sign); if (obj == null) { return null; } MethodInfo methodInfo = AccessTools.Method(obj.GetType(), "GetZDO", (Type[])null, (Type[])null); if (!(methodInfo != null)) { return null; } return methodInfo.Invoke(obj, null); } public static string Read(object zdo, string fallback) { if (zdo == null) { return fallback ?? ""; } MethodInfo[] methods = zdo.GetType().GetMethods(); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "GetString")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string)) { return ((string)methodInfo.Invoke(zdo, new object[2] { "text", fallback ?? "" })) ?? ""; } } } methods = zdo.GetType().GetMethods(); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "GetString")) { ParameterInfo[] parameters2 = methodInfo2.GetParameters(); if (parameters2.Length == 2 && parameters2[0].ParameterType == typeof(int)) { return ((string)methodInfo2.Invoke(zdo, new object[2] { -871206003, fallback ?? "" })) ?? ""; } } } return fallback ?? ""; } public static void Write(Sign sign, string text) { object obj = Nview(sign); object obj2 = Zdo(sign); if (obj == null || obj2 == null) { return; } MethodInfo methodInfo = AccessTools.Method(obj.GetType(), "ClaimOwnership", (Type[])null, (Type[])null); if (methodInfo != null && methodInfo.GetParameters().Length == 0) { methodInfo.Invoke(obj, null); } MethodInfo[] methods = obj2.GetType().GetMethods(); foreach (MethodInfo methodInfo2 in methods) { if (!(methodInfo2.Name != "Set")) { ParameterInfo[] parameters = methodInfo2.GetParameters(); if (parameters.Length == 2 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string)) { methodInfo2.Invoke(obj2, new object[2] { "text", text }); return; } } } methods = obj2.GetType().GetMethods(); foreach (MethodInfo methodInfo3 in methods) { if (!(methodInfo3.Name != "Set")) { ParameterInfo[] parameters2 = methodInfo3.GetParameters(); if (parameters2.Length == 2 && parameters2[0].ParameterType == typeof(int) && parameters2[1].ParameterType == typeof(string)) { methodInfo3.Invoke(obj2, new object[2] { -871206003, text }); break; } } } } } internal static class Ward { public static bool Allows(Vector3 position) { //IL_00e2: Unknown result type (might be due to invalid IL or missing references) try { Type type = AccessTools.TypeByName("PrivateArea"); if (type == null) { return true; } List<MethodInfo> list = (from m in AccessTools.GetDeclaredMethods(type) where m.Name == "CheckAccess" && m.IsStatic select m).ToList(); MethodInfo methodInfo = null; foreach (MethodInfo item in list) { ParameterInfo[] parameters = item.GetParameters(); if (parameters.Length != 0 && parameters[0].ParameterType == typeof(Vector3) && (methodInfo == null || parameters.Length < methodInfo.GetParameters().Length)) { methodInfo = item; } } if (methodInfo == null) { return true; } object[] array = new object[methodInfo.GetParameters().Length]; ParameterInfo[] parameters2 = methodInfo.GetParameters(); array[0] = position; for (int num = 1; num < parameters2.Length; num++) { if (parameters2[num].ParameterType == typeof(float)) { array[num] = 0f; } else if (parameters2[num].ParameterType == typeof(bool)) { array[num] = false; } else if (parameters2[num].ParameterType.IsValueType) { array[num] = Activator.CreateInstance(parameters2[num].ParameterType); } } return (bool)methodInfo.Invoke(null, array); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Ward check failed, allowing edit: " + ex.Message)); } return true; } } } internal static class TextClamp { public static void Patch(Harmony harmony) { //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown string[] array = new string[2] { "ZDO", "ZDOExtraData" }; for (int i = 0; i < array.Length; i++) { Type type = AccessTools.TypeByName(array[i]); if (type == null) { continue; } foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (!(declaredMethod.Name != "Set")) { ParameterInfo[] parameters = declaredMethod.GetParameters(); if (parameters.Length != 0 && !(parameters[^1].ParameterType != typeof(string))) { harmony.Patch((MethodBase)declaredMethod, new HarmonyMethod(typeof(TextClamp), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } } Type type2 = AccessTools.TypeByName("TextInput"); if (type2 == null) { return; } foreach (MethodInfo declaredMethod2 in AccessTools.GetDeclaredMethods(type2)) { if (!(declaredMethod2.Name != "RequestText")) { harmony.Patch((MethodBase)declaredMethod2, new HarmonyMethod(typeof(TextClamp), "RequestPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static void Prefix(object[] __args) { try { if (__args == null) { return; } bool flag = false; for (int i = 0; i < __args.Length; i++) { if (__args[i] is string text && text == "text") { flag = true; } else if (__args[i] is int num && num == -871206003) { flag = true; } } if (!flag) { return; } int num2 = Plugin.Limit(); for (int num3 = __args.Length - 1; num3 >= 0; num3--) { if (__args[num3] is string text2 && text2 != "text" && text2.Length > num2) { __args[num3] = text2.Substring(0, num2); break; } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Sign text clamp skipped: " + ex.Message)); } } } private static void RequestPrefix(object[] __args) { if (__args == null) { return; } bool flag = false; for (int i = 0; i < __args.Length; i++) { if (__args[i] is Sign) { flag = true; } } if (!flag) { return; } int num = Plugin.Limit(); for (int j = 0; j < __args.Length; j++) { if (__args[j] is int num2 && num2 > 0 && num2 < num) { __args[j] = num; } } } } [HarmonyPatch(typeof(Sign), "Awake")] internal static class SignAwakePatch { private static void Postfix(Sign __instance) { if ((Object)(object)__instance != (Object)null) { __instance.m_characterLimit = Plugin.Limit(); } } } [HarmonyPatch(typeof(Sign), "SetText")] internal static class SignSetTextPatch { private static void Prefix(Sign __instance, ref string __0) { if ((Object)(object)__instance != (Object)null) { __instance.m_characterLimit = Plugin.Limit(); } if (__0 == null) { __0 = ""; } int num = Plugin.Limit(); if (__0.Length > num) { __0 = __0.Substring(0, num); } } private static void Postfix(Sign __instance, string __0) { if (!((Object)(object)__instance == (Object)null) && __0 != null) { object obj = ZdoAccess.Zdo(__instance); if (obj != null && ZdoAccess.Read(obj, "") != __0) { ZdoAccess.Write(__instance, __0); } } } } [HarmonyPatch(typeof(Sign), "Interact")] internal static class SignInteractPatch { private static bool Prefix(Sign __instance, object[] __args, ref bool __result) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (Plugin.IsHeadless() || Plugin.ReplaceEditor == null || !Plugin.ReplaceEditor.Value) { return true; } bool flag = false; if (__args != null) { for (int i = 0; i < __args.Length; i++) { if (__args[i] is bool flag2) { flag = flag2; break; } } } if (flag) { __result = false; return false; } if ((Object)(object)__instance == (Object)null || !Ward.Allows(((Component)__instance).transform.position)) { __result = false; return false; } if ((Object)(object)SignEditor.Instance == (Object)null) { return true; } SignEditor.Instance.Open(__instance); __result = true; return false; } } [HarmonyPatch(typeof(Sign), "UpdateText")] internal static class SignUpdateTextPatch { private static bool Prefix(Sign __instance) { return !SignEditor.IsEditing(__instance); } private static void Postfix(Sign __instance) { if ((Object)(object)__instance == (Object)null) { return; } if (SignEditor.IsEditing(__instance)) { SignEditor.ApplyDraft(__instance); return; } object obj = ZdoAccess.Zdo(__instance); if (obj != null) { string text = Markup.RenderNewlines(ZdoAccess.Read(obj, __instance.m_defaultText ?? "")); string text2 = ReadWidget(__instance); if (text2 != text && (text2.IndexOf("\\n", StringComparison.Ordinal) >= 0 || text2.Length < text.Length)) { WriteWidget(__instance, text); } } } public static string ReadWidget(Sign sign) { FieldInfo fieldInfo = AccessTools.Field(typeof(Sign), "m_textWidget"); object obj = ((fieldInfo != null) ? fieldInfo.GetValue(sign) : null); if (obj == null) { return ""; } PropertyInfo property = obj.GetType().GetProperty("text"); if (!(property != null)) { return ""; } return (property.GetValue(obj, null) as string) ?? ""; } public static void WriteWidget(Sign sign, string text) { FieldInfo fieldInfo = AccessTools.Field(typeof(Sign), "m_textWidget"); object obj = ((fieldInfo != null) ? fieldInfo.GetValue(sign) : null); if (obj != null) { PropertyInfo property = obj.GetType().GetProperty("text"); if (property != null && property.CanWrite) { property.SetValue(obj, text, null); } } } } internal static class MouseFree { public static void Patch(Harmony harmony) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown Type type = AccessTools.TypeByName("GameCamera"); if (type != null) { MethodInfo methodInfo = AccessTools.Method(type, "LateUpdate", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(MouseFree), "AfterCamera", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { if (declaredMethod.Name.IndexOf("MouseCapture", StringComparison.Ordinal) >= 0 || !(declaredMethod.Name != "UpdateCursor")) { harmony.Patch((MethodBase)declaredMethod, new HarmonyMethod(typeof(MouseFree), "SkipCapture", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } Type type2 = AccessTools.TypeByName("ZInput"); if (type2 == null) { return; } foreach (MethodInfo declaredMethod2 in AccessTools.GetDeclaredMethods(type2)) { if (!(declaredMethod2.Name != "GetMouseDelta") && !(declaredMethod2.ReturnType != typeof(Vector2))) { harmony.Patch((MethodBase)declaredMethod2, (HarmonyMethod)null, new HarmonyMethod(typeof(MouseFree), "ZeroDelta", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } } private static bool SkipCapture() { if (!SignEditor.Blocking) { return true; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; return false; } private static void AfterCamera() { if (SignEditor.Blocking) { Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } } private static void ZeroDelta(ref Vector2 __result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (SignEditor.Blocking) { __result = Vector2.zero; } } } internal static class KeyGuard { public static void Patch(Harmony harmony) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Expected O, but got Unknown HarmonyMethod deny = new HarmonyMethod(typeof(KeyGuard), "Deny", (Type[])null); Type type = AccessTools.TypeByName("ZInput"); if (type != null) { foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type)) { TryPatch(harmony, declaredMethod, deny); TryQuietScroll(harmony, declaredMethod); } } Type type2 = AccessTools.TypeByName("UnityEngine.Input"); if (type2 != null) { MethodInfo[] methods = type2.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo method in methods) { TryPatch(harmony, method, deny); TryQuietScroll(harmony, method); } PropertyInfo property = type2.GetProperty("mouseScrollDelta"); MethodInfo methodInfo = ((property != null) ? property.GetGetMethod() : null); if (methodInfo != null) { TryQuietScroll(harmony, methodInfo); } } HarmonyMethod val = new HarmonyMethod(typeof(KeyGuard), "BlockTakeInput", (Type[])null); string[] array = new string[2] { "Player", "PlayerController" }; foreach (string text in array) { Type type3 = AccessTools.TypeByName(text); if (type3 == null) { continue; } foreach (MethodInfo declaredMethod2 in AccessTools.GetDeclaredMethods(type3)) { if (declaredMethod2.Name != "TakeInput" || declaredMethod2.ReturnType != typeof(bool)) { continue; } try { harmony.Patch((MethodBase)declaredMethod2, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Could not block " + text + ".TakeInput: " + ex.Message)); } } } } Type type4 = AccessTools.TypeByName("TextInput"); MethodInfo methodInfo2 = ((type4 != null) ? AccessTools.Method(type4, "IsVisible", (Type[])null, (Type[])null) : null); if (!(methodInfo2 != null) || !(methodInfo2.ReturnType == typeof(bool))) { return; } try { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(KeyGuard), "PretendTyping", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("Could not mark the editor as typing: " + ex2.Message)); } } } private static void TryQuietScroll(Harmony harmony, MethodInfo method) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown if (method == null) { return; } string name = method.Name; bool num = name == "GetAxis" || name == "GetAxisRaw"; bool flag = name.IndexOf("Scroll", StringComparison.OrdinalIgnoreCase) >= 0 || name == "get_mouseScrollDelta"; if (!num && !flag) { return; } HarmonyMethod val = null; if (method.ReturnType == typeof(float)) { val = new HarmonyMethod(typeof(KeyGuard), "QuietFloat", (Type[])null); } else if (method.ReturnType == typeof(Vector2)) { val = new HarmonyMethod(typeof(KeyGuard), "QuietVector", (Type[])null); } if (val == null) { return; } try { harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Could not quiet scroll on " + method.DeclaringType?.ToString() + "." + name + ": " + ex.Message)); } } } private static void QuietFloat(ref float __result) { if (SignEditor.Blocking) { __result = 0f; } } private static void QuietVector(ref Vector2 __result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (SignEditor.Blocking) { __result = Vector2.zero; } } private static void TryPatch(Harmony harmony, MethodInfo method, HarmonyMethod deny) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown if (method == null || method.ReturnType != typeof(bool)) { return; } string name = method.Name; if (name != "GetButton" && name != "GetButtonDown" && name != "GetButtonUp" && name != "GetKey" && name != "GetKeyDown" && name != "GetKeyUp") { return; } try { harmony.Patch((MethodBase)method, deny, new HarmonyMethod(typeof(KeyGuard), "SwallowCancel", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("Could not quiet " + method.DeclaringType?.ToString() + "." + name + ": " + ex.Message)); } } } private static bool Deny(object[] __args, ref bool __result) { if (!SignEditor.Blocking) { return true; } if (IsCancel(__args)) { return true; } __result = false; return false; } private static void SwallowCancel(MethodBase __originalMethod, object[] __args, ref bool __result) { if (SignEditor.Blocking && __result && !(__originalMethod == null) && IsCancel(__args)) { string name = __originalMethod.Name; if (!(name != "GetButtonDown") || !(name != "GetKeyDown")) { __result = false; SignEditor.QueueCancel(); } } } private static bool IsCancel(object[] args) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected I4, but got Unknown if (args == null || args.Length == 0 || args[0] == null) { return false; } if (args[0] is string a) { return string.Equals(a, "JoyButtonB", StringComparison.OrdinalIgnoreCase); } if (args[0] is KeyCode val) { int num = (int)val; if (num >= 330 && num <= 509) { return num % 20 == 11; } return false; } return false; } private static bool BlockTakeInput(ref bool __result) { if (!SignEditor.Blocking) { return true; } __result = false; return false; } private static void PretendTyping(ref bool __result) { if (SignEditor.Blocking) { __result = true; } } } [BepInPlugin("com.signwright.valheim", "Signwright", "1.1.18")] public class Plugin : BaseUnityPlugin { public const string Guid = "com.signwright.valheim"; public const string Name = "Signwright"; public const string Version = "1.1.18"; public static ConfigEntry<int> CharacterLimit; public static ConfigEntry<bool> ReplaceEditor; public static Plugin Instance { get; private set; } public static ManualLogSource Log { get; private set; } private void Awake() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_009b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; CharacterLimit = ((BaseUnityPlugin)this).Config.Bind<int>("General", "CharacterLimit", 400, new ConfigDescription("Cap for a wood sign, counted the way C# string.Length counts (UTF-16). Vanilla is 50. A few hundred is enough for a colored multi-line sign. This is not unlimited, and the plank does not grow.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 800), Array.Empty<object>())); ReplaceEditor = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceEditor", true, "Open the Signwright editor on the wood sign. Turn this off to keep the vanilla text box, still with the longer limit."); Harmony val = new Harmony("com.signwright.valheim"); val.PatchAll(typeof(Plugin).Assembly); TextClamp.Patch(val); MouseFree.Patch(val); KeyGuard.Patch(val); if (!IsHeadless()) { ((Component)this).gameObject.AddComponent<SignEditor>(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} {1} ready. CharacterLimit={2}. Headless={3}.", "Signwright", "1.1.18", CharacterLimit.Value, IsHeadless())); } public static bool IsHeadless() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 return (int)SystemInfo.graphicsDeviceType == 4; } public static int Limit() { int num = ((CharacterLimit != null) ? CharacterLimit.Value : 400); if (num < 50) { return 50; } if (num > 800) { return 800; } return num; } } public class SignEditor : MonoBehaviour { private class SymbolItem { public string Glyph; public string Name; public string Search; } private class SymbolGroup { public string Label; public List<SymbolItem> Items = new List<SymbolItem>(); } private Sign _sign; private SignDoc _doc = SignDoc.Blank(); private string _original = ""; private int _line; private int _run; private Vector2 _scroll; private Vector2 _symbolScroll; private string _hex = ""; private string _scribe = "Thor"; private string _symbolQuery = ""; private string _markupDraft = ""; private string _status = ""; private int _caret = -1; private int _caretEnd = -1; private int _placeCaret = -1; private bool _closeQueued; private int _group; private List<SymbolGroup> _groups = new List<SymbolGroup>(); private Rect _window = new Rect(40f, 40f, 560f, 720f); private GUIStyle _windowStyle; private GUIStyle _heading; private GUIStyle _note; private GUIStyle _field; private Texture2D _windowBg; private Texture2D _rule; public static SignEditor Instance { get; private set; } public static bool Blocking { get { if ((Object)(object)Instance != (Object)null) { return (Object)(object)Instance._sign != (Object)null; } return false; } } private void Awake() { Instance = this; LoadSymbols(); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } public static bool IsEditing(Sign sign) { if ((Object)(object)Instance != (Object)null) { return (Object)(object)Instance._sign == (Object)(object)sign; } return false; } public static void ApplyDraft(Sign sign) { if (!((Object)(object)Instance == (Object)null) && !((Object)(object)Instance._sign != (Object)(object)sign)) { SignUpdateTextPatch.WriteWidget(sign, Markup.RenderNewlines(Markup.Write(Instance._doc))); } } public void Open(Sign sign) { _sign = sign; object obj = ZdoAccess.Zdo(sign); _original = ((obj != null) ? ZdoAccess.Read(obj, sign.m_defaultText ?? "") : (sign.m_defaultText ?? "")); _doc = Markup.Parse(_original); _markupDraft = Markup.Write(_doc); _line = 0; _run = 0; SyncHex(); _status = "Editing this sign."; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } public static void QueueCancel() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance._sign != (Object)null) { Instance._closeQueued = true; } } private void Update() { if (!((Object)(object)_sign == (Object)null)) { if (PadCancel()) { _closeQueued = true; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; ApplyDraft(_sign); } } private void LateUpdate() { if (!((Object)(object)_sign == (Object)null) && _closeQueued) { _closeQueued = false; Close(save: false); } } private static bool PadCancel() { try { Type type = Type.GetType("UnityEngine.InputSystem.Gamepad, Unity.InputSystem"); if (type == null) { return false; } object obj = type.GetProperty("current")?.GetValue(null, null); if (obj == null) { return false; } object obj2 = obj.GetType().GetProperty("buttonEast")?.GetValue(obj, null); if (obj2 == null) { return false; } object obj3 = obj2.GetType().GetProperty("wasPressedThisFrame")?.GetValue(obj2, null); bool flag = default(bool); int num; if (obj3 is bool) { flag = (bool)obj3; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch (Exception) { return false; } } private void OnGUI() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 if (!((Object)(object)_sign == (Object)null)) { Event current = Event.current; if (current != null && (int)current.type == 4 && (int)current.keyCode == 27) { Close(save: false); current.Use(); return; } EnsureWindowStyle(); float num = Mathf.Max(1f, (float)Screen.height / 1080f); Matrix4x4 matrix = GUI.matrix; Color color = GUI.color; GUI.color = Color.white; GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f)); _window = GUI.Window(918273, _window, new WindowFunction(Draw), "Signwright", _windowStyle); GUI.matrix = matrix; GUI.color = color; } } private void EnsureWindowStyle() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Expected O, but got Unknown //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Expected O, but got Unknown //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Expected O, but got Unknown //IL_0257: Unknown result type (might be due to invalid IL or missing references) if (_windowStyle == null) { _windowBg = new Texture2D(1, 1, (TextureFormat)4, false); ((Object)_windowBg).hideFlags = (HideFlags)61; _windowBg.SetPixel(0, 0, new Color(0.11f, 0.086f, 0.07f, 0.96f)); _windowBg.Apply(); _windowStyle = new GUIStyle(GUI.skin.window); _windowStyle.normal.background = _windowBg; _windowStyle.onNormal.background = _windowBg; _windowStyle.hover.background = _windowBg; _windowStyle.focused.background = _windowBg; _windowStyle.active.background = _windowBg; _windowStyle.normal.textColor = new Color(0.93f, 0.86f, 0.74f); _windowStyle.fontStyle = (FontStyle)1; _windowStyle.padding = new RectOffset(12, 12, 28, 12); _heading = new GUIStyle(GUI.skin.label); _heading.fontStyle = (FontStyle)1; _heading.fontSize = 15; _heading.normal.textColor = new Color(0.96f, 0.89f, 0.75f); _heading.margin = new RectOffset(0, 0, 0, 0); _note = new GUIStyle(GUI.skin.label); _note.fontSize = 12; _note.wordWrap = true; _note.normal.textColor = new Color(0.74f, 0.65f, 0.52f); _field = new GUIStyle(GUI.skin.textField); _field.fontSize = 14; _field.normal.textColor = new Color(0.96f, 0.9f, 0.8f); _rule = new Texture2D(1, 1, (TextureFormat)4, false); ((Object)_rule).hideFlags = (HideFlags)61; _rule.SetPixel(0, 0, new Color(0.62f, 0.4f, 0.22f, 1f)); _rule.Apply(); } } private void Section(string title) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) GUILayout.Space(12f); GUILayout.Label(title, _heading, Array.Empty<GUILayoutOption>()); Rect rect = GUILayoutUtility.GetRect(1f, 2f); Color color = GUI.color; GUI.color = new Color(0.62f, 0.4f, 0.22f, 0.95f); GUI.DrawTexture(rect, (Texture)(object)_rule); GUI.color = color; GUILayout.Space(6f); } private static bool Marked(string label, bool on, params GUILayoutOption[] options) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Color backgroundColor = GUI.backgroundColor; if (on) { GUI.backgroundColor = new Color(0.95f, 0.62f, 0.32f); } bool result = ((options != null && options.Length != 0) ? GUILayout.Button(label, options) : GUILayout.Button(label, Array.Empty<GUILayoutOption>())); GUI.backgroundColor = backgroundColor; return result; } private void Draw(int id) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Unknown result type (might be due to invalid IL or missing references) //IL_0705: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_0553: Unknown result type (might be due to invalid IL or missing references) //IL_08da: Unknown result type (might be due to invalid IL or missing references) //IL_08ee: Unknown result type (might be due to invalid IL or missing references) //IL_094c: Unknown result type (might be due to invalid IL or missing references) Line line = CurrentLine(); Run run = CurrentRun(); _scroll = GUILayout.BeginScrollView(_scroll, Array.Empty<GUILayoutOption>()); string text = Markup.Write(_doc); int num = Plugin.Limit(); GUILayout.Label(text.Length + " / " + num, _note, Array.Empty<GUILayoutOption>()); if (text.Length > 50) { GUILayout.Label("A sign this long can only be read by players with this mod.", _note, Array.Empty<GUILayoutOption>()); } if (!string.IsNullOrEmpty(_status)) { GUILayout.Label(_status, _note, Array.Empty<GUILayoutOption>()); } Section("Text"); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (GUILayout.Button("New line", Array.Empty<GUILayoutOption>())) { AddLine(); } if (GUILayout.Button("Remove text", Array.Empty<GUILayoutOption>())) { RemoveRun(); } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int i = 0; i < _doc.Lines.Count; i++) { if (Marked("Line " + (i + 1), i == _line)) { _line = i; _run = 0; _caret = -1; _placeCaret = -1; SyncHex(); } } GUILayout.EndHorizontal(); if (_placeCaret >= 0) { GUI.FocusControl("sign-line"); } GUI.SetNextControlName("sign-line"); string text2 = GUILayout.TextField(run.Text ?? "", _field, Array.Empty<GUILayoutOption>()); if (text2 != run.Text) { run.Text = text2.Replace("\n", ""); } RememberCaret(run); Section("Style"); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (Marked("Left", line.Align == "left")) { line.Align = "left"; } if (Marked("Center", line.Align == "center")) { line.Align = "center"; } if (Marked("Right", line.Align == "right")) { line.Align = "right"; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); if (Marked("Normal", run.Baseline == null)) { run.Baseline = null; } if (Marked("Raised", run.Baseline == "sup")) { run.Baseline = "sup"; } if (Marked("Lowered", run.Baseline == "sub")) { run.Baseline = "sub"; } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Toggle("Italic", ref run.Italic); Toggle("Underline", ref run.Underline); Toggle("Strike", ref run.Strike); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Toggle("Highlight", ref run.Mark); Toggle("Small caps", ref run.SmallCaps); GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); bool flag = Choice("Size", run.Size.HasValue); bool flag2 = Choice("Height", run.VOffset.HasValue); bool flag3 = Choice("Spacing", run.CSpace.HasValue); bool flag4 = Choice("Tilt", run.Rotate.HasValue); GUILayout.EndHorizontal(); run.Size = (flag ? Measure("Size", run.Size ?? 5, -20, 24, zeroClears: false) : ((int?)null)); run.VOffset = (flag2 ? Measure("Height", run.VOffset ?? 1, -8, 8, zeroClears: true) : ((int?)null)); run.CSpace = (flag3 ? Measure("Spacing", run.CSpace ?? 1, -4, 6, zeroClears: true) : ((int?)null)); run.Rotate = (flag4 ? Measure("Tilt", run.Rotate ?? 5, -90, 90, zeroClears: true) : ((int?)null)); if (_groups.Count > 0) { Section("Symbols"); _symbolQuery = GUILayout.TextField(_symbolQuery ?? "", _field, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int j = 0; j < _groups.Count; j++) { if (Marked(_groups[j].Label, _group == j)) { _group = j; } } GUILayout.EndHorizontal(); _symbolScroll = GUILayout.BeginScrollView(_symbolScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(160f) }); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); int num2 = 0; string text3 = (_symbolQuery ?? "").Trim().ToLowerInvariant(); foreach (SymbolItem item in _groups[Mathf.Clamp(_group, 0, _groups.Count - 1)].Items) { if (text3.Length <= 0 || Matches(item, text3)) { if (GUILayout.Button(SymbolCaption(item), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(32f) })) { InsertAtCaret(run, item.Glyph); } num2++; if (num2 % 4 == 0) { GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); } } } GUILayout.EndHorizontal(); GUILayout.EndScrollView(); } Section("Inks"); DrawInkPicker(run); Color backgroundColor = GUI.backgroundColor; GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int k = 0; k < Camp.Inks.Length; k++) { Camp.Ink ink = Camp.Inks[k]; if (Markup.ParseHex(ink.Hex, out var r, out var g, out var b, out var _)) { GUI.backgroundColor = new Color((float)r / 255f, (float)g / 255f, (float)b / 255f); } if (GUILayout.Button(ink.Name, Array.Empty<GUILayoutOption>())) { PaintInk(ink); } if ((k + 1) % 5 == 0 && k + 1 < Camp.Inks.Length) { GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); } } GUILayout.EndHorizontal(); GUI.backgroundColor = backgroundColor; Section("Stamps"); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); for (int l = 0; l < Camp.Stamps.Length; l++) { if (GUILayout.Button(Camp.Stamps[l].Name, Array.Empty<GUILayoutOption>())) { Stamp(Camp.Stamps[l]); } if ((l + 1) % 4 == 0 && l + 1 < Camp.Stamps.Length) { GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); } } GUILayout.EndHorizontal(); Section("Runes"); GUILayout.Label("Carve replaces the text already in this box.", _note, Array.Empty<GUILayoutOption>()); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); _scribe = GUILayout.TextField(_scribe ?? "", _field, Array.Empty<GUILayoutOption>()); if (GUILayout.Button("Carve", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) })) { CarveIntoPiece(); } GUILayout.EndHorizontal(); if (GUILayout.Button("Add character name on new line", Array.Empty<GUILayoutOption>())) { CarveMyName(); } Section("Sign text"); GUI.SetNextControlName("sign-markup"); string text4 = GUILayout.TextArea(_markupDraft ?? "", _field, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(72f) }); if (GUI.GetNameOfFocusedControl() == "sign-markup") { if (text4 != _markupDraft) { _markupDraft = text4 ?? ""; _doc = Markup.Parse(_markupDraft); _line = 0; _run = 0; SyncHex(); } } else { _markupDraft = text; } GUILayout.EndScrollView(); GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUI.enabled = text.Length <= num; Color backgroundColor2 = GUI.backgroundColor; GUI.backgroundColor = new Color(0.78f, 0.5f, 0.28f); if (GUILayout.Button("Save", Array.Empty<GUILayoutOption>())) { Close(save: true); } GUI.backgroundColor = backgroundColor2; GUI.enabled = true; if (GUILayout.Button("Cancel", Array.Empty<GUILayoutOption>())) { Close(save: false); } GUILayout.EndHorizontal(); GUI.DragWindow(new Rect(0f, 0f, 10000f, 24f)); } private static void Toggle(string label, ref bool value) { if (Marked(label, value)) { value = !value; } } private static bool Choice(string label, bool on) { if (Marked(label, on)) { on = !on; } return on; } private void RememberCaret(Run run) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (GUI.GetNameOfFocusedControl() != "sign-line") { return; } TextEditor val = (TextEditor)GUIUtility.GetStateObject(typeof(TextEditor), GUIUtility.keyboardControl); if (val != null) { if (_placeCaret >= 0) { int caretEnd = (val.selectIndex = (val.cursorIndex = Mathf.Clamp(_placeCaret, 0, (run.Text ?? "").Length))); _caret = (_caretEnd = caretEnd); _placeCaret = -1; } else { _caret = val.cursorIndex; _caretEnd = val.selectIndex; } } } private void InsertAtCaret(Run run, string glyph) { if (!string.IsNullOrEmpty(glyph)) { string text = run.Text ?? ""; int num; int startIndex; if (_caret < 0) { num = (startIndex = text.Length); } else { num = Mathf.Clamp(Math.Min(_caret, _caretEnd), 0, text.Length); startIndex = Mathf.Clamp(Math.Max(_caret, _caretEnd), 0, text.Length); } run.Text = text.Substring(0, num) + glyph + text.Substring(startIndex); _caret = (_caretEnd = num + glyph.Length); _placeCaret = _caret; } } private static bool Matches(SymbolItem item, string query) { if (item.Glyph != null && item.Glyph.ToLowerInvariant().IndexOf(query) >= 0) { return true; } string text = (string.IsNullOrEmpty(item.Search) ? item.Name : item.Search); if (text != null) { return text.ToLowerInvariant().IndexOf(query) >= 0; } return false; } private static string SymbolCaption(SymbolItem item) { string text = (string.IsNullOrEmpty(item.Name) ? item.Glyph : item.Name); if (string.IsNullOrEmpty(item.Glyph) || item.Glyph.Length != 1) { return text; } int num = item.Glyph[0]; if (num >= 8592 && num <= 10175) { return item.Glyph + " " + text; } return text; } private static int? Measure(string label, int current, int min, int max, bool zeroClears) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label + " " + current, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(92f) }); current = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)current, (float)min, (float)max, Array.Empty<GUILayoutOption>())); GUILayout.EndHorizontal(); if (zeroClears && current == 0) { return null; } return current; } private void DrawInkPicker(Run run) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (!Markup.ParseHex(string.IsNullOrEmpty(run.Color) ? "000000" : run.Color, out var r, out var g, out var b, out var _)) { r = 0; g = 0; b = 0; } GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); Rect rect = GUILayoutUtility.GetRect(28f, 22f, (GUILayoutOption[])(object)new GUILayoutOption[2] { GUILayout.Width(28f), GUILayout.Height(22f) }); Color color = GUI.color; GUI.color = new Color((float)r / 255f, (float)g / 255f, (float)b / 255f, Mathf.Max(0.2f, (float)run.Alpha / 255f)); GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture); GUI.color = color; GUILayout.Label("Hex", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(32f) }); string text = GUILayout.TextField(_hex ?? "", _field, Array.Empty<GUILayoutOption>()); if (text != _hex) { _hex = text; if (Markup.ParseHex(text, out var r2, out var g2, out var b2, out var a2)) { run.Alpha = a2; ApplyChannels(run, r2, g2, b2, refreshHex: false); } } GUILayout.EndHorizontal(); int num = Channel("Red", r); int num2 = Channel("Green", g); int num3 = Channel("Blue", b); if (num != r || num2 != g || num3 != b) { ApplyChannels(run, num, num2, num3, refreshHex: true); } GUILayout.Label("Fade " + Mathf.RoundToInt((float)run.Alpha / 255f * 100f) + "%", Array.Empty<GUILayoutOption>()); int num4 = Mathf.RoundToInt((float)Mathf.RoundToInt(GUILayout.HorizontalSlider((float)run.Alpha / 255f * 100f, 0f, 100f, Array.Empty<GUILayoutOption>())) / 100f * 255f); if (num4 != run.Alpha) { run.Alpha = num4; if (num4 >= 255 && (run.Color == null || run.Color == "000000")) { run.Color = null; } else if (run.Color == null) { run.Color = "000000"; } } } private static int Channel(string label, int value) { GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>()); GUILayout.Label(label + " " + value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(92f) }); int result = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)value, 0f, 255f, Array.Empty<GUILayoutOption>())); GUILayout.EndHorizontal(); return result; } private void ApplyChannels(Run run, int r, int g, int b, bool refreshHex) { string text = r.ToString("x2") + g.ToString("x2") + b.ToString("x2"); run.Color = ((text == "000000" && run.Alpha >= 255) ? null : text); if (refreshHex) { _hex = run.Color ?? ""; } } private void PaintInk(Camp.Ink ink) { Run run = CurrentRun(); run.Color = ink.Hex; run.Alpha = 255; SyncHex(); _status = ink.Name; } private void Stamp(Camp.Stamp stamp) { ApplyPreset(stamp.Markup); _status = stamp.Name; } private void CarveIntoPiece() { string text = Camp.CarveRunes(_scribe); if (string.IsNullOrEmpty(text)) { _status = "Type letters to carve. th is one rune."; return; } CurrentRun().Text = text; _status = "Carved."; } private void CarveMyName() { string text = ""; try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null) { text = localPlayer.GetPlayerName(); } } catch (Exception) { text = ""; } if (string.IsNullOrEmpty(text)) { _status = "Enter the world first."; return; } Line line = new Line { Align = "center" }; line.Runs.Add(new Run { Text = text, Color = "ffeecc", Size = 4, Italic = true }); _doc.Lines.Add(line); _line = _doc.Lines.Count - 1; _run = 0; SyncHex(); _status = "Added your name."; } private void ApplyPreset(string text) { _doc = Markup.Parse(text); _line = 0; _run = 0; SyncHex(); } private void AddLine() { Line line = new Line { Align = CurrentLine().Align }; line.Runs.Add(new Run()); _doc.Lines.Insert(_line + 1, line); _line++; _run = 0; SyncHex(); } private void RemoveRun() { Line line = CurrentLine(); if (_doc.Lines.Count == 1 && line.Runs.Count == 1) { line.Runs[0] = new Run(); SyncHex(); return; } line.Runs.RemoveAt(_run); if (line.Runs.Count == 0) { _doc.Lines.RemoveAt(_line); _line = Mathf.Max(0, _line - 1); _run = 0; } else { _run = Mathf.Max(0, _run - 1); } SyncHex(); } private Line CurrentLine() { if (_line >= _doc.Lines.Count) { _line = _doc.Lines.Count - 1; } if (_line < 0) { _line = 0; } return _doc.Lines[_line]; } private Run CurrentRun() { Line line = CurrentLine(); if (_run >= line.Runs.Count) { _run = line.Runs.Count - 1; } if (_run < 0) { _run = 0; } return line.Runs[_run]; } private void SyncHex() { _hex = CurrentRun().Color ?? ""; } private void Close(bool save) { if ((Object)(object)_sign == (Object)null) { return; } if (save) { string text = Markup.Write(_doc); int num = Plugin.Limit(); if (text.Length > num) { text = text.Substring(0, num); } _sign.SetText(text); _status = "Saved."; } else { SignUpdateTextPatch.WriteWidget(_sign, Markup.RenderNewlines(_original)); } _sign = null; Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } private void LoadSymbols() { _groups.Clear(); string path = Path.Combine(Path.GetDirectoryName(AssemblyPath()) ?? "", "symbols.txt"); if (!File.Exists(path)) { SymbolGroup symbolGroup = new SymbolGroup { Label = "Marks" }; symbolGroup.Items.Add(new SymbolItem { Glyph = "←", Name = "left" }); symbolGroup.Items.Add(new SymbolItem { Glyph = "→", Name = "right" }); symbolGroup.Items.Add(new SymbolItem { Glyph = "⚠", Name = "warning" }); symbolGroup.Items.Add(new SymbolItem { Glyph = "⚔", Name = "swords" }); symbolGroup.Items.Add(new SymbolItem { Glyph = "⛏", Name = "pick" }); symbolGroup.Items.Add(new SymbolItem { Glyph = "ᚠ", Name = "rune" }); _groups.Add(symbolGroup); return; } SymbolGroup symbolGroup2 = null; string[] array = File.ReadAllLines(path); foreach (string text in array) { if (string.IsNullOrWhiteSpace(text)) { continue; } if (text.StartsWith("# ")) { symbolGroup2 = new SymbolGroup { Label = text.Substring(2).Trim() }; _groups.Add(symbolGroup2); } else if (symbolGroup2 != null) { string[] array2 = text.Split(new char[1] { '\t' }); string text2 = array2[0]; if (text2.Length != 0) { symbolGroup2.Items.Add(new SymbolItem { Glyph = text2, Name = ((array2.Length > 2) ? array2[2] : text2), Search = ((array2.Length > 3) ? array2[3] : ((array2.Length > 2) ? array2[2] : text2)).ToLowerInvariant() }); } } } } private static string AssemblyPath() { return typeof(SignEditor).Assembly.Location; } } }