Decompiled source of Signwright v1.1.18

Signwright.dll

Decompiled a day ago
using 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;
		}
	}
}