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 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 FixPhotonViewObservers { get; private set; } internal static ConfigEntry FixEmptyLocalizationTable { get; private set; } internal static ConfigEntry ForceRoomVolumeCheck { 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); 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("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."); FixPhotonViewObservers = ((BaseUnityPlugin)this).Config.Bind("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("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("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("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 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 _cleaned = new HashSet(); 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 observedComponents = __instance.ObservedComponents; if (observedComponents == null || observedComponents.Count == 0) { return; } List list = new List(); 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(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(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(); 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_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; } } } }