Decompiled source of VargheimStatueWorkshop v0.3.12

plugins/VargheimStatueWorkshop.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyVersion("0.0.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 VargheimStatueWorkshop
{
	[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
	internal static class AutoAlignPatch
	{
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
			{
				GameObject val = (GameObject)((Workshop.GhostField == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if (!((Object)(object)val == (Object)null) && val.activeInHierarchy && Workshop.IsStatue(val) && Workshop.Prefabs.TryGetValue(Workshop.Canonical(((Object)val).name), out var value) && value.IsModule)
				{
					AutoAlign.Apply(__instance, val, value);
				}
			}
		}
	}
	internal static class AutoAlign
	{
		private static readonly FieldInfo RayMask = AccessTools.Field(typeof(Player), "m_placeRayMask");

		internal static Transform Datum(GameObject go)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			foreach (Transform item in go.transform)
			{
				Transform val = item;
				if (((Object)val).name == "workshop_snap_assembly_datum")
				{
					return val;
				}
			}
			return null;
		}

		internal static void Apply(Player player, GameObject ghost, Workshop.StatueInfo info)
		{
			//IL_0059: 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_00a1: 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_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (ZInput.GetButton("AltPlace") || ZInput.GetButton("JoyAltPlace") || (Object)(object)GameCamera.instance == (Object)null || RayMask == null)
				{
					return;
				}
				int num = (int)RayMask.GetValue(player);
				Transform transform = ((Component)GameCamera.instance).transform;
				RaycastHit[] array = Physics.RaycastAll(transform.position, transform.forward, 60f, num);
				Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
				Piece val = null;
				RaycastHit[] array2 = array;
				for (int num2 = 0; num2 < array2.Length; num2++)
				{
					RaycastHit val2 = array2[num2];
					if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !((Component)((RaycastHit)(ref val2)).collider).transform.IsChildOf(ghost.transform))
					{
						val = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Piece>();
						break;
					}
				}
				if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)(object)ghost || !Workshop.IsStatue(((Component)val).gameObject) || !Workshop.Prefabs.TryGetValue(Workshop.Canonical(((Object)((Component)val).gameObject).name), out var value) || !value.IsModule || value.SelectionKey != info.SelectionKey)
				{
					return;
				}
				float num3 = ((value.StandardScale.x > 0f) ? (((Component)val).transform.localScale.x / value.StandardScale.x) : 1f);
				int num4 = 1;
				float num5 = float.MaxValue;
				for (int num6 = 0; num6 < Workshop.Multipliers.Length; num6++)
				{
					float num7 = Mathf.Abs(Workshop.Multipliers[num6] - num3);
					if (num7 < num5)
					{
						num5 = num7;
						num4 = num6;
					}
				}
				Workshop.Selection[info.SelectionKey] = num4;
				ghost.transform.localScale = info.StandardScale * Workshop.Multipliers[num4];
				ghost.transform.rotation = ((Component)val).transform.rotation;
				Transform val3 = Datum(((Component)val).gameObject);
				Transform val4 = Datum(ghost);
				if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null))
				{
					Transform transform2 = ghost.transform;
					transform2.position += val3.position - val4.position;
					Workshop.HudText = Workshop.Labels[num4] + "  |  lined up with the part you aim at  |  hold Shift to place freely";
				}
			}
			catch (Exception)
			{
			}
		}
	}
	[Serializable]
	public sealed class CollectionFile
	{
		public CollectionFigure[] figures;

		public string[] replaceKeys;
	}
	[Serializable]
	public sealed class CollectionFigure
	{
		public string key;

		public string model;

		public string label;
	}
	internal static class CollectionRegistration
	{
		internal static void Register()
		{
			string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "collection.json");
			if (!File.Exists(path))
			{
				return;
			}
			CollectionFile collectionFile = SpecReader.Collection(File.ReadAllText(path));
			if (collectionFile == null || collectionFile.figures == null)
			{
				throw new InvalidDataException("Workshop collection manifest missing figures");
			}
			Type type = AccessTools.TypeByName("VargheimStatues.Plugin");
			FieldInfo fieldInfo = ((type == null) ? null : AccessTools.Field(type, "Figures"));
			ConfigEntry<string> val = ((fieldInfo == null) ? null : (fieldInfo.GetValue(null) as ConfigEntry<string>));
			if (val == null)
			{
				throw new MissingFieldException("Original statue Figures configuration unavailable");
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			string[] array = val.Value.Split(';');
			foreach (string text in array)
			{
				hashSet.Add(text.Split(':')[0].Trim());
			}
			string current = val.Value;
			CollectionFigure[] figures = collectionFile.figures;
			foreach (CollectionFigure collectionFigure in figures)
			{
				if (string.IsNullOrEmpty(collectionFigure.key) || string.IsNullOrEmpty(collectionFigure.model) || string.IsNullOrEmpty(collectionFigure.label))
				{
					throw new InvalidDataException("Incomplete collection entry");
				}
				if (collectionFigure.key.IndexOfAny(new char[2] { ':', ';' }) >= 0 || collectionFigure.label.IndexOfAny(new char[2] { ':', ';' }) >= 0 || Path.GetFileName(collectionFigure.model) != collectionFigure.model)
				{
					throw new InvalidDataException("Invalid collection entry format");
				}
				if (!hashSet.Contains(collectionFigure.key))
				{
					string text2 = (collectionFigure.model.EndsWith(".obj", StringComparison.OrdinalIgnoreCase) ? collectionFigure.model.Substring(0, collectionFigure.model.Length - 4) : collectionFigure.model);
					if (ModelFiles.Find(collectionFigure.model).Length + ModelFiles.Find(text2 + ".vsm").Length <= 0 || ModelFiles.Find(collectionFigure.model + ".statue.json").Length != 1)
					{
						throw new InvalidDataException("Collection model/metadata missing or ambiguous: " + collectionFigure.model);
					}
					current = CollectionRows.Append(current, collectionFigure.key, collectionFigure.model, collectionFigure.label);
					hashSet.Add(collectionFigure.key);
					Workshop.Instance.LoggerForImport("Added collection hammer entry: " + collectionFigure.label);
				}
			}
			current = CollectionRows.WithoutKeys(current, collectionFile.replaceKeys);
			if (current != val.Value)
			{
				val.Value = current;
			}
		}
	}
	internal static class CollectionRows
	{
		internal static string WithoutKeys(string current, string[] keys)
		{
			if (keys == null || keys.Length == 0)
			{
				return current ?? "";
			}
			HashSet<string> hashSet = new HashSet<string>(keys, StringComparer.OrdinalIgnoreCase);
			List<string> list = new List<string>();
			string[] array = (current ?? "").Split(';');
			foreach (string text in array)
			{
				if (!string.IsNullOrWhiteSpace(text) && !hashSet.Contains(text.Split(':')[0].Trim()))
				{
					list.Add(text.Trim());
				}
			}
			return string.Join("; ", list.ToArray());
		}

		internal static string Append(string current, string key, string model, string label)
		{
			if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(model) || string.IsNullOrEmpty(label))
			{
				throw new InvalidDataException("Incomplete collection entry");
			}
			if (key.IndexOfAny(new char[2] { ':', ';' }) >= 0 || label.IndexOfAny(new char[2] { ':', ';' }) >= 0 || model.IndexOfAny(new char[4] { ':', ';', '/', '\\' }) >= 0 || !model.EndsWith(".obj", StringComparison.OrdinalIgnoreCase))
			{
				throw new InvalidDataException("Invalid collection entry format");
			}
			current = current ?? "";
			string[] array = current.Split(';');
			for (int i = 0; i < array.Length; i++)
			{
				if (string.Equals(array[i].Split(':')[0].Trim(), key, StringComparison.OrdinalIgnoreCase))
				{
					return current;
				}
			}
			string text = current.TrimEnd().TrimEnd(';');
			return ((text.Length == 0) ? "" : (text + "; ")) + key + ":" + model + ":" + label + ":1";
		}
	}
	internal static class Diag
	{
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		internal static class Register
		{
			[Serializable]
			[CompilerGenerated]
			private sealed class <>c
			{
				public static readonly <>c <>9 = new <>c();

				public static ConsoleEvent <>9__0_0;

				internal void <Postfix>b__0_0(ConsoleEventArgs args)
				{
					try
					{
						string text = Run();
						Workshop.Instance.LoggerForImport(text);
						string[] array = text.Split('\n');
						foreach (string text2 in array)
						{
							args.Context.AddString(text2);
						}
					}
					catch (Exception ex)
					{
						args.Context.AddString("vst_lod failed: " + ex.Message);
					}
				}
			}

			[HarmonyPostfix]
			private static void Postfix()
			{
				//IL_0033: 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_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Expected O, but got Unknown
				try
				{
					object obj = <>c.<>9__0_0;
					if (obj == null)
					{
						ConsoleEvent val = delegate(ConsoleEventArgs args)
						{
							try
							{
								string text = Run();
								Workshop.Instance.LoggerForImport(text);
								string[] array = text.Split('\n');
								foreach (string text2 in array)
								{
									args.Context.AddString(text2);
								}
							}
							catch (Exception ex2)
							{
								args.Context.AddString("vst_lod failed: " + ex2.Message);
							}
						};
						<>c.<>9__0_0 = val;
						obj = (object)val;
					}
					new ConsoleCommand("vst_lod", "Statue Workshop: renderer/LOD state of statues within 40 m (also written to the BepInEx log)", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
				}
				catch (Exception ex)
				{
					Workshop.Instance.LoggerForImport("vst_lod not registered: " + ex.Message);
				}
			}
		}

		private static string F(float v)
		{
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private static string V(Vector3 v)
		{
			//IL_0010: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			return "(" + F(v.x) + "," + F(v.y) + "," + F(v.z) + ")";
		}

		private static string Run()
		{
			//IL_0057: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_029e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Camera main = Camera.main;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)main == (Object)null)
			{
				return "vst_lod: load a world first.";
			}
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			Piece[] array = Object.FindObjectsByType<Piece>((FindObjectsSortMode)0);
			foreach (Piece val in array)
			{
				if (!Workshop.IsStatue(((Component)val).gameObject))
				{
					continue;
				}
				float num2 = Vector3.Distance(((Component)val).transform.position, ((Component)main).transform.position);
				if (num2 > 40f)
				{
					continue;
				}
				num++;
				stringBuilder.Append(Workshop.Canonical(((Object)val).name)).Append(" d=").Append(F(num2))
					.Append(" pos=")
					.Append(V(((Component)val).transform.position))
					.Append(" scale=")
					.Append(V(((Component)val).transform.localScale))
					.Append(" active=")
					.Append(((Component)val).gameObject.activeInHierarchy)
					.Append('\n');
				LODGroup[] componentsInChildren = ((Component)val).GetComponentsInChildren<LODGroup>(true);
				foreach (LODGroup val2 in componentsInChildren)
				{
					float num3 = val2.size * Mathf.Max(Mathf.Abs(((Component)val2).transform.lossyScale.x), Mathf.Max(Mathf.Abs(((Component)val2).transform.lossyScale.y), Mathf.Abs(((Component)val2).transform.lossyScale.z)));
					Vector3 val3 = ((Component)val2).transform.TransformPoint(val2.localReferencePoint);
					float num4 = Vector3.Distance(val3, ((Component)main).transform.position);
					float v = num3 / (2f * Mathf.Max(0.01f, num4) * Mathf.Tan(main.fieldOfView * 0.5f * ((float)Math.PI / 180f)));
					stringBuilder.Append("  LODGroup on ").Append(((Object)val2).name).Append(" enabled=")
						.Append(val2.enabled)
						.Append(" size=")
						.Append(F(val2.size))
						.Append(" (")
						.Append(F(num3))
						.Append(" m) ref=")
						.Append(V(val3))
						.Append(" screen=")
						.Append(F(v))
						.Append(" levels:");
					LOD[] lODs = val2.GetLODs();
					foreach (LOD val4 in lODs)
					{
						stringBuilder.Append(' ').Append(F(val4.screenRelativeTransitionHeight)).Append('/')
							.Append(val4.renderers.Length);
					}
					stringBuilder.Append('\n');
				}
				Renderer[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val5 in componentsInChildren2)
				{
					if (((Component)val5).gameObject.activeInHierarchy || ((Object)val5).name.StartsWith("statue", StringComparison.Ordinal) || ((Object)val5).name.StartsWith("workshop", StringComparison.Ordinal))
					{
						MeshFilter component = ((Component)val5).GetComponent<MeshFilter>();
						StringBuilder stringBuilder2 = stringBuilder.Append("  ").Append(((Object)val5).name).Append(" on=")
							.Append(val5.enabled)
							.Append(" act=")
							.Append(((Component)val5).gameObject.activeInHierarchy)
							.Append(" visible=")
							.Append(val5.isVisible)
							.Append(" layer=")
							.Append(LayerMask.LayerToName(((Component)val5).gameObject.layer))
							.Append(" bounds=");
						Bounds bounds = val5.bounds;
						StringBuilder stringBuilder3 = stringBuilder2.Append(V(((Bounds)(ref bounds)).center)).Append('+');
						bounds = val5.bounds;
						stringBuilder3.Append(V(((Bounds)(ref bounds)).size)).Append(" mesh=").Append(((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) ? (component.sharedMesh.vertexCount + "v") : "none")
							.Append(" mat=")
							.Append(((Object)(object)val5.sharedMaterial != (Object)null) ? ((Object)val5.sharedMaterial.shader).name : "none")
							.Append('\n');
					}
				}
			}
			if (num == 0)
			{
				return "vst_lod: no Vargheim statue within 40 m.";
			}
			return stringBuilder.ToString().TrimEnd();
		}
	}
	internal static class MiniJson
	{
		internal static object Parse(string s)
		{
			int i = 0;
			object result = Value(s, ref i);
			Ws(s, ref i);
			if (i < s.Length)
			{
				throw new FormatException("trailing text at " + i);
			}
			return result;
		}

		private static void Ws(string s, ref int i)
		{
			while (i < s.Length && char.IsWhiteSpace(s[i]))
			{
				i++;
			}
		}

		private static object Value(string s, ref int i)
		{
			Ws(s, ref i);
			if (i >= s.Length)
			{
				throw new FormatException("unexpected end");
			}
			switch (s[i])
			{
			case '{':
				return Obj(s, ref i);
			case '[':
				return Arr(s, ref i);
			case '"':
				return Str(s, ref i);
			default:
			{
				if (s.Length - i >= 4 && string.CompareOrdinal(s, i, "true", 0, 4) == 0)
				{
					i += 4;
					return true;
				}
				if (s.Length - i >= 5 && string.CompareOrdinal(s, i, "false", 0, 5) == 0)
				{
					i += 5;
					return false;
				}
				if (s.Length - i >= 4 && string.CompareOrdinal(s, i, "null", 0, 4) == 0)
				{
					i += 4;
					return null;
				}
				int num = i;
				while (i < s.Length && "+-0123456789.eE".IndexOf(s[i]) >= 0)
				{
					i++;
				}
				if (i == num)
				{
					throw new FormatException("bad value at " + i);
				}
				return double.Parse(s.Substring(num, i - num), NumberStyles.Float, CultureInfo.InvariantCulture);
			}
			}
		}

		private static Dictionary<string, object> Obj(string s, ref int i)
		{
			Dictionary<string, object> dictionary = new Dictionary<string, object>(StringComparer.Ordinal);
			i++;
			Ws(s, ref i);
			if (i < s.Length && s[i] == '}')
			{
				i++;
				return dictionary;
			}
			while (true)
			{
				Ws(s, ref i);
				string key = Str(s, ref i);
				Ws(s, ref i);
				if (i >= s.Length || s[i] != ':')
				{
					throw new FormatException("':' expected at " + i);
				}
				i++;
				dictionary[key] = Value(s, ref i);
				Ws(s, ref i);
				if (i >= s.Length || s[i] != ',')
				{
					break;
				}
				i++;
			}
			if (i < s.Length && s[i] == '}')
			{
				i++;
				return dictionary;
			}
			throw new FormatException("',' or '}' expected at " + i);
		}

		private static List<object> Arr(string s, ref int i)
		{
			List<object> list = new List<object>();
			i++;
			Ws(s, ref i);
			if (i < s.Length && s[i] == ']')
			{
				i++;
				return list;
			}
			while (true)
			{
				list.Add(Value(s, ref i));
				Ws(s, ref i);
				if (i >= s.Length || s[i] != ',')
				{
					break;
				}
				i++;
			}
			if (i < s.Length && s[i] == ']')
			{
				i++;
				return list;
			}
			throw new FormatException("',' or ']' expected at " + i);
		}

		private static string Str(string s, ref int i)
		{
			if (s[i] != '"')
			{
				throw new FormatException("string expected at " + i);
			}
			i++;
			StringBuilder stringBuilder = new StringBuilder();
			while (i < s.Length)
			{
				char c = s[i++];
				switch (c)
				{
				case '"':
					return stringBuilder.ToString();
				default:
					stringBuilder.Append(c);
					break;
				case '\\':
				{
					char c2 = s[i++];
					switch (c2)
					{
					case 'n':
						stringBuilder.Append('\n');
						break;
					case 't':
						stringBuilder.Append('\t');
						break;
					case 'r':
						stringBuilder.Append('\r');
						break;
					case 'b':
						stringBuilder.Append('\b');
						break;
					case 'f':
						stringBuilder.Append('\f');
						break;
					case 'u':
						stringBuilder.Append((char)int.Parse(s.Substring(i, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture));
						i += 4;
						break;
					default:
						stringBuilder.Append(c2);
						break;
					}
					break;
				}
				}
			}
			throw new FormatException("unterminated string");
		}

		internal static string S(Dictionary<string, object> d, string k)
		{
			if (d == null || !d.TryGetValue(k, out var value) || !(value is string))
			{
				return null;
			}
			return (string)value;
		}

		internal static float F(Dictionary<string, object> d, string k)
		{
			if (d == null || !d.TryGetValue(k, out var value) || value == null)
			{
				return 0f;
			}
			if (value is double)
			{
				return (float)(double)value;
			}
			if (value is bool)
			{
				if (!(bool)value)
				{
					return 0f;
				}
				return 1f;
			}
			return 0f;
		}

		internal static bool B(Dictionary<string, object> d, string k)
		{
			if (d != null && d.TryGetValue(k, out var value) && value is bool)
			{
				return (bool)value;
			}
			return false;
		}

		internal static float[] Floats(Dictionary<string, object> d, string k)
		{
			if (d == null || !d.TryGetValue(k, out var value))
			{
				return null;
			}
			if (!(value is List<object> list))
			{
				return null;
			}
			float[] array = new float[list.Count];
			for (int i = 0; i < list.Count; i++)
			{
				array[i] = ((list[i] is double) ? ((float)(double)list[i]) : 0f);
			}
			return array;
		}

		internal static List<Dictionary<string, object>> Objects(Dictionary<string, object> d, string k)
		{
			List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
			if (d == null || !d.TryGetValue(k, out var value))
			{
				return list;
			}
			if (!(value is List<object> list2))
			{
				return list;
			}
			foreach (object item2 in list2)
			{
				if (item2 is Dictionary<string, object> item)
				{
					list.Add(item);
				}
			}
			return list;
		}
	}
	internal static class ModelFiles
	{
		private static string s_baseDir;

		private static string BaseDir()
		{
			if (s_baseDir != null)
			{
				return s_baseDir;
			}
			Type type = AccessTools.TypeByName("VargheimStatues.Plugin");
			s_baseDir = ((type == null) ? "" : (Path.GetDirectoryName(type.Assembly.Location) ?? ""));
			return s_baseDir;
		}

		internal static string[] Find(string fileName)
		{
			List<string> list = new List<string>(Directory.GetFiles(Paths.PluginPath, fileName, SearchOption.AllDirectories));
			string path = Path.Combine(Path.Combine(Paths.ConfigPath, "VargheimStatues"), "models");
			if (Directory.Exists(path))
			{
				list.AddRange(Directory.GetFiles(path, fileName, SearchOption.AllDirectories));
			}
			if (list.Count <= 1)
			{
				return list.ToArray();
			}
			string b = BaseDir();
			if (b.Length > 0)
			{
				List<string> list2 = list.FindAll((string f) => f.StartsWith(b + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase));
				if (list2.Count == 1)
				{
					return list2.ToArray();
				}
			}
			return list.ToArray();
		}
	}
	[Serializable]
	public sealed class SnapAnchor
	{
		public string name;

		public float x;

		public float y;

		public float z;
	}
	internal static class ModularPieces
	{
		private static readonly Dictionary<string, List<float>> s_joints = new Dictionary<string, List<float>>(StringComparer.Ordinal);

		private static List<float> FamilyJoints(string family)
		{
			if (s_joints.TryGetValue(family, out var value))
			{
				return value;
			}
			value = new List<float>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			List<string> list = new List<string>(Directory.GetFiles(Paths.PluginPath, "*.obj.statue.json", SearchOption.AllDirectories));
			string path = Path.Combine(Path.Combine(Paths.ConfigPath, "VargheimStatues"), "models");
			if (Directory.Exists(path))
			{
				list.AddRange(Directory.GetFiles(path, "*.obj.statue.json", SearchOption.AllDirectories));
			}
			foreach (string item in list)
			{
				string fileName = Path.GetFileName(item);
				fileName = fileName.Substring(0, fileName.Length - ".statue.json".Length);
				if (!hashSet.Add(fileName))
				{
					continue;
				}
				try
				{
					AssetSpec assetSpec = AssetFinish.ReadSpec(fileName);
					if (assetSpec == null || assetSpec.family != family || assetSpec.snaps == null)
					{
						continue;
					}
					SnapAnchor[] snaps = assetSpec.snaps;
					foreach (SnapAnchor snapAnchor in snaps)
					{
						if (snapAnchor != null && snapAnchor.name == "assembly_datum")
						{
							float j = 0f - snapAnchor.y;
							if (j > 0.002f && !value.Exists((float h) => Mathf.Abs(h - j) < 0.002f))
							{
								value.Add(j);
							}
						}
					}
				}
				catch (Exception)
				{
				}
			}
			s_joints[family] = value;
			return value;
		}

		private static bool SupportWearOff()
		{
			try
			{
				Type type = AccessTools.TypeByName("VargheimStatues.SupportWear");
				MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Off", (Type[])null, (Type[])null));
				if (methodInfo != null)
				{
					return (bool)methodInfo.Invoke(null, null);
				}
			}
			catch (Exception ex)
			{
				Workshop.Instance.LoggerForImport("SupportWear.Off unavailable (" + ex.Message + "); falling back to a vanilla read.");
			}
			GameObject val = (((Object)(object)ZNetScene.instance == (Object)null) ? null : (ZNetScene.instance.GetPrefab("woodwall") ?? ZNetScene.instance.GetPrefab("wood_floor")));
			WearNTear val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<WearNTear>());
			if (!((Object)(object)val2 == (Object)null))
			{
				return !val2.m_noSupportWear;
			}
			return false;
		}

		internal static bool IsModule(AssetSpec spec)
		{
			if (spec != null && !string.IsNullOrEmpty(spec.family))
			{
				return !string.IsNullOrEmpty(spec.pieceKind);
			}
			return false;
		}

		internal static void Configure(GameObject root, AssetSpec spec)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Expected O, but got Unknown
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04df: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_050a: Unknown result type (might be due to invalid IL or missing references)
			if (!IsModule(spec))
			{
				return;
			}
			if (spec.figureHeight <= 0f || spec.assemblyHeight <= 0f || spec.stoneCost < 1)
			{
				throw new InvalidDataException("Invalid modular dimensions or Stone cost");
			}
			Piece component = root.GetComponent<Piece>();
			GameObject val = (((Object)(object)ObjectDB.instance == (Object)null) ? null : ObjectDB.instance.GetItemPrefab("Stone"));
			ItemDrop val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<ItemDrop>());
			if ((Object)(object)component == (Object)null || (Object)(object)val2 == (Object)null)
			{
				throw new InvalidDataException("Modular piece or Stone resource unavailable");
			}
			GameObject val3 = (((Object)(object)ObjectDB.instance == (Object)null) ? null : ObjectDB.instance.GetItemPrefab("Wood"));
			ItemDrop val4 = (((Object)(object)val3 == (Object)null) ? null : val3.GetComponent<ItemDrop>());
			List<Requirement> list = new List<Requirement>
			{
				new Requirement
				{
					m_resItem = val2,
					m_amount = spec.stoneCost,
					m_amountPerLevel = 0,
					m_recover = true
				}
			};
			if (spec.woodCost > 0 && (Object)(object)val4 != (Object)null)
			{
				list.Add(new Requirement
				{
					m_resItem = val4,
					m_amount = spec.woodCost,
					m_amountPerLevel = 0,
					m_recover = true
				});
			}
			component.m_resources = list.ToArray();
			component.m_groundOnly = false;
			WearNTear component2 = root.GetComponent<WearNTear>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.m_noSupportWear = SupportWearOff();
			}
			component.m_comfort = ((spec.pieceKind == "Torso") ? 1 : 0);
			string text = ((spec.family == "SpearSentinel") ? "Spear Guardian" : ((spec.family == "AxeSentinel") ? "Axe Guardian" : spec.family));
			string text2 = ((spec.pieceKind == "LowerBody") ? "lower body" : spec.pieceKind.ToLowerInvariant());
			component.m_description = text + " " + text2 + ", carved in grey stone. " + spec.stoneCost + " Stone" + ((spec.woodCost > 0) ? (" and " + spec.woodCost + " Wood") : "") + " at every size. Match sizes when assembling the statue.";
			Transform val5 = root.transform.Find("statue_figure");
			MeshFilter val6 = (((Object)(object)val5 == (Object)null) ? null : ((Component)val5).GetComponentInChildren<MeshFilter>());
			if ((Object)(object)val6 == (Object)null)
			{
				throw new InvalidDataException("Module snap reference mesh missing");
			}
			SnapAnchor snapAnchor = null;
			if (spec.snaps != null)
			{
				SnapAnchor[] snaps = spec.snaps;
				foreach (SnapAnchor snapAnchor2 in snaps)
				{
					if (snapAnchor2 != null && snapAnchor2.name == "assembly_datum")
					{
						if (snapAnchor != null)
						{
							throw new InvalidDataException("Duplicate statue assembly datum");
						}
						snapAnchor = snapAnchor2;
					}
				}
			}
			if (snapAnchor == null)
			{
				throw new InvalidDataException("Statue module requires one assembly_datum snap");
			}
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			foreach (Transform val7 in componentsInChildren)
			{
				if ((Object)(object)val7 != (Object)(object)root.transform && ((Component)val7).CompareTag("snappoint"))
				{
					((Component)val7).gameObject.tag = "Untagged";
					Object.Destroy((Object)(object)((Component)val7).gameObject);
				}
			}
			Mesh sharedMesh = val6.sharedMesh;
			float num;
			Bounds bounds;
			if (!((Object)(object)sharedMesh != (Object)null))
			{
				num = 0f;
			}
			else
			{
				bounds = sharedMesh.bounds;
				num = ((Bounds)(ref bounds)).min.y - snapAnchor.y;
			}
			float num2 = num;
			float num3;
			if (!((Object)(object)sharedMesh != (Object)null))
			{
				num3 = 0f;
			}
			else
			{
				bounds = sharedMesh.bounds;
				num3 = ((Bounds)(ref bounds)).max.y - snapAnchor.y;
			}
			float num4 = num3;
			List<float> list2 = new List<float> { 0f };
			foreach (float j in FamilyJoints(spec.family))
			{
				if (j >= num2 - 0.002f && j <= num4 + 0.002f && !list2.Exists((float h) => Mathf.Abs(h - j) < 0.002f))
				{
					list2.Add(j);
				}
			}
			foreach (float item in list2)
			{
				GameObject val8 = new GameObject("workshop_snap_" + ((item == 0f) ? snapAnchor.name : ("joint_" + item.ToString("0.000", CultureInfo.InvariantCulture))))
				{
					tag = "snappoint",
					layer = root.layer
				};
				Vector3 val9 = ((Component)val6).transform.TransformPoint(new Vector3(0f - snapAnchor.x, snapAnchor.y + item, snapAnchor.z));
				val8.transform.SetParent(root.transform, false);
				val8.transform.localPosition = root.transform.InverseTransformPoint(val9);
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "DropResources")]
	internal static class PaidStoneRefund
	{
		private static void Prefix(Piece __instance, out Requirement[] __state)
		{
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Expected O, but got Unknown
			__state = null;
			if (!Workshop.IsStatue(((Component)__instance).gameObject))
			{
				return;
			}
			ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
			ZDO val = (((Object)(object)component == (Object)null) ? null : component.GetZDO());
			if (val == null)
			{
				return;
			}
			int num = val.GetInt("vargheim_statue_stone_paid", -1);
			int num2 = val.GetInt("vargheim_statue_wood_paid", -1);
			if (num < 0 || __instance.m_resources == null || __instance.m_resources.Length < 1)
			{
				return;
			}
			__state = __instance.m_resources;
			List<Requirement> list = new List<Requirement>();
			Requirement[] resources = __instance.m_resources;
			foreach (Requirement val2 in resources)
			{
				if (!((Object)(object)val2.m_resItem == (Object)null))
				{
					string name = ((Object)((Component)val2.m_resItem).gameObject).name;
					int amount = ((name == "Stone") ? num : ((name == "Wood" && num2 >= 0) ? num2 : val2.m_amount));
					list.Add(new Requirement
					{
						m_resItem = val2.m_resItem,
						m_amount = amount,
						m_amountPerLevel = 0,
						m_recover = val2.m_recover
					});
				}
			}
			__instance.m_resources = list.ToArray();
		}

		private static Exception Finalizer(Exception __exception, Piece __instance, Requirement[] __state)
		{
			if (__state != null)
			{
				__instance.m_resources = __state;
			}
			return __exception;
		}
	}
	internal sealed class ObjData
	{
		internal readonly List<float[]> Positions = new List<float[]>();

		internal readonly List<float[]> Normals = new List<float[]>();

		internal readonly List<float[]> UVs = new List<float[]>();

		internal readonly List<int> Indices = new List<int>();

		internal static bool IsWorkshop(string[] lines)
		{
			for (int i = 0; i < Math.Min(lines.Length, 8); i++)
			{
				string text = lines[i].Trim();
				if (text.StartsWith("# Odin Workshop v7.", StringComparison.Ordinal) || text.StartsWith("# Workshop Odin UV-preserving distance LOD", StringComparison.Ordinal) || text == "# Vargheim Workshop OBJ" || text.StartsWith("# Welded pos+uv+normal", StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		internal static ObjData Parse(string[] lines)
		{
			ObjData objData = new ObjData();
			List<float[]> list = new List<float[]>();
			List<float[]> list2 = new List<float[]>();
			List<float[]> list3 = new List<float[]>();
			Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.Ordinal);
			for (int i = 0; i < lines.Length; i++)
			{
				string text = lines[i].Split('#')[0].Trim();
				if (text.Length == 0)
				{
					continue;
				}
				string[] array = text.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
				if (array[0] == "v")
				{
					Require(array.Length >= 4, "Incomplete position");
					list.Add(new float[3]
					{
						0f - Number(array[1]),
						Number(array[2]),
						Number(array[3])
					});
				}
				else if (array[0] == "vn")
				{
					Require(array.Length >= 4, "Incomplete normal");
					list2.Add(new float[3]
					{
						0f - Number(array[1]),
						Number(array[2]),
						Number(array[3])
					});
				}
				else if (array[0] == "vt")
				{
					Require(array.Length >= 3, "Incomplete texture coordinate");
					list3.Add(new float[2]
					{
						Number(array[1]),
						Number(array[2])
					});
				}
				else
				{
					if (!(array[0] == "f"))
					{
						continue;
					}
					Require(array.Length >= 4, "Incomplete face");
					int[] array2 = new int[array.Length - 1];
					for (int j = 1; j < array.Length; j++)
					{
						string[] array3 = array[j].Split('/');
						Require(array3.Length == 3 && array3[1].Length > 0 && array3[2].Length > 0, "Workshop faces require position/texture/normal indices");
						int index = Index(array3[0], list.Count);
						int index2 = Index(array3[1], list3.Count);
						int index3 = Index(array3[2], list2.Count);
						string key = index.ToString(CultureInfo.InvariantCulture) + "/" + index2.ToString(CultureInfo.InvariantCulture) + "/" + index3.ToString(CultureInfo.InvariantCulture);
						if (!dictionary.TryGetValue(key, out var value))
						{
							value = objData.Positions.Count;
							dictionary.Add(key, value);
							objData.Positions.Add(list[index]);
							objData.UVs.Add(list3[index2]);
							objData.Normals.Add(list2[index3]);
						}
						array2[j - 1] = value;
					}
					for (int k = 1; k < array2.Length - 1; k++)
					{
						objData.Indices.Add(array2[0]);
						objData.Indices.Add(array2[k + 1]);
						objData.Indices.Add(array2[k]);
					}
				}
			}
			Require(objData.Indices.Count > 0, "Workshop OBJ has no faces");
			return objData;
		}

		private static float Number(string value)
		{
			float num = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture);
			Require(!float.IsNaN(num) && !float.IsInfinity(num), "Nonfinite OBJ value");
			return num;
		}

		private static int Index(string value, int count)
		{
			int num = int.Parse(value, CultureInfo.InvariantCulture);
			int num2 = ((num < 0) ? (count + num) : (num - 1));
			Require(num != 0 && num2 >= 0 && num2 < count, "OBJ index outside source range");
			return num2;
		}

		private static void Require(bool condition, string message)
		{
			if (!condition)
			{
				throw new InvalidDataException(message);
			}
		}
	}
	internal static class SpecReader
	{
		internal static CollectionFile Collection(string text)
		{
			if (!(MiniJson.Parse(text) is Dictionary<string, object> dictionary))
			{
				return null;
			}
			CollectionFile collectionFile = new CollectionFile();
			List<CollectionFigure> list = new List<CollectionFigure>();
			foreach (Dictionary<string, object> item in MiniJson.Objects(dictionary, "figures"))
			{
				list.Add(new CollectionFigure
				{
					key = MiniJson.S(item, "key"),
					model = MiniJson.S(item, "model"),
					label = MiniJson.S(item, "label")
				});
			}
			collectionFile.figures = list.ToArray();
			List<string> list2 = new List<string>();
			if (dictionary.TryGetValue("replaceKeys", out var value) && value is List<object>)
			{
				foreach (object item2 in (List<object>)value)
				{
					if (item2 is string)
					{
						list2.Add((string)item2);
					}
				}
			}
			collectionFile.replaceKeys = list2.ToArray();
			return collectionFile;
		}

		internal static AssetSpec Asset(string text)
		{
			if (!(MiniJson.Parse(text) is Dictionary<string, object> dictionary))
			{
				return null;
			}
			AssetSpec assetSpec = new AssetSpec
			{
				family = MiniJson.S(dictionary, "family"),
				pieceKind = MiniJson.S(dictionary, "pieceKind"),
				assemblyHeight = MiniJson.F(dictionary, "assemblyHeight"),
				stoneCost = (int)Math.Round(MiniJson.F(dictionary, "stoneCost")),
				woodCost = (int)Math.Round(MiniJson.F(dictionary, "woodCost")),
				ownBase = MiniJson.B(dictionary, "ownBase"),
				baseHeight = MiniJson.F(dictionary, "baseHeight"),
				figureHeight = MiniJson.F(dictionary, "figureHeight"),
				albedo = MiniJson.S(dictionary, "albedo"),
				normal = MiniJson.S(dictionary, "normal"),
				metallicGloss = MiniJson.S(dictionary, "metallicGloss"),
				lod1 = MiniJson.S(dictionary, "lod1"),
				lod2 = MiniJson.S(dictionary, "lod2"),
				collision = MiniJson.S(dictionary, "collision"),
				lod1Normal = MiniJson.S(dictionary, "lod1Normal"),
				lod2Normal = MiniJson.S(dictionary, "lod2Normal"),
				lod1Albedo = MiniJson.S(dictionary, "lod1Albedo"),
				lod2Albedo = MiniJson.S(dictionary, "lod2Albedo")
			};
			if (dictionary.ContainsKey("smoothness"))
			{
				assetSpec.smoothness = MiniJson.F(dictionary, "smoothness");
			}
			if (dictionary.ContainsKey("normalStrength"))
			{
				assetSpec.normalStrength = MiniJson.F(dictionary, "normalStrength");
			}
			if (dictionary.ContainsKey("tintR"))
			{
				assetSpec.tintR = MiniJson.F(dictionary, "tintR");
			}
			if (dictionary.ContainsKey("tintG"))
			{
				assetSpec.tintG = MiniJson.F(dictionary, "tintG");
			}
			if (dictionary.ContainsKey("tintB"))
			{
				assetSpec.tintB = MiniJson.F(dictionary, "tintB");
			}
			if (dictionary.ContainsKey("snaps"))
			{
				List<SnapAnchor> list = new List<SnapAnchor>();
				foreach (Dictionary<string, object> item in MiniJson.Objects(dictionary, "snaps"))
				{
					list.Add(new SnapAnchor
					{
						name = MiniJson.S(item, "name"),
						x = MiniJson.F(item, "x"),
						y = MiniJson.F(item, "y"),
						z = MiniJson.F(item, "z")
					});
				}
				assetSpec.snaps = list.ToArray();
			}
			return assetSpec;
		}
	}
	[BepInPlugin("digi.vargheim.statueworkshop", "Vargheim Statue Workshop", "0.3.12")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Workshop : BaseUnityPlugin
	{
		internal sealed class StatueInfo
		{
			internal string Name;

			internal Vector3 StandardScale;

			internal float StandardHeight;

			internal string SelectionKey;

			internal bool IsModule;

			internal int StoneCost;

			internal int WoodCost;
		}

		internal sealed class Placement
		{
			internal string Name;

			internal Vector3 Scale;

			internal float Multiplier;

			internal int PaidStone = -1;

			internal int PaidWood = -1;
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class PreviewPatch
		{
			private static void Prefix(Player __instance, bool takeInput)
			{
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: 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_0110: 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)
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				HudText = null;
				GameObject val = (GameObject)((GhostField == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if ((Object)(object)val == (Object)null || !val.activeInHierarchy || !IsStatue(val))
				{
					return;
				}
				string key = Canonical(((Object)val).name);
				if (Prefabs.TryGetValue(key, out var value))
				{
					int num = Selected(value.SelectionKey);
					if (takeInput && Input.GetKeyDown(CycleKey.Value))
					{
						num = (num + 1) % Multipliers.Length;
						Selection[value.SelectionKey] = num;
					}
					val.transform.localScale = value.StandardScale * Multipliers[num];
					HudText = Labels[num] + "  |  " + (value.StandardHeight * Multipliers[num]).ToString("0.#") + " m assembly  |  " + ((object)CycleKey.Value/*cast due to .constrained prefix*/).ToString() + ": change size";
				}
			}

			private static void Postfix(Player __instance)
			{
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
				{
					return;
				}
				GameObject val = (GameObject)((GhostField == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if ((Object)(object)val == (Object)null || !val.activeInHierarchy || !IsStatue(val))
				{
					HudText = null;
					return;
				}
				string key = Canonical(((Object)val).name);
				if (Prefabs.TryGetValue(key, out var value))
				{
					val.transform.localScale = value.StandardScale * Multipliers[Selected(value.SelectionKey)];
				}
			}
		}

		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class PlacePatch
		{
			private static void Prefix(Player __instance, Piece piece, out Placement __state)
			{
				//IL_0062: 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)
				__state = Scope;
				Scope = null;
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)piece == (Object)null) && IsStatue(((Component)piece).gameObject))
				{
					string text = Canonical(((Object)((Component)piece).gameObject).name);
					if (Prefabs.TryGetValue(text, out var value))
					{
						Scope = new Placement
						{
							Name = text,
							Scale = value.StandardScale * Multipliers[Selected(value.SelectionKey)],
							Multiplier = Multipliers[Selected(value.SelectionKey)],
							PaidStone = ((!value.IsModule) ? (-1) : ((!__instance.NoCostCheat()) ? value.StoneCost : 0)),
							PaidWood = ((!value.IsModule) ? (-1) : ((!__instance.NoCostCheat()) ? value.WoodCost : 0))
						};
					}
				}
			}

			private static Exception Finalizer(Exception __exception, Placement __state)
			{
				Scope = __state;
				return __exception;
			}
		}

		[HarmonyPatch(typeof(ZNetView), "Awake")]
		private static class NetScalePatch
		{
			private static void Prefix(ZNetView __instance)
			{
				if (IsStatue(((Component)__instance).gameObject))
				{
					__instance.m_syncInitialScale = true;
				}
			}

			private static void Postfix(ZNetView __instance)
			{
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				if (Scope != null && IsStatue(((Component)__instance).gameObject) && !(Canonical(((Object)((Component)__instance).gameObject).name) != Scope.Name) && __instance.GetZDO() != null && __instance.IsOwner())
				{
					__instance.m_syncInitialScale = true;
					__instance.SetLocalScale(Scope.Scale);
					__instance.GetZDO().Set("vargheim_statue_size", Scope.Multiplier);
					if (Scope.PaidStone >= 0)
					{
						__instance.GetZDO().Set("vargheim_statue_stone_paid", Scope.PaidStone);
					}
					if (Scope.PaidWood >= 0)
					{
						__instance.GetZDO().Set("vargheim_statue_wood_paid", Scope.PaidWood);
					}
				}
			}
		}

		internal static Workshop Instance;

		internal static ConfigEntry<KeyCode> CycleKey;

		internal static ConfigEntry<float> OdinHeight;

		internal static ConfigEntry<float> OtherRatio;

		internal static ConfigEntry<float> Lod1At;

		internal static ConfigEntry<float> Lod2At;

		internal static ConfigEntry<float> CullAt;

		internal static ConfigEntry<bool> UseLods;

		internal static readonly Dictionary<string, StatueInfo> Prefabs = new Dictionary<string, StatueInfo>(StringComparer.Ordinal);

		internal static readonly Dictionary<string, int> Selection = new Dictionary<string, int>(StringComparer.Ordinal);

		internal static readonly string[] Labels = new string[4] { "Small", "Standard", "Large", "Monument" };

		internal static readonly float[] Multipliers = new float[4] { 0.4f, 1f, 1.5f, 2f };

		internal static readonly FieldInfo GhostField = AccessTools.Field(typeof(Player), "m_placementGhost");

		internal static string HudText;

		[ThreadStatic]
		internal static Placement Scope;

		private Harmony patches;

		internal void LoggerForImport(string message)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)message);
		}

		private void Awake()
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Expected O, but got Unknown
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Expected O, but got Unknown
			Instance = this;
			CycleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Placement", "CycleSizeKey", (KeyCode)287, "Cycle statue size while placing it. One hammer entry per statue.");
			OdinHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Collection", "OdinStandardHeight", 10f, new ConfigDescription("Odin's Standard figure height in metres, excluding its own base.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
			OtherRatio = ((BaseUnityPlugin)this).Config.Bind<float>("Collection", "OtherStatueHeightRatio", 0.82f, new ConfigDescription("Other statues' height relative to Odin at the same size setting.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 0.99f), Array.Empty<object>()));
			Lod1At = ((BaseUnityPlugin)this).Config.Bind<float>("Detail", "Lod1ScreenHeight", 0.1f, new ConfigDescription("Whole statue's share of screen height below which parts switch to the first distance model (all parts of one statue switch together). Restart to apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.9f), Array.Empty<object>()));
			Lod2At = ((BaseUnityPlugin)this).Config.Bind<float>("Detail", "Lod2ScreenHeight", 0.04f, new ConfigDescription("Share of screen height below which parts switch to the coarse distance model. Restart to apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.005f, 0.5f), Array.Empty<object>()));
			CullAt = ((BaseUnityPlugin)this).Config.Bind<float>("Detail", "HideBelowScreenHeight", 0.006f, new ConfigDescription("Share of screen height below which the statue is not drawn. Restart to apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.1f), Array.Empty<object>()));
			UseLods = ((BaseUnityPlugin)this).Config.Bind<bool>("Detail", "UseDistanceModels", true, "Swap to lighter models at a distance. Turn off if statue parts do not show; full detail is then always drawn. Restart to apply.");
			patches = new Harmony("digi.vargheim.statueworkshop");
			Type type = AccessTools.TypeByName("VargheimStatues.Carve");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "MakePiece", (Type[])null, (Type[])null));
			if (methodInfo == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Compatible VargheimStatues MakePiece method not found; workshop disabled.");
				return;
			}
			Type type2 = AccessTools.TypeByName("VargheimStatues.ObjModel");
			MethodInfo methodInfo2 = ((type2 == null) ? null : AccessTools.Method(type2, "Parse", new Type[2]
			{
				typeof(string[]),
				typeof(string)
			}, (Type[])null));
			if (methodInfo2 == null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Compatible OBJ import method not found; workshop disabled.");
				return;
			}
			patches.Patch((MethodBase)methodInfo2, new HarmonyMethod(typeof(WorkshopObjImport), "Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			patches.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Workshop), "BuiltStatue", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			patches.PatchAll(typeof(Workshop).Assembly);
			CollectionRegistration.Register();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Statue Workshop 0.3.12 ready: F6 cycles sizes; Odin is tallest at matching sizes. Fresh-server configuration.");
		}

		private void OnDestroy()
		{
			if (patches != null)
			{
				patches.UnpatchSelf();
			}
		}

		private void OnGUI()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(HudText))
			{
				GameObject val = (GameObject)(((Object)(object)Player.m_localPlayer == (Object)null || GhostField == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if (!((Object)(object)val == (Object)null) && val.activeInHierarchy)
				{
					GUI.Box(new Rect((float)Screen.width * 0.5f - 200f, (float)Screen.height * 0.73f, 400f, 30f), HudText);
				}
			}
		}

		internal static string Canonical(string n)
		{
			return (n ?? "").Replace("(Clone)", "").Trim();
		}

		internal static bool IsStatue(GameObject go)
		{
			if ((Object)(object)go != (Object)null)
			{
				return Canonical(((Object)go).name).StartsWith("VargheimStatue_", StringComparison.Ordinal);
			}
			return false;
		}

		internal static int Selected(string key)
		{
			if (!Selection.TryGetValue(key, out var value))
			{
				return 1;
			}
			return value;
		}

		internal static float NativeHeight(float tweak)
		{
			Type type = AccessTools.TypeByName("VargheimStatues.Plugin");
			FieldInfo fieldInfo = ((type == null) ? null : AccessTools.Field(type, "Height"));
			return Mathf.Max(0.01f, (((fieldInfo == null) ? null : (fieldInfo.GetValue(null) as ConfigEntry<float>))?.Value ?? 10f) * tweak);
		}

		private static void BuiltStatue(GameObject __result, string key, string creature, float tweak)
		{
			//IL_0086: 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_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__result == (Object)null)
			{
				return;
			}
			try
			{
				float num = NativeHeight(tweak);
				AssetSpec assetSpec = AssetFinish.ReadSpec(creature);
				bool num2 = AssetFinish.Apply(__result, creature);
				bool flag = ModularPieces.IsModule(assetSpec);
				bool flag2 = (flag ? assetSpec.family : key).IndexOf("odin", StringComparison.OrdinalIgnoreCase) >= 0;
				float num3 = OdinHeight.Value * (flag2 ? 1f : OtherRatio.Value);
				float num4 = (flag ? (assetSpec.figureHeight / assetSpec.assemblyHeight) : 1f);
				Transform transform = __result.transform;
				transform.localScale *= num3 / num * num4;
				ModularPieces.Configure(__result, assetSpec);
				ZNetView component = __result.GetComponent<ZNetView>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_syncInitialScale = true;
				}
				Prefabs[Canonical(((Object)__result).name)] = new StatueInfo
				{
					Name = Canonical(((Object)__result).name),
					StandardScale = __result.transform.localScale,
					StandardHeight = num3,
					SelectionKey = (flag ? ("family:" + assetSpec.family) : Canonical(((Object)__result).name)),
					IsModule = flag,
					StoneCost = (flag ? assetSpec.stoneCost : (-1)),
					WoodCost = (flag ? assetSpec.woodCost : (-1))
				};
				if (num2)
				{
					RefreshIcon(__result, key);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("Statue asset setup failed for " + key + ": " + ex));
			}
		}

		private static void RefreshIcon(GameObject piece, string key)
		{
			Type type = AccessTools.TypeByName("VargheimStatues.Icon");
			MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Render", new Type[2]
			{
				typeof(GameObject),
				typeof(string)
			}, (Type[])null));
			if (methodInfo == null)
			{
				return;
			}
			LODGroup componentInChildren = piece.GetComponentInChildren<LODGroup>();
			try
			{
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.ForceLOD(0);
				}
				object? obj = methodInfo.Invoke(null, new object[2] { piece, key });
				Sprite val = (Sprite)((obj is Sprite) ? obj : null);
				Piece component = piece.GetComponent<Piece>();
				if ((Object)(object)val != (Object)null && (Object)(object)component != (Object)null)
				{
					component.m_icon = val;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogWarning((object)("Statue icon refresh failed: " + ex.Message));
			}
			finally
			{
				if ((Object)(object)componentInChildren != (Object)null)
				{
					componentInChildren.ForceLOD(-1);
				}
			}
		}
	}
	[Serializable]
	public sealed class AssetSpec
	{
		public string family;

		public string pieceKind;

		public float assemblyHeight;

		public int stoneCost;

		public int woodCost;

		public SnapAnchor[] snaps;

		public bool ownBase;

		public float baseHeight;

		public float figureHeight;

		public string albedo;

		public string normal;

		public string metallicGloss;

		public string lod1;

		public string lod2;

		public string lod1Normal;

		public string lod2Normal;

		public string lod1Albedo;

		public string lod2Albedo;

		public string collision;

		public float smoothness = 0.04f;

		public float normalStrength = 0.3f;

		public float tintR = 1f;

		public float tintG = 1f;

		public float tintB = 1f;
	}
	internal static class AssetFinish
	{
		private static readonly Dictionary<string, Material> Materials = new Dictionary<string, Material>(StringComparer.OrdinalIgnoreCase);

		private static readonly Dictionary<string, Texture2D> Textures = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase);

		internal static AssetSpec ReadSpec(string model)
		{
			if (string.IsNullOrEmpty(model) || !model.EndsWith(".obj", StringComparison.OrdinalIgnoreCase))
			{
				return null;
			}
			string[] array = ModelFiles.Find(Path.GetFileName(model) + ".statue.json");
			if (array.Length == 0)
			{
				return null;
			}
			if (array.Length != 1)
			{
				throw new InvalidDataException("Ambiguous statue finish metadata for " + model);
			}
			return SpecReader.Asset(File.ReadAllText(array[0]));
		}

		internal static bool Apply(GameObject piece, string model)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Expected O, but got Unknown
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0441: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Unknown result type (might be due to invalid IL or missing references)
			//IL_044b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Unknown result type (might be due to invalid IL or missing references)
			//IL_047d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0482: Unknown result type (might be due to invalid IL or missing references)
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_051b: Unknown result type (might be due to invalid IL or missing references)
			//IL_053c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0548: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(model) || !model.EndsWith(".obj", StringComparison.OrdinalIgnoreCase))
			{
				return false;
			}
			string[] array = ModelFiles.Find(Path.GetFileName(model) + ".statue.json");
			if (array.Length == 0)
			{
				return false;
			}
			if (array.Length != 1)
			{
				throw new InvalidDataException("Ambiguous statue finish metadata for " + model);
			}
			string text = array[0];
			string directoryName = Path.GetDirectoryName(text);
			AssetSpec assetSpec = SpecReader.Asset(File.ReadAllText(text));
			if (assetSpec == null)
			{
				throw new InvalidDataException("Empty statue finish metadata");
			}
			Transform val = piece.transform.Find("statue_figure");
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidDataException("Statue figure transform missing");
			}
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
			if (!Materials.TryGetValue(text, out var value))
			{
				if (componentsInChildren.Length == 0)
				{
					throw new InvalidDataException("No figure renderer");
				}
				value = new Material(componentsInChildren[0].sharedMaterial);
				((Object)value).name = "Workshop carved stone";
				if (value.HasProperty("_Color"))
				{
					value.SetColor("_Color", new Color(assetSpec.tintR, assetSpec.tintG, assetSpec.tintB, 1f));
				}
				Texture2D val2 = LoadTexture(directoryName, assetSpec.albedo, linear: false);
				if ((Object)(object)val2 != (Object)null && value.HasProperty("_MainTex"))
				{
					value.SetTexture("_MainTex", (Texture)(object)val2);
					value.SetTextureScale("_MainTex", Vector2.one);
					value.SetTextureOffset("_MainTex", Vector2.zero);
				}
				Texture2D val3 = LoadTexture(directoryName, assetSpec.normal, linear: true);
				if ((Object)(object)val3 != (Object)null && value.HasProperty("_BumpMap"))
				{
					value.SetTexture("_BumpMap", (Texture)(object)val3);
					value.SetTextureScale("_BumpMap", Vector2.one);
					value.SetTextureOffset("_BumpMap", Vector2.zero);
					value.EnableKeyword("_NORMALMAP");
				}
				Float(value, "_BumpScale", Mathf.Clamp(assetSpec.normalStrength, 0f, 1f));
				Float(value, "_Metallic", 0f);
				Float(value, "_Glossiness", Mathf.Clamp01(assetSpec.smoothness));
				Float(value, "_Smoothness", Mathf.Clamp01(assetSpec.smoothness));
				Float(value, "_GlossMapScale", 1f);
				if (value.HasProperty("_MetallicGlossMap"))
				{
					Texture2D val4 = LoadTexture(directoryName, assetSpec.metallicGloss, linear: true);
					if ((Object)(object)val4 != (Object)null)
					{
						value.SetTexture("_MetallicGlossMap", (Texture)(object)val4);
						value.SetTextureScale("_MetallicGlossMap", Vector2.one);
						value.SetTextureOffset("_MetallicGlossMap", Vector2.zero);
					}
					else
					{
						Texture2D val5 = new Texture2D(1, 1, (TextureFormat)4, false, true);
						val5.SetPixel(0, 0, new Color(0f, 0f, 0f, Mathf.Clamp01(assetSpec.smoothness)));
						val5.Apply(false, true);
						value.SetTexture("_MetallicGlossMap", (Texture)(object)val5);
					}
				}
				if (value.HasProperty("_SpecColor"))
				{
					value.SetColor("_SpecColor", new Color(0.03f, 0.03f, 0.03f, 1f));
				}
				Materials[text] = value;
			}
			Renderer[] array2 = componentsInChildren;
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i].sharedMaterial = value;
			}
			if (assetSpec.ownBase || ModularPieces.IsModule(assetSpec))
			{
				if (assetSpec.figureHeight <= 0f || (!ModularPieces.IsModule(assetSpec) && assetSpec.baseHeight <= 0f))
				{
					throw new InvalidDataException("Own-base dimensions must be positive");
				}
				Transform[] componentsInChildren2 = piece.GetComponentsInChildren<Transform>(true);
				foreach (Transform val6 in componentsInChildren2)
				{
					if (((Object)val6).name.StartsWith("statue_plinth", StringComparison.Ordinal))
					{
						((Component)val6).gameObject.SetActive(false);
					}
				}
				if (ModularPieces.IsModule(assetSpec))
				{
					val.localPosition = new Vector3(0f, val.localPosition.y, 0f);
				}
				Bounds val7 = LocalBounds(piece.transform, val);
				float num = assetSpec.figureHeight + assetSpec.baseHeight;
				if (!ModularPieces.IsModule(assetSpec))
				{
					val.localScale *= num / assetSpec.figureHeight;
				}
				val7 = LocalBounds(piece.transform, val);
				val.localPosition -= new Vector3(0f, ((Bounds)(ref val7)).min.y, 0f);
				val7 = LocalBounds(piece.transform, val);
				if (!string.IsNullOrEmpty(assetSpec.collision))
				{
					AddCollision(piece, componentsInChildren, directoryName, assetSpec.collision);
					BoxCollider obj = piece.AddComponent<BoxCollider>();
					obj.center = new Vector3(((Bounds)(ref val7)).center.x, ((Bounds)(ref val7)).min.y + 0.03f, ((Bounds)(ref val7)).center.z);
					obj.size = new Vector3(Mathf.Max(0.05f, ((Bounds)(ref val7)).size.x * 0.6f), 0.06f, Mathf.Max(0.05f, ((Bounds)(ref val7)).size.z * 0.6f));
				}
				else
				{
					BoxCollider[] components = piece.GetComponents<BoxCollider>();
					foreach (BoxCollider obj2 in components)
					{
						obj2.center = ((Bounds)(ref val7)).center;
						obj2.size = ((Bounds)(ref val7)).size;
					}
				}
			}
			AddLods(val, componentsInChildren, value, assetSpec, directoryName, text);
			return true;
		}

		private static void AddCollision(GameObject piece, Renderer[] renderers, string dir, string model)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			if (renderers.Length != 1)
			{
				throw new InvalidDataException("Workshop collision requires one primary mesh renderer");
			}
			if (Path.GetFileName(model) != model)
			{
				throw new InvalidDataException("Collision must be a model filename");
			}
			Mesh val = LoadModel(model);
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidDataException("Could not load statue collision " + model);
			}
			GameObject val2 = new GameObject("workshop_collision")
			{
				layer = piece.layer
			};
			Transform transform = ((Component)renderers[0]).transform;
			val2.transform.SetParent(transform.parent, false);
			val2.transform.localPosition = transform.localPosition;
			val2.transform.localRotation = transform.localRotation;
			val2.transform.localScale = transform.localScale;
			MeshCollider obj = val2.AddComponent<MeshCollider>();
			obj.convex = false;
			obj.sharedMesh = val;
			BoxCollider[] components = piece.GetComponents<BoxCollider>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)components[i]);
			}
			Workshop.Instance.LoggerForImport("Installed fitted static collision: " + val.triangles.Length / 3 + " triangles.");
		}

		private static Mesh LoadModel(string model)
		{
			Type type = AccessTools.TypeByName("VargheimStatues.ObjModel");
			MethodInfo obj = ((type == null) ? null : AccessTools.Method(type, "Load", new Type[1] { typeof(string) }, (Type[])null));
			if (obj == null)
			{
				throw new MissingMethodException("Statue model loader unavailable");
			}
			object? obj2 = obj.Invoke(null, new object[1] { model });
			return (Mesh)((obj2 is Mesh) ? obj2 : null);
		}

		private static void AddLods(Transform figure, Renderer[] renderers, Material mat, AssetSpec spec, string dir, string file)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(spec.lod1) || !Workshop.UseLods.Value)
			{
				return;
			}
			if (renderers.Length != 1)
			{
				throw new InvalidDataException("Workshop LODs require one primary mesh renderer");
			}
			string[] array = new string[2] { spec.lod1, spec.lod2 };
			string[] array2 = new string[2] { spec.lod1Normal, spec.lod2Normal };
			string[] array3 = new string[2] { spec.lod1Albedo, spec.lod2Albedo };
			float value = Workshop.Lod1At.Value;
			float num = Mathf.Min(Workshop.Lod2At.Value, value * 0.9f);
			float num2 = Mathf.Min(Workshop.CullAt.Value, num * 0.9f);
			List<LOD> list = new List<LOD>();
			list.Add(new LOD(value, renderers));
			float[] array4 = new float[2] { num, num2 };
			for (int i = 0; i < array.Length; i++)
			{
				if (!string.IsNullOrEmpty(array[i]))
				{
					if (Path.GetFileName(array[i]) != array[i])
					{
						throw new InvalidDataException("LOD must be a model filename");
					}
					Mesh val = LoadModel(array[i]);
					if ((Object)(object)val == (Object)null)
					{
						throw new InvalidDataException("Could not load statue LOD " + array[i]);
					}
					GameObject val2 = new GameObject("workshop_lod" + (i + 1))
					{
						layer = ((Component)renderers[0]).gameObject.layer
					};
					val2.transform.SetParent(((Component)renderers[0]).transform.parent, false);
					val2.transform.localPosition = ((Component)renderers[0]).transform.localPosition;
					val2.transform.localRotation = ((Component)renderers[0]).transform.localRotation;
					val2.transform.localScale = ((Component)renderers[0]).transform.localScale;
					val2.AddComponent<MeshFilter>().sharedMesh = val;
					MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
					((Renderer)val3).sharedMaterial = LodMaterial(mat, spec, dir, file, i + 1, array2[i], array3[i]);
					((Renderer)val3).shadowCastingMode = renderers[0].shadowCastingMode;
					list.Add(new LOD((i + 1 < array.Length && !string.IsNullOrEmpty(array[i + 1])) ? array4[i] : num2, (Renderer[])(object)new Renderer[1] { (Renderer)val3 }));
				}
			}
			if (list.Count == 1)
			{
				return;
			}
			LODGroup val4 = ((Component)figure).gameObject.AddComponent<LODGroup>();
			val4.SetLODs(list.ToArray());
			Bounds val5 = LocalBounds(figure, figure);
			val4.localReferencePoint = ((Bounds)(ref val5)).center;
			val4.size = Mathf.Max(((Bounds)(ref val5)).size.x, Mathf.Max(((Bounds)(ref val5)).size.y, ((Bounds)(ref val5)).size.z));
			if (ModularPieces.IsModule(spec) && spec.figureHeight > 0f && spec.assemblyHeight > spec.figureHeight)
			{
				Bounds val6 = LocalBounds(figure, figure);
				float y = ((Bounds)(ref val6)).size.y;
				if (y > 0f)
				{
					val4.size = Mathf.Max(val4.size, y * spec.assemblyHeight / spec.figureHeight);
				}
			}
		}

		private static Material LodMaterial(Material full, AssetSpec spec, string dir, string file, int level, string normal, string albedo)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(normal) && string.IsNullOrEmpty(albedo))
			{
				return full;
			}
			string key = file + "#lod" + level;
			if (Materials.TryGetValue(key, out var value))
			{
				return value;
			}
			value = new Material(full);
			((Object)value).name = "Workshop carved stone LOD" + level;
			bool flag = !string.IsNullOrEmpty(albedo);
			if (flag)
			{
				Texture2D val = LoadTexture(dir, albedo, linear: false);
				if (value.HasProperty("_MainTex"))
				{
					value.SetTexture("_MainTex", (Texture)(object)val);
				}
				if (value.HasProperty("_MetallicGlossMap"))
				{
					Texture2D val2 = new Texture2D(1, 1, (TextureFormat)4, false, true);
					val2.SetPixel(0, 0, new Color(0f, 0f, 0f, Mathf.Clamp01(spec.smoothness)));
					val2.Apply(false, true);
					value.SetTexture("_MetallicGlossMap", (Texture)(object)val2);
				}
			}
			if (!string.IsNullOrEmpty(normal))
			{
				if (value.HasProperty("_BumpMap"))
				{
					value.SetTexture("_BumpMap", (Texture)(object)LoadTexture(dir, normal, linear: true));
					value.EnableKeyword("_NORMALMAP");
				}
			}
			else if (flag)
			{
				if (value.HasProperty("_BumpMap"))
				{
					value.SetTexture("_BumpMap", (Texture)null);
				}
				value.DisableKeyword("_NORMALMAP");
				Float(value, "_BumpScale", 0f);
			}
			Materials[key] = value;
			return value;
		}

		private static Bounds LocalBounds(Transform root, Transform figure)
		{
			//IL_0004: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0077: 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_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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)
			//IL_00a9: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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)
			bool flag = true;
			Bounds result = default(Bounds);
			MeshFilter[] componentsInChildren = ((Component)figure).GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val in componentsInChildren)
			{
				if ((Object)(object)val.sharedMesh == (Object)null)
				{
					continue;
				}
				Bounds bounds = val.sharedMesh.bounds;
				Matrix4x4 val2 = root.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(new Vector3(((j & 1) == 0) ? ((Bounds)(ref bounds)).min.x : ((Bounds)(ref bounds)).max.x, ((j & 2) == 0) ? ((Bounds)(ref bounds)).min.y : ((Bounds)(ref bounds)).max.y, ((j & 4) == 0) ? ((Bounds)(ref bounds)).min.z : ((Bounds)(ref bounds)).max.z));
					if (flag)
					{
						((Bounds)(ref result))..ctor(val3, Vector3.zero);
						flag = false;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val3);
					}
				}
			}
			if (flag)
			{
				throw new InvalidDataException("Figure has no mesh bounds");
			}
			return result;
		}

		private static void Float(Material mat, string name, float value)
		{
			if (mat.HasProperty(name))
			{
				mat.SetFloat(name, value);
			}
		}

		private static Texture2D LoadTexture(string dir, string name, bool linear)
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			string value = Path.GetFullPath(dir) + Path.DirectorySeparatorChar;
			string fullPath = Path.GetFullPath(Path.Combine(dir, name));
			if (!fullPath.StartsWith(value, StringComparison.OrdinalIgnoreCase))
			{
				throw new InvalidDataException("Asset texture escapes model folder");
			}
			if (!File.Exists(fullPath))
			{
				throw new FileNotFoundException("Statue texture missing", fullPath);
			}
			string key = fullPath + (linear ? "|lin" : "|srgb");
			if (Textures.TryGetValue(key, out var value2) && (Object)(object)value2 != (Object)null)
			{
				return value2;
			}
			value2 = new Texture2D(2, 2, (TextureFormat)4, true, linear);
			((Object)value2).name = Path.GetFileName(fullPath);
			if (!ImageConversion.LoadImage(value2, File.ReadAllBytes(fullPath), true))
			{
				throw new InvalidDataException("Invalid statue texture " + name);
			}
			((Texture)value2).wrapMode = (TextureWrapMode)1;
			((Texture)value2).filterMode = (FilterMode)2;
			((Texture)value2).anisoLevel = 4;
			Textures[key] = value2;
			return value2;
		}
	}
	internal static class WorkshopObjImport
	{
		private static bool Prefix(string[] __0, string __1, ref Mesh __result)
		{
			//IL_0069: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			if (!ObjData.IsWorkshop(__0))
			{
				return true;
			}
			ObjData objData = ObjData.Parse(__0);
			List<Vector3> list = new List<Vector3>(objData.Positions.Count);
			List<Vector3> list2 = new List<Vector3>(objData.Normals.Count);
			List<Vector2> list3 = new List<Vector2>(objData.UVs.Count);
			foreach (float[] position in objData.Positions)
			{
				list.Add(new Vector3(position[0], position[1], position[2]));
			}
			foreach (float[] normal in objData.Normals)
			{
				list2.Add(new Vector3(normal[0], normal[1], normal[2]));
			}
			foreach (float[] uV in objData.UVs)
			{
				list3.Add(new Vector2(uV[0], uV[1]));
			}
			Mesh val = new Mesh();
			((Object)val).name = __1 + "_WorkshopUV";
			val.indexFormat = (IndexFormat)(list.Count > 65535);
			val.SetVertices(list);
			val.SetNormals(list2);
			val.SetUVs(0, list3);
			val.SetTriangles(objData.Indices, 0);
			val.RecalculateBounds();
			val.RecalculateTangents();
			__result = val;
			Workshop.Instance.LoggerForImport("Imported " + __1 + " with authored UVs: " + list.Count + " vertices, " + objData.Indices.Count / 3 + " triangles.");
			return false;
		}
	}
}