Decompiled source of NH VLCEJesterArmor v1.0.0

plugins/NH_VLCEJesterArmor/NH_VLCEJesterArmor.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("NH_VLCEJesterArmor")]
[assembly: AssemblyProduct("NH VLCE Jester Armor")]
[assembly: AssemblyDescription("Nostalgia Heroes - VLCE Jester Helm/Armor/Legguards, iron-tier armor with vanilla iron recipes and stats (conditional body hiding)")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace NH_VLCEJesterArmor;

public static class BodyHider
{
	private sealed class Classified
	{
		public int[][] Tris;

		public byte[][] Region;

		public bool Ok;

		public string Info;
	}

	private const int HEAD = 1;

	private const int TORSO = 2;

	private const int LEGS = 4;

	private static readonly int HelmHash = StringExtensionMethods.GetStableHashCode("NH_VLCEJesterHelm");

	private static readonly int ChestHash = StringExtensionMethods.GetStableHashCode("NH_VLCEJesterArmor");

	private static readonly int LegsHash = StringExtensionMethods.GetStableHashCode("NH_VLCEJesterLegguards");

	private static readonly FieldRef<VisEquipment, int> fHelm = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentHelmetItemHash");

	private static readonly FieldRef<VisEquipment, int> fChest = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentChestItemHash");

	private static readonly FieldRef<VisEquipment, int> fLegs = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentLegItemHash");

	private static readonly FieldRef<VisEquipment, int> fModelIndex = AccessTools.FieldRefAccess<VisEquipment, int>("m_modelIndex");

	private static readonly FieldRef<VisEquipment, int> fCurModelIndex = AccessTools.FieldRefAccess<VisEquipment, int>("m_currentModelIndex");

	private static readonly FieldRef<VisEquipment, ZNetView> fNview = AccessTools.FieldRefAccess<VisEquipment, ZNetView>("m_nview");

	private static readonly Dictionary<Mesh, Classified> classified = new Dictionary<Mesh, Classified>();

	private static readonly Dictionary<long, Mesh> variants = new Dictionary<long, Mesh>();

	private static readonly Dictionary<Mesh, Mesh> variantSource = new Dictionary<Mesh, Mesh>();

	private static readonly Dictionary<Mesh, int> variantMask = new Dictionary<Mesh, int>();

	private static readonly Dictionary<int, int> lastLoggedMask = new Dictionary<int, int>();

	private static readonly HashSet<Mesh> warned = new HashSet<Mesh>();

	private static Transform[] bonesForClassify;

	private static int Region(string bone)
	{
		switch (bone)
		{
		case "Neck":
		case "Head":
		case "Jaw":
			return 1;
		default:
			if (!bone.EndsWith("UpLeg") && !bone.EndsWith("Leg") && !bone.EndsWith("Foot") && !bone.EndsWith("ToeBase"))
			{
				if (bone.StartsWith("Spine") || bone.EndsWith("Shoulder") || bone.EndsWith("Arm") || bone.Contains("Hand"))
				{
					return 2;
				}
				return 0;
			}
			goto case "Hips";
		case "Hips":
			return 4;
		}
	}

	private static int ModelNum(VisEquipment ve)
	{
		int result = fModelIndex.Invoke(ve);
		ZNetView val = fNview.Invoke(ve);
		if ((Object)(object)val != (Object)null && val.GetZDO() != null)
		{
			result = val.GetZDO().GetInt(ZDOVars.s_modelIndex, 0);
		}
		return result;
	}

	[HarmonyPatch(typeof(VisEquipment), "UpdateBaseModel")]
	[HarmonyPrefix]
	private static bool UpdateBaseModel_Prefix(VisEquipment __instance)
	{
		try
		{
			SkinnedMeshRenderer bodyModel = __instance.m_bodyModel;
			if (!Object.op_Implicit((Object)(object)bodyModel) || __instance.m_models == null || __instance.m_models.Length == 0)
			{
				return true;
			}
			Mesh sharedMesh = bodyModel.sharedMesh;
			if (!Object.op_Implicit((Object)(object)sharedMesh) || !variantSource.TryGetValue(sharedMesh, out var value))
			{
				return true;
			}
			int num = ModelNum(__instance);
			if (num < 0 || num >= __instance.m_models.Length)
			{
				return true;
			}
			return fCurModelIndex.Invoke(__instance) != num || !((Object)(object)__instance.m_models[num].m_mesh == (Object)(object)value);
		}
		catch
		{
			return true;
		}
	}

	[HarmonyPatch(typeof(VisEquipment), "UpdateEquipmentVisuals")]
	[HarmonyPostfix]
	private static void UpdateEquipmentVisuals_Postfix(VisEquipment __instance)
	{
		try
		{
			if (!__instance.m_isPlayer || __instance.m_isArmorStand)
			{
				return;
			}
			SkinnedMeshRenderer bodyModel = __instance.m_bodyModel;
			if (!Object.op_Implicit((Object)(object)bodyModel))
			{
				return;
			}
			int num = 0;
			if (Plugin.bodyHiding == null || Plugin.bodyHiding.Value)
			{
				num = (int)(((fHelm.Invoke(__instance) == HelmHash) ? 1u : 0u) | (uint)((fChest.Invoke(__instance) == ChestHash) ? 2 : 0)) | ((fLegs.Invoke(__instance) == LegsHash) ? 4 : 0);
			}
			Mesh sharedMesh = bodyModel.sharedMesh;
			if (!Object.op_Implicit((Object)(object)sharedMesh))
			{
				return;
			}
			if (!variantSource.TryGetValue(sharedMesh, out var value))
			{
				value = sharedMesh;
			}
			if (num == 0 && (Object)(object)value == (Object)(object)sharedMesh)
			{
				return;
			}
			Mesh val = ((num == 0) ? value : GetVariant(value, num));
			if (Object.op_Implicit((Object)(object)val) && (Object)(object)sharedMesh != (Object)(object)val)
			{
				bodyModel.sharedMesh = val;
				int instanceID = ((Object)__instance).GetInstanceID();
				if (!lastLoggedMask.TryGetValue(instanceID, out var value2) || value2 != num)
				{
					lastLoggedMask[instanceID] = num;
					Plugin.Log.LogInfo((object)("NHVJ body: " + ((Object)__instance).name + " mask=" + MaskName(num) + " -> body mesh '" + ((Object)val).name + "' (" + Tris(val) + " tris, original '" + ((Object)value).name + "' " + Tris(value) + ")"));
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("NHVJ body: " + ex));
		}
	}

	private static string MaskName(int m)
	{
		if (m != 0)
		{
			return (((m & 1) != 0) ? "head " : "") + (((m & 2) != 0) ? "torso+arms+hands " : "") + (((m & 4) != 0) ? "hips+legs+feet" : "");
		}
		return "none";
	}

	private static long Tris(Mesh m)
	{
		long num = 0L;
		for (int i = 0; i < m.subMeshCount; i++)
		{
			num += m.GetIndexCount(i) / 3;
		}
		return num;
	}

	private static Classified Classify(Mesh src, Transform[] bones)
	{
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		if (classified.TryGetValue(src, out var value))
		{
			return value;
		}
		value = new Classified();
		Mesh val = (src.isReadable ? src : null);
		if (!Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)Plugin.BodyTemplate) && Compatible(Plugin.BodyTemplate, src))
		{
			val = Plugin.BodyTemplate;
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			value.Info = "mesh '" + ((Object)src).name + "' not CPU-readable and does not match the bundled template (" + src.vertexCount + " verts) -> body hiding unavailable for this model";
			classified[src] = value;
			return value;
		}
		BoneWeight[] boneWeights = val.boneWeights;
		string[] names = bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "" : ((Object)b).name).ToArray();
		float[,] array = new float[val.vertexCount, 5];
		for (int num = 0; num < boneWeights.Length; num++)
		{
			BoneWeight val2 = boneWeights[num];
			Add(array, num, names, ((BoneWeight)(ref val2)).boneIndex0, ((BoneWeight)(ref val2)).weight0);
			Add(array, num, names, ((BoneWeight)(ref val2)).boneIndex1, ((BoneWeight)(ref val2)).weight1);
			Add(array, num, names, ((BoneWeight)(ref val2)).boneIndex2, ((BoneWeight)(ref val2)).weight2);
			Add(array, num, names, ((BoneWeight)(ref val2)).boneIndex3, ((BoneWeight)(ref val2)).weight3);
		}
		value.Tris = new int[val.subMeshCount][];
		value.Region = new byte[val.subMeshCount][];
		int[] array2 = new int[5];
		for (int num2 = 0; num2 < val.subMeshCount; num2++)
		{
			int[] triangles = val.GetTriangles(num2);
			value.Tris[num2] = triangles;
			byte[] array3 = new byte[triangles.Length / 3];
			value.Region[num2] = array3;
			for (int num3 = 0; num3 < array3.Length; num3++)
			{
				int num4 = 0;
				float num5 = 0f;
				int[] array4 = new int[3] { 1, 2, 4 };
				foreach (int num7 in array4)
				{
					float num8 = array[triangles[num3 * 3], Idx(num7)] + array[triangles[num3 * 3 + 1], Idx(num7)] + array[triangles[num3 * 3 + 2], Idx(num7)];
					if (num8 > num5)
					{
						num5 = num8;
						num4 = num7;
					}
				}
				array3[num3] = (byte)num4;
				array2[Idx(num4)]++;
			}
		}
		value.Ok = true;
		value.Info = "mesh '" + ((Object)src).name + "' (" + (((Object)(object)val == (Object)(object)src) ? "readable" : "via bundled template") + ") tris: head=" + array2[Idx(1)] + " torso+arms+hands=" + array2[Idx(2)] + " hips+legs+feet=" + array2[Idx(4)] + " unclassified=" + array2[0];
		classified[src] = value;
		return value;
	}

	private static int Idx(int r)
	{
		return r switch
		{
			4 => 3, 
			2 => 2, 
			1 => 1, 
			_ => 0, 
		};
	}

	private static void Add(float[,] vreg, int v, string[] names, int bi, float w)
	{
		if (!(w <= 0f) && bi >= 0 && bi < names.Length)
		{
			vreg[v, Idx(Region(names[bi]))] += w;
		}
	}

	private static bool Compatible(Mesh t, Mesh m)
	{
		if (t.vertexCount != m.vertexCount || t.subMeshCount != m.subMeshCount)
		{
			return false;
		}
		for (int i = 0; i < t.subMeshCount; i++)
		{
			if (t.GetIndexCount(i) != m.GetIndexCount(i))
			{
				return false;
			}
		}
		return true;
	}

	private static Mesh GetVariant(Mesh src, int mask)
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		long key = ((long)((Object)src).GetInstanceID() << 8) | (uint)mask;
		if (variants.TryGetValue(key, out var value) && Object.op_Implicit((Object)(object)value))
		{
			return value;
		}
		if (bonesForClassify == null)
		{
			return null;
		}
		Classified classified = Classify(src, bonesForClassify);
		if (!classified.Ok)
		{
			if (warned.Add(src))
			{
				Plugin.Log.LogWarning((object)("NHVJ body: " + classified.Info));
			}
			return src;
		}
		Mesh val = (src.isReadable ? src : Plugin.BodyTemplate);
		value = Object.Instantiate<Mesh>(val);
		((Object)value).name = ((Object)src).name + "_NHVJ_" + mask;
		Bounds bounds = src.bounds;
		int num = 0;
		for (int i = 0; i < classified.Tris.Length; i++)
		{
			int[] array = classified.Tris[i];
			byte[] array2 = classified.Region[i];
			List<int> list = new List<int>(array.Length);
			for (int j = 0; j < array2.Length; j++)
			{
				if (array2[j] != 0 && (array2[j] & mask) != 0)
				{
					num++;
					continue;
				}
				list.Add(array[j * 3]);
				list.Add(array[j * 3 + 1]);
				list.Add(array[j * 3 + 2]);
			}
			value.SetTriangles(list, i, false);
		}
		value.bounds = bounds;
		value.UploadMeshData(false);
		variants[key] = value;
		variantSource[value] = src;
		variantMask[value] = mask;
		Plugin.Log.LogInfo((object)("NHVJ body: built variant '" + ((Object)value).name + "' hidden " + num + " tris (" + MaskName(mask) + "); " + classified.Info));
		return value;
	}

	[HarmonyPatch(typeof(VisEquipment), "Awake")]
	[HarmonyPostfix]
	private static void Awake_Postfix(VisEquipment __instance)
	{
		if (bonesForClassify == null && __instance.m_isPlayer && Object.op_Implicit((Object)(object)__instance.m_bodyModel) && __instance.m_bodyModel.bones.Length == 53)
		{
			bonesForClassify = __instance.m_bodyModel.bones.ToArray();
		}
	}

	internal static void SelfTest(GameObject playerPrefab)
	{
		if (!Object.op_Implicit((Object)(object)playerPrefab))
		{
			Plugin.Log.LogWarning((object)"NHVJ body selftest: Player prefab not found");
			return;
		}
		VisEquipment component = playerPrefab.GetComponent<VisEquipment>();
		if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.m_bodyModel))
		{
			Plugin.Log.LogWarning((object)"NHVJ body selftest: Player VisEquipment/body missing");
			return;
		}
		SkinnedMeshRenderer bodyModel = component.m_bodyModel;
		Plugin.Log.LogInfo((object)("NHVJ body selftest: body renderer '" + ((Object)bodyModel).name + "' bones=" + bodyModel.bones.Length + " rootBone=" + (Object.op_Implicit((Object)(object)bodyModel.rootBone) ? ((Object)bodyModel.rootBone).name : "<null>") + " sharedMesh='" + (Object.op_Implicit((Object)(object)bodyModel.sharedMesh) ? ((Object)bodyModel.sharedMesh).name : "<null>") + "' models=" + ((component.m_models != null) ? component.m_models.Length : 0) + " template=" + (Object.op_Implicit((Object)(object)Plugin.BodyTemplate) ? (Plugin.BodyTemplate.vertexCount + " verts") : "<none>")));
		if (bonesForClassify == null)
		{
			bonesForClassify = bodyModel.bones.ToArray();
		}
		List<Mesh> list = (from m in (IEnumerable<PlayerModel>)(((object)component.m_models) ?? ((object)new PlayerModel[0]))
			select m.m_mesh into m
			where Object.op_Implicit((Object)(object)m)
			select m).ToList();
		if (list.Count == 0 && Object.op_Implicit((Object)(object)bodyModel.sharedMesh))
		{
			list.Add(bodyModel.sharedMesh);
		}
		foreach (Mesh item in list)
		{
			Plugin.Log.LogInfo((object)("NHVJ body selftest: model mesh '" + ((Object)item).name + "' verts=" + item.vertexCount + " submeshes=" + item.subMeshCount + " tris=" + Tris(item) + " readable=" + item.isReadable + " templateCompatible=" + (Object.op_Implicit((Object)(object)Plugin.BodyTemplate) && Compatible(Plugin.BodyTemplate, item))));
			for (int num = 1; num <= 7; num++)
			{
				GetVariant(item, num);
			}
		}
	}
}
[BepInPlugin("com.nostalgiaheroes.vlcejesterarmor", "NH VLCE Jester Armor", "1.0.0")]
[BepInDependency("com.jotunn.jotunn", "2.30.2")]
public sealed class Plugin : BaseUnityPlugin
{
	private sealed class Garment
	{
		public string Item;

		public string BaseItem;

		public string StatsFrom;

		public string DisplayName;

		public string Description;

		public int MinStationLevel;

		public GameObject Visual;

		public GameObject Drop;

		public Sprite Icon;

		public CustomRecipe Recipe;
	}

	public const string PluginGUID = "com.nostalgiaheroes.vlcejesterarmor";

	public const string PluginName = "NH VLCE Jester Armor";

	public const string PluginVersion = "1.0.0";

	private const string BundleFile = "nh_vlcejesterarmor";

	public const string HelmId = "NH_VLCEJesterHelm";

	public const string ChestId = "NH_VLCEJesterArmor";

	public const string LegsId = "NH_VLCEJesterLegguards";

	internal static Plugin Instance;

	internal static ManualLogSource Log;

	private readonly Garment[] garments = new Garment[3]
	{
		new Garment
		{
			Item = "NH_VLCEJesterHelm",
			BaseItem = "HelmetBronze",
			StatsFrom = "HelmetIron",
			MinStationLevel = 1,
			DisplayName = "VLCE Jester Helm",
			Description = "A black and bronze jester helm veined with purple chaos fissures. Protects like an iron helmet."
		},
		new Garment
		{
			Item = "NH_VLCEJesterArmor",
			BaseItem = "ArmorBronzeChest",
			StatsFrom = "ArmorIronChest",
			MinStationLevel = 2,
			DisplayName = "VLCE Jester Armor",
			Description = "Black and bronze jester armor with gauntlets, veined with purple chaos fissures. Protects like iron scale mail."
		},
		new Garment
		{
			Item = "NH_VLCEJesterLegguards",
			BaseItem = "ArmorBronzeLegs",
			StatsFrom = "ArmorIronLegs",
			MinStationLevel = 2,
			DisplayName = "VLCE Jester Legguards",
			Description = "Black and bronze jester legguards and boots, veined with purple chaos fissures. Protects like iron greaves."
		}
	};

	private ConfigEntry<bool> useVanillaShader;

	private ConfigEntry<bool> hideHair;

	private ConfigEntry<bool> hideBeard;

	internal static ConfigEntry<bool> bodyHiding;

	private ConfigEntry<float> baseSmooth;

	private ConfigEntry<float> metalSmooth;

	private ConfigEntry<float> metallic;

	private ConfigEntry<float> albedoMul;

	private AssetBundle bundle;

	internal static Mesh BodyTemplate;

	private readonly List<Material> runtimeMaterials = new List<Material>();

	private Harmony harmony;

	private Bounds? removedVisualBounds;

	private void Awake()
	{
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ad: Expected O, but got Unknown
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		try
		{
			useVanillaShader = ((BaseUnityPlugin)this).Config.Bind<bool>("Visual", "UseVanillaArmorShader", true, "true: Custom/Creature copy of the vanilla armor material (matte values below). false: bundled Unity Standard materials. Restart required.");
			baseSmooth = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "BaseSmoothness", 0.12f, "Custom/Creature _Glossiness (black armor / leather / purple). 0.12 = roughness 0.88. Restart required.");
			metalSmooth = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "MetalSmoothness", 0.45f, "Custom/Creature _MetalGloss (bronze areas of the metal mask). 0.45 = roughness 0.55. Restart required.");
			metallic = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "Metallic", 0.5f, "Custom/Creature _Metallic (multiplies the bronze metal mask; black areas are 0 in the mask). Restart required.");
			albedoMul = ((BaseUnityPlugin)this).Config.Bind<float>("Visual", "AlbedoMultiply", 0.9f, "Grey multiply on the albedo (_Color). 1 = unchanged. Keep >= 0.8 so the purple fissures stay readable. Restart required.");
			hideHair = ((BaseUnityPlugin)this).Config.Bind<bool>("Helm", "HideHair", true, "Helm hides hair (vanilla m_helmetHideHair). Restart required.");
			hideBeard = ((BaseUnityPlugin)this).Config.Bind<bool>("Helm", "HideBeard", true, "Helm hides beard (vanilla m_helmetHideBeard). The helm also hides the head/face body geometry. Restart required.");
			bodyHiding = ((BaseUnityPlugin)this).Config.Bind<bool>("Body", "HideCoveredBody", true, "Hide covered vanilla body regions (helm: head/neck; armor: torso+arms+hands; legguards: hips+legs+feet). Takes effect on the next equipment change.");
			string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
			string text = Path.Combine(directoryName, "nh_vlcejesterarmor");
			if (!File.Exists(text))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: bundle missing: " + text));
				return;
			}
			bundle = AssetUtils.LoadAssetBundle(text);
			if (!Object.op_Implicit((Object)(object)bundle))
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: failed to load bundle " + text));
				return;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: bundle loaded: " + text + " assets=" + string.Join(", ", bundle.GetAllAssetNames())));
			GameObject val = bundle.LoadAsset<GameObject>("NH_VLCE_BodyTemplate");
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.GetComponent<MeshFilter>()))
			{
				BodyTemplate = val.GetComponent<MeshFilter>().sharedMesh;
				((Object)val).name = "NH_VLCE_BodyTemplateRuntime";
			}
			Garment[] array = garments;
			foreach (Garment garment in array)
			{
				garment.Visual = bundle.LoadAsset<GameObject>(garment.Item + "_Visual");
				garment.Drop = bundle.LoadAsset<GameObject>(garment.Item + "_Drop");
				garment.Icon = bundle.LoadAsset<Sprite>(garment.Item + "_Icon");
				if (!Object.op_Implicit((Object)(object)garment.Visual) || !Object.op_Implicit((Object)(object)garment.Drop))
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: bundle is missing visual/drop for " + garment.Item));
					continue;
				}
				((Object)garment.Visual).name = garment.Item + "_VisualRuntime";
				((Object)garment.Drop).name = garment.Item + "_DropRuntime";
				((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + garment.Item + " assets: visual=" + ((Object)garment.Visual).name + " drop=" + ((Object)garment.Drop).name + " icon=" + (Object.op_Implicit((Object)(object)garment.Icon) ? ((Object)garment.Icon).name : "<none>")));
			}
			harmony = new Harmony("com.nostalgiaheroes.vlcejesterarmor");
			harmony.PatchAll(typeof(BodyHider));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: Harmony patches: " + string.Join(", ", (from m in harmony.GetPatchedMethods()
				select m.DeclaringType.Name + "." + m.Name).ToArray())));
			PrefabManager.OnVanillaPrefabsAvailable += RegisterItems;
			ItemManager.OnItemsRegisteredFejd += OnItemsRegisteredFejd;
			ItemManager.OnItemsRegistered += OnItemsRegistered;
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: Awake failed: " + ex));
		}
	}

	private void RegisterItems()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterItems;
		Garment[] array = garments;
		foreach (Garment garment in array)
		{
			if (Object.op_Implicit((Object)(object)garment.Visual) && Object.op_Implicit((Object)(object)garment.Drop))
			{
				RegisterItem(garment);
			}
		}
		try
		{
			BodyHider.SelfTest(PrefabManager.Instance.GetPrefab("Player"));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: body-hiding self test failed: " + ex));
		}
	}

	private void RegisterItem(Garment g)
	{
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Expected O, but got Unknown
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Expected O, but got Unknown
		//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		CustomItem val = null;
		try
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab(g.BaseItem);
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				throw new InvalidOperationException("vanilla base prefab missing: " + g.BaseItem);
			}
			if (Object.op_Implicit((Object)(object)PrefabManager.Instance.GetPrefab(g.Item)))
			{
				throw new InvalidOperationException("prefab name already taken: " + g.Item);
			}
			GameObject prefab2 = PrefabManager.Instance.GetPrefab(g.StatsFrom);
			ItemDrop val2 = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponent<ItemDrop>() : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				throw new InvalidOperationException("vanilla stats prefab missing: " + g.StatsFrom);
			}
			ItemConfig val3 = new ItemConfig();
			val3.Name = g.DisplayName;
			val3.Description = g.Description;
			val3.CraftingStation = "forge";
			val3.MinStationLevel = g.MinStationLevel;
			val3.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig
				{
					Item = "Iron",
					Amount = 20,
					AmountPerLevel = 5,
					Recover = true
				},
				new RequirementConfig
				{
					Item = "DeerHide",
					Amount = 2,
					AmountPerLevel = 0,
					Recover = true
				}
			};
			ItemConfig val4 = val3;
			if (Object.op_Implicit((Object)(object)g.Icon))
			{
				val4.Icons = (Sprite[])(object)new Sprite[1] { g.Icon };
			}
			val = new CustomItem(g.Item, g.BaseItem, val4);
			if (!Object.op_Implicit((Object)(object)val.ItemPrefab) || !Object.op_Implicit((Object)(object)val.ItemDrop))
			{
				throw new InvalidOperationException("failed to clone " + g.BaseItem);
			}
			SharedData shared = val.ItemDrop.m_itemData.m_shared;
			shared.m_armorMaterial = null;
			CopyVanillaStats(shared, val2.m_itemData.m_shared, g);
			if (g.Item == "NH_VLCEJesterHelm")
			{
				shared.m_helmetHideHair = (HelmetHairType)(hideHair.Value ? 1 : 0);
				shared.m_helmetHideBeard = (HelmetHairType)(hideBeard.Value ? 1 : 0);
			}
			Material[] mats = SwapWornVisual(val.ItemPrefab, g);
			SwapDropVisual(val.ItemPrefab, g, mats);
			if (Object.op_Implicit((Object)(object)g.Icon))
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { g.Icon };
			}
			if (val.Recipe == null || (Object)(object)val.Recipe.Recipe == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("NHVJ: " + g.Item + ": no recipe was created"));
			}
			g.Recipe = val.Recipe;
			if (!ItemManager.Instance.AddItem(val))
			{
				throw new InvalidOperationException("ItemManager rejected " + g.Item);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + " registered: '" + g.DisplayName + "' type=" + ((object)Unsafe.As<ItemType, ItemType>(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString() + " " + StatsText(shared) + " hideHair=" + ((object)Unsafe.As<HelmetHairType, HelmetHairType>(ref shared.m_helmetHideHair)/*cast due to .constrained prefix*/).ToString() + " hideBeard=" + ((object)Unsafe.As<HelmetHairType, HelmetHairType>(ref shared.m_helmetHideBeard)/*cast due to .constrained prefix*/).ToString() + " (stats from " + g.StatsFrom + ", fallback recipe forge " + g.MinStationLevel + ": Iron 20 (+5), DeerHide 2)"));
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: " + g.Item + " registration failed: " + ex));
			if (val != null && Object.op_Implicit((Object)(object)val.ItemPrefab))
			{
				Object.Destroy((Object)(object)val.ItemPrefab);
			}
		}
	}

	private Material[] SwapWornVisual(GameObject clone, Garment g)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Expected O, but got Unknown
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Expected O, but got Unknown
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Expected O, but got Unknown
		Material val = null;
		int layer = clone.layer;
		removedVisualBounds = null;
		List<Transform> list = new List<Transform>();
		foreach (Transform item2 in clone.transform)
		{
			Transform val2 = item2;
			if (((Object)val2).name == "attach" || ((Object)val2).name == "attach_skin")
			{
				list.Add(val2);
			}
		}
		foreach (Transform item3 in list)
		{
			Renderer componentInChildren = ((Component)item3).GetComponentInChildren<Renderer>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren) && Object.op_Implicit((Object)(object)componentInChildren.sharedMaterial) && !Object.op_Implicit((Object)(object)val))
			{
				val = componentInChildren.sharedMaterial;
			}
			layer = ((Component)item3).gameObject.layer;
			MeshFilter componentInChildren2 = ((Component)item3).GetComponentInChildren<MeshFilter>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren2) && Object.op_Implicit((Object)(object)componentInChildren2.sharedMesh) && !removedVisualBounds.HasValue)
			{
				removedVisualBounds = ToSpace(componentInChildren2.sharedMesh.bounds, clone.transform.worldToLocalMatrix * ((Component)componentInChildren2).transform.localToWorldMatrix);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + ": vanilla '" + ((Object)item3).name + "' activeSelf=" + ((Component)item3).gameObject.activeSelf));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + ": removing vanilla '" + ((Object)item3).name + "' (renderer " + (Object.op_Implicit((Object)(object)componentInChildren) ? (((Object)componentInChildren).name + " mat " + (Object.op_Implicit((Object)(object)componentInChildren.sharedMaterial) ? (((Object)componentInChildren.sharedMaterial).name + " [" + ((Object)componentInChildren.sharedMaterial.shader).name + "]") : "-")) : "-") + ")"));
			Object.DestroyImmediate((Object)(object)((Component)item3).gameObject);
		}
		if (!Object.op_Implicit((Object)(object)val) || ((Object)val.shader).name != "Custom/Creature")
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("ArmorBronzeChest");
			object obj;
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				obj = null;
			}
			else
			{
				Transform obj2 = prefab.transform.Find("attach_skin");
				obj = ((obj2 != null) ? ((Component)obj2).GetComponentInChildren<SkinnedMeshRenderer>(true) : null);
			}
			SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)obj;
			if (Object.op_Implicit((Object)(object)val3))
			{
				val = ((Renderer)val3).sharedMaterial;
			}
		}
		GameObject val4 = new GameObject("attach_skin");
		val4.transform.SetParent(clone.transform, false);
		val4.layer = layer;
		val4.SetActive(false);
		GameObject val5 = Object.Instantiate<GameObject>(g.Visual, clone.transform, false);
		Transform val6 = val5.transform.Find("attach_skin");
		if (!Object.op_Implicit((Object)(object)val6))
		{
			Object.DestroyImmediate((Object)(object)val5);
			throw new InvalidOperationException(g.Item + " visual has no attach_skin");
		}
		List<Transform> list2 = new List<Transform>();
		foreach (Transform item4 in val6)
		{
			Transform item = item4;
			list2.Add(item);
		}
		foreach (Transform item5 in list2)
		{
			item5.SetParent(val4.transform, false);
		}
		Object.DestroyImmediate((Object)(object)val5);
		Transform[] componentsInChildren = val4.GetComponentsInChildren<Transform>(true);
		foreach (Transform val7 in componentsInChildren)
		{
			((Component)val7).gameObject.layer = layer;
		}
		SkinnedMeshRenderer componentInChildren3 = val4.GetComponentInChildren<SkinnedMeshRenderer>(true);
		if (!Object.op_Implicit((Object)(object)componentInChildren3) || !Object.op_Implicit((Object)(object)componentInChildren3.sharedMesh))
		{
			throw new InvalidOperationException("custom SkinnedMeshRenderer missing after swap");
		}
		Material[] array = (((Renderer)componentInChildren3).sharedMaterials = BuildMaterials(((Renderer)componentInChildren3).sharedMaterials, val, g));
		((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + ": worn visual: attach_skin/" + ((Object)componentInChildren3).name + " mesh=" + ((Object)componentInChildren3.sharedMesh).name + " verts=" + componentInChildren3.sharedMesh.vertexCount + " bones=" + componentInChildren3.bones.Length + " rootBone=" + (Object.op_Implicit((Object)(object)componentInChildren3.rootBone) ? ((Object)componentInChildren3.rootBone).name : "<null>") + " materials=" + string.Join(", ", array.Select((Material m) => ((Object)m).name + " [" + ((Object)m.shader).name + "]").ToArray())));
		return array;
	}

	private Material[] BuildMaterials(Material[] bundled, Material vanilla, Garment g)
	{
		//IL_00e1: 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_010c: Expected O, but got Unknown
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		if (!useVanillaShader.Value)
		{
			return bundled;
		}
		if (!Object.op_Implicit((Object)(object)vanilla) || !Object.op_Implicit((Object)(object)vanilla.shader) || !vanilla.shader.isSupported || !vanilla.HasProperty("_MainTex") || !vanilla.HasProperty("_MetallicGlossMap"))
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("NHVJ: " + g.Item + ": Custom/Creature template unavailable; using bundled Standard materials"));
			return bundled;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + ": BEFORE (vanilla " + ((Object)vanilla).name + " [" + ((Object)vanilla.shader).name + "]): " + Props(vanilla)));
		Material[] array = (Material[])(object)new Material[bundled.Length];
		for (int i = 0; i < bundled.Length; i++)
		{
			Material val = bundled[i];
			Material val2 = new Material(vanilla)
			{
				name = ((Object)val).name.Replace("_Mat", "") + "_Creature"
			};
			val2.SetTexture("_MainTex", val.GetTexture("_MainTex"));
			val2.SetTexture("_BumpMap", val.GetTexture("_BumpMap"));
			val2.SetTexture("_MetallicGlossMap", val.GetTexture("_MetallicGlossMap"));
			float num = Mathf.Clamp(albedoMul.Value, 0.5f, 1f);
			Set(val2, "_Color", new Color(num, num, num, 1f));
			Set(val2, "_Metallic", Mathf.Clamp01(metallic.Value));
			Set(val2, "_MetalGloss", Mathf.Clamp01(metalSmooth.Value));
			Set(val2, "_Glossiness", Mathf.Clamp01(baseSmooth.Value));
			Set(val2, "_UseGlossmap", 0f);
			Set(val2, "_MetalColor", Color.white);
			Set(val2, "_EmissionColor", Color.black);
			if (val2.HasProperty("_EmissionMap"))
			{
				val2.SetTexture("_EmissionMap", (Texture)null);
			}
			Set(val2, "_Hue", 0f);
			Set(val2, "_Saturation", 0f);
			Set(val2, "_Value", 0f);
			if (val2.HasProperty("_BumpScale"))
			{
				val2.SetFloat("_BumpScale", 1f);
			}
			runtimeMaterials.Add(val2);
			array[i] = val2;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + ": AFTER " + ((Object)val2).name + ": " + Props(val2) + " _MainTex=" + TexName(val2, "_MainTex") + " _BumpMap=" + TexName(val2, "_BumpMap") + " _MetallicGlossMap=" + TexName(val2, "_MetallicGlossMap")));
		}
		return array;
	}

	private static void Set(Material m, string p, float v)
	{
		if (m.HasProperty(p))
		{
			m.SetFloat(p, v);
		}
	}

	private static void Set(Material m, string p, Color v)
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		if (m.HasProperty(p))
		{
			m.SetColor(p, v);
		}
	}

	private static string Props(Material m)
	{
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		return string.Join(" ", (from p in ((IEnumerable<string>)new string[5] { "_Glossiness", "_MetalGloss", "_Metallic", "_UseGlossmap", "_BumpScale" }).Where((Func<string, bool>)m.HasProperty)
			select p + "=" + m.GetFloat(p).ToString("0.###")).ToArray()) + (m.HasProperty("_Color") ? (" _Color=" + ((object)m.GetColor("_Color")/*cast due to .constrained prefix*/).ToString()) : "") + (m.HasProperty("_MetalColor") ? (" _MetalColor=" + ((object)m.GetColor("_MetalColor")/*cast due to .constrained prefix*/).ToString()) : "");
	}

	private static string TexName(Material m, string p)
	{
		if (!m.HasProperty(p))
		{
			return "<no prop>";
		}
		Texture texture = m.GetTexture(p);
		if (!Object.op_Implicit((Object)(object)texture))
		{
			return "<null>";
		}
		return ((Object)texture).name;
	}

	private void SwapDropVisual(GameObject clone, Garment g, Material[] mats)
	{
		//IL_0111: 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_0078: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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_0099: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: Unknown result type (might be due to invalid IL or missing references)
		//IL_020e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0232: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_026e: Unknown result type (might be due to invalid IL or missing references)
		//IL_027d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: Unknown result type (might be due to invalid IL or missing references)
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_0398: Unknown result type (might be due to invalid IL or missing references)
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		List<MeshRenderer> list = (from r in clone.GetComponentsInChildren<MeshRenderer>(true)
			where !IsUnderAttach(((Component)r).transform, clone.transform) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>()) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>().sharedMesh)
			select r).ToList();
		Bounds val2;
		Transform transform;
		int layer;
		string text;
		if (list.Count > 0)
		{
			MeshRenderer val = list.OrderByDescending(delegate(MeshRenderer r)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				Bounds bounds2 = ((Component)r).GetComponent<MeshFilter>().sharedMesh.bounds;
				Vector3 size3 = ((Bounds)(ref bounds2)).size;
				return ((Vector3)(ref size3)).sqrMagnitude;
			}).First();
			MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
			val2 = ToSpace(component.sharedMesh.bounds, clone.transform.worldToLocalMatrix * ((Component)val).transform.localToWorldMatrix);
			foreach (MeshRenderer item in list)
			{
				((Renderer)item).enabled = false;
			}
			transform = ((Component)val).transform;
			layer = ((Component)val).gameObject.layer;
			text = ((Object)component.sharedMesh).name;
		}
		else
		{
			if (!removedVisualBounds.HasValue)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("NHVJ: " + g.Item + ": no ground MeshRenderer; ground visual not replaced"));
				return;
			}
			val2 = removedVisualBounds.Value;
			transform = clone.transform;
			layer = clone.layer;
			text = "<removed attach>";
		}
		GameObject val3 = Object.Instantiate<GameObject>(g.Drop, clone.transform, false);
		((Object)val3).name = g.Item + "_DropVisual";
		Collider[] componentsInChildren = val3.GetComponentsInChildren<Collider>(true);
		foreach (Collider val4 in componentsInChildren)
		{
			Object.DestroyImmediate((Object)(object)val4);
		}
		Transform[] componentsInChildren2 = val3.GetComponentsInChildren<Transform>(true);
		foreach (Transform val5 in componentsInChildren2)
		{
			((Component)val5).gameObject.layer = layer;
		}
		((Renderer)val3.GetComponent<MeshRenderer>()).sharedMaterials = mats;
		Bounds bounds = val3.GetComponent<MeshFilter>().sharedMesh.bounds;
		Vector3 size = ((Bounds)(ref bounds)).size;
		bool flag = ((Bounds)(ref val2)).size.y < ((Bounds)(ref val2)).size.x * 0.5f && ((Bounds)(ref val2)).size.y < ((Bounds)(ref val2)).size.z * 0.5f;
		float num3 = Mathf.Max(new float[3]
		{
			((Bounds)(ref val2)).size.x,
			((Bounds)(ref val2)).size.y,
			((Bounds)(ref val2)).size.z
		}) / Mathf.Max(new float[3] { size.x, size.y, size.z });
		if (num3 <= 0f || float.IsNaN(num3) || float.IsInfinity(num3))
		{
			num3 = 1f;
		}
		val3.transform.localRotation = (flag ? Quaternion.Euler(-90f, 0f, 0f) : Quaternion.identity);
		val3.transform.localScale = Vector3.one * num3;
		val3.transform.localPosition = ((Bounds)(ref val2)).center;
		val3.transform.SetParent(transform, true);
		ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
		string[] obj = new string[12]
		{
			"NHVJ: ",
			g.Item,
			": ground visual: vanilla '",
			text,
			"' (+",
			Math.Max(0, list.Count - 1).ToString(),
			" more) hidden, size=",
			null,
			null,
			null,
			null,
			null
		};
		Vector3 size2 = ((Bounds)(ref val2)).size;
		obj[7] = ((Vector3)(ref size2)).ToString("F3");
		obj[8] = " scale=";
		obj[9] = num3.ToString("F3");
		obj[10] = " flat=";
		obj[11] = flag.ToString();
		logger.LogInfo((object)string.Concat(obj));
	}

	private static bool IsUnderAttach(Transform t, Transform root)
	{
		while (Object.op_Implicit((Object)(object)t) && (Object)(object)t != (Object)(object)root)
		{
			if (((Object)t).name.StartsWith("attach"))
			{
				return true;
			}
			t = t.parent;
		}
		return false;
	}

	private static Bounds ToSpace(Bounds b, Matrix4x4 m)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_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_0020: 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_008b: 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_0038: 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_004c: 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_0060: 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_0079: Unknown result type (might be due to invalid IL or missing references)
		Vector3 center = ((Bounds)(ref b)).center;
		Vector3 extents = ((Bounds)(ref b)).extents;
		Bounds result = default(Bounds);
		((Bounds)(ref result))..ctor(((Matrix4x4)(ref m)).MultiplyPoint3x4(center - extents), Vector3.zero);
		for (int i = 1; i < 8; i++)
		{
			((Bounds)(ref result)).Encapsulate(((Matrix4x4)(ref m)).MultiplyPoint3x4(center + new Vector3(((i & 1) != 0) ? extents.x : (0f - extents.x), ((i & 2) != 0) ? extents.y : (0f - extents.y), ((i & 4) != 0) ? extents.z : (0f - extents.z))));
		}
		return result;
	}

	private static void CopyVanillaStats(SharedData s, SharedData v, Garment g)
	{
		s.m_armor = v.m_armor;
		s.m_armorPerLevel = v.m_armorPerLevel;
		s.m_weight = v.m_weight;
		s.m_scaleWeightByQuality = v.m_scaleWeightByQuality;
		s.m_scaleByQuality = v.m_scaleByQuality;
		s.m_maxDurability = v.m_maxDurability;
		s.m_durabilityPerLevel = v.m_durabilityPerLevel;
		s.m_useDurability = v.m_useDurability;
		s.m_useDurabilityDrain = v.m_useDurabilityDrain;
		s.m_canBeReparied = v.m_canBeReparied;
		s.m_destroyBroken = v.m_destroyBroken;
		s.m_maxQuality = v.m_maxQuality;
		s.m_movementModifier = v.m_movementModifier;
		s.m_equipDuration = v.m_equipDuration;
		s.m_upgradeChance = v.m_upgradeChance;
		s.m_breakChance = v.m_breakChance;
		s.m_successUpgradeSteps = v.m_successUpgradeSteps;
		s.m_breakReturnIngreientsAmount = v.m_breakReturnIngreientsAmount;
		s.m_damageModifiers = ((v.m_damageModifiers != null) ? new List<DamageModPair>(v.m_damageModifiers) : new List<DamageModPair>());
		s.m_heatResistanceModifier = v.m_heatResistanceModifier;
		s.m_eitrRegenModifier = v.m_eitrRegenModifier;
		s.m_homeItemsStaminaModifier = v.m_homeItemsStaminaModifier;
		s.m_jumpStaminaModifier = v.m_jumpStaminaModifier;
		s.m_attackStaminaModifier = v.m_attackStaminaModifier;
		s.m_blockStaminaModifier = v.m_blockStaminaModifier;
		s.m_dodgeStaminaModifier = v.m_dodgeStaminaModifier;
		s.m_swimStaminaModifier = v.m_swimStaminaModifier;
		s.m_sneakStaminaModifier = v.m_sneakStaminaModifier;
		s.m_runStaminaModifier = v.m_runStaminaModifier;
		s.m_setName = "";
		s.m_setSize = 0;
		s.m_setStatusEffect = null;
		s.m_equipStatusEffect = null;
		if (!string.IsNullOrEmpty(v.m_setName) || Object.op_Implicit((Object)(object)v.m_setStatusEffect) || Object.op_Implicit((Object)(object)v.m_equipStatusEffect))
		{
			Log.LogWarning((object)("NHVJ: " + g.Item + ": vanilla " + g.StatsFrom + " has set/effect data (set '" + v.m_setName + "' size " + v.m_setSize + "); not copied (no set bonus by design)"));
		}
	}

	private static string StatsText(SharedData s)
	{
		return "armor=" + s.m_armor + " (+" + s.m_armorPerLevel + "/lvl) durability=" + s.m_maxDurability + " (+" + s.m_durabilityPerLevel + "/lvl) weight=" + s.m_weight + " maxQuality=" + s.m_maxQuality + " movement=" + s.m_movementModifier + " set='" + s.m_setName + "'";
	}

	private void OnItemsRegisteredFejd()
	{
		ApplyVanillaIronData(inWorld: false);
	}

	private void OnItemsRegistered()
	{
		ApplyVanillaIronData(inWorld: true);
	}

	private void ApplyVanillaIronData(bool inWorld)
	{
		try
		{
			ObjectDB instance = ObjectDB.instance;
			if (!Object.op_Implicit((Object)(object)instance))
			{
				return;
			}
			Garment[] array = garments;
			foreach (Garment g in array)
			{
				GameObject itemPrefab = instance.GetItemPrefab(g.Item);
				GameObject itemPrefab2 = instance.GetItemPrefab(g.StatsFrom);
				ItemDrop val = (Object.op_Implicit((Object)(object)itemPrefab) ? itemPrefab.GetComponent<ItemDrop>() : null);
				ItemDrop val2 = (Object.op_Implicit((Object)(object)itemPrefab2) ? itemPrefab2.GetComponent<ItemDrop>() : null);
				if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val2) && val.m_itemData.m_shared != val2.m_itemData.m_shared)
				{
					CopyVanillaStats(val.m_itemData.m_shared, val2.m_itemData.m_shared, g);
				}
				Recipe recipe = ((g.Recipe != null) ? g.Recipe.Recipe : null);
				if (!Object.op_Implicit((Object)(object)recipe))
				{
					continue;
				}
				Recipe val3 = ((instance.m_recipes == null) ? null : ((IEnumerable<Recipe>)instance.m_recipes).FirstOrDefault((Func<Recipe, bool>)((Recipe r) => Object.op_Implicit((Object)(object)r) && (Object)(object)r != (Object)(object)recipe && Object.op_Implicit((Object)(object)r.m_item) && ((Object)r.m_item).name == g.StatsFrom && r.m_resources != null && r.m_resources.Length != 0)));
				if (!Object.op_Implicit((Object)(object)val3))
				{
					if (inWorld)
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("NHVJ: " + g.Item + ": vanilla recipe for " + g.StatsFrom + " not found in ObjectDB; keeping the fallback recipe"));
					}
					continue;
				}
				recipe.m_craftingStation = val3.m_craftingStation;
				recipe.m_repairStation = val3.m_repairStation;
				recipe.m_minStationLevel = val3.m_minStationLevel;
				recipe.m_amount = 1;
				recipe.m_requireOnlyOneIngredient = val3.m_requireOnlyOneIngredient;
				recipe.m_qualityResultAmountMultiplier = val3.m_qualityResultAmountMultiplier;
				recipe.m_resources = val3.m_resources.Where((Requirement r) => r != null && Object.op_Implicit((Object)(object)r.m_resItem)).Select((Func<Requirement, Requirement>)((Requirement r) => new Requirement
				{
					m_resItem = r.m_resItem,
					m_amount = r.m_amount,
					m_extraAmountOnlyOneIngredient = r.m_extraAmountOnlyOneIngredient,
					m_amountPerLevel = r.m_amountPerLevel,
					m_upgraderResource = r.m_upgraderResource,
					m_recover = r.m_recover
				})).ToArray();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("NHVJ: " + g.Item + ": recipe copied from " + ((Object)val3).name + ": station=" + (Object.op_Implicit((Object)(object)recipe.m_craftingStation) ? ((Object)recipe.m_craftingStation).name : "<none>") + " level=" + recipe.m_minStationLevel + " resources=" + string.Join(", ", recipe.m_resources.Select((Requirement r) => ((Object)r.m_resItem).name + " " + r.m_amount + " (+" + r.m_amountPerLevel + "/lvl)" + (r.m_upgraderResource ? " [upgrade item]" : "")).ToArray()) + (Object.op_Implicit((Object)(object)val) ? (" stats: " + StatsText(val.m_itemData.m_shared)) : "")));
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)("NHVJ: applying vanilla iron data failed: " + ex));
		}
	}

	private void OnDestroy()
	{
		PrefabManager.OnVanillaPrefabsAvailable -= RegisterItems;
		ItemManager.OnItemsRegisteredFejd -= OnItemsRegisteredFejd;
		ItemManager.OnItemsRegistered -= OnItemsRegistered;
	}
}