Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SADmodelfix v1.0.0
BepInEx/plugins/REPOModelFixer/REPOModelFixer.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using REPOModelFixer.Fixers; using REPOModelFixer.Patches; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("REPOModelFixer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("REPOModelFixer")] [assembly: AssemblyTitle("REPOModelFixer")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOModelFixer { internal static class MyPluginInfo { public const string PLUGIN_GUID = "mrnak.REPOModelFixer"; public const string PLUGIN_NAME = "REPO Model Fixer"; public const string PLUGIN_VERSION = "1.0.0"; } [BepInPlugin("mrnak.REPOModelFixer", "REPO Model Fixer", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static ConfigEntry<bool> FixMeshColliders { get; private set; } internal static ConfigEntry<bool> FixRoomVolumeCheck { get; private set; } internal static ConfigEntry<bool> FixCenterOfMass { get; private set; } internal static ConfigEntry<bool> FixVolumeType { get; private set; } internal static ConfigEntry<bool> CheckHierarchy { get; private set; } internal static ConfigEntry<bool> FixHierarchy { get; private set; } internal static ConfigEntry<bool> VerboseLogging { get; private set; } internal static ConfigEntry<string> BlockList { get; private set; } private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); Harmony harmony = new Harmony("mrnak.REPOModelFixer"); try { REPOLibPatches.Apply(harmony); Log.LogInfo((object)"REPOLib patches applied."); } catch (Exception ex) { Log.LogWarning((object)("REPOLib not found or patch failed, using director fallback. (" + ex.GetType().Name + ")")); } DirectorPatches.Apply(harmony); Log.LogInfo((object)"REPO Model Fixer v1.0.0 loaded."); } private void BindConfig() { FixMeshColliders = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixMeshColliders", true, "Enable convex mode on non-convex MeshColliders so objects fall with correct shape physics."); FixRoomVolumeCheck = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixRoomVolumeCheck", true, "Recalculate RoomVolumeCheck.CheckPosition and currentSize from child colliders."); FixCenterOfMass = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixCenterOfMass", true, "Set Rigidbody.centerOfMass to the geometric center of all physics colliders."); FixVolumeType = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixVolumeType", true, "Auto-correct ValuableObject.volumeType based on the calculated bounding box."); CheckHierarchy = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "CheckHierarchy", true, "Log a warning when a mesh renderer is found directly on the prefab root."); FixHierarchy = ((BaseUnityPlugin)this).Config.Bind<bool>("Fixes", "FixHierarchy", false, "When CheckHierarchy finds a root-level mesh, automatically wrap it in an 'Object' child. EXPERIMENTAL."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "VerboseLogging", false, "Log detailed fix information for every prefab processed."); BlockList = ((BaseUnityPlugin)this).Config.Bind<string>("General", "BlockList", "", "Comma-separated list of prefab names to skip (exact match). E.g. ValuableMyMod,SomeEnemy"); } } internal static class PrefabFixerPipeline { private static readonly HashSet<int> _processed = new HashSet<int>(); private static HashSet<string>? _blockList; private static HashSet<string> BlockList { get { if (_blockList == null) { _blockList = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string value = Plugin.BlockList.Value; if (!string.IsNullOrWhiteSpace(value)) { string[] array = value.Split(','); for (int i = 0; i < array.Length; i++) { string text = array[i].Trim(); if (!string.IsNullOrEmpty(text)) { _blockList.Add(text); } } } } return _blockList; } } internal static void Process(GameObject? prefab, string modName = "") { if ((Object)(object)prefab == (Object)null) { return; } int instanceID = ((Object)prefab).GetInstanceID(); if (_processed.Contains(instanceID)) { return; } _processed.Add(instanceID); string name = ((Object)prefab).name; if (BlockList.Contains(name)) { if (Plugin.VerboseLogging.Value) { Plugin.Log.LogDebug((object)("[ModelFixer] Skipped (blocklisted): " + name)); } return; } string text = ((modName.Length > 0) ? (modName + "/" + name) : name); bool flag = false; try { if (Plugin.FixMeshColliders.Value) { flag |= MeshColliderFixer.Fix(prefab, text); } if (Plugin.CheckHierarchy.Value) { flag |= HierarchyChecker.Check(prefab, text, Plugin.FixHierarchy.Value); } Bounds? bounds = BoundsCalculator.Calculate(prefab); if (Plugin.FixRoomVolumeCheck.Value) { flag |= RoomVolumeCheckFixer.Fix(prefab, bounds, text); } if (Plugin.FixCenterOfMass.Value) { flag |= CenterOfMassFixer.Fix(prefab, bounds, text); } if (Plugin.FixVolumeType.Value) { flag |= VolumeTypeFixer.Fix(prefab, bounds, text); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[ModelFixer] Exception while processing {text}: {arg}"); } if (flag || Plugin.VerboseLogging.Value) { Plugin.Log.LogInfo((object)("[ModelFixer] Processed: " + text)); } } internal static void ClearCache() { _processed.Clear(); _blockList = null; } } } namespace REPOModelFixer.Patches { internal static class DirectorPatches { internal static void Apply(Harmony harmony) { PatchDirector(harmony, "ValuableDirector", "PostfixValuableDirectorAwake"); PatchDirector(harmony, "EnemyDirector", "PostfixEnemyDirectorAwake"); } private static void PatchDirector(Harmony harmony, string typeName, string postfixName) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown Type type = FindTypeInAssembly(typeName); if (type == null) { Plugin.Log.LogWarning((object)("[ModelFixer] " + typeName + " not found – director fallback skipped.")); return; } MethodInfo method = type.GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { Plugin.Log.LogWarning((object)("[ModelFixer] " + typeName + ".Awake not found.")); return; } MethodInfo method2 = typeof(DirectorPatches).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic); if (!(method2 == null)) { harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogDebug((object)("[ModelFixer] Patched " + typeName + ".Awake")); } } private static void PostfixValuableDirectorAwake(MonoBehaviour __instance) { try { ProcessAllPrefabsInDirector(__instance, "Valuable"); } catch (Exception ex) { Plugin.Log.LogDebug((object)("[ModelFixer] ValuableDirector postfix error: " + ex.Message)); } } private static void PostfixEnemyDirectorAwake(MonoBehaviour __instance) { try { ProcessAllPrefabsInDirector(__instance, "Enemy"); } catch (Exception ex) { Plugin.Log.LogDebug((object)("[ModelFixer] EnemyDirector postfix error: " + ex.Message)); } } private static void ProcessAllPrefabsInDirector(MonoBehaviour director, string modName) { FieldInfo[] fields = ((object)director).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); for (int i = 0; i < fields.Length; i++) { object value = fields[i].GetValue(director); if (value == null) { continue; } GameObject val = (GameObject)((value is GameObject) ? value : null); if (val != null) { PrefabFixerPipeline.Process(val, modName); } else { if (!(value is IList list)) { continue; } foreach (object item in list) { if (item != null) { GameObject val2 = (GameObject)((item is GameObject) ? item : null); if (val2 != null) { PrefabFixerPipeline.Process(val2, modName); continue; } TryProcessPrefabField(item, modName); TryProcessSpawnObjects(item, modName); } } } } } private static void TryProcessPrefabField(object obj, string modName) { object? obj2 = (obj.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? obj.GetType().GetField("Prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(obj); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); if (val != null) { PrefabFixerPipeline.Process(val, modName); } } private static void TryProcessSpawnObjects(object obj, string modName) { if (!(obj.GetType().GetField("spawnObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj) is IList list)) { return; } foreach (object item in list) { if (item != null) { GameObject val = (GameObject)((item is GameObject) ? item : null); if (val != null) { PrefabFixerPipeline.Process(val, modName); } else { TryProcessPrefabField(item, modName); } } } } private static Type? FindTypeInAssembly(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(typeName); if (type != null) { return type; } } return null; } } internal static class REPOLibPatches { internal static void Apply(Harmony harmony) { PatchMethod(harmony, "REPOLib.Modules.Valuables, REPOLib", "RegisterValuable", "PostfixRegisterValuable"); PatchMethod(harmony, "REPOLib.Modules.Enemies, REPOLib", "RegisterEnemy", "PostfixRegisterEnemy"); PatchMethod(harmony, "REPOLib.Modules.Items, REPOLib", "RegisterItem", "PostfixRegisterItem"); } private static void PatchMethod(Harmony harmony, string typeName, string methodName, string postfixName) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown Type type = Type.GetType(typeName); if (type == null) { Plugin.Log.LogDebug((object)("[ModelFixer] Type not found: " + typeName)); return; } MethodInfo methodInfo = null; MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.Name == methodName) { methodInfo = methodInfo2; break; } } if (methodInfo == null) { Plugin.Log.LogDebug((object)("[ModelFixer] Method not found: " + typeName + "." + methodName)); return; } MethodInfo method = typeof(REPOLibPatches).GetMethod(postfixName, BindingFlags.Static | BindingFlags.NonPublic); if (method == null) { Plugin.Log.LogWarning((object)("[ModelFixer] Postfix not found: " + postfixName)); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogDebug((object)("[ModelFixer] Patched " + typeName + "." + methodName)); } private static void PostfixRegisterValuable(object[] __args) { try { if (__args != null && __args.Length != 0) { object obj = __args[0]; MonoBehaviour val = (MonoBehaviour)((obj is MonoBehaviour) ? obj : null); if (!((Object)(object)val == (Object)null)) { PrefabFixerPipeline.Process(((Component)val).gameObject, "Valuable"); } } } catch (Exception ex) { Plugin.Log.LogDebug((object)("[ModelFixer] PostfixRegisterValuable error: " + ex.Message)); } } private static void PostfixRegisterEnemy(object[] __args) { try { if (__args != null && __args.Length != 0) { object obj = __args[0]; if (obj != null) { ProcessEnemyContent(obj); } } } catch (Exception ex) { Plugin.Log.LogDebug((object)("[ModelFixer] PostfixRegisterEnemy error: " + ex.Message)); } } private static void PostfixRegisterItem(object[] __args) { try { if (__args == null || __args.Length == 0) { return; } object obj = __args[0]; if (obj == null) { return; } object obj2 = obj.GetType().GetField("item", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj); if (obj2 != null) { object? obj3 = obj2.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(obj2); GameObject val = (GameObject)((obj3 is GameObject) ? obj3 : null); if ((Object)(object)val != (Object)null) { PrefabFixerPipeline.Process(val, "Item"); } } } catch (Exception ex) { Plugin.Log.LogDebug((object)("[ModelFixer] PostfixRegisterItem error: " + ex.Message)); } } private static void ProcessEnemyContent(object content) { if (!(content.GetType().GetField("spawnObjects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(content) is IList list)) { return; } foreach (object item in list) { if (item != null) { object? obj = item.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val != (Object)null) { PrefabFixerPipeline.Process(val, "Enemy"); } } } } } } namespace REPOModelFixer.Fixers { internal static class BoundsCalculator { internal static Bounds? Calculate(GameObject root) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) Transform transform = root.transform; bool valid = false; Bounds result = default(Bounds); Collider[] componentsInChildren = root.GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if (!val.isTrigger) { BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null); if (val2 != null) { EncapsulateBox(val2, transform, ref result, ref valid); } else { EncapsulateWorldBounds(val.bounds, transform, ref result, ref valid); } } } if (!valid) { return null; } return result; } private static void EncapsulateBox(BoxCollider box, Transform rootTf, ref Bounds result, ref bool valid) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)box).transform; Vector3 center = box.center; Vector3 val = box.size * 0.5f; for (int i = 0; i < 8; i++) { Vector3 val2 = center + new Vector3(((i & 1) == 0) ? (0f - val.x) : val.x, ((i & 2) == 0) ? (0f - val.y) : val.y, ((i & 4) == 0) ? (0f - val.z) : val.z); Vector3 val3 = transform.TransformPoint(val2); Vector3 val4 = rootTf.InverseTransformPoint(val3); if (!valid) { result = new Bounds(val4, Vector3.zero); valid = true; } else { ((Bounds)(ref result)).Encapsulate(val4); } } } private static void EncapsulateWorldBounds(Bounds worldBounds, Transform rootTf, ref Bounds result, ref bool valid) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) Vector3 min = ((Bounds)(ref worldBounds)).min; Vector3 max = ((Bounds)(ref worldBounds)).max; Vector3 val = default(Vector3); for (int i = 0; i < 8; i++) { ((Vector3)(ref val))..ctor(((i & 1) == 0) ? min.x : max.x, ((i & 2) == 0) ? min.y : max.y, ((i & 4) == 0) ? min.z : max.z); Vector3 val2 = rootTf.InverseTransformPoint(val); if (!valid) { result = new Bounds(val2, Vector3.zero); valid = true; } else { ((Bounds)(ref result)).Encapsulate(val2); } } } } internal static class CenterOfMassFixer { internal static bool Fix(GameObject root, Bounds? bounds, string context) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (!bounds.HasValue) { return false; } Rigidbody component = root.GetComponent<Rigidbody>(); if ((Object)(object)component == (Object)null) { return false; } Transform transform = ((Component)component).transform; Transform transform2 = root.transform; Bounds value = bounds.Value; Vector3 val = transform2.TransformPoint(((Bounds)(ref value)).center); Vector3 val2 = transform.InverseTransformPoint(val); Vector3 centerOfMass = component.centerOfMass; Vector3 val3 = centerOfMass - val2; if (((Vector3)(ref val3)).sqrMagnitude < 0.0004f) { return false; } component.centerOfMass = val2; if (Plugin.VerboseLogging.Value) { Plugin.Log.LogDebug((object)$"[ModelFixer][CoM] {context}: {centerOfMass}→{val2}"); } return true; } } internal static class HierarchyChecker { internal static bool Check(GameObject root, string context, bool autoFix) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (!((Object)(object)root.GetComponent<MeshRenderer>() != (Object)null) && !((Object)(object)root.GetComponent<SkinnedMeshRenderer>() != (Object)null)) { return false; } Plugin.Log.LogWarning((object)("[ModelFixer][Hierarchy] " + context + ": MeshRenderer found directly on prefab root. " + (autoFix ? "Auto-fixing hierarchy." : "Consider moving mesh under an 'Object' child."))); if (!autoFix) { return false; } GameObject val = new GameObject("Object"); val.transform.SetParent(root.transform, false); MoveComponentToChild<MeshFilter>(root, val); MoveComponentToChild<MeshRenderer>(root, val); MoveComponentToChild<SkinnedMeshRenderer>(root, val); if (Plugin.VerboseLogging.Value) { Plugin.Log.LogDebug((object)("[ModelFixer][Hierarchy] " + context + ": moved mesh components to 'Object' child.")); } return true; } private static void MoveComponentToChild<T>(GameObject source, GameObject dest) where T : Component { T component = source.GetComponent<T>(); if ((Object)(object)component == (Object)null) { return; } T val = dest.AddComponent<T>(); FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { try { fieldInfo.SetValue(val, fieldInfo.GetValue(component)); } catch { } } Object.Destroy((Object)(object)component); } } internal static class MeshColliderFixer { internal static bool Fix(GameObject root, string context) { bool result = false; MeshCollider[] componentsInChildren = root.GetComponentsInChildren<MeshCollider>(true); foreach (MeshCollider val in componentsInChildren) { if (((Collider)val).isTrigger || val.convex) { continue; } val.convex = true; GameObject gameObject = ((Component)val).gameObject; bool num = (Object)(object)gameObject.GetComponent("PhysGrabObjectCollider") != (Object)null; bool flag = (Object)(object)root.GetComponent("PhysGrabObject") != (Object)null; if (!num && flag) { Type type = FindTypeInDomain("PhysGrabObjectCollider"); if (type != null) { gameObject.AddComponent(type); } } if (Plugin.VerboseLogging.Value) { Plugin.Log.LogDebug((object)("[ModelFixer][MeshCollider] " + context + "/" + ((Object)gameObject).name + ": convex = true")); } result = true; } return result; } private static Type? FindTypeInDomain(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(typeName); if (type != null) { return type; } } return null; } } internal static class RoomVolumeCheckFixer { private static FieldInfo? _checkPositionField; private static FieldInfo? _currentSizeField; private static bool _reflectionReady; private static bool _reflectionFailed; internal static bool Fix(GameObject root, Bounds? bounds, string context) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) if (!bounds.HasValue) { return false; } Component component = root.GetComponent("RoomVolumeCheck"); MonoBehaviour val = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null); if ((Object)(object)val == (Object)null) { return false; } EnsureReflection(val); if (_reflectionFailed) { return false; } Bounds value = bounds.Value; try { Vector3 val2 = (Vector3)(((??)(Vector3?)_checkPositionField.GetValue(val)) ?? Vector3.zero); Vector3 val3 = (Vector3)(((??)(Vector3?)_currentSizeField.GetValue(val)) ?? Vector3.zero); Vector3 val4 = val2 - ((Bounds)(ref value)).center; bool num = ((Vector3)(ref val4)).sqrMagnitude > 0.0025f; val4 = val3 - ((Bounds)(ref value)).size; bool flag = ((Vector3)(ref val4)).sqrMagnitude > 0.0025f; if (!num && !flag) { return false; } _checkPositionField.SetValue(val, ((Bounds)(ref value)).center); _currentSizeField.SetValue(val, ((Bounds)(ref value)).size); if (Plugin.VerboseLogging.Value) { Plugin.Log.LogDebug((object)("[ModelFixer][RVC] " + context + ": " + $"center {val2}→{((Bounds)(ref value)).center} size {val3}→{((Bounds)(ref value)).size}")); } return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[ModelFixer][RVC] Reflection set failed for " + context + ": " + ex.Message)); return false; } } private static void EnsureReflection(MonoBehaviour rvc) { if (!_reflectionReady && !_reflectionFailed) { Type type = ((object)rvc).GetType(); _checkPositionField = FindField(type, "CheckPosition", "checkPosition"); _currentSizeField = FindField(type, "currentSize", "CurrentSize"); if (_checkPositionField == null || _currentSizeField == null) { Plugin.Log.LogWarning((object)"[ModelFixer][RVC] Could not find CheckPosition/currentSize fields on RoomVolumeCheck. Skipping RVC fix."); _reflectionFailed = true; } else { _reflectionReady = true; } } } private static FieldInfo? FindField(Type type, params string[] candidates) { foreach (string name in candidates) { FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { return field; } } return null; } } internal static class VolumeTypeFixer { private const int Tiny = 0; private const int Small = 1; private const int Medium = 2; private const int Big = 3; private const int Wide = 4; private const int Tall = 5; private const int VeryTall = 6; private static FieldInfo? _volumeTypeField; private static bool _reflectionReady; private static bool _reflectionFailed; internal static bool Fix(GameObject root, Bounds? bounds, string context) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (!bounds.HasValue) { return false; } Component component = root.GetComponent("ValuableObject"); MonoBehaviour val = (MonoBehaviour)(object)((component is MonoBehaviour) ? component : null); if ((Object)(object)val == (Object)null) { return false; } EnsureReflection(val); if (_reflectionFailed) { return false; } int num = Convert.ToInt32(_volumeTypeField.GetValue(val)); Bounds value = bounds.Value; int num2 = Classify(((Bounds)(ref value)).size); if (num == num2) { return false; } if (!IsSignificantlyWrong(num, num2)) { return false; } _volumeTypeField.SetValue(val, Enum.ToObject(_volumeTypeField.FieldType, num2)); _ = Plugin.VerboseLogging.Value; ManualLogSource log = Plugin.Log; string text = $"[ModelFixer][VolumeType] {context}: {num}→{num2} "; value = bounds.Value; log.LogInfo((object)(text + $"(size={((Bounds)(ref value)).size})")); return true; } private static int Classify(Vector3 size) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Abs(size.x); float num2 = Mathf.Abs(size.y); float num3 = Mathf.Abs(size.z); float num4 = Mathf.Max(num, num3); float num5 = num2; float num6 = Mathf.Max(new float[3] { num, num2, num3 }); float num7 = ((num4 > 0.001f) ? (num5 / num4) : 1f); float num8 = ((num5 > 0.001f) ? (num4 / num5) : 1f); if (num7 > 3f) { return 6; } if (num7 > 1.8f) { return 5; } if (num8 > 2f) { return 4; } if (num6 < 0.2f) { return 0; } if (num6 < 0.35f) { return 1; } if (num6 < 0.6f) { return 2; } return 3; } private static bool IsSignificantlyWrong(int current, int computed) { bool num = current >= 4; bool flag = computed >= 4; if (num != flag) { return true; } return Math.Abs(current - computed) >= 2; } private static void EnsureReflection(MonoBehaviour vo) { if (_reflectionReady || _reflectionFailed) { return; } _volumeTypeField = ((object)vo).GetType().GetField("volumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)vo).GetType().GetField("VolumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (_volumeTypeField == null) { if ((((object)vo).GetType().GetProperty("volumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? ((object)vo).GetType().GetProperty("VolumeType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) != null) { _reflectionFailed = true; Plugin.Log.LogWarning((object)"[ModelFixer][VolumeType] volumeType is a property, not a field. Skipping."); } else { _reflectionFailed = true; Plugin.Log.LogWarning((object)"[ModelFixer][VolumeType] Could not find volumeType field on ValuableObject. Skipping."); } } else { _reflectionReady = true; } } } }