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 MCZombieLegacyCompat v1.0.1
BepInEx/plugins/MCZombieLegacyCompat/MCZOMBIEfix.dll
Decompiled 4 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; using UnityEngine.AI; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace LegacyREPOCompat; [BepInPlugin("chatgpt.mczombiefix", "MCZOMBIEfix", "1.2.4")] public sealed class Plugin : BaseUnityPlugin { internal static ManualLogSource Log; internal static ConfigEntry<bool> GuaranteeMinecraftZombie; internal static ConfigEntry<bool> GuaranteeFreddyOnFNAF; internal static ConfigEntry<bool> VillageTargetedFixes; internal static ConfigEntry<bool> VillageBrokenChestContainment; internal static ConfigEntry<float> ArenaMusicMaxVolume; internal static ConfigEntry<bool> AutoSkipPrivateHostPassword; internal static ConfigEntry<bool> AutoPickBestRegionPrivateHost; internal static ConfigEntry<bool> VillageCleanupCrewTruckStartGuard; internal static ConfigEntry<bool> ShowAllEnemyHealthBars; internal static ConfigEntry<float> EnemyHealthBarMaxDistance; internal static ConfigEntry<float> EnemyHealthBarVisibleSeconds; internal static ConfigEntry<bool> VillageClickToggleDoors; internal static ConfigEntry<float> VillageLegacyEnemyTeleportSafeSeconds; internal static ConfigEntry<bool> RepairMinecraftLoadingGraphics; private Harmony _harmony; private void Awake() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; GuaranteeMinecraftZombie = ((BaseUnityPlugin)this).Config.Bind<bool>("MCZombie Compatibility", "Guarantee Zombie On Minecraft Maps", true, "On Minecraft maps, guarantees MCZombie by replacing one already-selected enemy slot of the same difficulty tier. It never adds an extra enemy group above the level's normal quota."); GuaranteeFreddyOnFNAF = ((BaseUnityPlugin)this).Config.Bind<bool>("Freddy Compatibility", "Guarantee Freddy On FNAF", true, "On FNAF levels, guarantees Freddy by replacing one already-selected enemy slot of the same difficulty tier. It never increases the normal enemy quota."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"MCZOMBIEfix 1.2.4 loaded."); _harmony = new Harmony("chatgpt.mczombiefix.v124"); Bridge.InstallBackroomsEnemySpawnFix(_harmony); ((MonoBehaviour)this).StartCoroutine(Bridge.MinecraftZombieLiveGuaranteeLoop()); ((MonoBehaviour)this).StartCoroutine(Bridge.MinecraftZombieDiagnosticsLoop()); Bridge.InstallMCZombieLegacyEnemyLookupFix(_harmony); ((MonoBehaviour)this).StartCoroutine(Bridge.FreddyFNAFLiveGuaranteeLoop()); if (GuaranteeMinecraftZombie.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[MCZOMBIEfix] MCZombie Minecraft live quota replacement active."); } if (GuaranteeFreddyOnFNAF.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[MCZOMBIEfix] Freddy FNAF live quota replacement active."); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[MCZOMBIEfix] MCZombie legacy horde enemy lookup compatibility active."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[MCZOMBIEfix] Backrooms FirstSpawnPointAdd replacement active; no Arena, Village, lobby or enemy-HUD repair is enabled."); } } public static class Bridge { private static bool _warpPathLogged; private static readonly Dictionary<string, List<GameObject>> ValuableCache = new Dictionary<string, List<GameObject>>(StringComparer.OrdinalIgnoreCase); private static bool _backroomsSpawnSuppressionLogged; private static bool _backroomsSpawnReplacementLogged; private static bool _backroomsNoLevelPointLogged; private static int _backroomsSpawnPointAssignments; private static EnemySetup _mcZombieSetup; private static EnemySetup _freddySetup; private static readonly Dictionary<int, float> FreddyLevelFirstSeenAt = new Dictionary<int, float>(); private static readonly HashSet<int> FreddyLiveDoneForGenerator = new HashSet<int>(); private static readonly Dictionary<int, EnemyParent> FreddyPendingVictim = new Dictionary<int, EnemyParent>(); private static readonly Dictionary<int, float> FreddyPendingAt = new Dictionary<int, float>(); private static readonly Dictionary<int, int> FreddyPendingActiveBefore = new Dictionary<int, int>(); private static readonly HashSet<int> FreddyLiveWaitLogged = new HashSet<int>(); private static readonly Dictionary<int, float> MinecraftZombieLevelFirstSeenAt = new Dictionary<int, float>(); private static readonly HashSet<int> MinecraftZombieLiveDoneForGenerator = new HashSet<int>(); private static readonly Dictionary<int, EnemyParent> MinecraftZombiePendingVictim = new Dictionary<int, EnemyParent>(); private static readonly Dictionary<int, float> MinecraftZombiePendingAt = new Dictionary<int, float>(); private static readonly Dictionary<int, int> MinecraftZombiePendingActiveBefore = new Dictionary<int, int>(); private static readonly HashSet<int> MinecraftZombieLiveWaitLogged = new HashSet<int>(); private static readonly Dictionary<int, EnemyParent> MinecraftZombieTracked = new Dictionary<int, EnemyParent>(); private static readonly HashSet<int> MinecraftZombieSpawnLogged = new HashSet<int>(); private static readonly HashSet<int> MinecraftZombieInvalidLogged = new HashSet<int>(); private static readonly Dictionary<int, Vector3> MinecraftZombieSafeBodyPosition = new Dictionary<int, Vector3>(); private static readonly Dictionary<int, Vector3> MinecraftZombieSafeParentPosition = new Dictionary<int, Vector3>(); private static readonly Dictionary<int, int> MinecraftZombieRescueCount = new Dictionary<int, int>(); private static readonly HashSet<int> VillageRescuedValuables = new HashSet<int>(); private static readonly HashSet<int> VillageRescueCandidateLogged = new HashSet<int>(); private static readonly Dictionary<int, Vector3> VillageRescueTargets = new Dictionary<int, Vector3>(); private static readonly Dictionary<int, int> VillageRescueRetryCounts = new Dictionary<int, int>(); private static readonly HashSet<int> VillageChestContainmentLogged = new HashSet<int>(); private static readonly HashSet<int> ArenaAudioSourcesCapped = new HashSet<int>(); private static readonly HashSet<string> SoundPlayLoopSignaturesLogged = new HashSet<string>(); private static bool _privateHostPasswordFlowArmed; private static float _privateHostPasswordFlowArmedAt = -1000f; private static bool _privateHostPasswordConfirmed; private static bool _privatePasswordPatchLogged; private static bool _privateHostRegionFlowArmed; private static float _privateHostRegionFlowArmedAt = -1000f; private static bool _privateHostRegionConfirmed; private static bool _privateRegionPatchLogged; private static int _villageNullDoorPrefabSkips; private static readonly Dictionary<int, float> VillageGeneratorFirstSeenAt = new Dictionary<int, float>(); private static readonly HashSet<int> VillageCleanupCrewRelocatedInstances = new HashSet<int>(); private static readonly HashSet<int> VillageTruckEnemyLoggedInstances = new HashSet<int>(); private static readonly Dictionary<int, float> EnemyObservedMaxHealth = new Dictionary<int, float>(); private static readonly Dictionary<int, GameObject> EnemyNativeHealthRoots = new Dictionary<int, GameObject>(); private static readonly Dictionary<int, float> EnemyLastObservedHealth = new Dictionary<int, float>(); private static readonly Dictionary<int, float> EnemyHealthVisibleUntil = new Dictionary<int, float>(); private static GameObject _nativeEnemyHealthTemplate; private static bool _enemyHealthReflectionLogged; private static bool _damageShowConflictLogged; private static readonly HashSet<int> VillageDoorToggleInstalled = new HashSet<int>(); private static readonly HashSet<int> VillageCleanupCrewTeleportBlockedInstances = new HashSet<int>(); private static bool _villageLegacyTPPatchInstalled; private static bool _minecraftLoadingReferenceMigrationInstalled; private static bool _minecraftLoadingGraphicPatchInstalled; private static readonly HashSet<string> MinecraftLoadingGraphicAppliedLevels = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> MinecraftLoadingGraphicMissingLogged = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static Sprite[] _villageGeneratedLoadingSprites; private static bool _villageGeneratedLoadingSpritesLogged; private static GameObject _villageLoadingOverlayRoot; private static Image _villageLoadingOverlayImage; private static int _villageLoadingOverlayGeneration; private static bool _strongholdDoorAudioResolved; private static bool _strongholdDoorAudioMissingLogged; private static AudioSource _strongholdDoorOpenSource; private static AudioSource _strongholdDoorCloseSource; private static AudioClip _villageWoodDoorOpenClip; private static AudioClip _villageWoodDoorCloseClip; private static bool _villageWoodDoorAudioResolved; private static bool _villageWoodDoorAudioMissingLogged; private static readonly Dictionary<string, GameObject> LegacyNetworkPrefabCache = new Dictionary<string, GameObject>(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary<string, string> PluginBundlePathCache = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> PluginBundlePathMissing = new HashSet<string>(StringComparer.OrdinalIgnoreCase); public static void RegisterEnemy(EnemySetup setup) { if ((Object)(object)setup != (Object)null) { _mcZombieSetup = setup; } try { Assembly assembly = FindAssembly("REPOLib"); if (!(assembly == null) && !((Object)(object)setup == (Object)null)) { Type contentType = assembly.GetType("REPOLib.Objects.Sdk.EnemyContent", throwOnError: false); Type type = assembly.GetType("REPOLib.Modules.Enemies", throwOnError: false); if (contentType == null || type == null) { throw new MissingMemberException("REPOLib 4 EnemyContent/Enemies introuvable."); } Object val = (Object)(object)ScriptableObject.CreateInstance(contentType); FieldInfo field = contentType.GetField("_setup", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = contentType.GetField("_spawnObjects", BindingFlags.Instance | BindingFlags.NonPublic); if (val == (Object)null || field == null || field2 == null) { throw new MissingFieldException("EnemyContent _setup/_spawnObjects introuvable."); } List<GameObject> list = FindZombieEnemyPrefabs(); if (list.Count == 0) { throw new Exception("Prefab Enemy - MCZombie introuvable."); } field.SetValue(val, setup); field2.SetValue(val, list); MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "RegisterEnemy" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == contentType); if (methodInfo == null) { throw new MissingMethodException("RegisterEnemy(EnemyContent) introuvable."); } methodInfo.Invoke(null, new object[1] { val }); Info("MCZombie: enemy registered through REPOLib 4."); } } catch (Exception ex) { Error("MCZombie RegisterEnemy bridge failed: " + Unwrap(ex)); } } public static void InstallMCZombieLegacyEnemyLookupFix(Harmony harmony) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.Enemies", throwOnError: false)); if (!(type == null)) { MethodInfo method = type.GetMethod("GetEnemyByName", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); MethodInfo method2 = typeof(Bridge).GetMethod("MCZombieLegacyGetEnemyByNamePrefix", BindingFlags.Static | BindingFlags.Public); if (!(method == null) && !(method2 == null)) { harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Info("MCZombie legacy GetEnemyByName bridge installed."); } } } catch (Exception ex) { Warn("MCZombie legacy GetEnemyByName bridge failed: " + Unwrap(ex)); } } public static bool MCZombieLegacyGetEnemyByNamePrefix(string name, ref EnemySetup __result) { if (string.IsNullOrEmpty(name) || (name.IndexOf("Zombie", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) < 0)) { return true; } EnemySetup found = _mcZombieSetup; if ((Object)(object)found == (Object)null) { TryFindModernEnemySetupContains("Zombie", out found); } if ((Object)(object)found == (Object)null) { return true; } __result = found; Info("MCZombie legacy GetEnemyByName redirected to modern EnemySetup | requested='" + name + "'."); return false; } private static bool TryFindModernEnemySetupContains(string contains, out EnemySetup found) { found = null; try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.Enemies", throwOnError: false)); if (type == null) { return false; } string[] array = new string[2] { "AllEnemies", "RegisteredEnemies" }; for (int i = 0; i < array.Length; i++) { PropertyInfo property = type.GetProperty(array[i], BindingFlags.Static | BindingFlags.Public); if (property == null || !(property.GetValue(null, null) is IEnumerable enumerable)) { continue; } foreach (object item in enumerable) { EnemySetup val = (EnemySetup)((item is EnemySetup) ? item : null); if (!((Object)(object)val == (Object)null)) { string text = ""; try { text = ((Object)val).name ?? ""; } catch { } TryGetEnemySetupIdentity(val, out var _, out var enemyName); if (text.IndexOf(contains, StringComparison.OrdinalIgnoreCase) >= 0 || (!string.IsNullOrEmpty(enemyName) && enemyName.IndexOf(contains, StringComparison.OrdinalIgnoreCase) >= 0)) { found = val; return true; } } } } } catch (Exception ex) { Warn("Modern enemy setup lookup failed for '" + contains + "': " + Unwrap(ex)); } return false; } public static IEnumerator FreddyFNAFLiveGuaranteeLoop() { while (true) { yield return (object)new WaitForSeconds(2f); try { if (Plugin.GuaranteeFreddyOnFNAF != null && Plugin.GuaranteeFreddyOnFNAF.Value && IsFNAFLevelName(GetCurrentLevelName()) && IsHostOrSingleplayer()) { if (!((Object)(object)_freddySetup == (Object)null)) { goto IL_009a; } if (TryFindModernEnemySetupContains("Freddy", out var found)) { _freddySetup = found; Info("Freddy modern EnemySetup resolved for FNAF quota guarantee."); goto IL_009a; } } goto end_IL_0043; IL_009a: LevelGenerator instance = LevelGenerator.Instance; if ((Object)(object)instance == (Object)null) { continue; } int instanceID = ((Object)instance).GetInstanceID(); if (!FreddyLevelFirstSeenAt.TryGetValue(instanceID, out var value)) { value = Time.realtimeSinceStartup; FreddyLevelFirstSeenAt[instanceID] = value; } if (FreddyLiveDoneForGenerator.Contains(instanceID) || Time.realtimeSinceStartup - value < 10f) { continue; } EnemyParent value2 = null; bool flag = FreddyPendingVictim.TryGetValue(instanceID, out value2); int num = CountActiveFreddys(); if (num > 0) { if (flag) { int value3 = -1; FreddyPendingActiveBefore.TryGetValue(instanceID, out value3); string text = (((Object)(object)value2 != (Object)null) ? (value2.enemyName ?? ((Object)value2).name ?? "<unknown>") : "<already gone>"); if ((Object)(object)value2 != (Object)null) { RemoveEnemyParentFromDirector(value2); DestroyEnemyParentNetworkSafe(value2); } int num2 = CountActiveEnemyParents(); FreddyLiveDoneForGenerator.Add(instanceID); FreddyPendingVictim.Remove(instanceID); FreddyPendingAt.Remove(instanceID); FreddyPendingActiveBefore.Remove(instanceID); Info("Freddy FNAF QUOTA REPLACE complete | replaced='" + text + "' | activeBefore=" + value3 + " | activeAfter=" + num2 + " | freddyCount=" + num + " | level='" + GetCurrentLevelName() + "'"); } else { FreddyLiveDoneForGenerator.Add(instanceID); Info("Freddy FNAF QUOTA OK | Freddy already active naturally | count=" + num + " | level='" + GetCurrentLevelName() + "'"); } } else if (flag) { float value4 = 0f; FreddyPendingAt.TryGetValue(instanceID, out value4); if (Time.realtimeSinceStartup - value4 > 6f) { Warn("Freddy FNAF QUOTA spawn verification timed out; original enemy kept."); FreddyPendingVictim.Remove(instanceID); FreddyPendingAt.Remove(instanceID); FreddyPendingActiveBefore.Remove(instanceID); } } else { BeginFreddyLiveReplacement(instanceID); } end_IL_0043:; } catch (Exception ex) { Error("Freddy FNAF quota replacement failed: " + Unwrap(ex)); } } } private static void BeginFreddyLiveReplacement(int generatorId) { //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: 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) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Invalid comparison between Unknown and I4 //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) int difficulty = -1; string enemyName = "Freddy"; if (!TryGetEnemySetupIdentity(_freddySetup, out difficulty, out enemyName)) { if (!FreddyLiveWaitLogged.Contains(generatorId)) { FreddyLiveWaitLogged.Add(generatorId); Warn("Freddy FNAF QUOTA: Freddy difficulty unavailable; waiting."); } return; } EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); if (array == null || array.Length == 0) { return; } Transform val = FindAnyPlayerTransform(); EnemyParent val2 = null; float num = -1f; EnemyParent[] array2 = array; foreach (EnemyParent val3 in array2) { if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null || !((Component)val3).gameObject.activeInHierarchy) { continue; } string text = val3.enemyName ?? ((Object)val3).name ?? string.Empty; if (text.IndexOf("Freddy", StringComparison.OrdinalIgnoreCase) < 0 && (int)val3.difficulty == difficulty) { float num2 = (((Object)(object)val != (Object)null) ? Vector3.Distance(val.position, ((Component)val3).transform.position) : 0f); if ((Object)(object)val2 == (Object)null || num2 > num) { val2 = val3; num = num2; } } } if ((Object)(object)val2 == (Object)null) { if (!FreddyLiveWaitLogged.Contains(generatorId)) { FreddyLiveWaitLogged.Add(generatorId); Warn("Freddy FNAF QUOTA: no active enemy of Freddy tier " + difficulty + " available to replace without changing the quota."); } return; } int num3 = CountActiveEnemyParents(); Vector3 position = ((Component)val2).transform.position; Vector3 val4 = position; NavMeshHit val5 = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val5, 6f, -1)) { val4 = ((NavMeshHit)(ref val5)).position; } Quaternion rotation = ((Component)val2).transform.rotation; if (!SpawnEnemyThroughModernREPOLib(_freddySetup, val4, rotation)) { Warn("Freddy FNAF QUOTA: modern Freddy spawn failed; original enemy kept."); return; } FreddyPendingVictim[generatorId] = val2; FreddyPendingAt[generatorId] = Time.realtimeSinceStartup; FreddyPendingActiveBefore[generatorId] = num3; Info("Freddy FNAF QUOTA REPLACE pending | replace='" + (val2.enemyName ?? ((Object)val2).name ?? "<unknown>") + "' | tier=" + difficulty + " | activeBefore=" + num3 + " | spawnAt=" + Vec(val4) + " | level='" + GetCurrentLevelName() + "'"); } private static bool SpawnEnemyThroughModernREPOLib(EnemySetup setup, Vector3 position, Quaternion rotation) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)setup == (Object)null) { return false; } try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.Enemies", throwOnError: false)); if (type == null) { return false; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "SpawnEnemy") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 4 && parameters[0].ParameterType == typeof(EnemySetup) && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion) && parameters[3].ParameterType == typeof(bool); }); if (methodInfo == null) { return false; } object obj = methodInfo.Invoke(null, new object[4] { setup, position, rotation, false }); if (!(obj is IEnumerable enumerable)) { return obj != null; } foreach (object item in enumerable) { if (item != null) { return true; } } return false; } catch (Exception ex) { Error("Modern enemy spawn failed: " + Unwrap(ex)); return false; } } private static int CountActiveFreddys() { int num = 0; EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); if (array == null) { return 0; } EnemyParent[] array2 = array; foreach (EnemyParent val in array2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { string text = val.enemyName ?? ((Object)val).name ?? string.Empty; if (text.IndexOf("Freddy", StringComparison.OrdinalIgnoreCase) >= 0) { num++; } } } return num; } public static IEnumerator MinecraftZombieLiveGuaranteeLoop() { while (true) { yield return (object)new WaitForSeconds(2f); try { if (Plugin.GuaranteeMinecraftZombie == null || !Plugin.GuaranteeMinecraftZombie.Value || !IsMinecraftLevelName(GetCurrentLevelName()) || !IsHostOrSingleplayer() || (Object)(object)_mcZombieSetup == (Object)null) { continue; } LevelGenerator instance = LevelGenerator.Instance; if ((Object)(object)instance == (Object)null) { continue; } int instanceID = ((Object)instance).GetInstanceID(); if (!MinecraftZombieLevelFirstSeenAt.TryGetValue(instanceID, out var value)) { value = Time.realtimeSinceStartup; MinecraftZombieLevelFirstSeenAt[instanceID] = value; } if (MinecraftZombieLiveDoneForGenerator.Contains(instanceID) || Time.realtimeSinceStartup - value < 10f) { continue; } EnemyParent value2 = null; bool flag = MinecraftZombiePendingVictim.TryGetValue(instanceID, out value2); int num = CountActiveMCZombies(); if (num > 0) { if (flag) { int value3 = -1; MinecraftZombiePendingActiveBefore.TryGetValue(instanceID, out value3); string text = (((Object)(object)value2 != (Object)null) ? (value2.enemyName ?? ((Object)value2).name ?? "<unknown>") : "<already gone>"); if ((Object)(object)value2 != (Object)null) { RemoveEnemyParentFromDirector(value2); DestroyEnemyParentNetworkSafe(value2); } int num2 = CountActiveEnemyParents(); MinecraftZombieLiveDoneForGenerator.Add(instanceID); MinecraftZombiePendingVictim.Remove(instanceID); MinecraftZombiePendingAt.Remove(instanceID); MinecraftZombiePendingActiveBefore.Remove(instanceID); Info("MCZombie LIVE QUOTA REPLACE complete | replaced='" + text + "' | activeBefore=" + value3 + " | activeAfter=" + num2 + " | zombieCount=" + num + " | level='" + GetCurrentLevelName() + "'"); } else { MinecraftZombieLiveDoneForGenerator.Add(instanceID); Info("MCZombie LIVE QUOTA OK | zombie already active naturally | count=" + num + " | level='" + GetCurrentLevelName() + "'"); } } else if (flag) { float value4 = 0f; MinecraftZombiePendingAt.TryGetValue(instanceID, out value4); if (Time.realtimeSinceStartup - value4 > 6f) { Warn("MCZombie LIVE QUOTA REPLACE spawn verification timed out; original enemy kept."); MinecraftZombiePendingVictim.Remove(instanceID); MinecraftZombiePendingAt.Remove(instanceID); MinecraftZombiePendingActiveBefore.Remove(instanceID); } } else { BeginMinecraftZombieLiveReplacement(instanceID); } } catch (Exception ex) { Error("MCZombie live quota replacement failed: " + Unwrap(ex)); } } } public static IEnumerator MinecraftZombieDiagnosticsLoop() { NavMeshHit val2 = default(NavMeshHit); while (true) { yield return (object)new WaitForSeconds(1f); try { if (!IsMinecraftLevelName(GetCurrentLevelName())) { MinecraftZombieTracked.Clear(); MinecraftZombieSpawnLogged.Clear(); MinecraftZombieInvalidLogged.Clear(); MinecraftZombieSafeBodyPosition.Clear(); MinecraftZombieSafeParentPosition.Clear(); MinecraftZombieRescueCount.Clear(); continue; } EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); if (array != null) { EnemyParent[] array2 = array; foreach (EnemyParent val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } string text = val.enemyName ?? ((Object)val).name ?? string.Empty; if (text.IndexOf("Zombie", StringComparison.OrdinalIgnoreCase) >= 0 || (((Object)val).name ?? string.Empty).IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) >= 0) { int instanceID = ((Object)val).GetInstanceID(); MinecraftZombieTracked[instanceID] = val; if (!MinecraftZombieSpawnLogged.Contains(instanceID)) { MinecraftZombieSpawnLogged.Add(instanceID); bool flag = NavMesh.SamplePosition(((Component)val).transform.position, ref val2, 1.5f, -1); Enemy componentInChildren = ((Component)val).GetComponentInChildren<Enemy>(true); float current = -1f; float maximum = -1f; bool flag2 = (Object)(object)componentInChildren != (Object)null && TryGetEnemyHealth(componentInChildren, out current, out maximum); Transform minecraftZombieBodyTransform = GetMinecraftZombieBodyTransform(val); Vector3 val3 = (((Object)(object)minecraftZombieBodyTransform != (Object)null) ? minecraftZombieBodyTransform.position : ((Component)val).transform.position); MinecraftZombieSafeBodyPosition[instanceID] = val3; MinecraftZombieSafeParentPosition[instanceID] = ((Component)val).transform.position; MinecraftZombieRescueCount[instanceID] = 0; Info("MCZombie TRACK start | id=" + instanceID + " | parentPos=" + Vec(((Component)val).transform.position) + " | bodyPos=" + Vec(val3) + " | active=" + ((Component)val).gameObject.activeInHierarchy + " | onNavMesh=" + flag + (flag2 ? (" | hp=" + current.ToString("0.##") + "/" + maximum.ToString("0.##")) : " | hp=<unavailable>")); } } } } KeyValuePair<int, EnemyParent>[] array3 = MinecraftZombieTracked.ToArray(); for (int j = 0; j < array3.Length; j++) { KeyValuePair<int, EnemyParent> keyValuePair = array3[j]; int key = keyValuePair.Key; EnemyParent value = keyValuePair.Value; bool flag3 = (Object)(object)value == (Object)null || (Object)(object)((Component)value).gameObject == (Object)null || !((Component)value).gameObject.activeInHierarchy; float current2 = -1f; float maximum2 = -1f; bool flag4 = false; if (!flag3) { Enemy componentInChildren2 = ((Component)value).GetComponentInChildren<Enemy>(true); flag4 = (Object)(object)componentInChildren2 != (Object)null && TryGetEnemyHealth(componentInChildren2, out current2, out maximum2); if (flag4 && current2 <= 0.01f) { flag3 = true; } if (!flag3) { RescueMinecraftZombieIfFalling(key, value); } } if (flag3 && !MinecraftZombieInvalidLogged.Contains(key)) { MinecraftZombieInvalidLogged.Add(key); string text2 = (((Object)(object)value != (Object)null) ? Vec(((Component)value).transform.position) : "<destroyed>"); Warn("MCZombie TRACK invalid/dead | id=" + key + " | pos=" + text2 + (flag4 ? (" | hp=" + current2.ToString("0.##") + "/" + maximum2.ToString("0.##")) : " | hp=<unavailable>") + " | level='" + GetCurrentLevelName() + "'"); } } } catch (Exception ex) { Warn("MCZombie diagnostics failed: " + Unwrap(ex)); } } } private static Transform GetMinecraftZombieBodyTransform(EnemyParent parent) { if ((Object)(object)parent == (Object)null || (Object)(object)((Component)parent).gameObject == (Object)null) { return null; } try { Transform val = ((Component)parent).transform.Find("Enable/Rigidbody/Center"); if ((Object)(object)val != (Object)null) { return val; } Rigidbody[] componentsInChildren = ((Component)parent).GetComponentsInChildren<Rigidbody>(true); if (componentsInChildren != null && componentsInChildren.Length > 0) { Rigidbody val2 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody b) => (Object)(object)b != (Object)null && ((Object)b).name.IndexOf("Rigidbody", StringComparison.OrdinalIgnoreCase) >= 0)); if ((Object)(object)val2 == (Object)null) { val2 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody b) => (Object)(object)b != (Object)null && !b.isKinematic)); } if ((Object)(object)val2 == (Object)null) { val2 = ((IEnumerable<Rigidbody>)componentsInChildren).FirstOrDefault((Func<Rigidbody, bool>)((Rigidbody b) => (Object)(object)b != (Object)null)); } if ((Object)(object)val2 != (Object)null) { return ((Component)val2).transform; } } Enemy componentInChildren = ((Component)parent).GetComponentInChildren<Enemy>(true); if ((Object)(object)componentInChildren != (Object)null) { return ((Component)componentInChildren).transform; } } catch { } return ((Component)parent).transform; } private static void RescueMinecraftZombieIfFalling(int id, EnemyParent parent) { //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0174: 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_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parent == (Object)null || (Object)(object)((Component)parent).gameObject == (Object)null) { return; } Transform minecraftZombieBodyTransform = GetMinecraftZombieBodyTransform(parent); if ((Object)(object)minecraftZombieBodyTransform == (Object)null) { return; } if (!MinecraftZombieSafeBodyPosition.TryGetValue(id, out var value)) { value = minecraftZombieBodyTransform.position; MinecraftZombieSafeBodyPosition[id] = value; } if (!MinecraftZombieSafeParentPosition.TryGetValue(id, out var value2)) { value2 = ((Component)parent).transform.position; MinecraftZombieSafeParentPosition[id] = value2; } Vector3 position = minecraftZombieBodyTransform.position; bool flag = !float.IsNaN(position.x) && !float.IsNaN(position.y) && !float.IsNaN(position.z) && !float.IsInfinity(position.x) && !float.IsInfinity(position.y) && !float.IsInfinity(position.z); if (flag && position.y >= value.y - 2.5f) { NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val, 2f, -1)) { MinecraftZombieSafeBodyPosition[id] = position; MinecraftZombieSafeParentPosition[id] = ((Component)parent).transform.position; } } else { if (flag && position.y >= value.y - 8f) { return; } int value3 = 0; MinecraftZombieRescueCount.TryGetValue(id, out value3); value3++; MinecraftZombieRescueCount[id] = value3; Vector3 val2 = value2; NavMeshHit val3 = default(NavMeshHit); if (NavMesh.SamplePosition(value2, ref val3, 4f, -1)) { val2 = ((NavMeshHit)(ref val3)).position; } Vector3 val4 = val2 - ((Component)parent).transform.position; ((Component)parent).transform.position = val2; object obj = GetMemberValue(parent, "Enemy"); if (obj == null) { obj = ((Component)parent).GetComponentInChildren<Enemy>(true); } object obj2 = ((obj == null) ? null : GetMemberValue(obj, "NavMeshAgent")); if (obj2 == null && obj != null) { obj2 = GetMemberValue(obj, "navMeshAgent"); } if (obj2 != null) { WarpCompat(obj2, val2); } Rigidbody[] componentsInChildren = ((Component)parent).GetComponentsInChildren<Rigidbody>(true); if (componentsInChildren != null) { Rigidbody[] array = componentsInChildren; foreach (Rigidbody val5 in array) { if (!((Object)(object)val5 == (Object)null)) { Vector3 position2 = (val5.position = (((Object)(object)((Component)val5).transform == (Object)(object)minecraftZombieBodyTransform) ? value : (val5.position + val4))); ((Component)val5).transform.position = position2; if (!val5.isKinematic) { val5.velocity = Vector3.zero; val5.angularVelocity = Vector3.zero; } val5.WakeUp(); } } } minecraftZombieBodyTransform.position = value; Physics.SyncTransforms(); Warn("MCZombie FALL RESCUE | id=" + id + " | count=" + value3 + " | fallenBody=" + Vec(position) + " | restoredBody=" + Vec(value) + " | parent=" + Vec(val2) + " | level='" + GetCurrentLevelName() + "'"); } } private static void BeginMinecraftZombieLiveReplacement(int generatorId) { //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected I4, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) int difficulty = -1; string enemyName = "Zombie"; if (!TryGetEnemySetupIdentity(_mcZombieSetup, out difficulty, out enemyName)) { if (!MinecraftZombieLiveWaitLogged.Contains(generatorId)) { MinecraftZombieLiveWaitLogged.Add(generatorId); Warn("MCZombie LIVE QUOTA: zombie difficulty unavailable; waiting."); } return; } EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); if (array == null || array.Length == 0) { return; } Transform val = FindAnyPlayerTransform(); EnemyParent val2 = null; float num = -1f; EnemyParent[] array2 = array; foreach (EnemyParent val3 in array2) { if ((Object)(object)val3 == (Object)null || (Object)(object)((Component)val3).gameObject == (Object)null || !((Component)val3).gameObject.activeInHierarchy) { continue; } string text = val3.enemyName ?? ((Object)val3).name ?? string.Empty; if (text.IndexOf("Zombie", StringComparison.OrdinalIgnoreCase) >= 0 || (((Object)val3).name ?? string.Empty).IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } int num2 = (int)val3.difficulty; if (num2 == difficulty) { float num3 = (((Object)(object)val != (Object)null) ? Vector3.Distance(val.position, ((Component)val3).transform.position) : 0f); if ((Object)(object)val2 == (Object)null || num3 > num) { val2 = val3; num = num3; } } } if ((Object)(object)val2 == (Object)null) { if (!MinecraftZombieLiveWaitLogged.Contains(generatorId)) { MinecraftZombieLiveWaitLogged.Add(generatorId); Warn("MCZombie LIVE QUOTA: no active enemy of zombie tier " + difficulty + " available to replace without changing the tier quota."); } return; } int num4 = CountActiveEnemyParents(); Vector3 position = ((Component)val2).transform.position; Vector3 val4 = position; NavMeshHit val5 = default(NavMeshHit); bool flag = NavMesh.SamplePosition(position, ref val5, 6f, -1); if (flag) { val4 = ((NavMeshHit)(ref val5)).position; } Quaternion rotation = ((Component)val2).transform.rotation; Info("MCZombie spawn position resolved | requested=" + Vec(position) + " | final=" + Vec(val4) + " | navMeshSnapped=" + flag + " | victim='" + (val2.enemyName ?? ((Object)val2).name ?? "<unknown>") + "'"); if (!SpawnMCZombieThroughModernREPOLib(val4, rotation)) { Warn("MCZombie LIVE QUOTA: modern zombie spawn failed; original enemy kept."); return; } MinecraftZombiePendingVictim[generatorId] = val2; MinecraftZombiePendingAt[generatorId] = Time.realtimeSinceStartup; MinecraftZombiePendingActiveBefore[generatorId] = num4; Info("MCZombie LIVE QUOTA REPLACE pending | replace='" + (val2.enemyName ?? ((Object)val2).name ?? "<unknown>") + "' | tier=" + difficulty + " | activeBefore=" + num4 + " | spawnAt=" + Vec(val4) + " | level='" + GetCurrentLevelName() + "'"); } private static bool SpawnMCZombieThroughModernREPOLib(Vector3 position, Quaternion rotation) { //IL_0087: 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) try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.Enemies", throwOnError: false)); if (type == null) { return false; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "SpawnEnemy") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 4 && parameters[0].ParameterType == typeof(EnemySetup) && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion) && parameters[3].ParameterType == typeof(bool); }); if (methodInfo == null) { return false; } object obj = methodInfo.Invoke(null, new object[4] { _mcZombieSetup, position, rotation, false }); if (!(obj is IEnumerable enumerable)) { return obj != null; } foreach (object item in enumerable) { if (item != null) { return true; } } return false; } catch (Exception ex) { Error("MCZombie modern live replacement spawn failed: " + Unwrap(ex)); return false; } } private static int CountActiveMCZombies() { int num = 0; EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); if (array == null) { return 0; } EnemyParent[] array2 = array; foreach (EnemyParent val in array2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { string text = val.enemyName ?? ((Object)val).name ?? string.Empty; if (text.IndexOf("Zombie", StringComparison.OrdinalIgnoreCase) >= 0 || (((Object)val).name ?? string.Empty).IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) >= 0) { num++; } } } return num; } private static int CountActiveEnemyParents() { int num = 0; EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); if (array == null) { return 0; } EnemyParent[] array2 = array; foreach (EnemyParent val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && ((Component)val).gameObject.activeInHierarchy) { num++; } } return num; } private static void RemoveEnemyParentFromDirector(EnemyParent parent) { if ((Object)(object)parent == (Object)null) { return; } try { EnemyDirector val = Object.FindObjectOfType<EnemyDirector>(); if (!((Object)(object)val == (Object)null) && GetMemberValue(val, "enemiesSpawned") is IList list && list.Contains(parent)) { list.Remove(parent); } } catch (Exception ex) { Warn("MCZombie quota replacement could not remove old EnemyParent from director list: " + Unwrap(ex)); } } private static void DestroyEnemyParentNetworkSafe(EnemyParent parent) { if ((Object)(object)parent == (Object)null || (Object)(object)((Component)parent).gameObject == (Object)null) { return; } GameObject gameObject = ((Component)parent).gameObject; try { Assembly assembly = FindAssembly("PhotonUnityNetworking"); Type type = ((assembly == null) ? null : assembly.GetType("Photon.Pun.PhotonNetwork", throwOnError: false)); MethodInfo methodInfo = ((type == null) ? null : type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "Destroy") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject); })); if (methodInfo != null) { methodInfo.Invoke(null, new object[1] { gameObject }); return; } } catch (Exception ex) { Warn("Photon destroy of replaced enemy failed; falling back to Unity destroy: " + Unwrap(ex)); } Object.Destroy((Object)(object)gameObject); } private static bool IsMCZombieSetup(EnemySetup setup) { if ((Object)(object)setup == (Object)null) { return false; } if (object.ReferenceEquals(setup, _mcZombieSetup)) { return true; } string text = ((Object)setup).name ?? string.Empty; if (text.IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("MC Zombie", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } if (!TryGetEnemySetupIdentity(setup, out var _, out var enemyName)) { return false; } if (enemyName.IndexOf("MCZombie", StringComparison.OrdinalIgnoreCase) < 0) { return enemyName.IndexOf("MC Zombie", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool TryGetEnemySetupIdentity(EnemySetup setup, out int difficulty, out string enemyName) { //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Expected I4, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected I4, but got Unknown difficulty = -1; enemyName = (((Object)(object)setup == (Object)null) ? string.Empty : (((Object)setup).name ?? string.Empty)); if ((Object)(object)setup == (Object)null) { return false; } try { object memberValue = GetMemberValue(setup, "spawnObjects"); if (memberValue is IEnumerable enumerable) { foreach (object item in enumerable) { GameObject val = ResolveEnemySpawnPrefab(item); if ((Object)(object)val == (Object)null) { continue; } EnemyParent val2 = val.GetComponentsInChildren<EnemyParent>(true)?.FirstOrDefault((Func<EnemyParent, bool>)((EnemyParent p) => (Object)(object)p != (Object)null)); if (!((Object)(object)val2 == (Object)null)) { difficulty = (int)val2.difficulty; if (!string.IsNullOrEmpty(val2.enemyName)) { enemyName = val2.enemyName; } return true; } } } if (object.ReferenceEquals(setup, _mcZombieSetup)) { List<GameObject> list = FindZombieEnemyPrefabs(); foreach (GameObject item2 in list) { if ((Object)(object)item2 == (Object)null) { continue; } EnemyParent val3 = item2.GetComponentsInChildren<EnemyParent>(true)?.FirstOrDefault((Func<EnemyParent, bool>)((EnemyParent p) => (Object)(object)p != (Object)null)); if (!((Object)(object)val3 == (Object)null)) { difficulty = (int)val3.difficulty; if (!string.IsNullOrEmpty(val3.enemyName)) { enemyName = val3.enemyName; } return true; } } } } catch (Exception ex) { Warn("MCZombie enemy-setup identity inspection failed: " + Unwrap(ex)); } return false; } private static GameObject ResolveEnemySpawnPrefab(object spawnObject) { if (spawnObject == null) { return null; } GameObject val = (GameObject)((spawnObject is GameObject) ? spawnObject : null); if ((Object)(object)val != (Object)null) { return val; } object memberValue = GetMemberValue(spawnObject, "Prefab"); GameObject val2 = (GameObject)((memberValue is GameObject) ? memberValue : null); if ((Object)(object)val2 != (Object)null) { return val2; } memberValue = GetMemberValue(spawnObject, "prefab"); return (GameObject)((memberValue is GameObject) ? memberValue : null); } private static bool IsFNAFLevelName(string levelName) { if (string.IsNullOrEmpty(levelName)) { return false; } if (levelName.IndexOf("FNAF", StringComparison.OrdinalIgnoreCase) < 0) { return levelName.IndexOf("Freddy", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool IsMinecraftLevelName(string levelName) { if (string.IsNullOrEmpty(levelName)) { return false; } if (levelName.IndexOf("Minecraft Village", StringComparison.OrdinalIgnoreCase) < 0 && levelName.IndexOf("Minecraft Cave", StringComparison.OrdinalIgnoreCase) < 0 && levelName.IndexOf("Minecraft Stronghold", StringComparison.OrdinalIgnoreCase) < 0) { return levelName.IndexOf("Stronghold", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static bool IsHostOrSingleplayer() { try { Assembly assembly = FindAssembly("PhotonUnityNetworking"); Type type = ((assembly == null) ? null : assembly.GetType("Photon.Pun.PhotonNetwork", throwOnError: false)); if (type == null) { return true; } PropertyInfo property = type.GetProperty("OfflineMode", BindingFlags.Static | BindingFlags.Public); if (property != null && Convert.ToBoolean(property.GetValue(null, null))) { return true; } PropertyInfo property2 = type.GetProperty("IsMasterClient", BindingFlags.Static | BindingFlags.Public); if (property2 == null) { return true; } return Convert.ToBoolean(property2.GetValue(null, null)); } catch { return true; } } private static Transform FindAnyPlayerTransform() { try { Assembly assembly = FindAssembly("Assembly-CSharp"); Type type = ((assembly == null) ? null : assembly.GetType("PlayerAvatar", throwOnError: false)); if (type == null) { return null; } Object[] array = Object.FindObjectsOfType(type); if (array == null || array.Length == 0) { return null; } Object[] array2 = array; foreach (Object val in array2) { Component val2 = (Component)(object)((val is Component) ? val : null); if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.transform == (Object)null) && val2.gameObject.activeInHierarchy) { object memberValue = GetMemberValue(val2, "isLocal"); if (memberValue is bool && (bool)memberValue) { return val2.transform; } memberValue = GetMemberValue(val2, "isLocalPlayer"); if (memberValue is bool && (bool)memberValue) { return val2.transform; } } } Object obj = array[0]; Component val3 = (Component)(object)((obj is Component) ? obj : null); return ((Object)(object)val3 == (Object)null) ? null : val3.transform; } catch { return null; } } public static IEnumerator AllEnemyNativeHealthLoop() { while (true) { yield return (object)new WaitForSeconds(0.12f); try { if (Plugin.ShowAllEnemyHealthBars == null || !Plugin.ShowAllEnemyHealthBars.Value) { HideAllNativeEnemyHealth(); } else if (IsDamageShowLoaded()) { HideAllNativeEnemyHealth(); if (!_damageShowConflictLogged) { _damageShowConflictLogged = true; Warn("Enemy Health UI paused because DamageShow/EnemyHealthBar is loaded. Remove or disable DamageShow to use LegacyREPOCompat native health bars."); } } else { UpdateNativeEnemyHealth(); } } catch (Exception ex) { if (!_enemyHealthReflectionLogged) { _enemyHealthReflectionLogged = true; Warn("Native enemy health UI failed: " + Unwrap(ex)); } } } } private static bool IsDamageShowLoaded() { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!(assembly == null)) { string text = assembly.GetName().Name ?? string.Empty; if (text.IndexOf("DamageShow", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("EnemyHealthBar", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } } catch { } return false; } private static void HideAllNativeEnemyHealth() { GameObject[] array = EnemyNativeHealthRoots.Values.ToArray(); foreach (GameObject val in array) { if ((Object)(object)val != (Object)null) { val.SetActive(false); } } } private static void UpdateNativeEnemyHealth() { //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindNativeEnemyHealthTemplate(); if ((Object)(object)val == (Object)null) { return; } Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return; } EnemyParent[] array = Object.FindObjectsOfType<EnemyParent>(); HashSet<int> hashSet = new HashSet<int>(); float num = ((Plugin.EnemyHealthBarMaxDistance != null) ? Plugin.EnemyHealthBarMaxDistance.Value : 40f); float num2 = ((Plugin.EnemyHealthBarVisibleSeconds != null) ? Plugin.EnemyHealthBarVisibleSeconds.Value : 4f); EnemyParent[] array2 = array; foreach (EnemyParent val2 in array2) { if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).gameObject == (Object)null || !((Component)val2).gameObject.activeInHierarchy) { continue; } Enemy componentInChildren = ((Component)val2).GetComponentInChildren<Enemy>(true); if ((Object)(object)componentInChildren == (Object)null) { continue; } int instanceID = ((Object)val2).GetInstanceID(); hashSet.Add(instanceID); float current; float maximum; bool flag = TryGetEnemyHealth(componentInChildren, out current, out maximum); GameObject value = null; EnemyNativeHealthRoots.TryGetValue(instanceID, out value); if (!flag) { if ((Object)(object)value != (Object)null) { value.SetActive(false); } continue; } if (!EnemyLastObservedHealth.TryGetValue(instanceID, out var value2)) { EnemyLastObservedHealth[instanceID] = current; if (!(maximum > 0f) || !(current < maximum - 0.01f)) { if ((Object)(object)value != (Object)null) { value.SetActive(false); } continue; } EnemyHealthVisibleUntil[instanceID] = Time.realtimeSinceStartup + num2; } if (Mathf.Abs(current - value2) > 0.01f) { EnemyHealthVisibleUntil[instanceID] = Time.realtimeSinceStartup + num2; EnemyLastObservedHealth[instanceID] = current; } else { EnemyLastObservedHealth[instanceID] = current; } float value3 = -1000f; EnemyHealthVisibleUntil.TryGetValue(instanceID, out value3); if (Time.realtimeSinceStartup > value3) { if ((Object)(object)value != (Object)null) { value.SetActive(false); } continue; } float num3 = Vector3.Distance(((Component)main).transform.position, ((Component)val2).transform.position); if (num3 > num) { if ((Object)(object)value != (Object)null) { value.SetActive(false); } continue; } GameObject val3 = value; if ((Object)(object)val3 == (Object)null) { val3 = CreateNativeEnemyHealthRoot(componentInChildren, val); if ((Object)(object)val3 == (Object)null) { continue; } EnemyNativeHealthRoots[instanceID] = val3; Info("Native enemy HealthUI attached | enemy=" + (val2.enemyName ?? ((Object)val2).name ?? "<unnamed>") + " | hp=" + current.ToString("0.##") + "/" + maximum.ToString("0.##")); } val3.SetActive(true); val3.transform.position = GetEnemyHealthAnchorFromHitbox(val2, componentInChildren); val3.transform.rotation = ((Component)main).transform.rotation; GameObject val4 = FindChildGameObject(val3.transform, "Health"); if ((Object)(object)val4 != (Object)null) { SetAnyTextComponent(val4, Mathf.CeilToInt(current).ToString()); GameObject val5 = FindChildGameObject(val4.transform, "HealthMax"); if ((Object)(object)val5 != (Object)null) { SetAnyTextComponent(val5, Mathf.CeilToInt(maximum).ToString()); } } } KeyValuePair<int, GameObject>[] array3 = EnemyNativeHealthRoots.ToArray(); for (int j = 0; j < array3.Length; j++) { KeyValuePair<int, GameObject> keyValuePair = array3[j]; if (!hashSet.Contains(keyValuePair.Key)) { if ((Object)(object)keyValuePair.Value != (Object)null) { Object.Destroy((Object)(object)keyValuePair.Value); } EnemyNativeHealthRoots.Remove(keyValuePair.Key); EnemyObservedMaxHealth.Remove(keyValuePair.Key); EnemyLastObservedHealth.Remove(keyValuePair.Key); EnemyHealthVisibleUntil.Remove(keyValuePair.Key); } } } private static Vector3 GetEnemyHealthAnchorFromHitbox(EnemyParent parent, Enemy enemy) { //IL_002d: 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_0062: 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) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)parent != (Object)null) ? ((Component)parent).transform : (((Object)(object)enemy != (Object)null) ? ((Component)enemy).transform : null)); if ((Object)(object)val == (Object)null) { return Vector3.zero; } Collider[] colliders = (((Object)(object)parent != (Object)null) ? ((Component)parent).GetComponentsInChildren<Collider>(true) : ((Component)enemy).GetComponentsInChildren<Collider>(true)); Bounds bounds; bool flag = TryGetCompactEnemyColliderBounds(colliders, val.position, includeTriggers: false, out bounds); if (!flag) { flag = TryGetCompactEnemyColliderBounds(colliders, val.position, includeTriggers: true, out bounds); } if (flag) { return new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + 0.08f, ((Bounds)(ref bounds)).center.z); } Renderer[] array = (((Object)(object)parent != (Object)null) ? ((Component)parent).GetComponentsInChildren<Renderer>(true) : ((Component)enemy).GetComponentsInChildren<Renderer>(true)); bool flag2 = false; Bounds val2 = default(Bounds); ((Bounds)(ref val2))..ctor(val.position, Vector3.zero); Renderer[] array2 = array; foreach (Renderer val3 in array2) { if ((Object)(object)val3 == (Object)null || !val3.enabled || !((Component)val3).gameObject.activeInHierarchy) { continue; } Bounds bounds2 = val3.bounds; Vector3 size = ((Bounds)(ref bounds2)).size; if (!(((Vector3)(ref size)).magnitude > 6f) && !(Vector3.Distance(((Bounds)(ref bounds2)).center, val.position) > 4f)) { if (!flag2) { val2 = bounds2; flag2 = true; } else { ((Bounds)(ref val2)).Encapsulate(bounds2); } } } if (flag2) { return new Vector3(((Bounds)(ref val2)).center.x, ((Bounds)(ref val2)).max.y + 0.08f, ((Bounds)(ref val2)).center.z); } return val.position + Vector3.up * 1.6f; } private static bool TryGetCompactEnemyColliderBounds(Collider[] colliders, Vector3 enemyOrigin, bool includeTriggers, out Bounds bounds) { //IL_0001: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0087: 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_007d: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; if (colliders == null) { return false; } foreach (Collider val in colliders) { if ((Object)(object)val == (Object)null || !val.enabled || (!includeTriggers && val.isTrigger)) { continue; } Bounds bounds2 = val.bounds; Vector3 size = ((Bounds)(ref bounds2)).size; float magnitude = ((Vector3)(ref size)).magnitude; float num = Vector3.Distance(((Bounds)(ref bounds2)).center, enemyOrigin); if (!(magnitude < 0.05f) && !(magnitude > 6f) && !(num > 4f)) { if (!flag) { bounds = bounds2; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(bounds2); } } } return flag; } private static GameObject FindNativeEnemyHealthTemplate() { if ((Object)(object)_nativeEnemyHealthTemplate != (Object)null) { return _nativeEnemyHealthTemplate; } Transform[] array = Object.FindObjectsOfType<Transform>(); Transform[] array2 = array; foreach (Transform val in array2) { if (!((Object)(object)val == (Object)null) && string.Equals(((Object)val).name, "Health", StringComparison.OrdinalIgnoreCase)) { Component[] components = ((Component)val).GetComponents<Component>(); if (components.Any((Component c) => (Object)(object)c != (Object)null && string.Equals(((object)c).GetType().Name, "HealthUI", StringComparison.OrdinalIgnoreCase))) { _nativeEnemyHealthTemplate = ((Component)val).gameObject; Info("Native enemy HUD template resolved: " + GetHierarchyPath(val)); return _nativeEnemyHealthTemplate; } } } return null; } private static GameObject CreateNativeEnemyHealthRoot(Enemy enemy, GameObject template) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_005a: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject("LegacyREPOCompat - Native Enemy Health"); Canvas val2 = val.AddComponent<Canvas>(); val2.renderMode = (RenderMode)2; val2.worldCamera = Camera.main; val2.sortingOrder = 1000; RectTransform component = val.GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(220f, 70f); } val.transform.localScale = Vector3.one * 0.006f; GameObject val3 = Object.Instantiate<GameObject>(template, val.transform, false); ((Object)val3).name = "Health"; val3.SetActive(true); Component[] components = val3.GetComponents<Component>(); Component[] array = components; foreach (Component val4 in array) { if (!((Object)(object)val4 == (Object)null) && string.Equals(((object)val4).GetType().Name, "HealthUI", StringComparison.OrdinalIgnoreCase)) { Behaviour val5 = (Behaviour)(object)((val4 is Behaviour) ? val4 : null); if ((Object)(object)val5 != (Object)null) { val5.enabled = false; } Object.Destroy((Object)(object)val4); } } RectTransform component2 = val3.GetComponent<RectTransform>(); if ((Object)(object)component2 != (Object)null) { component2.anchorMin = new Vector2(0.5f, 0.5f); component2.anchorMax = new Vector2(0.5f, 0.5f); component2.pivot = new Vector2(0.5f, 0.5f); component2.anchoredPosition = Vector2.zero; ((Transform)component2).localScale = Vector3.one; } return val; } catch (Exception ex) { Warn("Could not create native enemy HealthUI clone: " + Unwrap(ex)); return null; } } private static bool TryGetEnemyHealth(Enemy enemy, out float current, out float maximum) { current = 0f; maximum = 0f; if ((Object)(object)enemy == (Object)null) { return false; } object memberValue = GetMemberValue(enemy, "Health"); if (memberValue == null) { return false; } string[] names = new string[7] { "healthCurrent", "currentHealth", "HealthCurrent", "health", "Health", "hp", "HP" }; string[] names2 = new string[8] { "healthMax", "maxHealth", "HealthMax", "MaxHealth", "healthMaximum", "maximumHealth", "startingHealth", "startHealth" }; bool flag = TryReadNumericMember(memberValue, names, out current); bool flag2 = TryReadNumericMember(memberValue, names2, out maximum); if (!flag) { Type type = memberValue.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo[] fields = type.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { string text = fieldInfo.Name.ToLowerInvariant(); if (text.Contains("health") && !text.Contains("max") && !text.Contains("previous") && !text.Contains("old")) { object value; try { value = fieldInfo.GetValue(memberValue); } catch { continue; } if (TryConvertFloat(value, out current)) { flag = true; break; } } } } if (!flag) { return false; } int instanceID = ((Object)enemy).GetInstanceID(); if (!flag2 || maximum <= 0f) { if (!EnemyObservedMaxHealth.TryGetValue(instanceID, out var value2)) { value2 = current; } value2 = Mathf.Max(value2, current); EnemyObservedMaxHealth[instanceID] = value2; maximum = value2; } else { EnemyObservedMaxHealth[instanceID] = Mathf.Max(maximum, current); maximum = Mathf.Max(maximum, current); } current = Mathf.Max(0f, current); return maximum > 0f; } private static GameObject FindChildGameObject(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true); Transform[] array = componentsInChildren; foreach (Transform val in array) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase)) { return ((Component)val).gameObject; } } return null; } private static void SetAnyTextComponent(GameObject obj, string text) { if ((Object)(object)obj == (Object)null) { return; } Component[] components = obj.GetComponents<Component>(); Component[] array = components; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(property == null) && property.CanWrite && !(property.PropertyType != typeof(string))) { try { property.SetValue(val, text, null); break; } catch { } } } } private static bool TryReadNumericMember(object target, string[] names, out float value) { value = 0f; if (target == null) { return false; } foreach (string name in names) { object memberValue = GetMemberValue(target, name); if (TryConvertFloat(memberValue, out value)) { return true; } } return false; } private static bool TryConvertFloat(object value, out float result) { result = 0f; if (value == null) { return false; } try { if (value is float) { result = (float)value; return true; } if (value is double) { result = (float)(double)value; return true; } if (value is int) { result = (int)value; return true; } if (value is uint) { result = (uint)value; return true; } if (value is short) { result = (short)value; return true; } if (value is ushort) { result = (int)(ushort)value; return true; } if (value is byte) { result = (int)(byte)value; return true; } if (value is long) { result = (long)value; return true; } result = Convert.ToSingle(value); return true; } catch { return false; } } public static IEnumerator ArenaAudioLimiterLoop() { while (true) { yield return (object)new WaitForSeconds(0.75f); try { string currentLevelName = GetCurrentLevelName(); if (string.IsNullOrEmpty(currentLevelName) || currentLevelName.IndexOf("Arena", StringComparison.OrdinalIgnoreCase) < 0) { continue; } float num = ((Plugin.ArenaMusicMaxVolume == null) ? 0.3f : Mathf.Clamp01(Plugin.ArenaMusicMaxVolume.Value)); AudioSource[] array = Object.FindObjectsOfType<AudioSource>(); AudioSource[] array2 = array; foreach (AudioSource val in array2) { if (!((Object)(object)val == (Object)null) && val.isPlaying && val.loop && !((Object)(object)val.clip == (Object)null) && !(val.clip.length < 15f)) { if (val.volume > num) { val.volume = num; } int instanceID = ((Object)val).GetInstanceID(); if (!ArenaAudioSourcesCapped.Contains(instanceID)) { ArenaAudioSourcesCapped.Add(instanceID); Info("ARENA MUSIC CAPPED | " + GetHierarchyPath(((Component)val).transform) + " | clip=" + ((Object)val.clip).name + " | max=" + num); } } } } catch (Exception ex) { Warn("Arena music limiter failed: " + Unwrap(ex)); } } } public static void SoundPlayLoopLegacyCompat(object sound, bool playing, float pitch, float volume, float fade) { if (sound == null) { return; } try { Type type = sound.GetType(); MethodInfo[] array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "PlayLoop" orderby m.GetParameters().Length select m).ToArray(); MethodInfo[] array2 = array; foreach (MethodInfo methodInfo in array2) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] array3 = new object[parameters.Length]; int num2 = 0; bool flag = true; for (int num3 = 0; num3 < parameters.Length; num3++) { ParameterInfo parameterInfo = parameters[num3]; string text = (parameterInfo.Name ?? string.Empty).ToLowerInvariant(); if (parameterInfo.ParameterType == typeof(bool)) { array3[num3] = playing; } else if (parameterInfo.ParameterType == typeof(float)) { float num4; if (text.Contains("pitch")) { num4 = pitch; } else if (text.Contains("volume")) { num4 = volume; } else if (text.Contains("fade") || text.Contains("time")) { num4 = fade; } else { num4 = num2 switch { 1 => volume, 0 => pitch, _ => fade, }; num2++; } if (text.Contains("volume") && CurrentLevelContains("Arena") && Plugin.ArenaMusicMaxVolume != null) { num4 = Mathf.Min(num4, Plugin.ArenaMusicMaxVolume.Value); } array3[num3] = num4; } else { if (!parameterInfo.HasDefaultValue) { flag = false; break; } array3[num3] = parameterInfo.DefaultValue; } } if (flag) { try { methodInfo.Invoke(sound, array3); return; } catch { } } } string item = type.FullName + "::PlayLoop"; if (!SoundPlayLoopSignaturesLogged.Contains(item)) { SoundPlayLoopSignaturesLogged.Add(item); Warn("Legacy Sound.PlayLoop bridge found no compatible current overload on " + type.FullName + ". Current overloads: " + string.Join(" | ", array.Select(DescribeMethod).ToArray())); } } catch (Exception ex) { Warn("Legacy Sound.PlayLoop bridge failed: " + Unwrap(ex)); } } private static string DescribeMethod(MethodInfo method) { if (method == null) { return "<null>"; } return method.Name + "(" + string.Join(",", (from p in method.GetParameters() select p.ParameterType.Name + " " + p.Name).ToArray()) + ")"; } public static void RegisterNetworkPrefabLegacyCompat(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return; } try { CacheLegacyNetworkPrefab(prefab); Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false)); if (type == null) { return; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "RegisterNetworkPrefab") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject); }); if (methodInfo != null) { methodInfo.Invoke(null, new object[1] { prefab }); } Info("PaintedUtils: legacy network prefab registered/cached | id='" + ((Object)prefab).name + "'."); } catch (Exception ex) { Warn("PaintedUtils RegisterNetworkPrefab compatibility warning | prefab='" + (((Object)(object)prefab != (Object)null) ? ((Object)prefab).name : "<null>") + "' | " + Unwrap(ex)); } } private static void CacheLegacyNetworkPrefab(GameObject prefab) { if ((Object)(object)prefab == (Object)null || string.IsNullOrEmpty(((Object)prefab).name)) { return; } LegacyNetworkPrefabCache[((Object)prefab).name] = prefab; if (((Object)prefab).name.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { string text = ((Object)prefab).name.Substring(0, ((Object)prefab).name.Length - "(Clone)".Length).Trim(); if (!string.IsNullOrEmpty(text)) { LegacyNetworkPrefabCache[text] = prefab; } } } private static string NormalizePrefabId(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } string text = value.Trim(); if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - 7).Trim(); } char[] value2 = text.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray(); return new string(value2); } private static void EnsureLegacyNetworkPrefabRegistered(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return; } CacheLegacyNetworkPrefab(prefab); try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false)); if (type == null) { return; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "RegisterNetworkPrefab") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject); }); if (methodInfo != null) { methodInfo.Invoke(null, new object[1] { prefab }); Info("PaintedUtils: runtime network prefab registration ensured | id='" + ((Object)prefab).name + "'."); } } catch (Exception ex) { Warn("PaintedUtils runtime network prefab registration warning | prefab='" + ((Object)prefab).name + "' | " + Unwrap(ex)); } } private static GameObject FindLegacyNetworkPrefab(string prefabId) { if (string.IsNullOrEmpty(prefabId)) { return null; } if (LegacyNetworkPrefabCache.TryGetValue(prefabId, out var value) && (Object)(object)value != (Object)null) { return value; } GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); string text = NormalizePrefabId(prefabId); GameObject val = null; GameObject[] array2 = array; foreach (GameObject val2 in array2) { if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name)) { if (string.Equals(((Object)val2).name, prefabId, StringComparison.OrdinalIgnoreCase)) { CacheLegacyNetworkPrefab(val2); return val2; } if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(text) && string.Equals(NormalizePrefabId(((Object)val2).name), text, StringComparison.OrdinalIgnoreCase)) { val = val2; } } } if ((Object)(object)val != (Object)null) { CacheLegacyNetworkPrefab(val); Info("PaintedUtils: fuzzy legacy prefab resolved | requested='" + prefabId + "' | actual='" + ((Object)val).name + "'."); return val; } return null; } public static GameObject GetNetworkPrefabLegacyCompat(string prefabId) { try { if (string.IsNullOrEmpty(prefabId)) { return null; } GameObject val = FindLegacyNetworkPrefab(prefabId); if ((Object)(object)val != (Object)null) { return val; } Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false)); if (type == null) { return null; } PropertyInfo property = type.GetProperty("Prefabs", BindingFlags.Static | BindingFlags.Public); object obj = ((property == null) ? null : property.GetValue(null, null)); if (obj is IDictionary dictionary && dictionary.Contains(prefabId)) { object? obj2 = dictionary[prefabId]; return (GameObject)((obj2 is GameObject) ? obj2 : null); } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "GetNetworkPrefabRef" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(string)); if (methodInfo != null) { object value = methodInfo.Invoke(null, new object[1] { prefabId }); GameObject val2 = ToGameObject(value); if ((Object)(object)val2 != (Object)null) { return val2; } } return Resources.Load<GameObject>(prefabId); } catch (Exception ex) { Warn("PaintedUtils GetPrefab compatibility failed for '" + prefabId + "': " + Unwrap(ex)); return null; } } public static GameObject SpawnNetworkPrefabLegacyCompat(string prefabId, Vector3 position, Quaternion rotation, byte group, object[] data) { //IL_016f: 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) try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.NetworkPrefabs", throwOnError: false)); if (type == null) { throw new MissingMemberException("REPOLib.Modules.NetworkPrefabs introuvable."); } MethodInfo methodInfo = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "SpawnNetworkPrefab") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 5 && parameters[0].ParameterType.Name.IndexOf("PrefabRef", StringComparison.OrdinalIgnoreCase) >= 0 && parameters[1].ParameterType == typeof(Vector3) && parameters[2].ParameterType == typeof(Quaternion) && parameters[3].ParameterType == typeof(byte) && parameters[4].ParameterType == typeof(object[]); }); if (methodInfo == null) { throw new MissingMethodException("NetworkPrefabs.SpawnNetworkPrefab(PrefabRef, Vector3, Quaternion, byte, object[]) introuvable."); } MethodInfo methodInfo2 = type.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "GetNetworkPrefabRef" && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(string)); object obj = ((methodInfo2 == null) ? null : methodInfo2.Invoke(null, new object[1] { prefabId })); if (obj == null) { GameObject val = FindLegacyNetworkPrefab(prefabId); if ((Object)(object)val != (Object)null) { EnsureLegacyNetworkPrefabRegistered(val); if (methodInfo2 != null) { try { obj = methodInfo2.Invoke(null, new object[1] { prefabId }); } catch { obj = null; } } Type parameterType = methodInfo.GetParameters()[0].ParameterType; if (obj == null) { obj = ConstructPrefabRef(parameterType, val); } if (obj != null) { Info("PaintedUtils: built modern PrefabRef from legacy cached prefab | id='" + prefabId + "'."); } } } if (obj == null) { Warn("PaintedUtils: network prefab ID not registered/resolvable: " + prefabId); return null; } object? obj3 = methodInfo.Invoke(null, new object[5] { obj, position, rotation, group, data }); GameObject result = (GameObject)((obj3 is GameObject) ? obj3 : null); Info("PaintedUtils: legacy SpawnNetworkPrefab adapted for '" + prefabId + "'."); return result; } catch (Exception ex) { Error("PaintedUtils SpawnNetworkPrefab compatibility failed: " + Unwrap(ex)); return null; } } private static List<GameObject> GetLegacyBucket(object levelValuables, string bucket) { try { List<GameObject> list = new List<GameObject>(); if (levelValuables == null) { return list; } Type type = levelValuables.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo fieldInfo = type.GetFields(bindingAttr).FirstOrDefault((FieldInfo x) => string.Equals(x.Name, bucket, StringComparison.OrdinalIgnoreCase)); if (fieldInfo != null) { AddObjectsFromCollection(list, fieldInfo.GetValue(levelValuables)); } PropertyInfo propertyInfo = type.GetProperties(bindingAttr).FirstOrDefault((PropertyInfo x) => x.CanRead && string.Equals(x.Name, bucket, StringComparison.OrdinalIgnoreCase)); if (list.Count == 0 && propertyInfo != null) { AddObjectsFromCollection(list, propertyInfo.GetValue(levelValuables, null)); } if (list.Count > 0) { Info("Legacy valuable bridge: LevelValuables." + bucket + " converted to " + list.Count + " GameObject(s)."); return list; } Assembly assembly = FindAssembly("REPOLib"); if (assembly != null) { foreach (Type item in SafeGetTypes(assembly)) { if (item == null || item.Name.IndexOf("LevelValuables", StringComparison.OrdinalIgnoreCase) < 0) { continue; } MethodInfo[] methods = item.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name.IndexOf("Valuable", StringComparison.OrdinalIgnoreCase) < 0) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType.IsInstanceOfType(levelValuables)) { object collection = methodInfo.Invoke(null, new object[1] { levelValuables }); AddObjectsFromCollection(list, collection); if (list.Count > 0) { return list; } } } } } Warn("Legacy valuable bridge: could not resolve LevelValuables bucket '" + bucket + "'. Modern members: " + DescribeMembers(type)); return list; } catch (Exception ex) { Error("GetLegacyBucket(" + bucket + ") failed: " + Unwrap(ex)); return new List<GameObject>(); } } public static void InstallBackroomsEnemySpawnFix(Harmony harmony) { //IL_006f: 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_0082: Expected O, but got Unknown //IL_0082: Expected O, but got Unknown try { MethodInfo method = typeof(EnemyDirector).GetMethod("FirstSpawnPointAdd", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method2 = typeof(Bridge).GetMethod("BackroomsFirstSpawnPointPrefix", BindingFlags.Static | BindingFlags.Public); MethodInfo method3 = typeof(Bridge).GetMethod("BackroomsFirstSpawnPointFinalizer", BindingFlags.Static | BindingFlags.Public); if (method == null || method2 == null || method3 == null) { Warn("Backrooms: EnemyDirector.FirstSpawnPointAdd compatibility target not found."); return; } harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method3), (HarmonyMethod)null); Info("Backrooms: EnemyDirector.FirstSpawnPointAdd replacement patch active."); } catch (Exception ex) { Error("Backrooms enemy-spawn compatibility patch failed: " + Unwrap(ex)); } } public static bool BackroomsFirstSpawnPointPrefix(EnemyDirector __instance, EnemyParent _enemyParent) { //IL_0212: Unknown result type (might be due to invalid IL or missing references) if (!IsBackroomsLevel()) { return true; } try { if ((Object)(object)__instance == (Object)null || (Object)(object)_enemyParent == (Object)null) { return true; } List<LevelPoint> list = SemiFunc.LevelPointsGetAll(); if (list == null || list.Count == 0) { if (!_backroomsNoLevelPointLogged) { _backroomsNoLevelPointLogged = true; Warn("Backrooms: no LevelPoint available yet; falling back to vanilla FirstSpawnPointAdd."); } return true; } FieldInfo field = typeof(EnemyParent).GetField("firstSpawnPoint", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { Warn("Backrooms: EnemyParent.firstSpawnPoint field not found; falling back to vanilla."); return true; } FieldInfo field2 = typeof(EnemyDirector).GetField("enemyFirstSpawnPoints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); IList list2 = null; if (field2 != null) { object obj = field2.GetValue(__instance); if (obj == null) { try { obj = Activator.CreateInstance(field2.FieldType); field2.SetValue(__instance, obj); } catch { obj = null; } } list2 = obj as IList; } LevelPoint val = null; for (int i = 0; i < list.Count; i++) { LevelPoint val2 = list[i]; if (!((Object)(object)val2 == (Object)null) && !val2.Truck && (list2 == null || !list2.Contains(val2))) { val = val2; break; } } if ((Object)(object)val == (Object)null && list2 != null) { list2.Clear(); for (int j = 0; j < list.Count; j++) { LevelPoint val3 = list[j]; if (!((Object)(object)val3 == (Object)null) && !val3.Truck) { val = val3; break; } } } if ((Object)(object)val == (Object)null) { if (!_backroomsNoLevelPointLogged) { _backroomsNoLevelPointLogged = true; Warn("Backrooms: no usable non-truck LevelPoint found; falling back to vanilla."); } return true; } field.SetValue(_enemyParent, val); if (list2 != null && !list2.Contains(val)) { list2.Add(val); } _backroomsSpawnPointAssignments++; if (!_backroomsSpawnReplacementLogged) { _backroomsSpawnReplacementLogged = true; Info("Backrooms: FirstSpawnPointAdd replaced successfully; valid first spawn points are now assigned without running the broken vanilla body."); } if (_backroomsSpawnPointAssignments <= 6) { Info(string.Concat("Backrooms: assigned first spawn point #", _backroomsSpawnPointAssignments, " at ", ((Component)val).transform.position, " to enemy '", ((Object)_enemyParent).name, "'.")); } return false; } catch (Exception ex) { Error("Backrooms FirstSpawnPointAdd replacement failed; falling back to vanilla: " + Unwrap(ex)); return true; } } public static Exception BackroomsFirstSpawnPointFinalizer(Exception __exception) { if (__exception == null) { return null; } try { if (__exception is NullReferenceException && IsBackroomsLevel()) { if (!_backroomsSpawnSuppressionLogged) { _backroomsSpawnSuppressionLogged = true; Warn("Backrooms: fallback suppressed FirstSpawnPointAdd NullReferenceException."); } return null; } } catch (Exception ex) { Error("Backrooms FirstSpawnPointAdd fallback guard failed: " + Unwrap(ex)); } return __exception; } private static string GetCurrentLevelName() { try { FieldInfo field = typeof(RunManager).GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((field == null) ? null : field.GetValue(null)); if (obj == null) { return string.Empty; } object memberValue = GetMemberValue(obj, "levelCurrent"); if (memberValue == null) { return string.Empty; } Object val = (Object)((memberValue is Object) ? memberValue : null); if (val != (Object)null && !string.IsNullOrEmpty(val.name)) { return val.name; } object memberValue2 = GetMemberValue(memberValue, "name"); return (memberValue2 == null) ? string.Empty : memberValue2.ToString(); } catch { return string.Empty; } } private static bool CurrentLevelContains(string text) { string currentLevelName = GetCurrentLevelName(); if (!string.IsNullOrEmpty(currentLevelName)) { return currentLevelName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static bool IsBackroomsLevel() { return CurrentLevelContains("Backrooms"); } public static void InstallMinecraftLoadingReferenceMigration(Harmony harmony) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown if (harmony == null || Plugin.RepairMinecraftLoadingGraphics == null || !Plugin.RepairMinecraftLoadingGraphics.Value) { return; } try { Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.Levels", throwOnError: false)); MethodInfo methodInfo = ((type == null) ? null : type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return m.Name == "RegisterLevel" && parameters.Length == 1 && parameters[0].ParameterType.FullName == "REPOLib.Objects.Sdk.LevelContent"; })); MethodInfo method = typeof(Bridge).GetMethod("MinecraftLoadingReferenceRegistrationPrefix", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null || method == null) { Warn("Minecraft loading-reference migration unavailable: REPOLib Levels.RegisterLevel(LevelContent) not found."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _minecraftLoadingReferenceMigrationInstalled = true; Info("Minecraft loading-reference migration installed on REPOLib.Modules.Levels.RegisterLevel."); } catch (Exception ex) { Error("Minecraft loading-reference migration install failed: " + Unwrap(ex)); } } public static void MinecraftLoadingReferenceRegistrationPrefix(object __0) { if (!_minecraftLoadingReferenceMigrationInstalled || __0 == null || Plugin.RepairMinecraftLoadingGraphics == null || !Plugin.RepairMinecraftLoadingGraphics.Value) { return; } try { object memberValue = GetMemberValue(__0, "Level"); if (memberValue == null) { return; } Object val = (Object)((memberValue is Object) ? memberValue : null); string text = ((val != (Object)null) ? val.name : Convert.ToString(GetMemberValue(memberValue, "name"))); if (string.IsNullOrEmpty(text) || text.IndexOf("Minecraft Village", StringComparison.OrdinalIgnoreCase) < 0) { return; } object memberValue2 = GetMemberValue(__0, "Bundle"); AssetBundle val2 = (AssetBundle)((memberValue2 is AssetBundle) ? memberValue2 : null); if ((Object)(object)val2 == (Object)null) { Warn("MINECRAFT LOADING MIGRATION skipped | level='" + text + "' | LevelContent.Bundle=<null>"); return; } string[] allAssetNames = val2.GetAllAssetNames(); LogVillageLoadingAssetDiscovery(val2, allAssetNames); LogVillageLoadingLevelState(__0, memberValue); int num = 0; if (RepairEmptyLoadingGraphicReference(memberValue, "LoadingGraphic01", val2, allAssetNames, "village3")) { num++; } if (RepairEmptyLoadingGraphicReference(memberValue, "LoadingGraphic02", val2, allAssetNames, "village2")) { num++; } if (RepairEmptyLoadingGraphicReference(memberValue, "LoadingGraphic03", val2, allAssetNames, "village1")) { num++; } Info("MINECRAFT LOADING MIGRATION registration complete | level='" + text + "' | repaired=" + num + "/3"); } catch (Exception ex) { Warn("Minecraft loading-reference registration migration failed: " + Unwrap(ex)); } } private static void LogVillageLoadingAssetDiscovery(AssetBundle bundle, string[] assetNames) { if ((Object)(object)bundle == (Object)null) { Warn("MINECRAFT LOADING DISCOVERY skipped | bundle=<null>"); return; } if (assetNames == null) { assetNames = new string[0]; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; string[] array = assetNames; foreach (string text in array) { if (string.IsNullOrEmpty(text)) { continue; } string text2 = text.ToLowerInvariant(); bool flag = text2.EndsWith(".png") || text2.EndsWith(".jpg") || text2.EndsWith(".jpeg") || text2.EndsWith(".tga") || text2.EndsWith(".bmp") || text2.EndsWith(".psd"); bool flag2 = text2.IndexOf("load", StringComparison.Ordinal) >= 0 || text2.IndexOf("splash", StringComparison.Ordinal) >= 0 || text2.IndexOf("graphic", StringComparison.Ordinal) >= 0 || text2.IndexOf("title", StringComparison.Ordinal) >= 0 || text2.IndexOf("village", StringComparison.Ordinal) >= 0; if (!flag && !flag2) { continue; } num++; List<string> list = new List<string>(); try { Sprite val = bundle.LoadAsset<Sprite>(text); if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name)) { list.Add(((Object)val).name); } } catch { } try { Sprite[] array2 = bundle.LoadAssetWithSubAssets<Sprite>(text); if (array2 != null) { Sprite[] array3 = array2; foreach (Sprite val2 in array3) { if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name) && !list.Contains(((Object)val2).name)) { list.Add(((Object)val2).name); } } } } catch { } if (list.Count > 0) { num2++; if (num4 < 80) { Info("MINECRAFT LOADING DISCOVERY sprite asset | asset='" + text + "' | sprites='" + string.Join(",", list.ToArray()) + "'"); num4++; } continue; } try { Texture2D val3 = bundle.LoadAsset<Texture2D>(text); if ((Object)(object)val3 == (Object)null) { continue; } bool flag3 = ((Texture)val3).width >= 512 && ((Texture)val3).height >= 256; if (flag2 || flag3) { num3++; if (num5 < 80) { Info("MINECRAFT LOADING DISCOVERY texture asset | asset='" + text + "' | texture='" + ((Object)val3).name + "' | size=" + ((Texture)val3).width + "x" + ((Texture)val3).height + " | hint=" + flag2); num5++; } } } catch { } } Info("MINECRAFT LOADING DISCOVERY summary | totalAssets=" + assetNames.Length + " | plausiblePaths=" + num + " | spriteAssets=" + num2 + " | reportedLargeOrHintedTextures=" + num3 + " | logCaps=80/80"); LogVillageLoadingDeepDiscovery(bundle, assetNames); } private static void LogVillageLoadingDeepDiscovery(AssetBundle bundle, string[] assetNames) { if ((Object)(object)bundle == (Object)null) { return; } if (assetNames == null) { assetNames = new string[0]; } for (int i = 0; i < assetNames.Length; i++) { string text = assetNames[i]; if (string.IsNullOrEmpty(text)) { continue; } Info("MINECRAFT LOADING DEEP path | index=" + i + " | asset='" + text + "'"); try { Object[] array = bundle.LoadAssetWithSubAssets<Object>(text); int num = ((array != null) ? array.Length : 0); Info("MINECRAFT LOADING DEEP subassets | asset='" + text + "' | count=" + num); if (array == null) { continue; } int num2 = Math.Min(array.Length, 120); for (int j = 0; j < num2; j++) { Object val = array[j]; if (!(val == (Object)null)) { Texture2D val2 = (Texture2D)(object)((val is Texture2D) ? val : null); Sprite val3 = (Sprite)(object)((val is Sprite) ? val : null); string text2 = (((Object)(object)val2 != (Object)null) ? (" | size=" + ((Texture)val2).width + "x" + ((Texture)val2).height) : (((Object)(object)val3 != (Object)null && (Object)(object)val3.texture != (Object)null) ? (" | spriteTexture='" + ((Object)val3.texture).name + "' | textureSize=" + ((Texture)val3.texture).width + "x" + ((Texture)val3.texture).height) : string.Empty)); Info("MINECRAFT LOADING DEEP object | asset='" + text + "' | subIndex=" + j + " | type='" + ((object)val).GetType().FullName + "' | name='" + val.name + "'" + text2); } } } catch (Exception ex) { Warn("MINECRAFT LOADING DEEP subassets failed | asset='" + text + "' | error=" + Unwrap(ex)); } } try { Object[] array2 = bundle.LoadAllAssets<Object>(); int num3 = ((array2 != null) ? array2.Length : 0); int num4 = 0; int num5 = 0; int num6 = 0; if (array2 != null) { Object[] array3 = array2; foreach (Object val4 in array3) { if (!(val4 == (Object)null)) { Sprite val5 = (Sprite)(object)((val4 is Sprite) ? val4 : null); Texture2D val6 = (Texture2D)(object)((val4 is Texture2D) ? val4 : null); if ((Object)(object)val5 != (Object)null) { num4++; } if ((Object)(object)val6 != (Object)null) { num5++; } string text3 = val4.name