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 FixMeshColliders { get; private set; } internal static ConfigEntry FixRoomVolumeCheck { get; private set; } internal static ConfigEntry FixCenterOfMass { get; private set; } internal static ConfigEntry FixVolumeType { get; private set; } internal static ConfigEntry CheckHierarchy { get; private set; } internal static ConfigEntry FixHierarchy { get; private set; } internal static ConfigEntry VerboseLogging { get; private set; } internal static ConfigEntry 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("Fixes", "FixMeshColliders", true, "Enable convex mode on non-convex MeshColliders so objects fall with correct shape physics."); FixRoomVolumeCheck = ((BaseUnityPlugin)this).Config.Bind("Fixes", "FixRoomVolumeCheck", true, "Recalculate RoomVolumeCheck.CheckPosition and currentSize from child colliders."); FixCenterOfMass = ((BaseUnityPlugin)this).Config.Bind("Fixes", "FixCenterOfMass", true, "Set Rigidbody.centerOfMass to the geometric center of all physics colliders."); FixVolumeType = ((BaseUnityPlugin)this).Config.Bind("Fixes", "FixVolumeType", true, "Auto-correct ValuableObject.volumeType based on the calculated bounding box."); CheckHierarchy = ((BaseUnityPlugin)this).Config.Bind("Fixes", "CheckHierarchy", true, "Log a warning when a mesh renderer is found directly on the prefab root."); FixHierarchy = ((BaseUnityPlugin)this).Config.Bind("Fixes", "FixHierarchy", false, "When CheckHierarchy finds a root-level mesh, automatically wrap it in an 'Object' child. EXPERIMENTAL."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind("General", "VerboseLogging", false, "Log detailed fix information for every prefab processed."); BlockList = ((BaseUnityPlugin)this).Config.Bind("General", "BlockList", "", "Comma-separated list of prefab names to skip (exact match). E.g. ValuableMyMod,SomeEnemy"); } } internal static class PrefabFixerPipeline { private static readonly HashSet _processed = new HashSet(); private static HashSet? _blockList; private static HashSet BlockList { get { if (_blockList == null) { _blockList = new HashSet(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(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(); 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() != (Object)null) && !((Object)(object)root.GetComponent() != (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(root, val); MoveComponentToChild(root, val); MoveComponentToChild(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(GameObject source, GameObject dest) where T : Component { T component = source.GetComponent(); if ((Object)(object)component == (Object)null) { return; } T val = dest.AddComponent(); 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(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; } } } }