Decompiled source of ValFrames v0.5.0

plugins/ValFrames.dll

Decompiled 2 hours 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 Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
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("DezzyCode")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("DezzyCode")]
[assembly: AssemblyDescription("Pictures in frames to hang on your walls.")]
[assembly: AssemblyFileVersion("0.5.0.0")]
[assembly: AssemblyInformationalVersion("0.5.0+b69c79bebae53fe39b25402c20d0dd073c85ea38")]
[assembly: AssemblyProduct("ValFrames")]
[assembly: AssemblyTitle("ValFrames")]
[assembly: AssemblyVersion("0.5.0.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 ValFrames
{
	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;

			public Vector3 Scale = Vector3.one;

			public float Units = 0.01f;
		}

		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)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			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);
				axes.Scale = ReadScale(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)
			{
				switch (FirstString(item))
				{
				case "UpAxis":
					axes.Up = Whole(item, axes.Up);
					axes.Stated = true;
					break;
				case "UpAxisSign":
					axes.UpSign = Whole(item, axes.UpSign);
					break;
				case "UnitScaleFactor":
				{
					float num = (float)Fraction(item, 1.0);
					if (num > 0f)
					{
						axes.Units = num / 100f;
					}
					break;
				}
				}
			}
			return axes;
		}

		private static Vector3 ReadScale(Node root)
		{
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00aa: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			List<Node> list = new List<Node>();
			CollectNodes(root, "Model", list);
			foreach (Node item in list)
			{
				foreach (Node child in item.Children)
				{
					if (child.Name != "Properties70")
					{
						continue;
					}
					foreach (Node child2 in child.Children)
					{
						if (!(child2.Name != "P") && !(FirstString(child2) != "Lcl Scaling"))
						{
							Vector3 val = Triple(child2);
							if (val != Vector3.one && val.x > 0f && val.y > 0f && val.z > 0f)
							{
								Log.Info("  FBX object scale " + ((Vector3)(ref val)).ToString("0.###") + " applied.");
								return val;
							}
						}
					}
				}
			}
			return Vector3.one;
		}

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

		private static Vector3 Triple(Node node)
		{
			//IL_00a1: 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)
			List<float> list = new List<float>(3);
			foreach (object property in node.Properties)
			{
				if (property is double num)
				{
					list.Add((float)num);
				}
				else if (property is int num2)
				{
					list.Add(num2);
				}
			}
			if (list.Count < 3)
			{
				return Vector3.one;
			}
			return new Vector3(list[list.Count - 3], list[list.Count - 2], list[list.Count - 1]);
		}

		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 + 1]);
							list4.Add(list5[k]);
						}
						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("Drawer 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_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			int num = index * 3;
			float num2 = (float)source[num] * axes.Scale.x * axes.Units;
			float num3 = (float)source[num + 1] * axes.Scale.y * axes.Units;
			float num4 = (float)source[num + 2] * axes.Scale.z * axes.Units;
			if (axes.Up == 1)
			{
				return new Vector3(0f - num2, (axes.UpSign < 0) ? (0f - num3) : num3, num4);
			}
			return new Vector3(0f - 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 FrameModel
	{
		private const string SurfacePiece = "piece_table";

		private static readonly string[] Overlays = new string[5] { "snow", "ice", "frost", "wet", "moss" };

		private static MethodInfo _loadImage;

		private static bool _loadImageChecked;

		public static bool Build(GameObject prefab, string modelFile)
		{
			//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_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			string text = Beside(modelFile);
			if (text == null || !File.Exists(text))
			{
				Log.Warning("No " + modelFile + " next to the plugin; " + ((Object)prefab).name + " keeps its borrowed look.");
				return false;
			}
			FbxReader.Result result = FbxReader.Load(text, 0f);
			if (result == null)
			{
				return false;
			}
			Hang(result.Mesh);
			Material borrowed = BorrowMaterial(prefab);
			Strip(prefab);
			GameObject val = new GameObject("VF_FrameBody");
			val.transform.SetParent(prefab.transform, false);
			val.layer = prefab.layer;
			MeshFilter val2 = val.AddComponent<MeshFilter>();
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			val2.sharedMesh = result.Mesh;
			((Renderer)obj).sharedMaterials = Skins(borrowed, result, result.Mesh.subMeshCount);
			GameObject val3 = new GameObject("VF_FrameCollider");
			val3.transform.SetParent(prefab.transform, false);
			val3.layer = LayerMask.NameToLayer("piece");
			Bounds bounds = result.Mesh.bounds;
			BoxCollider obj2 = val3.AddComponent<BoxCollider>();
			obj2.center = ((Bounds)(ref bounds)).center;
			obj2.size = ((Bounds)(ref bounds)).size;
			Log.Info(((Object)prefab).name + ": " + ((Bounds)(ref bounds)).size.x.ToString("0.00") + " x " + ((Bounds)(ref bounds)).size.y.ToString("0.00") + " x " + ((Bounds)(ref bounds)).size.z.ToString("0.00") + " m from " + modelFile);
			return true;
		}

		private static void Hang(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_000b: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: 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)
			Bounds bounds = mesh.bounds;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(0f - ((Bounds)(ref bounds)).center.x, 0f - ((Bounds)(ref bounds)).center.y, 0f - ((Bounds)(ref bounds)).min.z);
			if (!(((Vector3)(ref val)).sqrMagnitude < 1E-06f))
			{
				List<Vector3> list = new List<Vector3>(mesh.vertexCount);
				mesh.GetVertices(list);
				for (int i = 0; i < list.Count; i++)
				{
					List<Vector3> list2 = list;
					int index = i;
					list2[index] += val;
				}
				mesh.SetVertices(list);
				mesh.RecalculateBounds();
			}
		}

		private static Material[] Skins(Material borrowed, FbxReader.Result model, int count)
		{
			Material[] array = (Material[])(object)new Material[Mathf.Max(1, count)];
			for (int i = 0; i < array.Length; i++)
			{
				FbxReader.Skin obj = ((model.Skins.Count > 0) ? model.Skins[Mathf.Min(i, model.Skins.Count - 1)] : null);
				Texture2D val = Decode(obj?.Colour, "colour " + i, linear: false);
				Texture2D relief = Decode(obj?.Normal, "normal " + i, linear: true);
				array[i] = (((Object)(object)val != (Object)null) ? Painted(borrowed, val, relief) : Plain(borrowed));
			}
			return array;
		}

		private static Material Plain(Material template)
		{
			//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
			Material val = (((Object)(object)template != (Object)null) ? new Material(template) : new Material(Shader.Find("Standard")));
			((Object)val).name = "VF_FramePlain";
			if (val.HasProperty("_RippleDistance"))
			{
				val.SetFloat("_RippleDistance", 0f);
			}
			if (val.HasProperty("_BumpMap"))
			{
				val.SetTexture("_BumpMap", (Texture)null);
			}
			return val;
		}

		private static Material Painted(Material template, Texture2D colour, Texture2D relief)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Material val = Plain(template);
			((Object)val).name = "VF_FramePainted";
			val.mainTexture = (Texture)(object)colour;
			if (val.HasProperty("_Color"))
			{
				val.color = Color.white;
			}
			if ((Object)(object)relief != (Object)null && val.HasProperty("_BumpMap"))
			{
				val.SetTexture("_BumpMap", (Texture)(object)relief);
				val.EnableKeyword("_NORMALMAP");
			}
			return val;
		}

		private static void Strip(GameObject prefab)
		{
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			SkinnedMeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			MeshFilter[] componentsInChildren3 = prefab.GetComponentsInChildren<MeshFilter>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			Collider[] componentsInChildren4 = prefab.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
		}

		private static Material BorrowMaterial(GameObject prefab)
		{
			GameObject prefab2 = PrefabManager.Instance.GetPrefab("piece_table");
			Material val = (((Object)(object)prefab2 != (Object)null) ? BestMaterial(prefab2) : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Log.Warning("No usable material on piece_table; falling back to the item stand's own.");
			return BestMaterial(prefab);
		}

		private static Material BestMaterial(GameObject prefab)
		{
			//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_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			Material result = null;
			float num = -1f;
			MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				Material sharedMaterial = ((Renderer)val).sharedMaterial;
				if (!((Object)(object)sharedMaterial == (Object)null) && !IsOverlay(((Object)sharedMaterial).name))
				{
					Bounds bounds = ((Renderer)val).bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					float sqrMagnitude = ((Vector3)(ref size)).sqrMagnitude;
					if (sqrMagnitude > num)
					{
						result = sharedMaterial;
						num = sqrMagnitude;
					}
				}
			}
			return result;
		}

		private static bool IsOverlay(string name)
		{
			string[] overlays = Overlays;
			foreach (string value in overlays)
			{
				if (name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			return false;
		}

		private static MethodInfo LoadImageMethod()
		{
			if (_loadImageChecked)
			{
				return _loadImage;
			}
			_loadImageChecked = true;
			Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule");
			if (type != null)
			{
				_loadImage = type.GetMethod("LoadImage", new Type[2]
				{
					typeof(Texture2D),
					typeof(byte[])
				});
			}
			if (_loadImage == null)
			{
				Log.Warning("Cannot decode images on this build; the frames keep the borrowed surface.");
			}
			return _loadImage;
		}

		private static Texture2D Decode(byte[] image, string label, bool linear)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			if (image == null)
			{
				return null;
			}
			MethodInfo methodInfo = LoadImageMethod();
			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 }))
			{
				Object.Destroy((Object)(object)val);
				Log.Warning("An embedded image (" + label + ") could not be read.");
				return null;
			}
			((Object)val).name = "VF_" + label.Replace(' ', '_');
			return val;
		}

		public static string Folder()
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (!string.IsNullOrEmpty(directoryName))
			{
				return directoryName;
			}
			return null;
		}

		public static string Beside(string file)
		{
			string text = Folder();
			if (text != null)
			{
				return Path.Combine(text, file);
			}
			return null;
		}
	}
	internal static class Frames
	{
		private sealed class Picture
		{
			public string Model;

			public string Prefab;

			public string English;

			public string German;
		}

		private static readonly string[] Sources = new string[2] { "itemstand", "itemstandh" };

		private static readonly Dictionary<string, string> Known = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
		{
			{ "aa", "VF_Frame_AA" },
			{ "cleo", "VF_Frame_Cleo" },
			{ "dennis", "VF_Frame_Dennis" },
			{ "dezzy", "VF_Frame_Dezzy" },
			{ "dezzyicon", "VF_Frame_DezzyIcon" },
			{ "exo", "VF_Frame_Exo" }
		};

		private static readonly string[] IconExtensions = new string[3] { ".png", ".jpg", ".jpeg" };

		private static List<Picture> Find()
		{
			List<Picture> list = new List<Picture>();
			string text = FrameModel.Folder();
			if (text == null || !Directory.Exists(text))
			{
				return list;
			}
			List<string> list2 = new List<string>(Directory.GetFiles(text, "*.fbx"));
			list2.Sort(StringComparer.OrdinalIgnoreCase);
			foreach (string item in list2)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item);
				string text2 = Key(fileNameWithoutExtension);
				if (text2.Length == 0)
				{
					Log.Warning(Path.GetFileName(item) + " has no usable name; skipped.");
					continue;
				}
				string text3 = Title(fileNameWithoutExtension);
				list.Add(new Picture
				{
					Model = Path.GetFileName(item),
					Prefab = (Known.TryGetValue(text2, out var value) ? value : ("VF_Frame_" + text2)),
					English = "Framed picture: " + text3,
					German = "Bild im Rahmen: " + text3
				});
			}
			return list;
		}

		private static string Key(string name)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string text = name.ToLowerInvariant();
			foreach (char c in text)
			{
				if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
				{
					stringBuilder.Append(c);
				}
				else if ((c == '_' || c == '-' || c == ' ') && stringBuilder.Length > 0 && stringBuilder[stringBuilder.Length - 1] != '_')
				{
					stringBuilder.Append('_');
				}
			}
			return stringBuilder.ToString().Trim(new char[1] { '_' });
		}

		private static string Title(string name)
		{
			string[] array = name.Replace('_', ' ').Replace('-', ' ').Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = char.ToUpperInvariant(array[i][0]) + array[i].Substring(1);
			}
			return string.Join(" ", array);
		}

		private static RequirementConfig[] Cost()
		{
			//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)
			//IL_0018: 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_0027: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			return (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "FineWood",
					Amount = 4,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "Resin",
					Amount = 2,
					Recover = true
				}
			};
		}

		public static void Create()
		{
			string text = Source();
			if (text == null)
			{
				Log.Error("Neither " + string.Join(" nor ", Sources) + " exists in this game; no frames were added.");
				return;
			}
			List<Picture> list = Find();
			if (list.Count == 0)
			{
				Log.Warning("No .fbx files next to the plugin; no frames were added.");
				return;
			}
			Translate(list);
			foreach (Picture item in list)
			{
				Build(text, item);
			}
		}

		private static string Source()
		{
			string[] sources = Sources;
			foreach (string text in sources)
			{
				if ((Object)(object)PrefabManager.Instance.GetPrefab(text) != (Object)null)
				{
					Log.Info("Frames are cloned from " + text + ".");
					return text;
				}
			}
			return null;
		}

		private static void Build(string source, Picture picture)
		{
			//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_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0047: 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_0064: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			PieceConfig val = new PieceConfig
			{
				Name = "$" + Token(picture),
				Description = "$vf_frame_desc",
				PieceTable = PieceTables.Hammer,
				Category = "Furniture",
				CraftingStation = CraftingStations.Workbench,
				Requirements = Cost(),
				Icon = Icon(picture.Model)
			};
			CustomPiece val2 = new CustomPiece(picture.Prefab, source, val);
			if ((Object)(object)val2.PiecePrefab == (Object)null)
			{
				Log.Warning("Could not clone " + source + " for " + picture.Prefab + ".");
			}
			else
			{
				Decorate(val2.PiecePrefab);
				FrameModel.Build(val2.PiecePrefab, picture.Model);
				PieceManager.Instance.AddPiece(val2);
				Log.Info(picture.Prefab + " registered from " + picture.Model + ".");
			}
		}

		private static void Decorate(GameObject prefab)
		{
			ItemStand[] componentsInChildren = prefab.GetComponentsInChildren<ItemStand>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
		}

		private static string Token(Picture picture)
		{
			return "vf_frame_" + Key(Path.GetFileNameWithoutExtension(picture.Model));
		}

		private static Sprite Icon(string modelFile)
		{
			string text = Path.GetFileNameWithoutExtension(modelFile) + "_icon";
			string text2 = null;
			string text3 = null;
			string[] iconExtensions = IconExtensions;
			foreach (string text4 in iconExtensions)
			{
				string text5 = FrameModel.Beside(text + text4);
				if (text5 != null && File.Exists(text5))
				{
					text2 = text + text4;
					text3 = text5;
					break;
				}
			}
			if (text3 == null)
			{
				Log.Warning("No " + text + ".png next to the plugin; the build menu shows the default icon.");
				return null;
			}
			Sprite obj = AssetUtils.LoadSpriteFromFile(text3);
			if ((Object)(object)obj == (Object)null)
			{
				Log.Warning(text2 + " could not be read as an icon.");
			}
			return obj;
		}

		private static void Translate(List<Picture> pictures)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string> { { "vf_frame_desc", "A picture for your wall." } };
			Dictionary<string, string> dictionary2 = new Dictionary<string, string> { { "vf_frame_desc", "Ein Bild für deine Wand." } };
			foreach (Picture picture in pictures)
			{
				dictionary[Token(picture)] = picture.English;
				dictionary2[Token(picture)] = picture.German;
			}
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, dictionary);
			text = "German";
			localization.AddTranslation(ref text, dictionary2);
		}
	}
	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.valframes", "ValFrames", "0.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "dezzycode.valheim.valframes";

		public const string Name = "ValFrames";

		public const string Version = "0.5.0";

		private void Awake()
		{
			Log.Init(((BaseUnityPlugin)this).Logger);
			PrefabManager.OnVanillaPrefabsAvailable += Create;
			Log.Info("ValFrames 0.5.0 by DezzyCode loaded.");
		}

		private void OnDestroy()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Create;
		}

		private void Create()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= Create;
			try
			{
				Frames.Create();
			}
			catch (Exception ex)
			{
				Log.Error("Could not add the frames: " + ex);
			}
		}
	}
}