Decompiled source of SADmodelfix v1.3.2

BepInEx/patchers/SAD/SADmodelfixpatcher.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
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.Logging;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using Mono.Collections.Generic;

[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("SADmodelfixpatcher")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SADmodelfixpatcher")]
[assembly: AssemblyTitle("SADmodelfixpatcher")]
[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 SillyValuablesCompatPatcher
{
	public static class Patcher
	{
		[CompilerGenerated]
		private sealed class <AllTypes>d__9 : IEnumerable<TypeDefinition>, IEnumerable, IEnumerator<TypeDefinition>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private TypeDefinition <>2__current;

			private int <>l__initialThreadId;

			private TypeDefinition t;

			public TypeDefinition <>3__t;

			private Enumerator<TypeDefinition> <>7__wrap1;

			private IEnumerator<TypeDefinition> <>7__wrap2;

			TypeDefinition IEnumerator<TypeDefinition>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <AllTypes>d__9(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				if ((uint)(num - -4) <= 1u || num == 2)
				{
					try
					{
						if (num == -4 || num == 2)
						{
							try
							{
							}
							finally
							{
								<>m__Finally2();
							}
						}
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = default(Enumerator<TypeDefinition>);
				<>7__wrap2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0054: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>2__current = t;
						<>1__state = 1;
						return true;
					case 1:
						<>1__state = -1;
						<>7__wrap1 = t.NestedTypes.GetEnumerator();
						<>1__state = -3;
						goto IL_00cf;
					case 2:
						{
							<>1__state = -4;
							goto IL_00b5;
						}
						IL_00cf:
						if (<>7__wrap1.MoveNext())
						{
							TypeDefinition current = <>7__wrap1.Current;
							<>7__wrap2 = AllTypes(current).GetEnumerator();
							<>1__state = -4;
							goto IL_00b5;
						}
						<>m__Finally1();
						<>7__wrap1 = default(Enumerator<TypeDefinition>);
						return false;
						IL_00b5:
						if (<>7__wrap2.MoveNext())
						{
							TypeDefinition current2 = <>7__wrap2.Current;
							<>2__current = current2;
							<>1__state = 2;
							return true;
						}
						<>m__Finally2();
						<>7__wrap2 = null;
						goto IL_00cf;
					}
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				((IDisposable)<>7__wrap1).Dispose();
			}

			private void <>m__Finally2()
			{
				<>1__state = -3;
				if (<>7__wrap2 != null)
				{
					<>7__wrap2.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<TypeDefinition> IEnumerable<TypeDefinition>.GetEnumerator()
			{
				<AllTypes>d__9 <AllTypes>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<AllTypes>d__ = this;
				}
				else
				{
					<AllTypes>d__ = new <AllTypes>d__9(0);
				}
				<AllTypes>d__.t = <>3__t;
				return <AllTypes>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<TypeDefinition>)this).GetEnumerator();
			}
		}

		private static ManualLogSource? _log;

		private static ManualLogSource Log => _log ?? (_log = Logger.CreateLogSource("SAD Model Fix"));

		public static IEnumerable<string> TargetDLLs { get; } = Array.Empty<string>();


		public static void Patch(AssemblyDefinition _)
		{
		}

		public static void Initialize()
		{
			try
			{
				Run();
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"[SillyValuables compat] Failed: {arg}");
			}
		}

		private static void Run()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Expected O, but got Unknown
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_0116: 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_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Expected O, but got Unknown
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Invalid comparison between Unknown and I4
			//IL_016e: 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_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Invalid comparison between Unknown and I4
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Invalid comparison between Unknown and I4
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Invalid comparison between Unknown and I4
			string text = Directory.GetFiles(Path.Combine(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(Patcher).Assembly.Location) ?? AppDomain.CurrentDomain.BaseDirectory, "..", "..")), "plugins"), "SillyValuables.dll", SearchOption.AllDirectories).FirstOrDefault();
			if (text == null)
			{
				Log.LogInfo((object)"[SillyValuables compat] SillyValuables.dll not found — nothing to do.");
				return;
			}
			string managedPath = Paths.ManagedPath;
			string text2 = Path.Combine(managedPath, "Assembly-CSharp.dll");
			if (!File.Exists(text2))
			{
				Log.LogWarning((object)("[SillyValuables compat] Assembly-CSharp.dll not found at " + text2));
				return;
			}
			byte[] buffer = File.ReadAllBytes(text);
			DefaultAssemblyResolver val = new DefaultAssemblyResolver();
			((BaseAssemblyResolver)val).AddSearchDirectory(managedPath);
			((BaseAssemblyResolver)val).AddSearchDirectory(Path.GetDirectoryName(text));
			ModuleDefinition val2 = ModuleDefinition.ReadModule((Stream)new MemoryStream(buffer), new ReaderParameters
			{
				AssemblyResolver = (IAssemblyResolver)(object)val
			});
			try
			{
				List<(MethodDefinition, Instruction)> list = new List<(MethodDefinition, Instruction)>();
				foreach (TypeDefinition item in ((IEnumerable<TypeDefinition>)val2.Types).SelectMany(AllTypes))
				{
					Enumerator<MethodDefinition> enumerator2 = item.Methods.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							MethodDefinition current = enumerator2.Current;
							if (!current.HasBody)
							{
								continue;
							}
							Enumerator<Instruction> enumerator3 = current.Body.Instructions.GetEnumerator();
							try
							{
								while (enumerator3.MoveNext())
								{
									Instruction current2 = enumerator3.Current;
									OpCode opCode = current2.OpCode;
									if ((int)((OpCode)(ref opCode)).Code != 110)
									{
										opCode = current2.OpCode;
										if ((int)((OpCode)(ref opCode)).Code != 39)
										{
											continue;
										}
									}
									object operand = current2.Operand;
									MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null);
									if (val3 != null && ((MemberReference)((MemberReference)val3).DeclaringType).Name == "Sound" && ((MemberReference)val3).Name == "PlayLoop" && val3.Parameters.Count == 4 && (int)((ParameterReference)val3.Parameters[0]).ParameterType.MetadataType == 2 && (int)((ParameterReference)val3.Parameters[1]).ParameterType.MetadataType == 12)
									{
										list.Add((current, current2));
									}
								}
							}
							finally
							{
								((IDisposable)enumerator3).Dispose();
							}
						}
					}
					finally
					{
						((IDisposable)enumerator2).Dispose();
					}
				}
				if (list.Count == 0)
				{
					Log.LogInfo((object)"[SillyValuables compat] No Sound.PlayLoop(4) calls found — already patched or version changed.");
					return;
				}
				ModuleDefinition val4 = ModuleDefinition.ReadModule(text2, new ReaderParameters
				{
					AssemblyResolver = (IAssemblyResolver)(object)val
				});
				try
				{
					TypeDefinition type = val4.GetType("Sound");
					if (type == null)
					{
						Log.LogWarning((object)"[SillyValuables compat] Sound type not found in Assembly-CSharp.");
						return;
					}
					MethodDefinition val5 = ((IEnumerable<MethodDefinition>)type.Methods).FirstOrDefault((Func<MethodDefinition, bool>)((MethodDefinition m) => ((MemberReference)m).Name == "PlayLoop" && ((MethodReference)m).Parameters.Count == 5 && (int)((ParameterReference)((MethodReference)m).Parameters[0]).ParameterType.MetadataType == 2 && (int)((ParameterReference)((MethodReference)m).Parameters[4]).ParameterType.MetadataType == 12));
					if (val5 == null)
					{
						Log.LogWarning((object)"[SillyValuables compat] Sound.PlayLoop(bool,float,float,float,float) not found in Assembly-CSharp.");
						return;
					}
					MethodReference operand2 = val2.ImportReference((MethodReference)(object)val5);
					foreach (var (val6, val7) in list)
					{
						MethodBodyRocks.SimplifyMacros(val6.Body);
						ILProcessor iLProcessor = val6.Body.GetILProcessor();
						Instruction val8 = iLProcessor.Create(OpCodes.Ldc_R4, 1f);
						iLProcessor.InsertBefore(val7, val8);
						val7.Operand = operand2;
						MethodBodyRocks.OptimizeMacros(val6.Body);
					}
					using MemoryStream memoryStream = new MemoryStream();
					val2.Write((Stream)memoryStream);
					File.WriteAllBytes(text, memoryStream.ToArray());
					Log.LogInfo((object)$"[SillyValuables compat] Patched {list.Count} Sound.PlayLoop(4) call(s) in SillyValuables.dll. Sounds will work correctly.");
				}
				finally
				{
					((IDisposable)val4)?.Dispose();
				}
			}
			finally
			{
				((IDisposable)val2)?.Dispose();
			}
		}

		[IteratorStateMachine(typeof(<AllTypes>d__9))]
		private static IEnumerable<TypeDefinition> AllTypes(TypeDefinition t)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <AllTypes>d__9(-2)
			{
				<>3__t = t
			};
		}
	}
}

BepInEx/plugins/SAD/SADmodelfix.dll

Decompiled 2 weeks 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 Photon.Pun;
using REPOModelFixer.Fixers;
using REPOModelFixer.Patches;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Tables;

[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("SADmodelfix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SADmodelfix")]
[assembly: AssemblyTitle("SADmodelfix")]
[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 = "SAD Model Fix";

		public const string PLUGIN_VERSION = "1.3.2";
	}
	[BepInPlugin("mrnak.REPOModelFixer", "SAD Model Fix", "1.3.2")]
	[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> FixPhotonViewObservers { get; private set; }

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

		internal static ConfigEntry<bool> ForceRoomVolumeCheck { 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);
			try
			{
				PhotonViewPatch.Apply(harmony);
				Log.LogInfo((object)"PhotonView observer patch applied.");
			}
			catch (Exception ex2)
			{
				Log.LogWarning((object)("PhotonView patch failed. (" + ex2.GetType().Name + ": " + ex2.Message + ")"));
			}
			try
			{
				LocalizedStringPatch.Apply(harmony);
				Log.LogInfo((object)"LocalizedString empty table patch applied.");
			}
			catch (Exception ex3)
			{
				Log.LogWarning((object)("LocalizedString patch failed. (" + ex3.GetType().Name + ": " + ex3.Message + ")"));
			}
			Log.LogInfo((object)"SAD Model Fix v1.3.2 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.");
			FixPhotonViewObservers = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixPhotonViewObservers", true, "Remove non-IPunObservable components from PhotonView.ObservedComponents on Start. Fixes spam errors from mods like AbioticFactorValuables (ChargingStation) and Minecraft items.");
			FixEmptyLocalizationTable = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixEmptyLocalizationTable", true, "Suppress ArgumentException spam from mods that register items with an empty LocalizedString TableReference. Returns empty string as fallback item name.");
			ForceRoomVolumeCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "ForceRoomVolumeCheck", false, "Always recalculate RoomVolumeCheck bounds from colliders, ignoring the mod author's original values. Use when objects spawn inside floors/walls despite having a non-zero RoomVolumeCheck size.");
			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 LocalizedStringPatch
	{
		internal static void Apply(Harmony harmony)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			MethodInfo method = typeof(LocalizedString).GetMethod("GetLocalizedString", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method == null)
			{
				Plugin.Log.LogWarning((object)"[ModelFixer] LocalizedString.GetLocalizedString() not found – skipping localization patch.");
				return;
			}
			MethodInfo method2 = typeof(LocalizedStringPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static bool Prefix(LocalizedString __instance, ref string __result)
		{
			//IL_0010: 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)
			if (!Plugin.FixEmptyLocalizationTable.Value)
			{
				return true;
			}
			try
			{
				TableReference tableReference = ((LocalizedReference)__instance).TableReference;
				if (string.IsNullOrEmpty(((TableReference)(ref tableReference)).TableCollectionName) && ((TableReference)(ref tableReference)).TableCollectionNameGuid == Guid.Empty)
				{
					if (Plugin.VerboseLogging.Value)
					{
						Plugin.Log.LogDebug((object)"[ModelFixer] LocalizedString.GetLocalizedString(): empty TableReference suppressed.");
					}
					__result = string.Empty;
					return false;
				}
			}
			catch
			{
			}
			return true;
		}
	}
	internal static class PhotonViewPatch
	{
		private static readonly HashSet<int> _cleaned = new HashSet<int>();

		internal static void Apply(Harmony harmony)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			MethodInfo method = typeof(PhotonView).GetMethod("SerializeView", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				Plugin.Log.LogWarning((object)"[ModelFixer] PhotonView.SerializeView() not found – skipping observer patch.");
				return;
			}
			MethodInfo method2 = typeof(PhotonViewPatch).GetMethod("Prefix", BindingFlags.Static | BindingFlags.NonPublic);
			harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		private static void Prefix(PhotonView __instance)
		{
			if (!Plugin.FixPhotonViewObservers.Value)
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (_cleaned.Contains(instanceID))
			{
				return;
			}
			_cleaned.Add(instanceID);
			List<Component> observedComponents = __instance.ObservedComponents;
			if (observedComponents == null || observedComponents.Count == 0)
			{
				return;
			}
			List<Component> list = new List<Component>();
			foreach (Component item in observedComponents)
			{
				if (!(item is IPunObservable))
				{
					list.Add(item);
				}
			}
			if (list.Count == 0)
			{
				return;
			}
			foreach (Component item2 in list)
			{
				observedComponents.Remove(item2);
				if (Plugin.VerboseLogging.Value)
				{
					string text = (((Object)(object)item2 != (Object)null) ? ((object)item2).GetType().Name : "null");
					Plugin.Log.LogDebug((object)("[ModelFixer] PhotonView on '" + ((Object)((Component)__instance).gameObject).name + "': removed non-IPunObservable '" + text + "' from ObservedComponents."));
				}
			}
			if (!Plugin.VerboseLogging.Value)
			{
				Plugin.Log.LogInfo((object)("[ModelFixer] PhotonView on '" + ((Object)((Component)__instance).gameObject).name + "': " + $"removed {list.Count} non-IPunObservable component(s) from ObservedComponents."));
			}
		}
	}
	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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_004a: 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_00b4: 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)
			{
				Vector3 size = ((Bounds)(ref result)).size;
				if (!(((Vector3)(ref size)).sqrMagnitude < 0.0001f))
				{
					goto IL_00d8;
				}
			}
			valid = false;
			result = default(Bounds);
			MeshFilter[] componentsInChildren2 = root.GetComponentsInChildren<MeshFilter>(true);
			foreach (MeshFilter val3 in componentsInChildren2)
			{
				Mesh sharedMesh = val3.sharedMesh;
				if (!((Object)(object)sharedMesh == (Object)null))
				{
					EncapsulateLocalBounds(sharedMesh.bounds, ((Component)val3).transform, transform, ref result, ref valid);
				}
			}
			goto IL_00d8;
			IL_00d8:
			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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003d: 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_0051: 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_0065: 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_006e: 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_0075: 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);
				EncapsulatePoint(rootTf.InverseTransformPoint(transform.TransformPoint(val2)), ref result, ref valid);
			}
		}

		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)
			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);
				EncapsulatePoint(rootTf.InverseTransformPoint(val), ref result, ref valid);
			}
		}

		private static void EncapsulateLocalBounds(Bounds localBounds, Transform tf, 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_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_005e: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			Vector3 center = ((Bounds)(ref localBounds)).center;
			Vector3 extents = ((Bounds)(ref localBounds)).extents;
			for (int i = 0; i < 8; i++)
			{
				Vector3 val = center + new Vector3(((i & 1) == 0) ? (0f - extents.x) : extents.x, ((i & 2) == 0) ? (0f - extents.y) : extents.y, ((i & 4) == 0) ? (0f - extents.z) : extents.z);
				EncapsulatePoint(rootTf.InverseTransformPoint(tf.TransformPoint(val)), ref result, ref valid);
			}
		}

		private static void EncapsulatePoint(Vector3 pt, ref Bounds result, ref bool valid)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (!valid)
			{
				result = new Bounds(pt, Vector3.zero);
				valid = true;
			}
			else
			{
				((Bounds)(ref result)).Encapsulate(pt);
			}
		}
	}
	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_00df: 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_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_00ab: 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_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)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: 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_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: 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_0191: 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);
				bool flag;
				if (Plugin.ForceRoomVolumeCheck.Value)
				{
					Vector3 val4 = val2 - ((Bounds)(ref value)).center;
					int num;
					if (!(((Vector3)(ref val4)).sqrMagnitude > 0.0025f))
					{
						val4 = val3 - ((Bounds)(ref value)).size;
						num = ((((Vector3)(ref val4)).sqrMagnitude > 0.0025f) ? 1 : 0);
					}
					else
					{
						num = 1;
					}
					flag = (byte)num != 0;
				}
				else
				{
					flag = val3.x < 0.01f || val3.y < 0.01f || val3.z < 0.01f;
				}
				if (!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;
			}
		}
	}
}