Decompiled source of SADmodelfix v1.0.0

BepInEx/plugins/REPOModelFixer/REPOModelFixer.dll

Decompiled 2 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using REPOModelFixer.Fixers;
using REPOModelFixer.Patches;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("REPOModelFixer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("REPOModelFixer")]
[assembly: AssemblyTitle("REPOModelFixer")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 REPOModelFixer
{
	internal static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "mrnak.REPOModelFixer";

		public const string PLUGIN_NAME = "REPO Model Fixer";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	[BepInPlugin("mrnak.REPOModelFixer", "REPO Model Fixer", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static ConfigEntry<bool> FixMeshColliders { get; private set; }

		internal static ConfigEntry<bool> FixRoomVolumeCheck { get; private set; }

		internal static ConfigEntry<bool> FixCenterOfMass { get; private set; }

		internal static ConfigEntry<bool> FixVolumeType { get; private set; }

		internal static ConfigEntry<bool> CheckHierarchy { get; private set; }

		internal static ConfigEntry<bool> FixHierarchy { get; private set; }

		internal static ConfigEntry<bool> VerboseLogging { get; private set; }

		internal static ConfigEntry<string> BlockList { get; private set; }

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			Harmony harmony = new Harmony("mrnak.REPOModelFixer");
			try
			{
				REPOLibPatches.Apply(harmony);
				Log.LogInfo((object)"REPOLib patches applied.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("REPOLib not found or patch failed, using director fallback. (" + ex.GetType().Name + ")"));
			}
			DirectorPatches.Apply(harmony);
			Log.LogInfo((object)"REPO Model Fixer v1.0.0 loaded.");
		}

		private void BindConfig()
		{
			FixMeshColliders = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixMeshColliders", true, "Enable convex mode on non-convex MeshColliders so objects fall with correct shape physics.");
			FixRoomVolumeCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixRoomVolumeCheck", true, "Recalculate RoomVolumeCheck.CheckPosition and currentSize from child colliders.");
			FixCenterOfMass = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixCenterOfMass", true, "Set Rigidbody.centerOfMass to the geometric center of all physics colliders.");
			FixVolumeType = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixVolumeType", true, "Auto-correct ValuableObject.volumeType based on the calculated bounding box.");
			CheckHierarchy = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "CheckHierarchy", true, "Log a warning when a mesh renderer is found directly on the prefab root.");
			FixHierarchy = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixHierarchy", false, "When CheckHierarchy finds a root-level mesh, automatically wrap it in an 'Object' child. EXPERIMENTAL.");
			VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Log detailed fix information for every prefab processed.");
			BlockList = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BlockList", "", "Comma-separated list of prefab names to skip (exact match). E.g. ValuableMyMod,SomeEnemy");
		}
	}
	internal static class PrefabFixerPipeline
	{
		private static readonly HashSet<int> _processed = new HashSet<int>();

		private static HashSet<string>? _blockList;

		private static HashSet<string> BlockList
		{
			get
			{
				if (_blockList == null)
				{
					_blockList = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
					string value = Plugin.BlockList.Value;
					if (!string.IsNullOrWhiteSpace(value))
					{
						string[] array = value.Split(',');
						for (int i = 0; i < array.Length; i++)
						{
							string text = array[i].Trim();
							if (!string.IsNullOrEmpty(text))
							{
								_blockList.Add(text);
							}
						}
					}
				}
				return _blockList;
			}
		}

		internal static void Process(GameObject? prefab, string modName = "")
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)prefab).GetInstanceID();
			if (_processed.Contains(instanceID))
			{
				return;
			}
			_processed.Add(instanceID);
			string name = ((Object)prefab).name;
			if (BlockList.Contains(name))
			{
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogDebug((object)("[ModelFixer] Skipped (blocklisted): " + name));
				}
				return;
			}
			string text = ((modName.Length > 0) ? (modName + "/" + name) : name);
			bool flag = false;
			try
			{
				if (Plugin.FixMeshColliders.Value)
				{
					flag |= MeshColliderFixer.Fix(prefab, text);
				}
				if (Plugin.CheckHierarchy.Value)
				{
					flag |= HierarchyChecker.Check(prefab, text, Plugin.FixHierarchy.Value);
				}
				Bounds? bounds = BoundsCalculator.Calculate(prefab);
				if (Plugin.FixRoomVolumeCheck.Value)
				{
					flag |= RoomVolumeCheckFixer.Fix(prefab, bounds, text);
				}
				if (Plugin.FixCenterOfMass.Value)
				{
					flag |= CenterOfMassFixer.Fix(prefab, bounds, text);
				}
				if (Plugin.FixVolumeType.Value)
				{
					flag |= VolumeTypeFixer.Fix(prefab, bounds, text);
				}
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"[ModelFixer] Exception while processing {text}: {arg}");
			}
			if (flag || Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("[ModelFixer] Processed: " + text));
			}
		}

		internal static void ClearCache()
		{
			_processed.Clear();
			_blockList = null;
		}
	}
}
namespace REPOModelFixer.Patches
{
	internal static class DirectorPatches
	{
		internal static void Apply(Harmony harmony)
		{
			PatchDirector(harmony, "ValuableDirector", "PostfixValuableDirectorAwake");
			PatchDirector(harmony, "EnemyDirector", "PostfixEnemyDirectorAwake");
		}

		private static void PatchDirector(Harmony harmony, string typeName, string postfixName)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			Type type = FindTypeInAssembly(typeName);
			if (type == null)
			{
				Plugin.Log.LogWarning((object)("[ModelFixer] " + typeName + " not found – director fallback skipped."));
				return;
			}
			MethodInfo method = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				Plugin.Log.LogWarning((object)("[ModelFixer] " + typeName + ".Awake not found."));
				return;
			}
			MethodInfo method2 = typeof(DirectorPatches).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic);
			if (!(method2 == null))
			{
				harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogDebug((object)("[ModelFixer] Patched " + typeName + ".Awake"));
			}
		}

		private static void PostfixValuableDirectorAwake(MonoBehaviour __instance)
		{
			try
			{
				ProcessAllPrefabsInDirector(__instance, "Valuable");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] ValuableDirector postfix error: " + ex.Message));
			}
		}

		private static void PostfixEnemyDirectorAwake(MonoBehaviour __instance)
		{
			try
			{
				ProcessAllPrefabsInDirector(__instance, "Enemy");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] EnemyDirector postfix error: " + ex.Message));
			}
		}

		private static void ProcessAllPrefabsInDirector(MonoBehaviour director, string modName)
		{
			FieldInfo[] fields = ((object)director).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < fields.Length; i++)
			{
				object value = fields[i].GetValue(director);
				if (value == null)
				{
					continue;
				}
				GameObject val = (GameObject)((value is GameObject) ? value : null);
				if (val != null)
				{
					PrefabFixerPipeline.Process(val, modName);
				}
				else
				{
					if (!(value is IList list))
					{
						continue;
					}
					foreach (object item in list)
					{
						if (item != null)
						{
							GameObject val2 = (GameObject)((item is GameObject) ? item : null);
							if (val2 != null)
							{
								PrefabFixerPipeline.Process(val2, modName);
								continue;
							}
							TryProcessPrefabField(item, modName);
							TryProcessSpawnObjects(item, modName);
						}
					}
				}
			}
		}

		private static void TryProcessPrefabField(object obj, string modName)
		{
			object? obj2 = (obj.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? obj.GetType().GetField("Prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj);
			GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
			if (val != null)
			{
				PrefabFixerPipeline.Process(val, modName);
			}
		}

		private static void TryProcessSpawnObjects(object obj, string modName)
		{
			if (!(obj.GetType().GetField("spawnObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj) is IList list))
			{
				return;
			}
			foreach (object item in list)
			{
				if (item != null)
				{
					GameObject val = (GameObject)((item is GameObject) ? item : null);
					if (val != null)
					{
						PrefabFixerPipeline.Process(val, modName);
					}
					else
					{
						TryProcessPrefabField(item, modName);
					}
				}
			}
		}

		private static Type? FindTypeInAssembly(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(typeName);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
	internal static class REPOLibPatches
	{
		internal static void Apply(Harmony harmony)
		{
			PatchMethod(harmony, "REPOLib.Modules.Valuables, REPOLib", "RegisterValuable", "PostfixRegisterValuable");
			PatchMethod(harmony, "REPOLib.Modules.Enemies, REPOLib", "RegisterEnemy", "PostfixRegisterEnemy");
			PatchMethod(harmony, "REPOLib.Modules.Items, REPOLib", "RegisterItem", "PostfixRegisterItem");
		}

		private static void PatchMethod(Harmony harmony, string typeName, string methodName, string postfixName)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			Type type = Type.GetType(typeName);
			if (type == null)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] Type not found: " + typeName));
				return;
			}
			MethodInfo methodInfo = null;
			MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (methodInfo2.Name == methodName)
				{
					methodInfo = methodInfo2;
					break;
				}
			}
			if (methodInfo == null)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] Method not found: " + typeName + "." + methodName));
				return;
			}
			MethodInfo method = typeof(REPOLibPatches).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic);
			if (method == null)
			{
				Plugin.Log.LogWarning((object)("[ModelFixer] Postfix not found: " + postfixName));
				return;
			}
			harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Plugin.Log.LogDebug((object)("[ModelFixer] Patched " + typeName + "." + methodName));
		}

		private static void PostfixRegisterValuable(object[] __args)
		{
			try
			{
				if (__args != null && __args.Length != 0)
				{
					object obj = __args[0];
					MonoBehaviour val = (MonoBehaviour)((obj is MonoBehaviour) ? obj : null);
					if (!((Object)(object)val == (Object)null))
					{
						PrefabFixerPipeline.Process(((Component)val).gameObject, "Valuable");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] PostfixRegisterValuable error: " + ex.Message));
			}
		}

		private static void PostfixRegisterEnemy(object[] __args)
		{
			try
			{
				if (__args != null && __args.Length != 0)
				{
					object obj = __args[0];
					if (obj != null)
					{
						ProcessEnemyContent(obj);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] PostfixRegisterEnemy error: " + ex.Message));
			}
		}

		private static void PostfixRegisterItem(object[] __args)
		{
			try
			{
				if (__args == null || __args.Length == 0)
				{
					return;
				}
				object obj = __args[0];
				if (obj == null)
				{
					return;
				}
				object obj2 = obj.GetType().GetField("item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj);
				if (obj2 != null)
				{
					object? obj3 = obj2.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj2);
					GameObject val = (GameObject)((obj3 is GameObject) ? obj3 : null);
					if ((Object)(object)val != (Object)null)
					{
						PrefabFixerPipeline.Process(val, "Item");
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer] PostfixRegisterItem error: " + ex.Message));
			}
		}

		private static void ProcessEnemyContent(object content)
		{
			if (!(content.GetType().GetField("spawnObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(content) is IList list))
			{
				return;
			}
			foreach (object item in list)
			{
				if (item != null)
				{
					object? obj = item.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item);
					GameObject val = (GameObject)((obj is GameObject) ? obj : null);
					if ((Object)(object)val != (Object)null)
					{
						PrefabFixerPipeline.Process(val, "Enemy");
					}
				}
			}
		}
	}
}
namespace REPOModelFixer.Fixers
{
	internal static class BoundsCalculator
	{
		internal static Bounds? Calculate(GameObject root)
		{
			//IL_000b: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = root.transform;
			bool valid = false;
			Bounds result = default(Bounds);
			Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!val.isTrigger)
				{
					BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null);
					if (val2 != null)
					{
						EncapsulateBox(val2, transform, ref result, ref valid);
					}
					else
					{
						EncapsulateWorldBounds(val.bounds, transform, ref result, ref valid);
					}
				}
			}
			if (!valid)
			{
				return null;
			}
			return result;
		}

		private static void EncapsulateBox(BoxCollider box, Transform rootTf, ref Bounds result, ref bool valid)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)box).transform;
			Vector3 center = box.center;
			Vector3 val = box.size * 0.5f;
			for (int i = 0; i < 8; i++)
			{
				Vector3 val2 = center + new Vector3(((i & 1) == 0) ? (0f - val.x) : val.x, ((i & 2) == 0) ? (0f - val.y) : val.y, ((i & 4) == 0) ? (0f - val.z) : val.z);
				Vector3 val3 = transform.TransformPoint(val2);
				Vector3 val4 = rootTf.InverseTransformPoint(val3);
				if (!valid)
				{
					result = new Bounds(val4, Vector3.zero);
					valid = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val4);
				}
			}
		}

		private static void EncapsulateWorldBounds(Bounds worldBounds, Transform rootTf, ref Bounds result, ref bool valid)
		{
			//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_0023: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			Vector3 min = ((Bounds)(ref worldBounds)).min;
			Vector3 max = ((Bounds)(ref worldBounds)).max;
			Vector3 val = default(Vector3);
			for (int i = 0; i < 8; i++)
			{
				((Vector3)(ref val))..ctor(((i & 1) == 0) ? min.x : max.x, ((i & 2) == 0) ? min.y : max.y, ((i & 4) == 0) ? min.z : max.z);
				Vector3 val2 = rootTf.InverseTransformPoint(val);
				if (!valid)
				{
					result = new Bounds(val2, Vector3.zero);
					valid = true;
				}
				else
				{
					((Bounds)(ref result)).Encapsulate(val2);
				}
			}
		}
	}
	internal static class CenterOfMassFixer
	{
		internal static bool Fix(GameObject root, Bounds? bounds, string context)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (!bounds.HasValue)
			{
				return false;
			}
			Rigidbody component = root.GetComponent<Rigidbody>();
			if ((Object)(object)component == (Object)null)
			{
				return false;
			}
			Transform transform = ((Component)component).transform;
			Transform transform2 = root.transform;
			Bounds value = bounds.Value;
			Vector3 val = transform2.TransformPoint(((Bounds)(ref value)).center);
			Vector3 val2 = transform.InverseTransformPoint(val);
			Vector3 centerOfMass = component.centerOfMass;
			Vector3 val3 = centerOfMass - val2;
			if (((Vector3)(ref val3)).sqrMagnitude < 0.0004f)
			{
				return false;
			}
			component.centerOfMass = val2;
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogDebug((object)$"[ModelFixer][CoM] {context}: {centerOfMass}→{val2}");
			}
			return true;
		}
	}
	internal static class HierarchyChecker
	{
		internal static bool Check(GameObject root, string context, bool autoFix)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			if (!((Object)(object)root.GetComponent<MeshRenderer>() != (Object)null) && !((Object)(object)root.GetComponent<SkinnedMeshRenderer>() != (Object)null))
			{
				return false;
			}
			Plugin.Log.LogWarning((object)("[ModelFixer][Hierarchy] " + context + ": MeshRenderer found directly on prefab root. " + (autoFix ? "Auto-fixing hierarchy." : "Consider moving mesh under an 'Object' child.")));
			if (!autoFix)
			{
				return false;
			}
			GameObject val = new GameObject("Object");
			val.transform.SetParent(root.transform, false);
			MoveComponentToChild<MeshFilter>(root, val);
			MoveComponentToChild<MeshRenderer>(root, val);
			MoveComponentToChild<SkinnedMeshRenderer>(root, val);
			if (Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogDebug((object)("[ModelFixer][Hierarchy] " + context + ": moved mesh components to 'Object' child."));
			}
			return true;
		}

		private static void MoveComponentToChild<T>(GameObject source, GameObject dest) where T : Component
		{
			T component = source.GetComponent<T>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			T val = dest.AddComponent<T>();
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					fieldInfo.SetValue(val, fieldInfo.GetValue(component));
				}
				catch
				{
				}
			}
			Object.Destroy((Object)(object)component);
		}
	}
	internal static class MeshColliderFixer
	{
		internal static bool Fix(GameObject root, string context)
		{
			bool result = false;
			MeshCollider[] componentsInChildren = root.GetComponentsInChildren<MeshCollider>(true);
			foreach (MeshCollider val in componentsInChildren)
			{
				if (((Collider)val).isTrigger || val.convex)
				{
					continue;
				}
				val.convex = true;
				GameObject gameObject = ((Component)val).gameObject;
				bool num = (Object)(object)gameObject.GetComponent("PhysGrabObjectCollider") != (Object)null;
				bool flag = (Object)(object)root.GetComponent("PhysGrabObject") != (Object)null;
				if (!num && flag)
				{
					Type type = FindTypeInDomain("PhysGrabObjectCollider");
					if (type != null)
					{
						gameObject.AddComponent(type);
					}
				}
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogDebug((object)("[ModelFixer][MeshCollider] " + context + "/" + ((Object)gameObject).name + ": convex = true"));
				}
				result = true;
			}
			return result;
		}

		private static Type? FindTypeInDomain(string typeName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(typeName);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
	internal static class RoomVolumeCheckFixer
	{
		private static FieldInfo? _checkPositionField;

		private static FieldInfo? _currentSizeField;

		private static bool _reflectionReady;

		private static bool _reflectionFailed;

		internal static bool Fix(GameObject root, Bounds? bounds, string context)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00bc: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			if (!bounds.HasValue)
			{
				return false;
			}
			Component component = root.GetComponent("RoomVolumeCheck");
			MonoBehaviour val = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			EnsureReflection(val);
			if (_reflectionFailed)
			{
				return false;
			}
			Bounds value = bounds.Value;
			try
			{
				Vector3 val2 = (Vector3)(((??)(Vector3?)_checkPositionField.GetValue(val)) ?? Vector3.zero);
				Vector3 val3 = (Vector3)(((??)(Vector3?)_currentSizeField.GetValue(val)) ?? Vector3.zero);
				Vector3 val4 = val2 - ((Bounds)(ref value)).center;
				bool num = ((Vector3)(ref val4)).sqrMagnitude > 0.0025f;
				val4 = val3 - ((Bounds)(ref value)).size;
				bool flag = ((Vector3)(ref val4)).sqrMagnitude > 0.0025f;
				if (!num && !flag)
				{
					return false;
				}
				_checkPositionField.SetValue(val, ((Bounds)(ref value)).center);
				_currentSizeField.SetValue(val, ((Bounds)(ref value)).size);
				if (Plugin.VerboseLogging.Value)
				{
					Plugin.Log.LogDebug((object)("[ModelFixer][RVC] " + context + ": " + $"center {val2}→{((Bounds)(ref value)).center}  size {val3}→{((Bounds)(ref value)).size}"));
				}
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[ModelFixer][RVC] Reflection set failed for " + context + ": " + ex.Message));
				return false;
			}
		}

		private static void EnsureReflection(MonoBehaviour rvc)
		{
			if (!_reflectionReady && !_reflectionFailed)
			{
				Type type = ((object)rvc).GetType();
				_checkPositionField = FindField(type, "CheckPosition", "checkPosition");
				_currentSizeField = FindField(type, "currentSize", "CurrentSize");
				if (_checkPositionField == null || _currentSizeField == null)
				{
					Plugin.Log.LogWarning((object)"[ModelFixer][RVC] Could not find CheckPosition/currentSize fields on RoomVolumeCheck. Skipping RVC fix.");
					_reflectionFailed = true;
				}
				else
				{
					_reflectionReady = true;
				}
			}
		}

		private static FieldInfo? FindField(Type type, params string[] candidates)
		{
			foreach (string name in candidates)
			{
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					return field;
				}
			}
			return null;
		}
	}
	internal static class VolumeTypeFixer
	{
		private const int Tiny = 0;

		private const int Small = 1;

		private const int Medium = 2;

		private const int Big = 3;

		private const int Wide = 4;

		private const int Tall = 5;

		private const int VeryTall = 6;

		private static FieldInfo? _volumeTypeField;

		private static bool _reflectionReady;

		private static bool _reflectionFailed;

		internal static bool Fix(GameObject root, Bounds? bounds, string context)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			if (!bounds.HasValue)
			{
				return false;
			}
			Component component = root.GetComponent("ValuableObject");
			MonoBehaviour val = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			EnsureReflection(val);
			if (_reflectionFailed)
			{
				return false;
			}
			int num = Convert.ToInt32(_volumeTypeField.GetValue(val));
			Bounds value = bounds.Value;
			int num2 = Classify(((Bounds)(ref value)).size);
			if (num == num2)
			{
				return false;
			}
			if (!IsSignificantlyWrong(num, num2))
			{
				return false;
			}
			_volumeTypeField.SetValue(val, Enum.ToObject(_volumeTypeField.FieldType, num2));
			_ = Plugin.VerboseLogging.Value;
			ManualLogSource log = Plugin.Log;
			string text = $"[ModelFixer][VolumeType] {context}: {num}→{num2} ";
			value = bounds.Value;
			log.LogInfo((object)(text + $"(size={((Bounds)(ref value)).size})"));
			return true;
		}

		private static int Classify(Vector3 size)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Abs(size.x);
			float num2 = Mathf.Abs(size.y);
			float num3 = Mathf.Abs(size.z);
			float num4 = Mathf.Max(num, num3);
			float num5 = num2;
			float num6 = Mathf.Max(new float[3] { num, num2, num3 });
			float num7 = ((num4 > 0.001f) ? (num5 / num4) : 1f);
			float num8 = ((num5 > 0.001f) ? (num4 / num5) : 1f);
			if (num7 > 3f)
			{
				return 6;
			}
			if (num7 > 1.8f)
			{
				return 5;
			}
			if (num8 > 2f)
			{
				return 4;
			}
			if (num6 < 0.2f)
			{
				return 0;
			}
			if (num6 < 0.35f)
			{
				return 1;
			}
			if (num6 < 0.6f)
			{
				return 2;
			}
			return 3;
		}

		private static bool IsSignificantlyWrong(int current, int computed)
		{
			bool num = current >= 4;
			bool flag = computed >= 4;
			if (num != flag)
			{
				return true;
			}
			return Math.Abs(current - computed) >= 2;
		}

		private static void EnsureReflection(MonoBehaviour vo)
		{
			if (_reflectionReady || _reflectionFailed)
			{
				return;
			}
			_volumeTypeField = ((object)vo).GetType().GetField("volumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)vo).GetType().GetField("VolumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (_volumeTypeField == null)
			{
				if ((((object)vo).GetType().GetProperty("volumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)vo).GetType().GetProperty("VolumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) != null)
				{
					_reflectionFailed = true;
					Plugin.Log.LogWarning((object)"[ModelFixer][VolumeType] volumeType is a property, not a field. Skipping.");
				}
				else
				{
					_reflectionFailed = true;
					Plugin.Log.LogWarning((object)"[ModelFixer][VolumeType] Could not find volumeType field on ValuableObject. Skipping.");
				}
			}
			else
			{
				_reflectionReady = true;
			}
		}
	}
}