Decompiled source of BetrSigns v1.0.5

plugins/BetrSigns.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[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("DezzyCode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("DezzyCode")]
[assembly: AssemblyDescription("Twelve signs to write on, with a choice of text colour.")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyInformationalVersion("1.0.5+01d1d85edf38992f14f4d620fc90904122241514")]
[assembly: AssemblyProduct("BetrSigns")]
[assembly: AssemblyTitle("BetrSigns")]
[assembly: AssemblyVersion("1.0.5.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 BetrSigns
{
	internal static class FbxReader
	{
		public sealed class Skin
		{
			public byte[] Colour;

			public byte[] Normal;
		}

		private sealed class Axes
		{
			public int Up = 2;

			public int UpSign = 1;

			public bool Stated;
		}

		private sealed class Part
		{
			public double[] Vertices;

			public int[] PolygonIndices;

			public double[] Uvs;

			public int[] UvIndices;
		}

		private sealed class Node
		{
			public string Name;

			public readonly List<object> Properties = new List<object>();

			public readonly List<Node> Children = new List<Node>();
		}

		public sealed class Result
		{
			public Mesh Mesh;

			public Bounds PanelBounds;

			public bool HasPanel;

			public string TextureName;

			public readonly List<Skin> Skins = new List<Skin>();
		}

		public enum Front
		{
			Read,
			Forward,
			Backward,
			Up,
			Down,
			Left,
			Right
		}

		private const string Magic = "Kaydara FBX Binary  ";

		private static readonly char[] Separators = new char[2] { '/', '\\' };

		private static readonly char[] Terminator = new char[1];

		private const float PanelLift = 0.012f;

		public static Result Load(string path, float targetWidth, Front front = Front.Read)
		{
			try
			{
				byte[] data = File.ReadAllBytes(path);
				if (!Verify(data))
				{
					Log.Warning("Not a binary FBX: " + path);
					return null;
				}
				Node node = Parse(data);
				List<Part> list = new List<Part>();
				Collect(node, list);
				if (list.Count == 0)
				{
					Log.Warning("No mesh found in " + path);
					return null;
				}
				Axes axes = ReadAxes(node);
				Log.Info("  FBX holds the scene " + ((axes.Up == 1) ? "Y up" : ((axes.Up == 0) ? "X up" : "Z up")) + ((axes.UpSign < 0) ? " (inverted)" : string.Empty) + (axes.Stated ? string.Empty : ", not stated - read as Z up"));
				Result result = Build(list, targetWidth, front, axes);
				if (result != null)
				{
					result.TextureName = FindTexture(node);
					CollectSkins(node, result.Skins);
					for (int i = 0; i < result.Skins.Count; i++)
					{
						Skin skin = result.Skins[i];
						Log.Info("  FBX material " + i + ": colour " + ((skin.Colour != null) ? (skin.Colour.Length / 1024 + " KB") : "none") + ", normal " + ((skin.Normal != null) ? (skin.Normal.Length / 1024 + " KB") : "none"));
					}
				}
				return result;
			}
			catch (Exception ex)
			{
				Log.Warning("Could not read " + path + ": " + ex.Message);
				return null;
			}
		}

		private static void CollectSkins(Node root, List<Skin> skins)
		{
			Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>();
			CollectImages(root, dictionary);
			List<Node> list = new List<Node>();
			CollectNodes(root, "Texture", list);
			foreach (Node item in list)
			{
				string text = FirstString(item) ?? string.Empty;
				string text2 = BaseName(ChildString(item, "RelativeFilename") ?? ChildString(item, "FileName"));
				if (text2 == null || !dictionary.TryGetValue(text2, out var value))
				{
					continue;
				}
				bool flag = text.IndexOf("normal", StringComparison.OrdinalIgnoreCase) >= 0;
				if (!flag || skins.Count == 0)
				{
					if (!flag)
					{
						skins.Add(new Skin
						{
							Colour = value
						});
					}
				}
				else
				{
					skins[skins.Count - 1].Normal = value;
				}
			}
		}

		private static Axes ReadAxes(Node root)
		{
			Axes axes = new Axes();
			List<Node> list = new List<Node>();
			CollectNodes(root, "P", list);
			foreach (Node item in list)
			{
				string text = FirstString(item);
				if (!(text == "UpAxis"))
				{
					if (text == "UpAxisSign")
					{
						axes.UpSign = Whole(item, axes.UpSign);
					}
				}
				else
				{
					axes.Up = Whole(item, axes.Up);
					axes.Stated = true;
				}
			}
			return axes;
		}

		private static int Whole(Node node, int fallback)
		{
			for (int num = node.Properties.Count - 1; num >= 0; num--)
			{
				object obj = node.Properties[num];
				if (obj is int)
				{
					return (int)obj;
				}
				if (obj is long num2)
				{
					return (int)num2;
				}
				if (obj is double num3)
				{
					return (int)num3;
				}
			}
			return fallback;
		}

		private static void CollectImages(Node node, Dictionary<string, byte[]> images)
		{
			if (node.Name == "Video")
			{
				string text = BaseName(ChildString(node, "RelativeFilename") ?? ChildString(node, "FileName"));
				byte[] array = ChildBytes(node, "Content");
				if (text != null && array != null && !images.ContainsKey(text))
				{
					images[text] = array;
				}
			}
			foreach (Node child in node.Children)
			{
				CollectImages(child, images);
			}
		}

		private static void CollectNodes(Node node, string name, List<Node> found)
		{
			if (node.Name == name)
			{
				found.Add(node);
			}
			foreach (Node child in node.Children)
			{
				CollectNodes(child, name, found);
			}
		}

		private static string FirstString(Node node)
		{
			foreach (object property in node.Properties)
			{
				if (property is string { Length: >0 } text)
				{
					return text.Split(Terminator)[0];
				}
			}
			return null;
		}

		private static string ChildString(Node node, string name)
		{
			foreach (Node child in node.Children)
			{
				if (child.Name == name)
				{
					return FirstString(child);
				}
			}
			return null;
		}

		private static byte[] ChildBytes(Node node, string name)
		{
			foreach (Node child in node.Children)
			{
				if (child.Name != name)
				{
					continue;
				}
				foreach (object property in child.Properties)
				{
					if (property is byte[] array && array.Length > 64)
					{
						return array;
					}
				}
			}
			return null;
		}

		private static string BaseName(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}
			int num = path.LastIndexOfAny(Separators);
			string text = ((num >= 0) ? path.Substring(num + 1) : path);
			if (text.Length != 0)
			{
				return text;
			}
			return null;
		}

		private static string FindTexture(Node root)
		{
			string found = null;
			Search(root, ref found);
			return found;
		}

		private static void Search(Node node, ref string found)
		{
			if (found != null)
			{
				return;
			}
			if (node.Name == "RelativeFilename" || node.Name == "FileName")
			{
				foreach (object property in node.Properties)
				{
					if (property is string { Length: >0 } text)
					{
						int num = text.LastIndexOfAny(Separators);
						string text2 = ((num >= 0) ? text.Substring(num + 1) : text);
						text2 = text2.Split(Terminator)[0];
						if (text2.Length > 0)
						{
							found = text2;
							return;
						}
					}
				}
			}
			foreach (Node child in node.Children)
			{
				Search(child, ref found);
			}
		}

		private static bool Verify(byte[] data)
		{
			if (data.Length < 27)
			{
				return false;
			}
			for (int i = 0; i < "Kaydara FBX Binary  ".Length; i++)
			{
				if (data[i] != "Kaydara FBX Binary  "[i])
				{
					return false;
				}
			}
			return true;
		}

		private static Node Parse(byte[] data)
		{
			uint num = BitConverter.ToUInt32(data, 23);
			Node node = new Node
			{
				Name = "root"
			};
			ReadChildren(data, 27, data.Length, num >= 7500, node);
			return node;
		}

		private static void ReadChildren(byte[] data, int position, int end, bool wide, Node parent)
		{
			while (position < end)
			{
				long num;
				long num2;
				if (wide)
				{
					num = BitConverter.ToInt64(data, position);
					num2 = BitConverter.ToInt64(data, position + 8);
					position += 24;
				}
				else
				{
					num = BitConverter.ToUInt32(data, position);
					num2 = BitConverter.ToUInt32(data, position + 4);
					position += 12;
				}
				int num3 = data[position];
				position++;
				if (num == 0L)
				{
					break;
				}
				Node node = new Node
				{
					Name = Encoding.ASCII.GetString(data, position, num3)
				};
				position += num3;
				for (long num4 = 0L; num4 < num2; num4++)
				{
					node.Properties.Add(ReadProperty(data, ref position));
				}
				if (position < num)
				{
					ReadChildren(data, position, (int)num, wide, node);
				}
				parent.Children.Add(node);
				position = (int)num;
			}
		}

		private static object ReadProperty(byte[] data, ref int position)
		{
			char c = (char)data[position];
			position++;
			switch (c)
			{
			case 'Y':
			{
				short num8 = BitConverter.ToInt16(data, position);
				position += 2;
				return (int)num8;
			}
			case 'C':
			{
				byte num7 = data[position];
				position++;
				return num7 != 0;
			}
			case 'I':
			{
				int num6 = BitConverter.ToInt32(data, position);
				position += 4;
				return num6;
			}
			case 'F':
			{
				float num5 = BitConverter.ToSingle(data, position);
				position += 4;
				return (double)num5;
			}
			case 'D':
			{
				double num4 = BitConverter.ToDouble(data, position);
				position += 8;
				return num4;
			}
			case 'L':
			{
				long num3 = BitConverter.ToInt64(data, position);
				position += 8;
				return num3;
			}
			case 'S':
			{
				int num2 = BitConverter.ToInt32(data, position);
				position += 4;
				string result = Encoding.UTF8.GetString(data, position, num2);
				position += num2;
				return result;
			}
			case 'R':
			{
				int num = BitConverter.ToInt32(data, position);
				position += 4;
				byte[] array = new byte[num];
				Buffer.BlockCopy(data, position, array, 0, num);
				position += num;
				return array;
			}
			case 'f':
				return ReadArray(data, ref position, 4, doubles: false);
			case 'd':
				return ReadArray(data, ref position, 8, doubles: true);
			case 'i':
				return ReadIntArray(data, ref position, 4);
			case 'l':
				return ReadIntArray(data, ref position, 8);
			case 'b':
				return ReadIntArray(data, ref position, 1);
			default:
				throw new InvalidDataException("Unknown FBX property type '" + c + "'");
			}
		}

		private static byte[] RawArray(byte[] data, ref int position, int elementSize, out int count)
		{
			count = BitConverter.ToInt32(data, position);
			int num = BitConverter.ToInt32(data, position + 4);
			int num2 = BitConverter.ToInt32(data, position + 8);
			position += 12;
			byte[] array = new byte[num2];
			Buffer.BlockCopy(data, position, array, 0, num2);
			position += num2;
			if (num != 1)
			{
				return array;
			}
			using MemoryStream stream = new MemoryStream(array, 2, array.Length - 2);
			using DeflateStream deflateStream = new DeflateStream(stream, CompressionMode.Decompress);
			using MemoryStream memoryStream = new MemoryStream(count * elementSize);
			byte[] array2 = new byte[8192];
			int count2;
			while ((count2 = deflateStream.Read(array2, 0, array2.Length)) > 0)
			{
				memoryStream.Write(array2, 0, count2);
			}
			return memoryStream.ToArray();
		}

		private static double[] ReadArray(byte[] data, ref int position, int elementSize, bool doubles)
		{
			int count;
			byte[] value = RawArray(data, ref position, elementSize, out count);
			double[] array = new double[count];
			for (int i = 0; i < count; i++)
			{
				array[i] = (doubles ? BitConverter.ToDouble(value, i * 8) : ((double)BitConverter.ToSingle(value, i * 4)));
			}
			return array;
		}

		private static int[] ReadIntArray(byte[] data, ref int position, int elementSize)
		{
			int count;
			byte[] array = RawArray(data, ref position, elementSize, out count);
			int[] array2 = new int[count];
			for (int i = 0; i < count; i++)
			{
				array2[i] = elementSize switch
				{
					4 => BitConverter.ToInt32(array, i * 4), 
					8 => (int)BitConverter.ToInt64(array, i * 8), 
					_ => array[i], 
				};
			}
			return array2;
		}

		private static void Collect(Node node, List<Part> parts)
		{
			if (node.Name == "Geometry")
			{
				Part part = ReadGeometry(node);
				if (part != null)
				{
					parts.Add(part);
				}
			}
			foreach (Node child in node.Children)
			{
				Collect(child, parts);
			}
		}

		private static Part ReadGeometry(Node geometry)
		{
			Part part = new Part();
			foreach (Node child in geometry.Children)
			{
				switch (child.Name)
				{
				case "Vertices":
					part.Vertices = ((child.Properties.Count > 0) ? (child.Properties[0] as double[]) : null);
					break;
				case "PolygonVertexIndex":
					part.PolygonIndices = ((child.Properties.Count > 0) ? (child.Properties[0] as int[]) : null);
					break;
				case "LayerElementUV":
					foreach (Node child2 in child.Children)
					{
						if (child2.Name == "UV" && child2.Properties.Count > 0)
						{
							part.Uvs = child2.Properties[0] as double[];
						}
						else if (child2.Name == "UVIndex" && child2.Properties.Count > 0)
						{
							part.UvIndices = child2.Properties[0] as int[];
						}
					}
					break;
				}
			}
			if (part.Vertices == null || part.PolygonIndices == null)
			{
				return null;
			}
			return part;
		}

		private static Result Build(List<Part> parts, float targetWidth, Front front, Axes axes)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Expected O, but got Unknown
			//IL_021b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			List<Vector3> list = new List<Vector3>(256);
			List<List<int>> list2 = new List<List<int>>(parts.Count);
			List<int> list3 = new List<int>(parts.Count);
			Bounds panelBounds = default(Bounds);
			bool hasPanel = false;
			for (int i = 0; i < parts.Count; i++)
			{
				Part part = parts[i];
				List<int> list4 = new List<int>(part.PolygonIndices.Length * 3);
				List<int> list5 = new List<int>(8);
				list3.Add(list.Count);
				for (int j = 0; j < part.PolygonIndices.Length; j++)
				{
					int num = part.PolygonIndices[j];
					bool num2 = num < 0;
					if (num2)
					{
						num = ~num;
					}
					list.Add(Convert(part.Vertices, num, axes));
					list5.Add(list.Count - 1);
					if (num2)
					{
						for (int k = 1; k + 1 < list5.Count; k++)
						{
							list4.Add(list5[0]);
							list4.Add(list5[k]);
							list4.Add(list5[k + 1]);
						}
						list5.Clear();
					}
				}
				list2.Add(list4);
			}
			if (parts.Count > 1)
			{
				Face(list, list3[1], (parts.Count > 2) ? list3[2] : list.Count);
			}
			else
			{
				Turn(list, front);
			}
			Bounds val = Extent(list, 0, list.Count);
			float x = ((Bounds)(ref val)).size.x;
			if (targetWidth > 0f && x > 0.0001f)
			{
				float num3 = targetWidth / x;
				for (int l = 0; l < list.Count; l++)
				{
					list[l] *= num3;
				}
			}
			Bounds val2 = Extent(list, 0, list.Count);
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(0f - ((Bounds)(ref val2)).center.x, 0f - ((Bounds)(ref val2)).min.y, 0f - ((Bounds)(ref val2)).center.z);
			if (((Vector3)(ref val3)).sqrMagnitude > 1E-06f)
			{
				for (int m = 0; m < list.Count; m++)
				{
					list[m] += val3;
				}
				Log.Debug("  FBX pivot moved by " + ((Vector3)(ref val3)).ToString("0.000") + " so the model rests on the ground");
			}
			if (parts.Count > 1)
			{
				int num4 = list3[1];
				int num5 = ((parts.Count > 2) ? list3[2] : list.Count);
				for (int n = num4; n < num5; n++)
				{
					list[n] += new Vector3(0f, 0f, 0.012f);
				}
				panelBounds = Extent(list, num4, num5);
				hasPanel = num5 > num4;
				Log.Debug("  FBX panel lifted " + 0.012f.ToString("0.000") + " m clear of the body");
			}
			List<Vector2> list6 = FileUvs(parts, list.Count);
			Mesh val4 = new Mesh
			{
				name = "EW_DrawerMesh"
			};
			val4.SetVertices(list);
			val4.SetUVs(0, list6);
			val4.subMeshCount = list2.Count;
			for (int num6 = 0; num6 < list2.Count; num6++)
			{
				val4.SetTriangles(list2[num6], num6);
			}
			val4.RecalculateNormals();
			val4.RecalculateTangents();
			val4.RecalculateBounds();
			return new Result
			{
				Mesh = val4,
				PanelBounds = panelBounds,
				HasPanel = hasPanel
			};
		}

		public static void Reproject(Mesh mesh, float tiles)
		{
			if (!((Object)(object)mesh == (Object)null))
			{
				List<Vector3> list = new List<Vector3>(mesh.vertexCount);
				mesh.GetVertices(list);
				List<List<int>> list2 = new List<List<int>>(mesh.subMeshCount);
				for (int i = 0; i < mesh.subMeshCount; i++)
				{
					List<int> list3 = new List<int>();
					mesh.GetTriangles(list3, i);
					list2.Add(list3);
				}
				mesh.SetUVs(0, PlanarUvs(list, list2, tiles));
			}
		}

		private static void Turn(List<Vector3> vertices, Front front)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			Func<Vector3, Vector3> func;
			switch (front)
			{
			default:
				return;
			case Front.Up:
				func = (Vector3 v) => new Vector3(v.x, 0f - v.z, v.y);
				break;
			case Front.Down:
				func = (Vector3 v) => new Vector3(v.x, v.z, 0f - v.y);
				break;
			case Front.Right:
				func = (Vector3 v) => new Vector3(0f - v.z, v.y, v.x);
				break;
			case Front.Left:
				func = (Vector3 v) => new Vector3(v.z, v.y, 0f - v.x);
				break;
			case Front.Backward:
				func = (Vector3 v) => new Vector3(0f - v.x, v.y, 0f - v.z);
				break;
			}
			for (int num = 0; num < vertices.Count; num++)
			{
				vertices[num] = func(vertices[num]);
			}
			Log.Debug("  FBX front told as " + front.ToString() + "; turned to face forward.");
		}

		private static void Face(List<Vector3> vertices, int from, int to)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0079: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			if (to <= from)
			{
				return;
			}
			Bounds val = Extent(vertices, 0, vertices.Count);
			Bounds val2 = Extent(vertices, from, to);
			Vector3 val3 = ((Bounds)(ref val2)).center - ((Bounds)(ref val)).center;
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor((((Bounds)(ref val)).size.x > 0.0001f) ? (val3.x / ((Bounds)(ref val)).size.x) : 0f, (((Bounds)(ref val)).size.y > 0.0001f) ? (val3.y / ((Bounds)(ref val)).size.y) : 0f, (((Bounds)(ref val)).size.z > 0.0001f) ? (val3.z / ((Bounds)(ref val)).size.z) : 0f);
			Func<Vector3, Vector3> func = null;
			string text = "forward already";
			if (Mathf.Abs(val4.y) > Mathf.Abs(val4.x) && Mathf.Abs(val4.y) > Mathf.Abs(val4.z))
			{
				text = ((val4.y > 0f) ? "up" : "down");
				func = ((val4.y > 0f) ? ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(v.x, 0f - v.z, v.y))) : ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(v.x, v.z, 0f - v.y))));
			}
			else if (Mathf.Abs(val4.x) > Mathf.Abs(val4.z))
			{
				text = ((val4.x > 0f) ? "right" : "left");
				func = ((val4.x > 0f) ? ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(0f - v.z, v.y, v.x))) : ((Func<Vector3, Vector3>)((Vector3 v) => new Vector3(v.z, v.y, 0f - v.x))));
			}
			else if (val4.z < 0f)
			{
				text = "backward";
				func = (Vector3 v) => new Vector3(0f - v.x, v.y, 0f - v.z);
			}
			if (func == null)
			{
				Log.Debug("  FBX front: " + text);
				return;
			}
			for (int num = 0; num < vertices.Count; num++)
			{
				vertices[num] = func(vertices[num]);
			}
			Log.Info("Sign model was facing " + text + "; turned to face forward.");
		}

		private static List<Vector2> FileUvs(List<Part> parts, int total)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2> list = new List<Vector2>(total);
			foreach (Part part in parts)
			{
				for (int i = 0; i < part.PolygonIndices.Length; i++)
				{
					list.Add(UvFor(part, i));
				}
			}
			while (list.Count < total)
			{
				list.Add(Vector2.zero);
			}
			return list;
		}

		private static List<Vector2> PlanarUvs(List<Vector3> vertices, List<List<int>> submeshes, float tiles)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			List<Vector2> list = new List<Vector2>(vertices.Count);
			for (int i = 0; i < vertices.Count; i++)
			{
				list.Add(Vector2.zero);
			}
			foreach (List<int> submesh in submeshes)
			{
				for (int j = 0; j + 2 < submesh.Count; j += 3)
				{
					Vector3 val = vertices[submesh[j]];
					Vector3 val2 = vertices[submesh[j + 1]];
					Vector3 val3 = vertices[submesh[j + 2]];
					Vector3 normal = Vector3.Cross(val2 - val, val3 - val);
					for (int k = 0; k < 3; k++)
					{
						list[submesh[j + k]] = Project(vertices[submesh[j + k]], normal) * tiles;
					}
				}
			}
			return list;
		}

		private static Vector2 Project(Vector3 point, Vector3 normal)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Abs(normal.x);
			float num2 = Mathf.Abs(normal.y);
			float num3 = Mathf.Abs(normal.z);
			if (num >= num2 && num >= num3)
			{
				return new Vector2(point.z, point.y);
			}
			if (!(num2 >= num3))
			{
				return new Vector2(point.x, point.y);
			}
			return new Vector2(point.x, point.z);
		}

		private static Bounds Extent(List<Vector3> vertices, int from, int to)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (to <= from || from >= vertices.Count)
			{
				return default(Bounds);
			}
			Bounds result = default(Bounds);
			((Bounds)(ref result))..ctor(vertices[from], Vector3.zero);
			for (int i = from; i < to && i < vertices.Count; i++)
			{
				((Bounds)(ref result)).Encapsulate(vertices[i]);
			}
			return result;
		}

		private static Vector3 Convert(double[] source, int index, Axes axes)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			int num = index * 3;
			float num2 = (float)source[num];
			float num3 = (float)source[num + 1];
			float num4 = (float)source[num + 2];
			if (axes.Up == 1)
			{
				return new Vector3(num2, (axes.UpSign < 0) ? (0f - num3) : num3, num4);
			}
			return new Vector3(num2, (axes.UpSign < 0) ? (0f - num4) : num4, 0f - num3);
		}

		private static Vector2 UvFor(Part part, int polygonVertex)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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)
			if (part.Uvs == null)
			{
				return Vector2.zero;
			}
			int num = ((part.UvIndices == null) ? polygonVertex : ((polygonVertex < part.UvIndices.Length) ? part.UvIndices[polygonVertex] : (-1)));
			if (num < 0 || num * 2 + 1 >= part.Uvs.Length)
			{
				return Vector2.zero;
			}
			return new Vector2((float)part.Uvs[num * 2], (float)part.Uvs[num * 2 + 1]);
		}
	}
	internal static class Log
	{
		private static ManualLogSource _source;

		public static void Init(ManualLogSource source)
		{
			_source = source;
		}

		public static void Info(string message)
		{
			ManualLogSource source = _source;
			if (source != null)
			{
				source.LogInfo((object)message);
			}
		}

		public static void Warning(string message)
		{
			ManualLogSource source = _source;
			if (source != null)
			{
				source.LogWarning((object)message);
			}
		}

		public static void Error(string message)
		{
			ManualLogSource source = _source;
			if (source != null)
			{
				source.LogError((object)message);
			}
		}

		public static void Debug(string message)
		{
			ManualLogSource source = _source;
			if (source != null)
			{
				source.LogDebug((object)message);
			}
		}
	}
	[BepInPlugin("dezzycode.valheim.betrsigns", "BetrSigns", "1.0.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "dezzycode.valheim.betrsigns";

		public const string Name = "BetrSigns";

		public const string Version = "1.0.5";

		private Harmony _harmony;

		public static readonly List<string> PatchFailures = new List<string>();

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log.Init(((BaseUnityPlugin)this).Logger);
			_harmony = new Harmony("dezzycode.valheim.betrsigns");
			ApplyPatches();
			SignPieces.Register();
			if (PatchFailures.Count == 0)
			{
				Log.Info("BetrSigns 1.0.5 loaded, all patches applied.");
			}
			else
			{
				Log.Error(string.Format("{0} {1} loaded with {2} failed patch(es): ", "BetrSigns", "1.0.5", PatchFailures.Count) + string.Join(", ", PatchFailures.ToArray()));
			}
		}

		private void ApplyPatches()
		{
			PatchFailures.Clear();
			Type[] types = typeof(Plugin).Assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.GetCustomAttributes(typeof(HarmonyPatch), inherit: true).Length != 0)
				{
					try
					{
						_harmony.CreateClassProcessor(type).Patch();
						Log.Debug("Patched " + type.FullName + ".");
					}
					catch (Exception ex)
					{
						PatchFailures.Add(type.Name);
						Log.Error("Patch " + type.FullName + " failed: " + ex.Message);
					}
				}
			}
		}

		private void OnDestroy()
		{
			SignColors.ClosePalette();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	internal sealed class ColoredSign : MonoBehaviour
	{
		private static readonly int ColorKey = StringExtensionMethods.GetStableHashCode("bs_text_color");

		private Sign _sign;

		private ZNetView _view;

		private int _applied = -1;

		public int Index
		{
			get
			{
				ZDO val = (((Object)(object)View != (Object)null) ? View.GetZDO() : null);
				if (val == null)
				{
					return 0;
				}
				return SignColors.Clamp(val.GetInt(ColorKey, 0));
			}
		}

		private ZNetView View
		{
			get
			{
				if (!((Object)(object)_view != (Object)null))
				{
					return _view = ((Component)this).GetComponent<ZNetView>();
				}
				return _view;
			}
		}

		private Sign Sign
		{
			get
			{
				if (!((Object)(object)_sign != (Object)null))
				{
					return _sign = ((Component)this).GetComponent<Sign>();
				}
				return _sign;
			}
		}

		public void Apply()
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)Sign == (Object)null) && !((Object)(object)Sign.m_textWidget == (Object)null))
			{
				int index = Index;
				if (index != _applied)
				{
					((Graphic)Sign.m_textWidget).color = SignColors.Palette[index];
					_applied = index;
				}
			}
		}

		public void Store(int index)
		{
			ZDO val = (((Object)(object)View != (Object)null) ? View.GetZDO() : null);
			if (val != null)
			{
				View.ClaimOwnership();
				val.Set(ColorKey, SignColors.Clamp(index), false);
				Apply();
			}
		}
	}
	internal static class SignColors
	{
		[HarmonyPatch(typeof(Sign), "UpdateText")]
		private static class UpdateTextPatch
		{
			private static void Postfix(Sign __instance)
			{
				ColoredSign coloredSign = default(ColoredSign);
				if (((Component)__instance).TryGetComponent<ColoredSign>(ref coloredSign))
				{
					coloredSign.Apply();
				}
			}
		}

		[HarmonyPatch(typeof(Sign), "Interact")]
		private static class InteractPatch
		{
			private static bool Prefix(Sign __instance, bool hold, bool alt, ref bool __result)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				ColoredSign sign = default(ColoredSign);
				if (!alt || hold || !((Component)__instance).TryGetComponent<ColoredSign>(ref sign))
				{
					return true;
				}
				__result = PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, true, false);
				if (__result)
				{
					OpenPalette(sign);
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Sign), "GetHoverText")]
		private static class HoverTextPatch
		{
			private static void Postfix(Sign __instance, ref string __result)
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				ColoredSign coloredSign = default(ColoredSign);
				if (((Component)__instance).TryGetComponent<ColoredSign>(ref coloredSign) && PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
				{
					string text = ((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "$KEY_AltKeys + $KEY_Use" : (AltKeyName() + " + $KEY_Use"));
					__result += Localization.instance.Localize("\n[<color=yellow><b>" + text + "</b></color>] $bs_sign_color");
				}
			}
		}

		[HarmonyPatch(typeof(Menu), "Update")]
		private static class EscapeClosesPatch
		{
			private static bool Prefix()
			{
				if (!PaletteOpen || Menu.IsVisible())
				{
					return true;
				}
				if (!ZInput.GetKeyDown((KeyCode)27, false) && !ZInput.GetButtonDown("JoyButtonB"))
				{
					return true;
				}
				ClosePalette();
				return false;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__ClosePalette;
		}

		public static readonly Color[] Palette = (Color[])(object)new Color[12]
		{
			new Color(0.059f, 0.051f, 0.035f),
			new Color(0.05f, 0.05f, 0.05f),
			new Color(1f, 1f, 1f),
			new Color(0.62f, 0.08f, 0.06f),
			new Color(0.93f, 0.45f, 0.12f),
			new Color(0.95f, 0.78f, 0.25f),
			new Color(0.33f, 0.52f, 0.18f),
			new Color(0.55f, 0.78f, 0.95f),
			new Color(0.14f, 0.27f, 0.62f),
			new Color(0.52f, 0.3f, 0.78f),
			new Color(0.72f, 0.45f, 0.25f),
			new Color(0.62f, 0.64f, 0.66f)
		};

		private static GameObject _panel;

		private static ColoredSign _target;

		private static bool _inputBlocked;

		private const float Swatch = 64f;

		private const float Gap = 12f;

		private const int Columns = 6;

		public static bool PaletteOpen
		{
			get
			{
				if ((Object)(object)_panel != (Object)null)
				{
					return _panel.activeSelf;
				}
				return false;
			}
		}

		public static int Clamp(int index)
		{
			if (index < 0 || index >= Palette.Length)
			{
				return 0;
			}
			return index;
		}

		private static string AltKeyName()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				ZInput instance = ZInput.instance;
				ReadOnlyArray<InputBinding>? obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					ButtonDef buttonDef = instance.GetButtonDef("AltPlace");
					if (buttonDef == null)
					{
						obj = null;
					}
					else
					{
						InputAction buttonAction = buttonDef.ButtonAction;
						obj = ((buttonAction != null) ? new ReadOnlyArray<InputBinding>?(buttonAction.bindings) : ((ReadOnlyArray<InputBinding>?)null));
					}
				}
				ReadOnlyArray<InputBinding>? val = obj;
				object obj2;
				if (!val.HasValue || val.Value.Count <= 0)
				{
					obj2 = null;
				}
				else
				{
					InputBinding val2 = val.Value[0];
					obj2 = ((InputBinding)(ref val2)).effectivePath;
				}
				string text = (string)obj2;
				if (text != null && text.IndexOf("shift", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return "$bs_key_shift";
				}
			}
			catch (Exception ex)
			{
				Log.Debug("Could not read the alternative-use binding: " + ex.Message);
			}
			return "$KEY_AltPlace";
		}

		private static void OpenPalette(ColoredSign sign)
		{
			//IL_006d: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			if (GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null))
			{
				ClosePalette();
				_target = sign;
				int num = (Palette.Length + 6 - 1) / 6;
				float num2 = 504f;
				float num3 = 70f + (float)num * 64f + (float)(num - 1) * 12f + 90f;
				_panel = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, num2, num3, false);
				((Object)_panel).name = "BS_Palette";
				GUIManager.Instance.CreateText(Localization.instance.Localize("$bs_palette_title"), _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -36f), GUIManager.Instance.AveriaSerifBold, 24, GUIManager.Instance.ValheimOrange, true, Color.black, num2 - 40f, 36f, false).GetComponent<Text>().alignment = (TextAnchor)4;
				int index = sign.Index;
				for (int i = 0; i < Palette.Length; i++)
				{
					int num4 = i % 6;
					int num5 = i / 6;
					float num6 = 30f + (float)num4 * 76f + 32f - num2 * 0.5f;
					float num7 = -70f - (float)num5 * 76f - 32f;
					AddSwatch(i, new Vector2(num6, num7), i == index);
				}
				ButtonClickedEvent onClick = GUIManager.Instance.CreateButton(Localization.instance.Localize("$bs_palette_close"), _panel.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 38f), 160f, 40f).GetComponent<Button>().onClick;
				object obj = <>O.<0>__ClosePalette;
				if (obj == null)
				{
					UnityAction val = ClosePalette;
					<>O.<0>__ClosePalette = val;
					obj = (object)val;
				}
				((UnityEvent)onClick).AddListener((UnityAction)obj);
				SetInputBlocked(blocked: true);
			}
		}

		private static void AddSwatch(int index, Vector2 position, bool selected)
		{
			//IL_002b: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateButton(string.Empty, _panel.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), position, 64f, 64f);
			((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				Pick(index);
			});
			GameObject val2 = new GameObject("Colour", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val2.transform.SetParent(val.transform, false);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.anchorMin = Vector2.zero;
			val3.anchorMax = Vector2.one;
			float num = (selected ? 6f : 10f);
			val3.offsetMin = new Vector2(num, num);
			val3.offsetMax = new Vector2(0f - num, 0f - num);
			Image component = val2.GetComponent<Image>();
			((Graphic)component).color = Palette[index];
			((Graphic)component).raycastTarget = false;
			if (selected)
			{
				Outline obj = val2.AddComponent<Outline>();
				((Shadow)obj).effectColor = GUIManager.Instance.ValheimOrange;
				((Shadow)obj).effectDistance = new Vector2(3f, 3f);
			}
			Text[] componentsInChildren = val.GetComponentsInChildren<Text>(true);
			for (int num2 = 0; num2 < componentsInChildren.Length; num2++)
			{
				componentsInChildren[num2].text = string.Empty;
			}
		}

		private static void Pick(int index)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_target != (Object)null && PrivateArea.CheckAccess(((Component)_target).transform.position, 0f, true, false))
			{
				_target.Store(index);
			}
			ClosePalette();
		}

		public static void ClosePalette()
		{
			if ((Object)(object)_panel != (Object)null)
			{
				Object.Destroy((Object)(object)_panel);
			}
			_panel = null;
			_target = null;
			SetInputBlocked(blocked: false);
		}

		private static void SetInputBlocked(bool blocked)
		{
			if (_inputBlocked != blocked)
			{
				GUIManager.BlockInput(blocked);
				_inputBlocked = blocked;
			}
		}
	}
	internal static class SignModel
	{
		private static MethodInfo _loadImage;

		private static bool _loadImageChecked;

		public static bool Dress(GameObject prefab, string modelPath, float textGap)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			MeshFilter val = VisualOf(prefab);
			if ((Object)(object)val == (Object)null)
			{
				Log.Warning("The game's sign has no mesh to replace.");
				return false;
			}
			FbxReader.Result result = FbxReader.Load(modelPath, 1f);
			if ((Object)(object)result?.Mesh == (Object)null)
			{
				return false;
			}
			Mesh val2 = Centre(result.Mesh);
			Bounds bounds = val2.bounds;
			Transform transform = ((Component)val).transform;
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = Vector3.one;
			val.sharedMesh = val2;
			MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				((Renderer)component).sharedMaterial = Paint(((Renderer)component).sharedMaterial, result);
			}
			BoxCollider componentInChildren = prefab.GetComponentInChildren<BoxCollider>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				((Component)componentInChildren).transform.localPosition = Vector3.zero;
				componentInChildren.center = ((Bounds)(ref bounds)).center;
				componentInChildren.size = ((Bounds)(ref bounds)).size;
			}
			Sign component2 = prefab.GetComponent<Sign>();
			Canvas val3 = (((Object)(object)component2 != (Object)null && (Object)(object)component2.m_textWidget != (Object)null) ? ((Component)component2.m_textWidget).GetComponentInParent<Canvas>(true) : prefab.GetComponentInChildren<Canvas>(true));
			if ((Object)(object)val3 != (Object)null)
			{
				Transform text = (((Object)(object)component2 != (Object)null && (Object)(object)component2.m_textWidget != (Object)null) ? ((TMP_Text)component2.m_textWidget).transform : ((Component)val3).transform);
				FaceText(prefab.transform, transform, ((Component)val3).transform, text, ((Bounds)(ref bounds)).max.z + textGap);
			}
			else
			{
				Log.Warning("The sign's text canvas was not found; its text stays where the game's sign has it.");
			}
			if ((Object)(object)component2 != (Object)null && (Object)(object)component2.m_textWidget != (Object)null)
			{
				TrueColours((TMP_Text)(object)component2.m_textWidget);
			}
			LODGroup component3 = prefab.GetComponent<LODGroup>();
			if ((Object)(object)component3 != (Object)null)
			{
				component3.RecalculateBounds();
			}
			return true;
		}

		private static void FaceText(Transform root, Transform visual, Transform canvas, Transform text, float depth)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			float z = root.InverseTransformPoint(visual.TransformPoint(new Vector3(0f, 0f, depth))).z;
			float z2 = root.InverseTransformPoint(text.position).z;
			Vector3 val = root.InverseTransformPoint(canvas.position);
			val.z += z - z2;
			canvas.position = root.TransformPoint(val);
			Log.Info("  Sign text moved from z " + z2.ToString("0.000") + " to " + z.ToString("0.000"));
		}

		private static void TrueColours(TMP_Text text)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			Material fontSharedMaterial = text.fontSharedMaterial;
			if (!((Object)(object)fontSharedMaterial == (Object)null) && fontSharedMaterial.HasProperty("_FaceColor"))
			{
				Material val = new Material(fontSharedMaterial)
				{
					name = ((Object)fontSharedMaterial).name + " (BetrSigns)"
				};
				val.SetColor("_FaceColor", Color.white);
				text.fontSharedMaterial = val;
			}
		}

		private static MeshFilter VisualOf(GameObject prefab)
		{
			MeshFilter[] componentsInChildren = prefab.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)((Component)val).GetComponentInParent<Canvas>(true) == (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private static Mesh Centre(Mesh mesh)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: 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)
			Bounds bounds = mesh.bounds;
			Vector3 center = ((Bounds)(ref bounds)).center;
			if (((Vector3)(ref center)).sqrMagnitude < 1E-08f)
			{
				return mesh;
			}
			Vector3[] vertices = mesh.vertices;
			for (int i = 0; i < vertices.Length; i++)
			{
				ref Vector3 reference = ref vertices[i];
				reference -= center;
			}
			mesh.vertices = vertices;
			mesh.RecalculateBounds();
			return mesh;
		}

		private static Material Paint(Material template, FbxReader.Result model)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			Material val = (((Object)(object)template != (Object)null) ? new Material(template) : new Material(Shader.Find("Standard")));
			((Object)val).name = "BS_Sign";
			FbxReader.Skin obj = ((model.Skins.Count > 0) ? model.Skins[0] : null);
			Texture2D val2 = Decode(obj?.Colour, linear: false);
			Texture2D val3 = Decode(obj?.Normal, linear: true);
			if ((Object)(object)val2 != (Object)null)
			{
				val.mainTexture = (Texture)(object)val2;
				val.mainTextureScale = Vector2.one;
				val.mainTextureOffset = Vector2.zero;
				if (val.HasProperty("_Color"))
				{
					val.color = Color.white;
				}
			}
			if (val.HasProperty("_BumpMap"))
			{
				val.SetTexture("_BumpMap", (Texture)(object)val3);
				if ((Object)(object)val3 != (Object)null)
				{
					val.EnableKeyword("_NORMALMAP");
				}
			}
			return val;
		}

		private static MethodInfo LoadImageMethod()
		{
			if (_loadImageChecked)
			{
				return _loadImage;
			}
			_loadImageChecked = true;
			_loadImage = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule")?.GetMethod("LoadImage", new Type[2]
			{
				typeof(Texture2D),
				typeof(byte[])
			});
			if (_loadImage == null)
			{
				Log.Warning("Cannot decode embedded images; signs keep the game's texture.");
			}
			return _loadImage;
		}

		private static Texture2D Decode(byte[] image, bool linear)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			MethodInfo methodInfo = ((image != null) ? LoadImageMethod() : null);
			if (methodInfo == null)
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear);
			if ((bool)methodInfo.Invoke(null, new object[2] { val, image }))
			{
				return val;
			}
			Object.Destroy((Object)(object)val);
			Log.Warning("An embedded sign image could not be decoded.");
			return null;
		}
	}
	internal static class SignPieces
	{
		private sealed class Look
		{
			public string File;

			public string Prefab;

			public string English;

			public string German;
		}

		private const string BaseSign = "sign";

		private const float TextGap = 0.01f;

		private static readonly Look[] Looks = new Look[12]
		{
			new Look
			{
				File = "1",
				Prefab = "BS_Sign_01",
				English = "Meadows wood sign",
				German = "Wiesenholz-Schild"
			},
			new Look
			{
				File = "2",
				Prefab = "BS_Sign_02",
				English = "Black Forest wood sign",
				German = "Schwarzwaldholz-Schild"
			},
			new Look
			{
				File = "3",
				Prefab = "BS_Sign_03",
				English = "Swamp wood sign",
				German = "Sumpfholz-Schild"
			},
			new Look
			{
				File = "4",
				Prefab = "BS_Sign_04",
				English = "Fine wood sign",
				German = "Feinholz-Schild"
			},
			new Look
			{
				File = "5",
				Prefab = "BS_Sign_05",
				English = "Mountain stone sign",
				German = "Bergstein-Schild"
			},
			new Look
			{
				File = "6",
				Prefab = "BS_Sign_06",
				English = "Frost stone sign",
				German = "Froststein-Schild"
			},
			new Look
			{
				File = "7",
				Prefab = "BS_Sign_07",
				English = "Mistlands stone sign",
				German = "Nebelstein-Schild"
			},
			new Look
			{
				File = "8",
				Prefab = "BS_Sign_08",
				English = "Ashlands stone sign",
				German = "Aschestein-Schild"
			},
			new Look
			{
				File = "9",
				Prefab = "BS_Sign_09",
				English = "Sandstone sign",
				German = "Sandstein-Schild"
			},
			new Look
			{
				File = "10",
				Prefab = "BS_Sign_10",
				English = "Mossy stone sign",
				German = "Moosstein-Schild"
			},
			new Look
			{
				File = "11",
				Prefab = "BS_Sign_11",
				English = "Darkwood sign",
				German = "Dunkelholz-Schild"
			},
			new Look
			{
				File = "12",
				Prefab = "BS_Sign_12",
				English = "Marble sign",
				German = "Marmor-Schild"
			}
		};

		public static void Register()
		{
			Translate();
			PrefabManager.OnVanillaPrefabsAvailable += Create;
		}

		private static string Token(Look look)
		{
			return "bs_sign_" + look.File;
		}

		private static void Translate()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			Dictionary<string, string> dictionary = new Dictionary<string, string>
			{
				{ "bs_sign_desc", "A sign to write on. Shift and use to pick the colour of the text." },
				{ "bs_sign_color", "Text colour" },
				{ "bs_palette_title", "Text colour" },
				{ "bs_palette_close", "Close" },
				{ "bs_key_shift", "Shift" }
			};
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>
			{
				{ "bs_sign_desc", "Ein Schild zum Beschriften. Mit Shift und Benutzen wählst du die Schriftfarbe." },
				{ "bs_sign_color", "Schriftfarbe" },
				{ "bs_palette_title", "Schriftfarbe" },
				{ "bs_palette_close", "Schließen" },
				{ "bs_key_shift", "Umschalt" }
			};
			Look[] looks = Looks;
			foreach (Look look in looks)
			{
				dictionary[Token(look)] = look.English;
				dictionary2[Token(look)] = look.German;
			}
			string text = "English";
			localization.AddTranslation(ref text, dictionary);
			text = "German";
			localization.AddTranslation(ref text, dictionary2);
		}

		private static void Create()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Create;
			if ((Object)(object)PrefabManager.Instance.GetPrefab("sign") == (Object)null)
			{
				Log.Error("The game has no prefab called \"sign\"; no signs are added.");
				return;
			}
			int num = 0;
			Look[] looks = Looks;
			for (int i = 0; i < looks.Length; i++)
			{
				if (Build(looks[i]))
				{
					num++;
				}
			}
			Log.Info(num + " of " + Looks.Length + " signs added.");
		}

		private static bool Build(Look look)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			string text = Beside("models", look.File + ".fbx");
			if (text == null)
			{
				Log.Warning("models/" + look.File + ".fbx is missing beside the plugin; " + look.Prefab + " is left out.");
				return false;
			}
			PieceConfig val = new PieceConfig
			{
				Name = "$" + Token(look),
				Description = "$bs_sign_desc",
				PieceTable = PieceTables.Hammer,
				Icon = LoadIcon(look)
			};
			CustomPiece val2 = new CustomPiece(look.Prefab, "sign", val);
			if ((Object)(object)val2.PiecePrefab == (Object)null)
			{
				Log.Warning("Could not clone the game's sign for " + look.Prefab + ".");
				return false;
			}
			if (!SignModel.Dress(val2.PiecePrefab, text, 0.01f))
			{
				Log.Warning(look.Prefab + " keeps the game's own look: its model could not be used.");
			}
			val2.PiecePrefab.AddComponent<ColoredSign>();
			PieceManager.Instance.AddPiece(val2);
			Log.Debug(look.Prefab + " registered from models/" + look.File + ".fbx.");
			return true;
		}

		private static Sprite LoadIcon(Look look)
		{
			string text = Beside("icons", look.File + "_icon.png");
			if (text == null)
			{
				Log.Warning("icons/" + look.File + "_icon.png is missing; " + look.Prefab + " keeps the game sign's icon.");
				return null;
			}
			return AssetUtils.LoadSpriteFromFile(text);
		}

		public static string Beside(string folder, string file)
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (directoryName == null)
			{
				return null;
			}
			string text = Path.Combine(Path.Combine(directoryName, folder), file);
			if (!File.Exists(text))
			{
				return null;
			}
			return text;
		}
	}
}