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 GuaranteeMinecraftZombie; internal static ConfigEntry GuaranteeFreddyOnFNAF; internal static ConfigEntry VillageTargetedFixes; internal static ConfigEntry VillageBrokenChestContainment; internal static ConfigEntry ArenaMusicMaxVolume; internal static ConfigEntry AutoSkipPrivateHostPassword; internal static ConfigEntry AutoPickBestRegionPrivateHost; internal static ConfigEntry VillageCleanupCrewTruckStartGuard; internal static ConfigEntry ShowAllEnemyHealthBars; internal static ConfigEntry EnemyHealthBarMaxDistance; internal static ConfigEntry EnemyHealthBarVisibleSeconds; internal static ConfigEntry VillageClickToggleDoors; internal static ConfigEntry VillageLegacyEnemyTeleportSafeSeconds; internal static ConfigEntry 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("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("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> ValuableCache = new Dictionary>(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 FreddyLevelFirstSeenAt = new Dictionary(); private static readonly HashSet FreddyLiveDoneForGenerator = new HashSet(); private static readonly Dictionary FreddyPendingVictim = new Dictionary(); private static readonly Dictionary FreddyPendingAt = new Dictionary(); private static readonly Dictionary FreddyPendingActiveBefore = new Dictionary(); private static readonly HashSet FreddyLiveWaitLogged = new HashSet(); private static readonly Dictionary MinecraftZombieLevelFirstSeenAt = new Dictionary(); private static readonly HashSet MinecraftZombieLiveDoneForGenerator = new HashSet(); private static readonly Dictionary MinecraftZombiePendingVictim = new Dictionary(); private static readonly Dictionary MinecraftZombiePendingAt = new Dictionary(); private static readonly Dictionary MinecraftZombiePendingActiveBefore = new Dictionary(); private static readonly HashSet MinecraftZombieLiveWaitLogged = new HashSet(); private static readonly Dictionary MinecraftZombieTracked = new Dictionary(); private static readonly HashSet MinecraftZombieSpawnLogged = new HashSet(); private static readonly HashSet MinecraftZombieInvalidLogged = new HashSet(); private static readonly Dictionary MinecraftZombieSafeBodyPosition = new Dictionary(); private static readonly Dictionary MinecraftZombieSafeParentPosition = new Dictionary(); private static readonly Dictionary MinecraftZombieRescueCount = new Dictionary(); private static readonly HashSet VillageRescuedValuables = new HashSet(); private static readonly HashSet VillageRescueCandidateLogged = new HashSet(); private static readonly Dictionary VillageRescueTargets = new Dictionary(); private static readonly Dictionary VillageRescueRetryCounts = new Dictionary(); private static readonly HashSet VillageChestContainmentLogged = new HashSet(); private static readonly HashSet ArenaAudioSourcesCapped = new HashSet(); private static readonly HashSet SoundPlayLoopSignaturesLogged = new HashSet(); 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 VillageGeneratorFirstSeenAt = new Dictionary(); private static readonly HashSet VillageCleanupCrewRelocatedInstances = new HashSet(); private static readonly HashSet VillageTruckEnemyLoggedInstances = new HashSet(); private static readonly Dictionary EnemyObservedMaxHealth = new Dictionary(); private static readonly Dictionary EnemyNativeHealthRoots = new Dictionary(); private static readonly Dictionary EnemyLastObservedHealth = new Dictionary(); private static readonly Dictionary EnemyHealthVisibleUntil = new Dictionary(); private static GameObject _nativeEnemyHealthTemplate; private static bool _enemyHealthReflectionLogged; private static bool _damageShowConflictLogged; private static readonly HashSet VillageDoorToggleInstalled = new HashSet(); private static readonly HashSet VillageCleanupCrewTeleportBlockedInstances = new HashSet(); private static bool _villageLegacyTPPatchInstalled; private static bool _minecraftLoadingReferenceMigrationInstalled; private static bool _minecraftLoadingGraphicPatchInstalled; private static readonly HashSet MinecraftLoadingGraphicAppliedLevels = new HashSet(StringComparer.OrdinalIgnoreCase); private static readonly HashSet MinecraftLoadingGraphicMissingLogged = new HashSet(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 LegacyNetworkPrefabCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary PluginBundlePathCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly HashSet PluginBundlePathMissing = new HashSet(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 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 ?? "") : ""); 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(); 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 ?? "") + "' | 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(); 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 ?? "") : ""); 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(); 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(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=")); } } } } KeyValuePair[] array3 = MinecraftZombieTracked.ToArray(); for (int j = 0; j < array3.Length; j++) { KeyValuePair 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(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) : ""); Warn("MCZombie TRACK invalid/dead | id=" + key + " | pos=" + text2 + (flag4 ? (" | hp=" + current2.ToString("0.##") + "/" + maximum2.ToString("0.##")) : " | hp=") + " | 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(true); if (componentsInChildren != null && componentsInChildren.Length > 0) { Rigidbody val2 = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Rigidbody b) => (Object)(object)b != (Object)null && ((Object)b).name.IndexOf("Rigidbody", StringComparison.OrdinalIgnoreCase) >= 0)); if ((Object)(object)val2 == (Object)null) { val2 = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Rigidbody b) => (Object)(object)b != (Object)null && !b.isKinematic)); } if ((Object)(object)val2 == (Object)null) { val2 = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Rigidbody b) => (Object)(object)b != (Object)null)); } if ((Object)(object)val2 != (Object)null) { return ((Component)val2).transform; } } Enemy componentInChildren = ((Component)parent).GetComponentInChildren(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(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(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(); 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 ?? "") + "'"); 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 ?? "") + "' | 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(); 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(); 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(); 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(true)?.FirstOrDefault((Func)((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 list = FindZombieEnemyPrefabs(); foreach (GameObject item2 in list) { if ((Object)(object)item2 == (Object)null) { continue; } EnemyParent val3 = item2.GetComponentsInChildren(true)?.FirstOrDefault((Func)((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(); HashSet hashSet = new HashSet(); 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(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 ?? "") + " | 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[] array3 = EnemyNativeHealthRoots.ToArray(); for (int j = 0; j < array3.Length; j++) { KeyValuePair 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(true) : ((Component)enemy).GetComponentsInChildren(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(true) : ((Component)enemy).GetComponentsInChildren(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[] 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(); 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(); val2.renderMode = (RenderMode)2; val2.worldCamera = Camera.main; val2.sortingOrder = 1000; RectTransform component = val.GetComponent(); if ((Object)(object)component != (Object)null) { component.sizeDelta = new Vector2(220f, 70f); } val.transform.localScale = Vector3.one * 0.006f; GameObject val3 = Object.Instantiate(template, val.transform, false); ((Object)val3).name = "Health"; val3.SetActive(true); Component[] components = val3.GetComponents(); 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(); 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(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[] 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[] 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 ""; } 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 : "") + "' | " + 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(); 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(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 GetLegacyBucket(object levelValuables, string bucket) { try { List list = new List(); 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(); } } 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 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="); 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="); 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 list = new List(); try { Sprite val = bundle.LoadAsset(text); if ((Object)(object)val != (Object)null && !string.IsNullOrEmpty(((Object)val).name)) { list.Add(((Object)val).name); } } catch { } try { Sprite[] array2 = bundle.LoadAssetWithSubAssets(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(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(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(); 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 ?? string.Empty; string text4 = text3.ToLowerInvariant(); bool flag = text4.IndexOf("load", StringComparison.Ordinal) >= 0 || text4.IndexOf("village", StringComparison.Ordinal) >= 0 || text4.IndexOf("splash", StringComparison.Ordinal) >= 0 || text4.IndexOf("graphic", StringComparison.Ordinal) >= 0; bool flag2 = (Object)(object)val6 != (Object)null && ((Texture)val6).width >= 512 && ((Texture)val6).height >= 256; if ((flag || !((Object)(object)val5 == (Object)null) || flag2) && num6 < 160) { string text5 = (((Object)(object)val6 != (Object)null) ? (" | size=" + ((Texture)val6).width + "x" + ((Texture)val6).height) : (((Object)(object)val5 != (Object)null && (Object)(object)val5.texture != (Object)null) ? (" | spriteTexture='" + ((Object)val5.texture).name + "' | textureSize=" + ((Texture)val5.texture).width + "x" + ((Texture)val5.texture).height) : string.Empty)); Info("MINECRAFT LOADING DEEP all-object | type='" + ((object)val4).GetType().FullName + "' | name='" + text3 + "'" + text5); num6++; } } } } Info("MINECRAFT LOADING DEEP summary | allObjects=" + num3 + " | sprites=" + num4 + " | textures=" + num5 + " | interestingLogged=" + num6 + " | assetPaths=" + assetNames.Length); } catch (Exception ex2) { Warn("MINECRAFT LOADING DEEP LoadAllAssets failed | error=" + Unwrap(ex2)); } } private static void LogVillageLoadingLevelState(object levelContent, object level) { Info("MINECRAFT LOADING LEVELSTATE begin | levelContentType='" + ((levelContent != null) ? levelContent.GetType().FullName : "") + "' | levelType='" + ((level != null) ? level.GetType().FullName : "") + "'"); LogVillageLoadingObjectFields("LevelContent", levelContent, 220); LogVillageLoadingObjectFields("Level", level, 320); Info("MINECRAFT LOADING LEVELSTATE end"); } private static void LogVillageLoadingObjectFields(string label, object target, int cap) { if (target == null) { Info("MINECRAFT LOADING LEVELSTATE object | label='" + label + "' | value="); return; } Type type = target.GetType(); int num = 0; HashSet hashSet = new HashSet(StringComparer.Ordinal); for (Type type2 = type; type2 != null && type2 != typeof(object) && num < cap; type2 = type2.BaseType) { FieldInfo[] fields; try { fields = type2.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } catch { continue; } FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { if (fieldInfo == null || num >= cap) { break; } string item = type2.FullName + "::field::" + fieldInfo.Name; if (hashSet.Add(item)) { object value = null; string text = null; try { value = fieldInfo.GetValue(target); } catch (Exception ex) { text = Unwrap(ex); } Info("MINECRAFT LOADING LEVELSTATE field | object='" + label + "' | declaring='" + type2.FullName + "' | name='" + fieldInfo.Name + "' | fieldType='" + fieldInfo.FieldType.FullName + "' | value=" + ((text == null) ? DescribeVillageLoadingValue(value) : (""))); num++; } } } PropertyInfo[] array2; try { array2 = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } catch { array2 = new PropertyInfo[0]; } PropertyInfo[] array3 = array2; foreach (PropertyInfo propertyInfo in array3) { if (propertyInfo == null || num >= cap) { break; } if (!propertyInfo.CanRead || propertyInfo.GetIndexParameters().Length != 0) { continue; } string text2 = (propertyInfo.Name ?? string.Empty).ToLowerInvariant(); if (text2.IndexOf("load", StringComparison.Ordinal) < 0 && text2.IndexOf("graphic", StringComparison.Ordinal) < 0 && text2.IndexOf("image", StringComparison.Ordinal) < 0 && text2.IndexOf("sprite", StringComparison.Ordinal) < 0 && text2.IndexOf("prefab", StringComparison.Ordinal) < 0 && text2.IndexOf("content", StringComparison.Ordinal) < 0 && !(text2 == "level") && !(text2 == "bundle")) { continue; } string item2 = type.FullName + "::property::" + propertyInfo.Name; if (hashSet.Add(item2)) { object value2 = null; string text3 = null; try { value2 = propertyInfo.GetValue(target, null); } catch (Exception ex2) { text3 = Unwrap(ex2); } Info("MINECRAFT LOADING LEVELSTATE property | object='" + label + "' | name='" + propertyInfo.Name + "' | propertyType='" + propertyInfo.PropertyType.FullName + "' | value=" + ((text3 == null) ? DescribeVillageLoadingValue(value2) : (""))); num++; } } Info("MINECRAFT LOADING LEVELSTATE object-summary | label='" + label + "' | type='" + type.FullName + "' | logged=" + num + " | cap=" + cap); } private static string DescribeVillageLoadingValue(object value) { if (value == null) { return ""; } if (value is string text) { return "'" + text.Replace("'", "\\'") + "'"; } Type type = value.GetType(); if (type.IsPrimitive || type.IsEnum || value is decimal) { return Convert.ToString(value); } AssetBundle val = (AssetBundle)((value is AssetBundle) ? value : null); if ((Object)(object)val != (Object)null) { return "AssetBundle(name='" + ((Object)val).name + "')"; } Object val2 = (Object)((value is Object) ? value : null); if (val2 != (Object)null) { return "UnityObject(type='" + ((object)val2).GetType().FullName + "',name='" + val2.name + "')"; } if (type.FullName != null && type.FullName.IndexOf("PrefabRef`1", StringComparison.Ordinal) >= 0) { string text2 = Convert.ToString(GetMemberValue(value, "PrefabName")); string text3 = Convert.ToString(GetMemberValue(value, "ResourcePath")); object memberValue = GetMemberValue(value, "bundle"); AssetBundle val3 = (AssetBundle)((memberValue is AssetBundle) ? memberValue : null); return "PrefabRef(prefab='" + text2 + "',resource='" + text3 + "',bundle=" + (((Object)(object)val3 != (Object)null) ? "yes" : "no") + ")"; } if (value is ICollection collection) { return "Collection(type='" + type.FullName + "',count=" + collection.Count + ")"; } return "Object(type='" + type.FullName + "')"; } private static bool RepairEmptyLoadingGraphicReference(object level, string levelMemberName, AssetBundle bundle, string[] assetNames, string expectedSpriteName) { object memberValue = GetMemberValue(level, levelMemberName); if (memberValue == null) { Warn("MINECRAFT LOADING MIGRATION missing PrefabRef | member=" + levelMemberName + " | expected='" + expectedSpriteName + "'"); return false; } string text = Convert.ToString(GetMemberValue(memberValue, "PrefabName")); string text2 = Convert.ToString(GetMemberValue(memberValue, "ResourcePath")); object memberValue2 = GetMemberValue(memberValue, "bundle"); AssetBundle val = (AssetBundle)((memberValue2 is AssetBundle) ? memberValue2 : null); if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2)) { if ((Object)(object)val == (Object)null) { bool flag = TrySetMemberValue(memberValue, "bundle", bundle); Info("MINECRAFT LOADING MIGRATION kept existing ref | member=" + levelMemberName + " | prefab='" + text + "' | resource='" + text2 + "' | bundleAttached=" + flag); } return true; } string text3 = null; if (assetNames != null) { foreach (string text4 in assetNames) { if (!string.IsNullOrEmpty(FindWantedLoadingGraphicName(text4, new string[1] { expectedSpriteName }))) { text3 = text4; break; } } } if (string.IsNullOrEmpty(text3)) { Warn("MINECRAFT LOADING MIGRATION asset missing | member=" + levelMemberName + " | expected='" + expectedSpriteName + "'"); return false; } bool flag2 = TrySetMemberValue(memberValue, "prefabName", expectedSpriteName); bool flag3 = TrySetMemberValue(memberValue, "resourcePath", text3); bool flag4 = TrySetMemberValue(memberValue, "bundle", bundle); Info("MINECRAFT LOADING MIGRATION repaired | member=" + levelMemberName + " | prefab='" + expectedSpriteName + "' | resource='" + text3 + "' | nameSet=" + flag2 + " | pathSet=" + flag3 + " | bundleSet=" + flag4); if (flag2 && flag3) { return flag4; } return false; } public static void InstallMinecraftLoadingGraphicFix(Harmony harmony) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown if (harmony == null || Plugin.RepairMinecraftLoadingGraphics == null || !Plugin.RepairMinecraftLoadingGraphics.Value) { return; } try { Type type = AccessTools.TypeByName("LoadingUI"); MethodInfo methodInfo = ((type == null) ? null : type.GetMethod("LevelAnimationStart", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); MethodInfo method = typeof(Bridge).GetMethod("MinecraftLoadingGraphicPostfix", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null || method == null) { Warn("Minecraft loading-graphic repair unavailable: LoadingUI.LevelAnimationStart target not found."); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _minecraftLoadingGraphicPatchInstalled = true; Info("Minecraft loading-graphic repair installed on LoadingUI.LevelAnimationStart."); } catch (Exception ex) { Error("Minecraft loading-graphic repair install failed: " + Unwrap(ex)); } } public static void MinecraftLoadingGraphicPostfix(object __instance) { if (!_minecraftLoadingGraphicPatchInstalled || __instance == null || Plugin.RepairMinecraftLoadingGraphics == null || !Plugin.RepairMinecraftLoadingGraphics.Value) { return; } try { string currentLevelName = GetCurrentLevelName(); if (string.IsNullOrEmpty(currentLevelName)) { return; } string[] array = null; bool flag = currentLevelName.IndexOf("Minecraft Village", StringComparison.OrdinalIgnoreCase) >= 0; if (!flag) { HideVillageLoadingFallbackOverlay(); } if (flag) { array = new string[3] { "village3", "village2", "village1" }; } else { if (currentLevelName.IndexOf("Stronghold", StringComparison.OrdinalIgnoreCase) < 0) { return; } array = new string[3] { "level stronghold2 01", "level stronghold2 02", "level stronghold2 03" }; } Sprite val = ResolveCurrentLevelLoadingGraphic("LoadingGraphic01", array[0]); Sprite val2 = ResolveCurrentLevelLoadingGraphic("LoadingGraphic02", array[1]); Sprite val3 = ResolveCurrentLevelLoadingGraphic("LoadingGraphic03", array[2]); Sprite[] array2 = Resources.FindObjectsOfTypeAll(); if ((Object)(object)val == (Object)null) { val = FindLoadedSprite(array2, array[0]); } if ((Object)(object)val2 == (Object)null) { val2 = FindLoadedSprite(array2, array[1]); } if ((Object)(object)val3 == (Object)null) { val3 = FindLoadedSprite(array2, array[2]); } if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { array2 = ExpandSpritesFromLoadedBundles(array2, array); if ((Object)(object)val == (Object)null) { val = FindLoadedSprite(array2, array[0]); } if ((Object)(object)val2 == (Object)null) { val2 = FindLoadedSprite(array2, array[1]); } if ((Object)(object)val3 == (Object)null) { val3 = FindLoadedSprite(array2, array[2]); } } bool flag2 = false; if (flag && (Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null && (Object)(object)val3 == (Object)null) { Sprite[] orCreateVillageLoadingFallbackSprites = GetOrCreateVillageLoadingFallbackSprites(); if (orCreateVillageLoadingFallbackSprites != null && orCreateVillageLoadingFallbackSprites.Length >= 3) { val = orCreateVillageLoadingFallbackSprites[0]; val2 = orCreateVillageLoadingFallbackSprites[1]; val3 = orCreateVillageLoadingFallbackSprites[2]; flag2 = true; } } int num = 0; if ((Object)(object)val != (Object)null && TryAssignLoadingGraphicSprite(__instance, "loadingGraphic01", val)) { num++; } if ((Object)(object)val2 != (Object)null && TryAssignLoadingGraphicSprite(__instance, "loadingGraphic02", val2)) { num++; } if ((Object)(object)val3 != (Object)null && TryAssignLoadingGraphicSprite(__instance, "loadingGraphic03", val3)) { num++; } bool flag3 = false; if (flag2 && (Object)(object)val != (Object)null) { flag3 = ShowVillageLoadingFallbackOverlay(__instance, val); MonoBehaviour val4 = (MonoBehaviour)((__instance is MonoBehaviour) ? __instance : null); if ((Object)(object)val4 != (Object)null && flag3) { val4.StartCoroutine(VillageLoadingOverlayReassertLoop(__instance, val, ++_villageLoadingOverlayGeneration)); } } if (num > 0 || flag3) { if (!MinecraftLoadingGraphicAppliedLevels.Contains(currentLevelName)) { MinecraftLoadingGraphicAppliedLevels.Add(currentLevelName); Info("MINECRAFT LOADING GRAPHICS restored | level='" + currentLevelName + "' | applied=" + num + "/3 | overlay=" + flag3 + " | sprites=" + string.Join(",", array)); } } else if (!MinecraftLoadingGraphicMissingLogged.Contains(currentLevelName)) { MinecraftLoadingGraphicMissingLogged.Add(currentLevelName); Warn("MINECRAFT LOADING GRAPHICS not found in loaded assets | level='" + currentLevelName + "' | expected=" + string.Join(",", array)); } } catch (Exception ex) { Warn("Minecraft loading-graphic repair failed: " + Unwrap(ex)); } } private static void HideVillageLoadingFallbackOverlay() { _villageLoadingOverlayGeneration++; if ((Object)(object)_villageLoadingOverlayRoot != (Object)null) { _villageLoadingOverlayRoot.SetActive(false); } } private static bool ShowVillageLoadingFallbackOverlay(object loadingUi, Sprite sprite) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0150: 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) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (loadingUi == null || (Object)(object)sprite == (Object)null) { return false; } try { Component val = (Component)((loadingUi is Component) ? loadingUi : null); if ((Object)(object)val == (Object)null) { return false; } Transform transform = val.transform; if ((Object)(object)transform == (Object)null) { return false; } if ((Object)(object)_villageLoadingOverlayRoot == (Object)null || (Object)(object)_villageLoadingOverlayImage == (Object)null) { _villageLoadingOverlayRoot = new GameObject("LegacyREPOCompat Village Loading Overlay", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); ((Object)_villageLoadingOverlayRoot).hideFlags = (HideFlags)61; _villageLoadingOverlayImage = _villageLoadingOverlayRoot.GetComponent(); if ((Object)(object)_villageLoadingOverlayImage == (Object)null) { return false; } ((Graphic)_villageLoadingOverlayImage).raycastTarget = false; _villageLoadingOverlayImage.preserveAspect = false; ((Graphic)_villageLoadingOverlayImage).color = Color.white; } Transform transform2 = _villageLoadingOverlayRoot.transform; if ((Object)(object)transform2.parent != (Object)(object)transform) { transform2.SetParent(transform, false); } RectTransform val2 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); if ((Object)(object)val2 != (Object)null) { val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = Vector2.zero; val2.sizeDelta = Vector2.zero; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; ((Transform)val2).localScale = Vector3.one; } _villageLoadingOverlayImage.sprite = sprite; ((Behaviour)_villageLoadingOverlayImage).enabled = true; ((Graphic)_villageLoadingOverlayImage).color = Color.white; _villageLoadingOverlayRoot.SetActive(true); transform2.SetAsLastSibling(); BringLoadingUiMemberToFront(loadingUi, "levelNumberText"); BringLoadingUiMemberToFront(loadingUi, "levelNameText"); BringLoadingUiMemberToFront(loadingUi, "stuckTransform"); Info("MINECRAFT LOADING OVERLAY shown | level='Minecraft Village' | sprite='" + ((Object)sprite).name + "' | active=" + _villageLoadingOverlayRoot.activeInHierarchy + " | parent='" + ((Object)transform).name + "'"); return true; } catch (Exception ex) { Warn("MINECRAFT LOADING OVERLAY failed | error=" + Unwrap(ex)); return false; } } private static IEnumerator VillageLoadingOverlayReassertLoop(object loadingUi, Sprite sprite, int generation) { float[] delays = new float[6] { 0f, 0.03f, 0.1f, 0.25f, 0.5f, 1f }; for (int i = 0; i < delays.Length; i++) { if (generation != _villageLoadingOverlayGeneration) { break; } if (delays[i] <= 0f) { yield return null; } else { yield return (object)new WaitForSecondsRealtime(delays[i]); } if (generation == _villageLoadingOverlayGeneration && GetCurrentLevelName().IndexOf("Minecraft Village", StringComparison.OrdinalIgnoreCase) >= 0) { ShowVillageLoadingFallbackOverlay(loadingUi, sprite); continue; } break; } } private static void BringLoadingUiMemberToFront(object loadingUi, string memberName) { if (loadingUi == null || string.IsNullOrEmpty(memberName)) { return; } object memberValue = GetMemberValue(loadingUi, memberName); Transform val = (Transform)((memberValue is Transform) ? memberValue : null); if ((Object)(object)val == (Object)null) { Component val2 = (Component)((memberValue is Component) ? memberValue : null); if ((Object)(object)val2 != (Object)null) { val = val2.transform; } } if ((Object)(object)val != (Object)null) { val.SetAsLastSibling(); } } private static Sprite[] GetOrCreateVillageLoadingFallbackSprites() { if (_villageGeneratedLoadingSprites != null && _villageGeneratedLoadingSprites.Length == 3 && (Object)(object)_villageGeneratedLoadingSprites[0] != (Object)null && (Object)(object)_villageGeneratedLoadingSprites[1] != (Object)null && (Object)(object)_villageGeneratedLoadingSprites[2] != (Object)null) { return _villageGeneratedLoadingSprites; } try { _villageGeneratedLoadingSprites = (Sprite[])(object)new Sprite[3] { CreateVillageLoadingFallbackSprite(0), CreateVillageLoadingFallbackSprite(1), CreateVillageLoadingFallbackSprite(2) }; if (!_villageGeneratedLoadingSpritesLogged) { _villageGeneratedLoadingSpritesLogged = true; Info("MINECRAFT LOADING FALLBACK generated | level='Minecraft Village' | sprites=3 | source=procedural-pixel-art"); } return _villageGeneratedLoadingSprites; } catch (Exception ex) { Warn("MINECRAFT LOADING FALLBACK generation failed | error=" + Unwrap(ex)); return null; } } private static Sprite CreateVillageLoadingFallbackSprite(int variant) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0247: 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_024f: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_04b0: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_0544: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(384, 216, (TextureFormat)4, false); ((Object)val).name = "LegacyREPOCompat Village Loading " + (variant + 1); ((Texture)val).filterMode = (FilterMode)0; ((Texture)val).wrapMode = (TextureWrapMode)1; Color32 b = default(Color32); Color32 a = default(Color32); Color32 val2 = default(Color32); Color32 val3 = default(Color32); Color32 color = default(Color32); Color32 color2 = default(Color32); Color32 color3 = default(Color32); Color32 color4 = default(Color32); switch (variant) { case 0: ((Color32)(ref b))..ctor((byte)30, (byte)44, (byte)66, byte.MaxValue); ((Color32)(ref a))..ctor((byte)70, (byte)83, (byte)91, byte.MaxValue); ((Color32)(ref val2))..ctor((byte)47, (byte)78, (byte)49, byte.MaxValue); ((Color32)(ref val3))..ctor((byte)73, (byte)57, (byte)42, byte.MaxValue); ((Color32)(ref color))..ctor((byte)91, (byte)67, (byte)43, byte.MaxValue); ((Color32)(ref color2))..ctor((byte)54, (byte)45, (byte)40, byte.MaxValue); ((Color32)(ref color3))..ctor((byte)76, (byte)78, (byte)76, byte.MaxValue); ((Color32)(ref color4))..ctor((byte)228, (byte)181, (byte)88, byte.MaxValue); break; case 1: ((Color32)(ref b))..ctor((byte)38, (byte)30, (byte)51, byte.MaxValue); ((Color32)(ref a))..ctor((byte)92, (byte)59, (byte)61, byte.MaxValue); ((Color32)(ref val2))..ctor((byte)39, (byte)62, (byte)40, byte.MaxValue); ((Color32)(ref val3))..ctor((byte)66, (byte)49, (byte)38, byte.MaxValue); ((Color32)(ref color))..ctor((byte)86, (byte)59, (byte)38, byte.MaxValue); ((Color32)(ref color2))..ctor((byte)48, (byte)39, (byte)38, byte.MaxValue); ((Color32)(ref color3))..ctor((byte)68, (byte)69, (byte)67, byte.MaxValue); ((Color32)(ref color4))..ctor((byte)239, (byte)163, (byte)68, byte.MaxValue); break; default: ((Color32)(ref b))..ctor((byte)14, (byte)18, (byte)31, byte.MaxValue); ((Color32)(ref a))..ctor((byte)31, (byte)36, (byte)50, byte.MaxValue); ((Color32)(ref val2))..ctor((byte)29, (byte)45, (byte)31, byte.MaxValue); ((Color32)(ref val3))..ctor((byte)52, (byte)42, (byte)35, byte.MaxValue); ((Color32)(ref color))..ctor((byte)67, (byte)50, (byte)35, byte.MaxValue); ((Color32)(ref color2))..ctor((byte)37, (byte)33, (byte)34, byte.MaxValue); ((Color32)(ref color3))..ctor((byte)57, (byte)59, (byte)60, byte.MaxValue); ((Color32)(ref color4))..ctor((byte)242, (byte)191, (byte)82, byte.MaxValue); break; } Color32[] array = (Color32[])(object)new Color32[82944]; int num = 78; for (int i = 0; i < 216; i++) { Color32 val4; if (i < num) { val4 = ((i < 58) ? val3 : val2); } else { float t = (float)(i - num) / (float)Math.Max(1, 216 - num - 1); val4 = LerpColor32(a, b, t); } int num2 = i * 384; for (int j = 0; j < 384; j++) { array[num2 + j] = val4; } } for (int k = 0; k < 384; k += 16) { int rectHeight = 12 + (k / 16 + variant * 3) % 4 * 5; FillPixelRect(array, 384, 216, k, 58, 12, rectHeight, new Color32((byte)24, (byte)45, (byte)28, byte.MaxValue)); } int num3 = 118 + variant * 8; FillPixelRect(array, 384, 216, num3, 58, 116, 62, color); FillPixelRect(array, 384, 216, num3 + 12, 58, 20, 42, color3); FillPixelRect(array, 384, 216, num3 + 79, 58, 22, 36, color3); for (int l = 0; l < 6; l++) { FillPixelRect(array, 384, 216, num3 - 10 + l * 8, 120 + l * 7, 136 - l * 16, 8, color2); } FillPixelRect(array, 384, 216, num3 + 43, 76, 18, 18, color4); FillPixelRect(array, 384, 216, num3 + 74, 76, 18, 18, color4); FillPixelRect(array, 384, 216, num3 + 51, 58, 22, 34, new Color32((byte)47, (byte)34, (byte)25, byte.MaxValue)); Color32 color5 = default(Color32); ((Color32)(ref color5))..ctor((byte)91, (byte)78, (byte)60, byte.MaxValue); for (int m = 0; m < 58; m++) { int num4 = 14 + (58 - m) / 2; FillPixelRect(array, 384, 216, 192 - num4, m, num4 * 2, 1, color5); } FillPixelRect(array, 384, 216, 302 - variant * 18, 164 + variant * 8, 18, 18, new Color32((byte)210, (byte)211, (byte)188, byte.MaxValue)); Color32 color6 = default(Color32); ((Color32)(ref color6))..ctor((byte)8, (byte)9, (byte)11, byte.MaxValue); FillPixelRect(array, 384, 216, 0, 0, 384, 5, color6); FillPixelRect(array, 384, 216, 0, 211, 384, 5, color6); FillPixelRect(array, 384, 216, 0, 0, 5, 216, color6); FillPixelRect(array, 384, 216, 379, 0, 5, 216, color6); val.SetPixels32(array); val.Apply(false, false); Sprite val5 = Sprite.Create(val, new Rect(0f, 0f, 384f, 216f), new Vector2(0.5f, 0.5f), 100f); ((Object)val5).name = "Legacy Village Loading " + (variant + 1); return val5; } private static void FillPixelRect(Color32[] pixels, int textureWidth, int textureHeight, int x, int y, int rectWidth, int rectHeight, Color32 color) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (pixels == null || textureWidth <= 0 || textureHeight <= 0 || rectWidth <= 0 || rectHeight <= 0) { return; } int num = Math.Max(0, x); int num2 = Math.Max(0, y); int num3 = Math.Min(textureWidth, x + rectWidth); int num4 = Math.Min(textureHeight, y + rectHeight); for (int i = num2; i < num4; i++) { int num5 = i * textureWidth; for (int j = num; j < num3; j++) { pixels[num5 + j] = color; } } } private static Color32 LerpColor32(Color32 a, Color32 b, float t) { //IL_0078: Unknown result type (might be due to invalid IL or missing references) t = Mathf.Clamp01(t); return new Color32((byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.r, (float)(int)b.r, t)), (byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.g, (float)(int)b.g, t)), (byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.b, (float)(int)b.b, t)), (byte)Mathf.RoundToInt(Mathf.Lerp((float)(int)a.a, (float)(int)b.a, t))); } private static object GetCurrentLevelObject() { try { FieldInfo field = typeof(RunManager).GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((field == null) ? null : field.GetValue(null)); return (obj == null) ? null : GetMemberValue(obj, "levelCurrent"); } catch { return null; } } private static Sprite ResolveCurrentLevelLoadingGraphic(string levelMemberName, string expectedSpriteName) { object currentLevelObject = GetCurrentLevelObject(); if (currentLevelObject == null) { return null; } object memberValue = GetMemberValue(currentLevelObject, levelMemberName); if (memberValue == null) { Warn("MINECRAFT LOADING PREFABREF missing | member=" + levelMemberName + " | expected='" + expectedSpriteName + "'"); return null; } string text = Convert.ToString(GetMemberValue(memberValue, "PrefabName")); string text2 = Convert.ToString(GetMemberValue(memberValue, "ResourcePath")); object memberValue2 = GetMemberValue(memberValue, "Prefab"); Sprite val = (Sprite)((memberValue2 is Sprite) ? memberValue2 : null); if ((Object)(object)val != (Object)null) { Info("MINECRAFT LOADING PREFABREF resolved | member=" + levelMemberName + " | prefab='" + text + "' | resource='" + text2 + "' | sprite='" + ((Object)val).name + "'"); return val; } object memberValue3 = GetMemberValue(memberValue, "bundle"); AssetBundle val2 = (AssetBundle)((memberValue3 is AssetBundle) ? memberValue3 : null); if ((Object)(object)val2 != (Object)null && !string.IsNullOrEmpty(text2)) { try { val = val2.LoadAsset(text2); } catch { } if ((Object)(object)val == (Object)null) { try { Sprite[] array = val2.LoadAssetWithSubAssets(text2); val = FindLoadedSprite(array, expectedSpriteName); if ((Object)(object)val == (Object)null && array != null && array.Length > 0) { val = array[0]; } } catch { } } } if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null) { try { string[] allAssetNames = val2.GetAllAssetNames(); if (allAssetNames != null) { string[] array2 = allAssetNames; foreach (string text3 in array2) { if (string.IsNullOrEmpty(FindWantedLoadingGraphicName(text3, new string[1] { expectedSpriteName }))) { continue; } try { val = val2.LoadAsset(text3); } catch { } if ((Object)(object)val == (Object)null) { try { Sprite[] array3 = val2.LoadAssetWithSubAssets(text3); val = FindLoadedSprite(array3, expectedSpriteName); if ((Object)(object)val == (Object)null && array3 != null && array3.Length > 0) { val = array3[0]; } } catch { } } if ((Object)(object)val != (Object)null) { break; } } } } catch { } } if ((Object)(object)val != (Object)null) { Info("MINECRAFT LOADING PREFABREF bundle resolved | member=" + levelMemberName + " | prefab='" + text + "' | resource='" + text2 + "' | sprite='" + ((Object)val).name + "'"); return val; } Warn("MINECRAFT LOADING PREFABREF unresolved | member=" + levelMemberName + " | type='" + memberValue.GetType().FullName + "' | prefab='" + text + "' | resource='" + text2 + "' | bundle=" + (((Object)(object)val2 != (Object)null) ? "yes" : "no") + " | resolvedType='" + ((memberValue2 != null) ? memberValue2.GetType().FullName : "") + "'"); return null; } private static Sprite[] ExpandSpritesFromLoadedBundles(Sprite[] alreadyLoaded, string[] wantedNames) { //IL_0179: 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) List list = new List(); if (alreadyLoaded != null) { foreach (Sprite val in alreadyLoaded) { if ((Object)(object)val != (Object)null && !list.Contains(val)) { list.Add(val); } } } foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle == (Object)null) { continue; } string[] allAssetNames; try { allAssetNames = allLoadedAssetBundle.GetAllAssetNames(); } catch { continue; } if (allAssetNames == null) { continue; } string[] array = allAssetNames; foreach (string text in array) { string text2 = FindWantedLoadingGraphicName(text, wantedNames); if (string.IsNullOrEmpty(text2)) { continue; } int count = list.Count; try { Sprite val2 = allLoadedAssetBundle.LoadAsset(text); if ((Object)(object)val2 != (Object)null && !list.Contains(val2)) { list.Add(val2); } } catch { } try { Sprite[] array2 = allLoadedAssetBundle.LoadAssetWithSubAssets(text); if (array2 != null) { Sprite[] array3 = array2; foreach (Sprite val3 in array3) { if ((Object)(object)val3 != (Object)null && !list.Contains(val3)) { list.Add(val3); } } } } catch { } if ((Object)(object)FindLoadedSprite(list.ToArray(), text2) == (Object)null) { try { Texture2D val4 = allLoadedAssetBundle.LoadAsset(text); if ((Object)(object)val4 != (Object)null && ((Texture)val4).width > 0 && ((Texture)val4).height > 0) { Sprite val5 = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f), 100f); ((Object)val5).name = text2; list.Add(val5); } } catch { } } if (list.Count > count) { Info("MINECRAFT LOADING GRAPHICS loaded from open bundle | asset='" + text + "' | target='" + text2 + "'"); } } } return list.ToArray(); } private static string FindWantedLoadingGraphicName(string assetName, string[] wantedNames) { if (string.IsNullOrEmpty(assetName) || wantedNames == null) { return null; } string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(assetName); foreach (string text in wantedNames) { if (!string.IsNullOrEmpty(text) && (string.Equals(fileNameWithoutExtension, text, StringComparison.OrdinalIgnoreCase) || assetName.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0)) { return text; } } return null; } private static string FindPluginBundlePath(string fileName) { if (string.IsNullOrEmpty(fileName)) { return null; } if (PluginBundlePathCache.TryGetValue(fileName, out var value)) { return value; } if (PluginBundlePathMissing.Contains(fileName)) { return null; } try { string pluginPath = Paths.PluginPath; if (string.IsNullOrEmpty(pluginPath) || !Directory.Exists(pluginPath)) { return null; } string[] files = Directory.GetFiles(pluginPath, fileName, SearchOption.AllDirectories); if (files != null && files.Length > 0) { PluginBundlePathCache[fileName] = files[0]; return files[0]; } } catch (Exception ex) { Warn("Plugin bundle path search failed for '" + fileName + "': " + Unwrap(ex)); } PluginBundlePathMissing.Add(fileName); return null; } private static Sprite FindLoadedSprite(Sprite[] allSprites, string wantedName) { if (allSprites == null || string.IsNullOrEmpty(wantedName)) { return null; } foreach (Sprite val in allSprites) { if (!((Object)(object)val == (Object)null) && string.Equals(((Object)val).name, wantedName, StringComparison.OrdinalIgnoreCase)) { return val; } } foreach (Sprite val2 in allSprites) { if (!((Object)(object)val2 == (Object)null) && !string.IsNullOrEmpty(((Object)val2).name) && ((Object)val2).name.IndexOf(wantedName, StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } } return null; } private static bool TryAssignLoadingGraphicSprite(object loadingUi, string memberName, Sprite sprite) { if (loadingUi == null || (Object)(object)sprite == (Object)null || string.IsNullOrEmpty(memberName)) { return false; } object memberValue = GetMemberValue(loadingUi, memberName); if (memberValue == null) { return false; } Type type = memberValue.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; PropertyInfo property = type.GetProperty("sprite", bindingAttr); if (property != null && property.CanWrite && property.PropertyType.IsInstanceOfType(sprite)) { property.SetValue(memberValue, sprite, null); return true; } FieldInfo field = type.GetField("sprite", bindingAttr); if (field != null && field.FieldType.IsInstanceOfType(sprite)) { field.SetValue(memberValue, sprite); return true; } return false; } public static IEnumerator VillageLegacyTeleportGuardInstallLoop(Harmony harmony) { int attempt = 0; while (true) { if (attempt < 30) { if (!TryInstallVillageLegacyTeleportGuard(harmony)) { yield return (object)new WaitForSeconds(1f); attempt++; continue; } break; } if (Plugin.VillageCleanupCrewTruckStartGuard != null && Plugin.VillageCleanupCrewTruckStartGuard.Value) { Warn("Minecraft Village Cleanup Crew targeted teleport guard unavailable after 30 seconds: Enemy.EnemyTeleported was not found."); } break; } } private static bool TryInstallVillageLegacyTeleportGuard(Harmony harmony) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown if (_villageLegacyTPPatchInstalled) { return true; } if (harmony == null || Plugin.VillageCleanupCrewTruckStartGuard == null || !Plugin.VillageCleanupCrewTruckStartGuard.Value) { return true; } try { Type type = AccessTools.TypeByName("Enemy"); if (type == null) { return false; } MethodInfo[] array = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "EnemyTeleported" select m).ToArray(); MethodInfo method = typeof(Bridge).GetMethod("MinecraftVillageCleanupCrewEnemyTeleportedPrefix", BindingFlags.Static | BindingFlags.Public); if (array.Length == 0 || method == null) { return false; } int num = 0; MethodInfo[] array2 = array; foreach (MethodInfo methodInfo in array2) { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); num++; } _villageLegacyTPPatchInstalled = num > 0; if (_villageLegacyTPPatchInstalled) { Info("Minecraft Village Cleanup Crew targeted Enemy.EnemyTeleported guard installed | overloads=" + num); } return _villageLegacyTPPatchInstalled; } catch (Exception ex) { Warn("Minecraft Village Cleanup Crew targeted teleport guard install retry: " + Unwrap(ex)); return false; } } public static bool MinecraftVillageCleanupCrewEnemyTeleportedPrefix(object __instance) { //IL_018c: Unknown result type (might be due to invalid IL or missing references) try { if (Plugin.VillageCleanupCrewTruckStartGuard == null || !Plugin.VillageCleanupCrewTruckStartGuard.Value || !CurrentLevelContains("Minecraft Village") || __instance == null) { return true; } Component val = (Component)((__instance is Component) ? __instance : null); if ((Object)(object)val == (Object)null) { return true; } EnemyParent componentInParent = val.GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { return true; } string text = componentInParent.enemyName ?? ((Object)componentInParent).name ?? string.Empty; if (text.IndexOf("Cleanup Crew", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("CleanupCrew", StringComparison.OrdinalIgnoreCase) < 0) { return true; } LevelGenerator instance = LevelGenerator.Instance; if ((Object)(object)instance == (Object)null) { return true; } int instanceID = ((Object)instance).GetInstanceID(); if (!VillageGeneratorFirstSeenAt.TryGetValue(instanceID, out var value)) { value = Time.realtimeSinceStartup; VillageGeneratorFirstSeenAt[instanceID] = value; } float num = ((Plugin.VillageLegacyEnemyTeleportSafeSeconds != null) ? Plugin.VillageLegacyEnemyTeleportSafeSeconds.Value : 60f); float num2 = Time.realtimeSinceStartup - value; if (num2 >= num) { return true; } int instanceID2 = ((Object)componentInParent).GetInstanceID(); if (!VillageCleanupCrewTeleportBlockedInstances.Contains(instanceID2)) { VillageCleanupCrewTeleportBlockedInstances.Add(instanceID2); Info("VILLAGE CLEANUP CREW TELEPORT SAFE START | blocked old EnemyTeleported for " + num.ToString("0.0") + "s only for Cleanup Crew | age=" + num2.ToString("0.0") + "s | pos=" + Vec(((Component)componentInParent).transform.position)); } return false; } catch (Exception ex) { Warn("Minecraft Village Cleanup Crew targeted teleport guard failed open: " + Unwrap(ex)); return true; } } public static AudioSource GetStrongholdDoorAudioSource(bool opening) { ResolveStrongholdDoorAudio(); if (!opening) { return _strongholdDoorCloseSource; } return _strongholdDoorOpenSource; } public static AudioClip GetVillageWoodDoorAudioClip(bool opening) { ResolveVillageWoodDoorAudio(); if (!opening) { return _villageWoodDoorCloseClip; } return _villageWoodDoorOpenClip; } private static void ResolveVillageWoodDoorAudio() { if (_villageWoodDoorAudioResolved) { return; } try { List clips = LoadAudioClipsFromPluginBundle("Minecraft_Village.repobundle"); _villageWoodDoorOpenClip = FindBestWoodDoorClip(clips, opening: true, fromVillageBundle: true); _villageWoodDoorCloseClip = FindBestWoodDoorClip(clips, opening: false, fromVillageBundle: true); AudioClip[] clips2 = Resources.FindObjectsOfTypeAll(); if ((Object)(object)_villageWoodDoorOpenClip == (Object)null) { _villageWoodDoorOpenClip = FindBestWoodDoorClip(clips2, opening: true, fromVillageBundle: false); } if ((Object)(object)_villageWoodDoorCloseClip == (Object)null) { _villageWoodDoorCloseClip = FindBestWoodDoorClip(clips2, opening: false, fromVillageBundle: false); } _villageWoodDoorAudioResolved = (Object)(object)_villageWoodDoorOpenClip != (Object)null || (Object)(object)_villageWoodDoorCloseClip != (Object)null; if (_villageWoodDoorAudioResolved) { Info("VILLAGE WOOD DOOR AUDIO resolved | open=" + (((Object)(object)_villageWoodDoorOpenClip != (Object)null) ? ((Object)_villageWoodDoorOpenClip).name : "") + " | close=" + (((Object)(object)_villageWoodDoorCloseClip != (Object)null) ? ((Object)_villageWoodDoorCloseClip).name : "")); } else if (!_villageWoodDoorAudioMissingLogged) { _villageWoodDoorAudioMissingLogged = true; Info("VILLAGE WOOD DOOR AUDIO not found; metal/iron clips are intentionally rejected."); } } catch (Exception ex) { Warn("Village wood door audio lookup failed: " + Unwrap(ex)); } } private static List LoadAudioClipsFromPluginBundle(string fileName) { List list = new List(); string text = FindPluginBundlePath(fileName); if (string.IsNullOrEmpty(text)) { return list; } AssetBundle val = null; try { val = AssetBundle.LoadFromFile(text); if ((Object)(object)val == (Object)null) { return list; } AudioClip[] array = val.LoadAllAssets(); if (array != null) { AudioClip[] array2 = array; foreach (AudioClip val2 in array2) { if ((Object)(object)val2 != (Object)null && !list.Contains(val2)) { list.Add(val2); } } } } catch (Exception ex) { Warn("Door audio bundle read failed | file='" + fileName + "' | " + Unwrap(ex)); } finally { if ((Object)(object)val != (Object)null) { try { val.Unload(false); } catch { } } } return list; } private static AudioClip FindBestWoodDoorClip(IEnumerable clips, bool opening, bool fromVillageBundle) { if (clips == null) { return null; } AudioClip result = null; int num = int.MinValue; foreach (AudioClip clip in clips) { if ((Object)(object)clip == (Object)null || string.IsNullOrEmpty(((Object)clip).name)) { continue; } string text = ((Object)clip).name.ToLowerInvariant(); if (text.Contains("iron") || text.Contains("metal")) { continue; } int num2 = (fromVillageBundle ? 16 : 0); if (text.Contains("door")) { num2 += 8; } if (text.Contains("wood") || text.Contains("oak")) { num2 += 12; } if (text.Contains("creak")) { num2 += 3; } if (opening) { if (text.Contains("open")) { num2 += 14; } if (text.Contains("close") || text.Contains("shut")) { num2 -= 12; } } else { if (text.Contains("close") || text.Contains("shut")) { num2 += 14; } if (text.Contains("open")) { num2 -= 12; } } if ((fromVillageBundle || text.Contains("wood") || text.Contains("oak")) && num2 > num) { num = num2; result = clip; } } if (num < (fromVillageBundle ? 20 : 20)) { return null; } return result; } private static void ResolveStrongholdDoorAudio() { if (_strongholdDoorAudioResolved) { return; } try { AudioSource[] array = Resources.FindObjectsOfTypeAll(); AudioSource[] array2 = array; foreach (AudioSource val in array2) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { string a = ((Object)((Component)val).gameObject).name ?? string.Empty; if ((Object)(object)_strongholdDoorOpenSource == (Object)null && string.Equals(a, "DoorAudioButtonOpen", StringComparison.OrdinalIgnoreCase)) { _strongholdDoorOpenSource = val; } if ((Object)(object)_strongholdDoorCloseSource == (Object)null && string.Equals(a, "DoorAudioButtonClose", StringComparison.OrdinalIgnoreCase)) { _strongholdDoorCloseSource = val; } } } _strongholdDoorAudioResolved = (Object)(object)_strongholdDoorOpenSource != (Object)null || (Object)(object)_strongholdDoorCloseSource != (Object)null; if (_strongholdDoorAudioResolved) { Info("STRONGHOLD DOOR AUDIO template resolved | openSource=" + (((Object)(object)_strongholdDoorOpenSource != (Object)null) ? ((Object)((Component)_strongholdDoorOpenSource).gameObject).name : "") + " | closeSource=" + (((Object)(object)_strongholdDoorCloseSource != (Object)null) ? ((Object)((Component)_strongholdDoorCloseSource).gameObject).name : "") + " | clips are not copied unless non-metal wood audio is separately resolved"); } else if (!_strongholdDoorAudioMissingLogged) { _strongholdDoorAudioMissingLogged = true; Info("STRONGHOLD DOOR AUDIO template not loaded yet; Village door audio uses its own wood-clip resolver."); } } catch (Exception ex) { Warn("Stronghold door audio template lookup failed: " + Unwrap(ex)); } } public static void InstallMinecraftVillageMapGuards(Harmony harmony) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown if (harmony == null) { return; } try { Type type = AccessTools.TypeByName("Map"); if (type == null) { Warn("Minecraft Village map guard unavailable: Map type not found."); return; } MethodInfo methodInfo = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "AddDoor") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length >= 2 && parameters.Any((ParameterInfo p) => p.ParameterType == typeof(GameObject)); }); MethodInfo method = typeof(Bridge).GetMethod("MinecraftVillageMapAddDoorPrefix", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null || method == null) { Warn("Minecraft Village map guard unavailable: Map.AddDoor target not found."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Info("Minecraft Village map guard active: null Map.AddDoor prefabs are skipped."); } catch (Exception ex) { Warn("Minecraft Village Map.AddDoor guard install failed: " + Unwrap(ex)); } } public static bool MinecraftVillageMapAddDoorPrefix(object[] __args) { try { if (!CurrentLevelContains("Minecraft Village")) { return true; } if (__args == null) { return true; } GameObject val = null; foreach (object obj in __args) { GameObject val2 = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val2 != (Object)null) { val = val2; } } if ((Object)(object)val != (Object)null) { return true; } _villageNullDoorPrefabSkips++; if (_villageNullDoorPrefabSkips <= 8) { Warn("VILLAGE MAP DOOR SKIPPED | null doorPrefab | count=" + _villageNullDoorPrefabSkips); } return false; } catch (Exception ex) { Warn("Minecraft Village Map.AddDoor guard failed: " + Unwrap(ex)); return true; } } public static void InstallMinecraftVillageChestContainment(Harmony harmony) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (harmony == null) { return; } try { MethodInfo method = typeof(PhysGrabHinge).GetMethod("Awake", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo method2 = typeof(Bridge).GetMethod("MinecraftHingeAwakeFinalizer", BindingFlags.Static | BindingFlags.Public); if (method == null || method2 == null) { Warn("Minecraft Village chest containment unavailable: PhysGrabHinge.Awake target not found."); return; } harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null); Info("Minecraft Village broken-chest containment patch active."); } catch (Exception ex) { Error("Minecraft Village chest containment install failed: " + Unwrap(ex)); } } public static Exception MinecraftHingeAwakeFinalizer(PhysGrabHinge __instance, Exception __exception) { if (__exception == null) { return null; } try { if (Plugin.VillageBrokenChestContainment != null && Plugin.VillageBrokenChestContainment.Value && CurrentLevelContains("Minecraft Village") && (Object)(object)__instance != (Object)null) { string hierarchyPath = GetHierarchyPath(((Component)__instance).transform); if (hierarchyPath.IndexOf("Minecraft Chest", StringComparison.OrdinalIgnoreCase) >= 0 && hierarchyPath.IndexOf("Hinge Template", StringComparison.OrdinalIgnoreCase) >= 0) { ((Behaviour)__instance).enabled = false; int instanceID = ((Object)__instance).GetInstanceID(); if (!VillageChestContainmentLogged.Contains(instanceID)) { VillageChestContainmentLogged.Add(instanceID); Warn("VILLAGE CHEST CONTAINED | disabled broken PhysGrabHinge | " + hierarchyPath); } return null; } } } catch (Exception ex) { Error("Minecraft Village chest containment failed: " + Unwrap(ex)); } return __exception; } public static IEnumerator MinecraftVillageRepairLoop() { while (true) { yield return (object)new WaitForSeconds(5f); try { if (!CurrentLevelContains("Minecraft Village") || !IsHostOrSingleplayer()) { continue; } LevelGenerator instance = LevelGenerator.Instance; if (!((Object)(object)instance == (Object)null)) { int instanceID = ((Object)instance).GetInstanceID(); if (!VillageGeneratorFirstSeenAt.TryGetValue(instanceID, out var value)) { value = Time.realtimeSinceStartup; VillageGeneratorFirstSeenAt[instanceID] = value; } if (Plugin.VillageTargetedFixes != null && Plugin.VillageTargetedFixes.Value) { RescueEmbeddedMinecraftVillageValuables(); } if (Plugin.VillageCleanupCrewTruckStartGuard != null && Plugin.VillageCleanupCrewTruckStartGuard.Value && Time.realtimeSinceStartup - value <= 25f) { GuardMinecraftVillageTruckEnemiesAtStart(instanceID); } } } catch (Exception ex) { Error("Minecraft Village repair loop failed: " + Unwrap(ex)); } } } private static void RescueEmbeddedMinecraftVillageValuables() { //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_018c: 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_044e: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: 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_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_0515: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_040c: 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) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_0527: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_05ba: Unknown result type (might be due to invalid IL or missing references) //IL_05cd: Unknown result type (might be due to invalid IL or missing references) //IL_05d2: Unknown result type (might be due to invalid IL or missing references) //IL_0589: Unknown result type (might be due to invalid IL or missing references) //IL_05dd: Unknown result type (might be due to invalid IL or missing references) //IL_05df: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Unknown result type (might be due to invalid IL or missing references) //IL_0600: Unknown result type (might be due to invalid IL or missing references) //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Unknown result type (might be due to invalid IL or missing references) //IL_066b: Unknown result type (might be due to invalid IL or missing references) //IL_0680: Unknown result type (might be due to invalid IL or missing references) //IL_0696: Unknown result type (might be due to invalid IL or missing references) //IL_06ac: Unknown result type (might be due to invalid IL or missing references) //IL_060b: Unknown result type (might be due to invalid IL or missing references) //IL_060d: Unknown result type (might be due to invalid IL or missing references) //IL_070a: Unknown result type (might be due to invalid IL or missing references) PhysGrabObject[] array = Object.FindObjectsOfType(); if (array == null) { return; } List minecraftVillageTruckLevelPoints = GetMinecraftVillageTruckLevelPoints(); PhysGrabObject[] array2 = array; foreach (PhysGrabObject val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).transform == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } int instanceID = ((Object)val).GetInstanceID(); ValuableObject component = ((Component)val).GetComponent(); if ((Object)(object)component == (Object)null) { continue; } string text = ((Object)val).name ?? string.Empty; if (text.IndexOf("Valuable Present", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Enemy Valuable", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } string hierarchyPath = GetHierarchyPath(((Component)val).transform); bool flag = hierarchyPath.IndexOf("Minecraft Chest/", StringComparison.OrdinalIgnoreCase) >= 0; bool flag2 = hierarchyPath.IndexOf("S - Clearing(Clone)/Item Holder (9)/", StringComparison.OrdinalIgnoreCase) >= 0; if (flag2) { continue; } bool flag3 = Plugin.VillageTargetedFixes != null && Plugin.VillageTargetedFixes.Value; bool flag4 = VillageRescueTargets.ContainsKey(instanceID); bool flag5 = minecraftVillageTruckLevelPoints != null && minecraftVillageTruckLevelPoints.Count > 0 && MinDistanceToPoints(((Component)val).transform.position, minecraftVillageTruckLevelPoints) <= 22f; if (!flag3 || (!flag && !flag4)) { continue; } if (flag3 && flag) { DetachValuableFromBrokenMinecraftChest(val, hierarchyPath); } Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); if (componentsInChildren == null || componentsInChildren.Length == 0 || !TryGetCombinedBounds(componentsInChildren, out var bounds)) { continue; } if (VillageRescueTargets.TryGetValue(instanceID, out var value)) { float num = Vector3.Distance(((Bounds)(ref bounds)).center, value); if (num <= 0.22f) { Vector3 point = Vector3.zero; Vector3 standingPoint = Vector3.zero; bool flag6 = TryGetPlayerNavMeshPoint(out point) && HasReachableGrabAccess(val, bounds, point, out standingPoint); VillageRescueTargets.Remove(instanceID); VillageRescueRetryCounts.Remove(instanceID); VillageRescuedValuables.Add(instanceID); Info("VILLAGE RESCUE STABLE | " + ((Object)val).name + " | center=" + Vec(((Bounds)(ref bounds)).center) + " | target=" + Vec(value) + " | error=" + num.ToString("0.00") + " | grabbableAfter=" + flag6 + (flag6 ? (" | stand=" + Vec(standingPoint)) : string.Empty) + " | path=" + GetHierarchyPath(((Component)val).transform)); continue; } int value2 = 0; VillageRescueRetryCounts.TryGetValue(instanceID, out value2); if (value2 >= 6) { Warn("VILLAGE RESCUE VERIFY FAILED | " + ((Object)val).name + " | current=" + Vec(((Bounds)(ref bounds)).center) + " | target=" + Vec(value) + " | error=" + num.ToString("0.00")); VillageRescueTargets.Remove(instanceID); VillageRescueRetryCounts.Remove(instanceID); VillageRescuedValuables.Add(instanceID); } else { ForceMoveValuableRoot(val, ((Bounds)(ref bounds)).center, value, out var rootBefore, out var rootAfter, out var rigidbodyCount); value2++; VillageRescueRetryCounts[instanceID] = value2; Info("VILLAGE RESCUE REAPPLY #" + value2 + " | " + ((Object)val).name + " | centerBefore=" + Vec(((Bounds)(ref bounds)).center) + " | target=" + Vec(value) + " | rootBefore=" + Vec(rootBefore) + " | rootAfter=" + Vec(rootAfter) + " | rigidbodies=" + rigidbodyCount); } } else { if (VillageRescuedValuables.Contains(instanceID)) { continue; } List list = FindStaticEmbeddingColliders(val, componentsInChildren, bounds); if (list != null && list.Count > 0 && !flag && !flag2 && flag5) { int instanceID2 = ((Object)val).GetInstanceID(); if (!VillageRescueCandidateLogged.Contains(instanceID2)) { VillageRescueCandidateLogged.Add(instanceID2); Info("VILLAGE START-ZONE WALL SUSPECT | " + ((Object)val).name + " | blockers=" + list.Count + " | center=" + Vec(((Bounds)(ref bounds)).center) + " | path=" + GetHierarchyPath(((Component)val).transform)); } } if (TryFindVillageRescueTarget(val, bounds, list, out var center, out var reason)) { Vector3 v = center - ((Bounds)(ref bounds)).center; if (v.y < -0.05f) { Warn("VILLAGE RESCUE rejected downward move | " + ((Object)val).name + " | delta=" + Vec(v)); continue; } if (((Vector3)(ref v)).magnitude > 6f) { Warn("VILLAGE RESCUE rejected >6m move | " + ((Object)val).name + " | delta=" + Vec(v)); continue; } ForceMoveValuableRoot(val, ((Bounds)(ref bounds)).center, center, out var rootBefore2, out var rootAfter2, out var rigidbodyCount2); VillageRescueTargets[instanceID] = center; VillageRescueRetryCounts[instanceID] = 0; Vector3 point2 = Vector3.zero; bool flag7 = TryGetPlayerNavMeshPoint(out point2) && IsNavPointReachable(point2, center); Bounds bounds2; bool flag8 = TryGetCombinedBounds(((Component)val).GetComponentsInChildren(true), out bounds2); Vector3 standingPoint2 = Vector3.zero; bool flag9 = flag7 && flag8 && HasReachableGrabAccess(val, bounds2, point2, out standingPoint2); Info("VILLAGE RESCUE MOVED | " + ((Object)val).name + " | reason=" + reason + " | from=" + Vec(((Bounds)(ref bounds)).center) + " | to=" + Vec(center) + " | delta=" + Vec(v) + " | rootBefore=" + Vec(rootBefore2) + " | rootAfter=" + Vec(rootAfter2) + " | rigidbodies=" + rigidbodyCount2 + " | reachableAfter=" + flag7 + " | grabbableAfter=" + flag9 + (flag9 ? (" | stand=" + Vec(standingPoint2)) : string.Empty) + " | path=" + GetHierarchyPath(((Component)val).transform)); } } } } private static void ForceMoveValuableRoot(PhysGrabObject obj, Vector3 currentCenter, Vector3 targetCenter, out Vector3 rootBefore, out Vector3 rootAfter, out int rigidbodyCount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) rootBefore = Vector3.zero; rootAfter = Vector3.zero; rigidbodyCount = 0; if ((Object)(object)obj == (Object)null || (Object)(object)((Component)obj).transform == (Object)null) { return; } Vector3 val = targetCenter - currentCenter; rootBefore = ((Component)obj).transform.position; Rigidbody[] componentsInChildren = ((Component)obj).GetComponentsInChildren(true); rigidbodyCount = ((componentsInChildren != null) ? componentsInChildren.Length : 0); ((Component)obj).transform.position = ((Component)obj).transform.position + val; Physics.SyncTransforms(); if (componentsInChildren != null) { Rigidbody[] array = componentsInChildren; foreach (Rigidbody val2 in array) { if (!((Object)(object)val2 == (Object)null)) { val2.position = ((Component)val2).transform.position; if (!val2.isKinematic) { val2.velocity = Vector3.zero; val2.angularVelocity = Vector3.zero; val2.WakeUp(); } } } } Physics.SyncTransforms(); rootAfter = ((Component)obj).transform.position; } private static bool DetachValuableFromBrokenMinecraftChest(PhysGrabObject obj, string originalPath) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null || (Object)(object)((Component)obj).transform == (Object)null) { return false; } try { Transform parent = ((Component)obj).transform.parent; Transform val = null; int num = 0; while ((Object)(object)parent != (Object)null && num++ < 20) { string text = ((Object)parent).name ?? string.Empty; if (text.Equals("Minecraft Chest", StringComparison.OrdinalIgnoreCase)) { val = parent; break; } parent = parent.parent; } if ((Object)(object)val == (Object)null) { return false; } Transform parent2 = val.parent; Vector3 position = ((Component)obj).transform.position; Quaternion rotation = ((Component)obj).transform.rotation; ((Component)obj).transform.SetParent(parent2, true); ((Component)obj).transform.position = position; ((Component)obj).transform.rotation = rotation; Physics.SyncTransforms(); Info("VILLAGE CHEST LOOT DETACHED | " + ((Object)obj).name + " | from=" + originalPath + " | to=" + GetHierarchyPath(((Component)obj).transform)); return true; } catch (Exception ex) { Warn("Village chest-loot detach failed | " + (((Object)(object)obj != (Object)null) ? ((Object)obj).name : "") + " | " + Unwrap(ex)); return false; } } private static void GuardMinecraftVillageTruckEnemiesAtStart(int generatorId) { //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) try { if (!CurrentLevelContains("Minecraft Village") || !IsHostOrSingleplayer()) { return; } List minecraftVillageTruckLevelPoints = GetMinecraftVillageTruckLevelPoints(); if (minecraftVillageTruckLevelPoints.Count == 0) { return; } Type type = AccessTools.TypeByName("EnemyParent"); if (type == null) { return; } Object[] array = Object.FindObjectsOfType(type); if (array == null || array.Length == 0) { return; } 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) { continue; } string text = Convert.ToString(GetMemberValue(val2, "enemyName")) ?? ((Object)val2).name ?? string.Empty; float num = MinDistanceToPoints(val2.transform.position, minecraftVillageTruckLevelPoints); int instanceID = ((Object)val2).GetInstanceID(); bool flag = string.Equals(text, "Cleanup Crew", StringComparison.OrdinalIgnoreCase) || text.IndexOf("Cleanup Crew", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("CleanupCrew", StringComparison.OrdinalIgnoreCase) >= 0; if ((flag || num <= 25f) && !VillageTruckEnemyLoggedInstances.Contains(instanceID)) { VillageTruckEnemyLoggedInstances.Add(instanceID); Info("VILLAGE TRUCK ENEMY | name=" + text + " | pos=" + Vec(val2.transform.position) + " | minTruckPointDistance=" + num.ToString("0.00") + " | generator=" + generatorId); } if (!flag || num > 35f || VillageCleanupCrewRelocatedInstances.Contains(instanceID)) { continue; } Vector3 target = Vector3.zero; if (!TryFindVillageEnemyStartRelocationTarget(minecraftVillageTruckLevelPoints, out target)) { Warn("VILLAGE CLEANUP CREW TRUCK GUARD | Cleanup Crew detected near truck but no safe relocation target was found."); continue; } Vector3 position = val2.transform.position; if (!TryRelocateEnemyParent(val2, target)) { Warn("VILLAGE CLEANUP CREW TRUCK GUARD | relocation failed | from=" + Vec(position) + " | target=" + Vec(target)); continue; } VillageCleanupCrewRelocatedInstances.Add(instanceID); Info("VILLAGE CLEANUP CREW TRUCK GUARD MOVED | from=" + Vec(position) + " | to=" + Vec(target) + " | oldTruckDistance=" + num.ToString("0.00")); } } catch (Exception ex) { Warn("Minecraft Village truck-enemy start guard failed: " + Unwrap(ex)); } } private static List GetMinecraftVillageTruckLevelPoints() { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) List list = new List(); try { Type type = AccessTools.TypeByName("LevelPoint"); if (type == null) { return list; } Object[] array = Object.FindObjectsOfType(type); 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)) { bool flag = false; object memberValue = GetMemberValue(val2, "Truck"); if (memberValue is bool) { flag = (bool)memberValue; } string hierarchyPath = GetHierarchyPath(val2.transform); bool flag2 = hierarchyPath.IndexOf("S - Clearing(Clone)/Truck Run/", StringComparison.OrdinalIgnoreCase) >= 0; if (flag || flag2) { list.Add(val2.transform.position); } } } } catch (Exception ex) { Warn("Village truck LevelPoint discovery failed: " + Unwrap(ex)); } return list; } private static float MinDistanceToPoints(Vector3 position, List points) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (points == null || points.Count == 0) { return float.MaxValue; } float num = float.MaxValue; foreach (Vector3 point in points) { float num2 = Vector3.Distance(position, point); if (num2 < num) { num = num2; } } return num; } private static bool TryFindVillageEnemyStartRelocationTarget(List truckPoints, out Vector3 target) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013c: 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_0152: 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_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) target = Vector3.zero; try { Type type = AccessTools.TypeByName("LevelPoint"); if (type == null) { return false; } Object[] array = Object.FindObjectsOfType(type); if (array == null || array.Length == 0) { return false; } Vector3 point = Vector3.zero; bool flag = TryGetPlayerNavMeshPoint(out point); float num = float.MaxValue; bool result = false; Object[] array2 = array; NavMeshHit val3 = default(NavMeshHit); 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) { continue; } object memberValue = GetMemberValue(val2, "Truck"); object memberValue2 = GetMemberValue(val2, "inStartRoom"); bool flag2 = memberValue is bool && (bool)memberValue; bool flag3 = memberValue2 is bool && (bool)memberValue2; if (flag2 || flag3 || val2.transform.position.y < -1.5f || !NavMesh.SamplePosition(val2.transform.position, ref val3, 1.75f, -1)) { continue; } float num2 = MinDistanceToPoints(((NavMeshHit)(ref val3)).position, truckPoints); if (!(num2 < 45f) && (!flag || IsNavPointReachable(point, ((NavMeshHit)(ref val3)).position))) { float num3 = (flag ? Vector3.Distance(point, ((NavMeshHit)(ref val3)).position) : num2); float num4 = num3 + Mathf.Abs(((NavMeshHit)(ref val3)).position.y) * 0.1f; if (!(num4 >= num)) { num = num4; target = ((NavMeshHit)(ref val3)).position; result = true; } } } return result; } catch (Exception ex) { Warn("Village Cleanup Crew relocation target search failed: " + Unwrap(ex)); return false; } } private static bool TryRelocateEnemyParent(Component enemyParent, Vector3 target) { //IL_001f: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemyParent == (Object)null || (Object)(object)enemyParent.transform == (Object)null) { return false; } try { enemyParent.transform.position = target; Physics.SyncTransforms(); object memberValue = GetMemberValue(enemyParent, "Enemy"); Component val = (Component)((memberValue is Component) ? memberValue : null); object obj = ((memberValue == null) ? null : GetMemberValue(memberValue, "NavMeshAgent")); if (obj == null && memberValue != null) { obj = GetMemberValue(memberValue, "navMeshAgent"); } if (obj == null && (Object)(object)val != (Object)null) { Component[] componentsInChildren = val.GetComponentsInChildren(true); obj = ((IEnumerable)componentsInChildren).FirstOrDefault((Func)((Component c) => (Object)(object)c != (Object)null && string.Equals(((object)c).GetType().Name, "EnemyNavMeshAgent", StringComparison.OrdinalIgnoreCase))); } if (obj != null) { WarpCompat(obj, target); } Rigidbody[] componentsInChildren2 = enemyParent.GetComponentsInChildren(true); if (componentsInChildren2 != null) { Rigidbody[] array = componentsInChildren2; foreach (Rigidbody val2 in array) { if (!((Object)(object)val2 == (Object)null)) { val2.position = ((Component)val2).transform.position; if (!val2.isKinematic) { val2.velocity = Vector3.zero; val2.angularVelocity = Vector3.zero; } } } } Physics.SyncTransforms(); return Vector3.Distance(enemyParent.transform.position, target) <= 1.5f; } catch (Exception ex) { Warn("Enemy relocation failed: " + Unwrap(ex)); return false; } } public static IEnumerator VillageDoorToggleInstallLoop() { while (true) { yield return (object)new WaitForSeconds(1.25f); try { if (Plugin.VillageClickToggleDoors != null && Plugin.VillageClickToggleDoors.Value && CurrentLevelContains("Minecraft Village")) { InstallVillageDoorToggles(); } } catch (Exception ex) { Warn("Minecraft Village door-toggle installer failed: " + Unwrap(ex)); } } } private static void InstallVillageDoorToggles() { PhysGrabHinge[] array = Object.FindObjectsOfType(); PhysGrabHinge[] array2 = array; foreach (PhysGrabHinge val in array2) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { continue; } string hierarchyPath = GetHierarchyPath(((Component)val).transform); if (hierarchyPath.IndexOf("Minecraft Chest", StringComparison.OrdinalIgnoreCase) >= 0 || hierarchyPath.IndexOf("Hinge Template", StringComparison.OrdinalIgnoreCase) >= 0 || hierarchyPath.IndexOf("S - Clearing", StringComparison.OrdinalIgnoreCase) >= 0 || hierarchyPath.IndexOf("Truck", StringComparison.OrdinalIgnoreCase) >= 0) { continue; } HingeJoint val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).GetComponentInChildren(true); } if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).GetComponentInParent(); } if ((Object)(object)val2 == (Object)null) { continue; } PhysGrabObject val3 = ((Component)val).GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val).GetComponentInParent(); } GameObject val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : ((Component)val2).gameObject); if ((Object)(object)val4 == (Object)null || (hierarchyPath.IndexOf("Door", StringComparison.OrdinalIgnoreCase) < 0 && (((Object)val4).name ?? string.Empty).IndexOf("Door", StringComparison.OrdinalIgnoreCase) < 0)) { continue; } Component[] componentsInChildren = val4.GetComponentsInChildren(true); if (!componentsInChildren.Any((Component c) => (Object)(object)c != (Object)null && string.Equals(((object)c).GetType().Name, "DirtFinderMapDoor", StringComparison.OrdinalIgnoreCase)) && hierarchyPath.IndexOf("Oak Door", StringComparison.OrdinalIgnoreCase) < 0 && hierarchyPath.IndexOf("Iron Door", StringComparison.OrdinalIgnoreCase) < 0) { continue; } VillageMinecraftDoorToggle component = val4.GetComponent(); if (!((Object)(object)component != (Object)null)) { component = val4.AddComponent(); component.Configure(val2, val4.transform, val3, val); int instanceID = ((Object)val4).GetInstanceID(); if (!VillageDoorToggleInstalled.Contains(instanceID)) { VillageDoorToggleInstalled.Add(instanceID); Info("VILLAGE DOOR CLICK TOGGLE installed | " + hierarchyPath); } } } } private static bool TryGetCombinedBounds(Collider[] colliders, out Bounds bounds) { //IL_0001: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) bounds = default(Bounds); bool flag = false; foreach (Collider val in colliders) { if (!((Object)(object)val == (Object)null) && val.enabled && !val.isTrigger) { if (!flag) { bounds = val.bounds; flag = true; } else { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } } return flag; } private static bool IsSupportedClosestPointCollider(Collider c) { if (c is BoxCollider || c is SphereCollider || c is CapsuleCollider) { return true; } MeshCollider val = (MeshCollider)(object)((c is MeshCollider) ? c : null); if ((Object)(object)val != (Object)null) { return val.convex; } return false; } private static bool IsOwnCollider(PhysGrabObject obj, Collider c) { if ((Object)(object)obj == (Object)null || (Object)(object)c == (Object)null || (Object)(object)((Component)c).transform == (Object)null) { return false; } if (!((Object)(object)((Component)c).transform == (Object)(object)((Component)obj).transform)) { return ((Component)c).transform.IsChildOf(((Component)obj).transform); } return true; } private static bool IsStaticLevelBlocker(PhysGrabObject obj, Collider c) { if ((Object)(object)c == (Object)null || !c.enabled || c.isTrigger || IsOwnCollider(obj, c)) { return false; } if ((Object)(object)((Component)c).GetComponentInParent() != (Object)null) { return false; } if ((Object)(object)((Component)c).GetComponentInParent() != (Object)null) { return false; } string hierarchyPath = GetHierarchyPath(((Component)c).transform); if (hierarchyPath.IndexOf("Player", StringComparison.OrdinalIgnoreCase) >= 0 || hierarchyPath.IndexOf("Enemy", StringComparison.OrdinalIgnoreCase) >= 0 || hierarchyPath.IndexOf("Cart", StringComparison.OrdinalIgnoreCase) >= 0 || hierarchyPath.IndexOf("Truck", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (!((Object)(object)c.attachedRigidbody == (Object)null)) { return c.attachedRigidbody.isKinematic; } return true; } private static List FindStaticEmbeddingColliders(PhysGrabObject obj, Collider[] own, Bounds bounds) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) List list = new List(); Collider[] array = Physics.OverlapBox(((Bounds)(ref bounds)).center, Vector3.Max(((Bounds)(ref bounds)).extents * 0.92f, Vector3.one * 0.02f), Quaternion.identity, -1, (QueryTriggerInteraction)1); Collider[] array2 = array; Vector3 val5 = default(Vector3); float num = default(float); foreach (Collider val in array2) { if (!IsStaticLevelBlocker(obj, val)) { continue; } bool flag = false; if (IsSupportedClosestPointCollider(val)) { Vector3 val2 = val.ClosestPoint(((Bounds)(ref bounds)).center); Vector3 val3 = val2 - ((Bounds)(ref bounds)).center; if (((Vector3)(ref val3)).sqrMagnitude <= 2.5E-05f) { flag = true; } } if (!flag) { foreach (Collider val4 in own) { if (!((Object)(object)val4 == (Object)null) && val4.enabled && !val4.isTrigger && IsSupportedClosestPointCollider(val4) && IsSupportedClosestPointCollider(val) && Physics.ComputePenetration(val4, ((Component)val4).transform.position, ((Component)val4).transform.rotation, val, ((Component)val).transform.position, ((Component)val).transform.rotation, ref val5, ref num) && num > 0.045f) { flag = true; break; } } } if (flag && !list.Contains(val)) { list.Add(val); } } RaycastHit[] array3 = Physics.RaycastAll(((Bounds)(ref bounds)).center + Vector3.up * 2.5f, Vector3.down, 5f, -1, (QueryTriggerInteraction)1); Array.Sort(array3, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array4 = array3; for (int num2 = 0; num2 < array4.Length; num2++) { RaycastHit val6 = array4[num2]; Collider collider = ((RaycastHit)(ref val6)).collider; if (IsStaticLevelBlocker(obj, collider)) { float num3 = ((RaycastHit)(ref val6)).point.y - ((Bounds)(ref bounds)).min.y; float num4 = Mathf.Clamp(((Bounds)(ref bounds)).size.y * 0.22f, 0.06f, 0.2f); if (num3 > num4 && ((RaycastHit)(ref val6)).point.y > ((Bounds)(ref bounds)).center.y - ((Bounds)(ref bounds)).extents.y * 0.65f && !list.Contains(collider)) { list.Add(collider); } break; } } return list; } private static bool TryFindVillageRescueTarget(PhysGrabObject obj, Bounds bounds, List knownBlockers, out Vector3 center, out string reason) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0153: 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_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017e: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0190: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) center = ((Bounds)(ref bounds)).center; reason = null; Vector3 center2 = ((Bounds)(ref bounds)).center; string hierarchyPath = GetHierarchyPath(((Component)obj).transform); bool flag = hierarchyPath.IndexOf("Minecraft Chest/", StringComparison.OrdinalIgnoreCase) >= 0; bool flag2 = hierarchyPath.IndexOf("S - Clearing(Clone)/Item Holder (9)/", StringComparison.OrdinalIgnoreCase) >= 0; if (!TryGetPlayerNavMeshPoint(out var point)) { return false; } Vector3 standingPoint; bool flag3 = HasReachableGrabAccess(obj, bounds, point, out standingPoint); if (!flag && flag3) { return false; } NavMeshHit val = default(NavMeshHit); bool flag4 = NavMesh.SamplePosition(center2, ref val, 1.5f, -1); bool flag5 = knownBlockers != null && knownBlockers.Count > 0; float[] array = new float[9] { 0f, 0.55f, 0.9f, 1.3f, 1.8f, 2.4f, 3.2f, 4.2f, 5.2f }; float num = float.MaxValue; Vector3 val2 = center2; string text = null; NavMeshHit val4 = default(NavMeshHit); Vector3 val5 = default(Vector3); for (int i = 0; i < array.Length; i++) { int num2 = ((i == 0) ? 1 : 20); for (int j = 0; j < num2; j++) { float num3 = ((num2 == 1) ? 0f : (360f / (float)num2 * (float)j)); Vector3 val3 = ((num2 == 1) ? Vector3.zero : (Quaternion.Euler(0f, num3, 0f) * Vector3.forward * array[i])); if (!NavMesh.SamplePosition(center2 + val3, ref val4, (i == 0) ? 5.5f : 1.15f, -1) || !IsNavPointReachable(point, ((NavMeshHit)(ref val4)).position)) { continue; } ((Vector3)(ref val5))..ctor(((NavMeshHit)(ref val4)).position.x, ((NavMeshHit)(ref val4)).position.y + ((Bounds)(ref bounds)).extents.y + 0.12f, ((NavMeshHit)(ref val4)).position.z); Vector3 val6 = val5 - center2; Vector2 val7 = new Vector2(val6.x, val6.z); float magnitude = ((Vector2)(ref val7)).magnitude; if (!(((Vector3)(ref val6)).magnitude > 6f) && !(val6.y < -0.05f) && IsSafeValuablePlacement(obj, val5, ((Bounds)(ref bounds)).extents) && WouldPlacementBeGrabbable(obj, bounds, val5, point)) { bool flag6 = IsStaticRayBlocked(obj, val5, center2); string text2 = (flag ? "broken-chest-loot" : (flag2 ? "extraction-holder-inaccessible" : (flag5 ? "embedded-ungrabbable" : (flag6 ? ((val6.y > 0.18f) ? "buried-ungrabbable" : "wall-ungrabbable") : (flag4 ? "ungrabbable" : "no-local-navmesh-ungrabbable"))))); float num4 = magnitude + Mathf.Max(0f, val6.y) * 0.18f + array[i] * 0.03f; if (num4 < num) { num = num4; val2 = val5; text = text2; } } } } if (text == null) { return false; } center = val2; reason = text; return true; } private static bool HasReachableGrabAccess(PhysGrabObject obj, Bounds bounds, Vector3 playerNav, out Vector3 standingPoint) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015d: 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_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) standingPoint = Vector3.zero; float[] array = new float[5] { 0.75f, 1.1f, 1.55f, 2.1f, 2.6f }; Vector3[] array2 = (Vector3[])(object)new Vector3[3] { ((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).center + Vector3.up * Mathf.Min(0.3f, ((Bounds)(ref bounds)).extents.y * 0.65f), ((Bounds)(ref bounds)).center - Vector3.up * Mathf.Min(0.18f, ((Bounds)(ref bounds)).extents.y * 0.35f) }; float[] array3 = array; NavMeshHit val2 = default(NavMeshHit); foreach (float num in array3) { for (int j = 0; j < 16; j++) { float num2 = 22.5f * (float)j; Vector3 val = Quaternion.Euler(0f, num2, 0f) * Vector3.forward * num; if (!NavMesh.SamplePosition(((Bounds)(ref bounds)).center + val, ref val2, 0.85f, -1) || !IsNavPointReachable(playerNav, ((NavMeshHit)(ref val2)).position)) { continue; } Vector3 val3 = ((NavMeshHit)(ref val2)).position + Vector3.up * 1.2f; Vector3[] array4 = array2; foreach (Vector3 val4 in array4) { float num3 = Vector3.Distance(val3, val4); if (!(num3 > 3.1f) && !IsStaticRayBlocked(obj, val3, val4)) { standingPoint = ((NavMeshHit)(ref val2)).position; return true; } } } } return false; } private static bool WouldPlacementBeGrabbable(PhysGrabObject obj, Bounds oldBounds, Vector3 candidateCenter, Vector3 playerNav) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector3 size = ((Bounds)(ref oldBounds)).size; Bounds bounds = default(Bounds); ((Bounds)(ref bounds))..ctor(candidateCenter, size); Vector3 standingPoint; return HasReachableGrabAccess(obj, bounds, playerNav, out standingPoint); } private static bool TryGetPlayerNavMeshPoint(out Vector3 point) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) point = Vector3.zero; try { Transform val = FindAnyPlayerTransform(); if ((Object)(object)val == (Object)null) { return false; } NavMeshHit val2 = default(NavMeshHit); if (!NavMesh.SamplePosition(val.position, ref val2, 4f, -1)) { return false; } point = ((NavMeshHit)(ref val2)).position; return true; } catch { return false; } } private static bool IsNavPointReachable(Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { NavMeshPath val = new NavMeshPath(); if (!NavMesh.CalculatePath(from, to, -1, val)) { return false; } return (int)val.status == 0 && val.corners != null && val.corners.Length >= 1; } catch { return false; } } private static bool IsStaticRayBlocked(PhysGrabObject obj, Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.05f) { return false; } Vector3 val2 = val / magnitude; RaycastHit[] array = Physics.RaycastAll(from, val2, magnitude, -1, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val3 = array2[num]; Collider collider = ((RaycastHit)(ref val3)).collider; if (IsStaticLevelBlocker(obj, collider) && ((RaycastHit)(ref val3)).distance < magnitude - 0.04f) { return true; } } return false; } private static bool IsSafeValuablePlacement(PhysGrabObject obj, Vector3 center, Vector3 extents) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Max(0.03f, extents.x * 0.82f), Mathf.Max(0.03f, extents.y * 0.82f), Mathf.Max(0.03f, extents.z * 0.82f)); Collider[] array = Physics.OverlapBox(center, val, Quaternion.identity, -1, (QueryTriggerInteraction)1); float num = center.y - val.y; Collider[] array2 = array; foreach (Collider val2 in array2) { if (IsStaticLevelBlocker(obj, val2)) { Bounds bounds = val2.bounds; if (!(((Bounds)(ref bounds)).max.y <= num + 0.1f)) { return false; } } } return true; } private static string GetHierarchyPath(Transform t) { if ((Object)(object)t == (Object)null) { return ""; } List list = new List(); Transform val = t; int num = 0; while ((Object)(object)val != (Object)null && num++ < 24) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list.ToArray()); } private static string Vec(Vector3 v) { return "(" + v.x.ToString("0.00") + "," + v.y.ToString("0.00") + "," + v.z.ToString("0.00") + ")"; } public static void InstallPrivateHostPasswordSkip(Harmony harmony) { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown if (harmony == null) { return; } try { Type type = AccessTools.TypeByName("MenuManager"); Type type2 = AccessTools.TypeByName("MenuPagePassword"); if (type == null || type2 == null) { Warn("Private password skip unavailable: MenuManager/MenuPagePassword type not found."); return; } MethodInfo methodInfo = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "PagePopUpTwoOptions" orderby m.GetParameters().Count((ParameterInfo p) => p.ParameterType == typeof(string)) descending select m).FirstOrDefault(); MethodInfo methodInfo2 = AccessTools.Method(type2, "Update", (Type[])null, (Type[])null); MethodInfo method = typeof(Bridge).GetMethod("PrivateHostPopupPrefix", BindingFlags.Static | BindingFlags.Public); MethodInfo method2 = typeof(Bridge).GetMethod("PrivateHostPasswordUpdatePrefix", BindingFlags.Static | BindingFlags.Public); if (methodInfo == null || methodInfo2 == null || method == null || method2 == null) { Warn("Private password skip unavailable: required menu method not found."); return; } harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Info("Private lobby host password skip patch active."); } catch (Exception ex) { Warn("Private lobby host password skip install failed: " + Unwrap(ex)); } } public static void PrivateHostPopupPrefix(object[] __args) { try { bool flag = Plugin.AutoSkipPrivateHostPassword != null && Plugin.AutoSkipPrivateHostPassword.Value; bool flag2 = Plugin.AutoPickBestRegionPrivateHost != null && Plugin.AutoPickBestRegionPrivateHost.Value; if ((!flag && !flag2) || __args == null) { return; } string[] array = (from string x in __args.Where((object a) => a is string) where !string.IsNullOrEmpty(x) select x).ToArray(); if (array.Length == 0) { return; } string text = string.Join(" ", array).ToLowerInvariant(); bool flag3 = text.Contains("random players") || text.Contains("mean people") || text.Contains("public game") || text.Contains("matchmaking"); if ((text.Contains("private game") || text.Contains("best computer") || text.Contains("are you this friend") || (text.Contains("host") && text.Contains("friend"))) && !flag3) { if (flag) { _privateHostPasswordFlowArmed = true; _privateHostPasswordFlowArmedAt = Time.realtimeSinceStartup; _privateHostPasswordConfirmed = false; Info("PRIVATE PASSWORD SKIP armed for private-host flow."); } if (flag2) { _privateHostRegionFlowArmed = true; _privateHostRegionFlowArmedAt = Time.realtimeSinceStartup; _privateHostRegionConfirmed = false; Info("PRIVATE REGION SKIP armed for private-host flow."); } } } catch (Exception ex) { if (!_privatePasswordPatchLogged) { _privatePasswordPatchLogged = true; Warn("Private host popup detection failed: " + Unwrap(ex)); } } } public static void PrivateHostPasswordUpdatePrefix(object __instance) { try { if (Plugin.AutoSkipPrivateHostPassword == null || !Plugin.AutoSkipPrivateHostPassword.Value || !_privateHostPasswordFlowArmed || _privateHostPasswordConfirmed || __instance == null) { return; } float num = Time.realtimeSinceStartup - _privateHostPasswordFlowArmedAt; if (num < 0f || num > 15f) { _privateHostPasswordFlowArmed = false; _privateHostPasswordConfirmed = false; return; } MethodInfo methodInfo = AccessTools.Method(__instance.GetType(), "ConfirmButton", (Type[])null, (Type[])null); if (methodInfo == null) { if (!_privatePasswordPatchLogged) { _privatePasswordPatchLogged = true; Warn("Private password skip: MenuPagePassword.ConfirmButton not found."); } _privateHostPasswordFlowArmed = false; } else { _privateHostPasswordConfirmed = true; _privateHostPasswordFlowArmed = false; methodInfo.Invoke(__instance, null); Info("PRIVATE PASSWORD SKIP confirmed host password page (no join-password bypass)."); } } catch (Exception ex) { _privateHostPasswordFlowArmed = false; if (!_privatePasswordPatchLogged) { _privatePasswordPatchLogged = true; Warn("Private password auto-skip failed: " + Unwrap(ex)); } } } public static void InstallPrivateHostBestRegionSkip(Harmony harmony) { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown if (harmony == null) { return; } try { Type type = AccessTools.TypeByName("MenuPageRegions"); if (type == null) { Warn("Private Best Region skip unavailable: MenuPageRegions type not found."); return; } MethodInfo methodInfo = AccessTools.Method(type, "Start", (Type[])null, (Type[])null); MethodInfo method = typeof(Bridge).GetMethod("PrivateHostRegionsStartPostfix", BindingFlags.Static | BindingFlags.Public); MethodInfo methodInfo2 = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "PickRegion") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 1 && parameters[0].ParameterType == typeof(string); }); if (methodInfo == null || method == null || methodInfo2 == null) { Warn("Private Best Region skip unavailable: MenuPageRegions.Start/PickRegion(string) not found."); return; } harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Info("Private lobby Best Region auto-pick patch active (immediate selection restored)."); } catch (Exception ex) { Warn("Private Best Region auto-pick install failed: " + Unwrap(ex)); } } public static void PrivateHostRegionsStartPostfix(object __instance) { try { if (Plugin.AutoPickBestRegionPrivateHost == null || !Plugin.AutoPickBestRegionPrivateHost.Value || !_privateHostRegionFlowArmed || _privateHostRegionConfirmed || __instance == null) { return; } float num = Time.realtimeSinceStartup - _privateHostRegionFlowArmedAt; if (num < 0f || num > 20f) { _privateHostRegionFlowArmed = false; _privateHostRegionConfirmed = false; return; } MethodInfo methodInfo = __instance.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(delegate(MethodInfo m) { if (m.Name != "PickRegion") { return false; } ParameterInfo[] parameters = m.GetParameters(); return parameters.Length == 1 && parameters[0].ParameterType == typeof(string); }); if (methodInfo == null) { if (!_privateRegionPatchLogged) { _privateRegionPatchLogged = true; Warn("Private Best Region skip: PickRegion(string) not found at runtime."); } _privateHostRegionFlowArmed = false; } else { _privateHostRegionConfirmed = true; _privateHostRegionFlowArmed = false; methodInfo.Invoke(__instance, new object[1] { string.Empty }); Info("PRIVATE REGION SKIP selected Best Region for private-host flow."); } } catch (Exception ex) { _privateHostRegionFlowArmed = false; if (!_privateRegionPatchLogged) { _privateRegionPatchLogged = true; Warn("Private Best Region auto-pick failed: " + Unwrap(ex)); } } } public static ValuableObject GetValuableByNameCompat(string name) { return FindValuableObject(name, contains: false); } public static ValuableObject GetValuableThatContainsNameCompat(string name) { return FindValuableObject(name, contains: true); } public static bool TryGetValuableByNameCompat(string name, out ValuableObject valuable) { valuable = FindValuableObject(name, contains: false); return (Object)(object)valuable != (Object)null; } public static bool TryGetValuableThatContainsNameCompat(string name, out ValuableObject valuable) { valuable = FindValuableObject(name, contains: true); return (Object)(object)valuable != (Object)null; } private static ValuableObject FindValuableObject(string name, bool contains) { if (string.IsNullOrEmpty(name)) { return null; } foreach (object allValuablePrefabRef in GetAllValuablePrefabRefs()) { GameObject val = ToGameObject(allValuablePrefabRef); if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)val).name ?? string.Empty; if (contains ? (text.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0) : string.Equals(text, name, StringComparison.OrdinalIgnoreCase)) { ValuableObject component = val.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } } return null; } private static List GetCurrentLevelValuablesByVolume(object volumeType) { List list = new List(); int num; try { num = Convert.ToInt32(volumeType); } catch { return list; } string[] array = new string[7] { "tiny", "small", "medium", "big", "wide", "tall", "veryTall" }; if (num < 0 || num >= array.Length) { return list; } string bucket = array[num]; object obj2 = null; FieldInfo field = typeof(RunManager).GetField("instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { obj2 = field.GetValue(null); } if (obj2 == null) { return list; } object memberValue = GetMemberValue(obj2, "levelCurrent"); if (memberValue == null) { return list; } object memberValue2 = GetMemberValue(memberValue, "ValuablePresets"); if (!(memberValue2 is IEnumerable enumerable)) { return list; } foreach (object item in enumerable) { List legacyBucket = GetLegacyBucket(item, bucket); foreach (GameObject item2 in legacyBucket) { if ((Object)(object)item2 != (Object)null && !list.Contains(item2)) { list.Add(item2); } } } return list; } private static IEnumerable GetAllValuablePrefabRefs() { Assembly repolib = FindAssembly("REPOLib"); Type valuablesType = ((repolib == null) ? null : repolib.GetType("REPOLib.Modules.Valuables", throwOnError: false)); if (valuablesType == null) { yield break; } PropertyInfo all = valuablesType.GetProperty("AllValuables", BindingFlags.Static | BindingFlags.Public); if (all == null) { yield break; } IEnumerable values = null; try { values = all.GetValue(null, null) as IEnumerable; } catch { } if (values == null) { yield break; } foreach (object value in values) { if (value != null) { yield return value; } } } private static object FindPrefabRefForGameObject(GameObject prefab) { if ((Object)(object)prefab == (Object)null) { return null; } object obj = null; foreach (object allValuablePrefabRef in GetAllValuablePrefabRefs()) { GameObject val = ToGameObject(allValuablePrefabRef); if (!((Object)(object)val == (Object)null)) { if (object.ReferenceEquals(val, prefab)) { return allValuablePrefabRef; } if (obj == null && string.Equals(((Object)val).name, ((Object)prefab).name, StringComparison.OrdinalIgnoreCase)) { obj = allValuablePrefabRef; } } } return obj; } private static bool TrySetMemberValue(object obj, string name, object value) { if (obj == null || string.IsNullOrEmpty(name)) { return false; } Type type = obj.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo fieldInfo = type.GetFields(bindingAttr).FirstOrDefault((FieldInfo x) => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); if (fieldInfo != null) { try { fieldInfo.SetValue(obj, value); return true; } catch { } } PropertyInfo propertyInfo = type.GetProperties(bindingAttr).FirstOrDefault((PropertyInfo x) => x.CanWrite && string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); if (propertyInfo != null) { try { propertyInfo.SetValue(obj, value, null); return true; } catch { } } return false; } private static object GetMemberValue(object obj, string name) { if (obj == null) { return null; } Type type = obj.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo fieldInfo = type.GetFields(bindingAttr).FirstOrDefault((FieldInfo x) => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); if (fieldInfo != null) { try { return fieldInfo.GetValue(obj); } catch { } } PropertyInfo propertyInfo = type.GetProperties(bindingAttr).FirstOrDefault((PropertyInfo x) => x.CanRead && string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase)); if (propertyInfo != null) { try { return propertyInfo.GetValue(obj, null); } catch { } } return null; } public static GameObject SpawnValuableCompat(ValuableObject valuable, Vector3 position, Quaternion rotation) { //IL_0097: 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) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)valuable == (Object)null) { return null; } Assembly assembly = FindAssembly("REPOLib"); Type type = ((assembly == null) ? null : assembly.GetType("REPOLib.Modules.Valuables", throwOnError: false)); if (type == null) { throw new MissingMemberException("REPOLib.Modules.Valuables introuvable."); } GameObject gameObject = ((Component)valuable).gameObject; foreach (MethodInfo item in from x in type.GetMethods(BindingFlags.Static | BindingFlags.Public) where x.Name == "SpawnValuable" select x) { ParameterInfo[] parameters = item.GetParameters(); object[] array = TryBuildSpawnArgs(parameters, valuable, gameObject, position, rotation); if (array != null) { object value = item.Invoke(null, array); GameObject val = ToGameObject(value); if ((Object)(object)val != (Object)null) { Info("Legacy SpawnValuable adapted through " + Describe(item) + "."); return val; } } } if (!IsHostOrSingleplayer()) { return null; } GameObject result = Object.Instantiate(gameObject, position, rotation); Warn("Legacy SpawnValuable: no modern PrefabRef spawn matched; used host-only local Instantiate fallback."); return result; } catch (Exception ex) { Error("SpawnValuableCompat failed: " + Unwrap(ex)); return null; } } private static object[] TryBuildSpawnArgs(ParameterInfo[] p, ValuableObject valuable, GameObject prefab, Vector3 position, Quaternion rotation) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) object[] array = new object[p.Length]; for (int i = 0; i < p.Length; i++) { Type parameterType = p[i].ParameterType; if (parameterType == typeof(Vector3)) { array[i] = position; continue; } if (parameterType == typeof(Quaternion)) { array[i] = rotation; continue; } if (parameterType.IsInstanceOfType(valuable)) { array[i] = valuable; continue; } if (parameterType == typeof(GameObject)) { array[i] = prefab; continue; } if (parameterType == typeof(string)) { array[i] = ((Object)prefab).name; continue; } object obj = null; if (parameterType.Name.IndexOf("PrefabRef", StringComparison.OrdinalIgnoreCase) >= 0) { obj = FindPrefabRefForGameObject(prefab); } if (obj != null && parameterType.IsInstanceOfType(obj)) { array[i] = obj; continue; } object obj2 = TryBuildArgument(parameterType, prefab); if (obj2 != null) { array[i] = obj2; continue; } if (p[i].HasDefaultValue) { array[i] = p[i].DefaultValue; continue; } if (parameterType == typeof(bool)) { array[i] = false; continue; } if (parameterType.IsValueType) { array[i] = Activator.CreateInstance(parameterType); continue; } return null; } return array; } public static void WarpCompat(object enemyNavMeshAgent, Vector3 position) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if (enemyNavMeshAgent == null) { return; } try { Type type = enemyNavMeshAgent.GetType(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "Warp")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Vector3)) { methodInfo.Invoke(enemyNavMeshAgent, new object[1] { position }); WarpLog("EnemyNavMeshAgent.Warp(Vector3)"); return; } } } Type type2 = type; while (type2 != null) { FieldInfo[] fields = type2.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!((fieldInfo.FieldType.FullName ?? "") == "UnityEngine.AI.NavMeshAgent")) { continue; } object value = fieldInfo.GetValue(enemyNavMeshAgent); if (value != null) { MethodInfo method = value.GetType().GetMethod("Warp", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(Vector3) }, null); if (method != null) { method.Invoke(value, new object[1] { position }); WarpLog("UnityEngine.AI.NavMeshAgent.Warp(Vector3)"); return; } } } type2 = type2.BaseType; } Component val = (Component)((enemyNavMeshAgent is Component) ? enemyNavMeshAgent : null); if ((Object)(object)val != (Object)null) { val.transform.position = position; WarpLog("transform.position fallback"); } } catch (Exception ex) { Error("WarpCompat failed: " + Unwrap(ex)); } } private static void AddObjectsFromCollection(List dst, object collection) { if (!(collection is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { GameObject val = ToGameObject(item); if ((Object)(object)val != (Object)null && !dst.Contains(val)) { dst.Add(val); } } } private static GameObject ToGameObject(object value) { if (value == null) { return null; } GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val != (Object)null) { return val; } Component val2 = (Component)((value is Component) ? value : null); if ((Object)(object)val2 != (Object)null) { return val2.gameObject; } Type type = value.GetType(); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; string[] array = new string[8] { "Prefab", "prefab", "GameObject", "gameObject", "Asset", "asset", "Value", "value" }; foreach (string name in array) { PropertyInfo property = type.GetProperty(name, bindingAttr); if (property != null && property.CanRead) { object obj = null; try { obj = property.GetValue(value, null); } catch { } GameObject val3 = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val3 != (Object)null) { return val3; } Component val4 = (Component)((obj is Component) ? obj : null); if ((Object)(object)val4 != (Object)null) { return val4.gameObject; } } FieldInfo field = type.GetField(name, bindingAttr); if (field != null) { object obj3 = null; try { obj3 = field.GetValue(value); } catch { } GameObject val5 = (GameObject)((obj3 is GameObject) ? obj3 : null); if ((Object)(object)val5 != (Object)null) { return val5; } Component val6 = (Component)((obj3 is Component) ? obj3 : null); if ((Object)(object)val6 != (Object)null) { return val6.gameObject; } } } return null; } private static object TryBuildArgument(Type targetType, GameObject prefab) { try { if (targetType == typeof(GameObject)) { return prefab; } if (targetType.IsGenericType && targetType.GetGenericTypeDefinition().Name.StartsWith("PrefabRef`", StringComparison.Ordinal)) { return ConstructPrefabRef(targetType, prefab); } if (targetType.Name.StartsWith("PrefabRef", StringComparison.Ordinal)) { return ConstructPrefabRef(targetType, prefab); } if (typeof(ScriptableObject).IsAssignableFrom(targetType)) { object obj = ScriptableObject.CreateInstance(targetType); if (PopulatePrefabMembers(obj, targetType, prefab)) { return obj; } } } catch { } return null; } private static object ConstructPrefabRef(Type targetType, GameObject prefab) { ConstructorInfo[] constructors = targetType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (ConstructorInfo constructorInfo in constructors) { ParameterInfo[] parameters = constructorInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(GameObject)) { return constructorInfo.Invoke(new object[1] { prefab }); } if (parameters.Length == 1 && parameters[0].ParameterType == typeof(string)) { return constructorInfo.Invoke(new object[1] { ((Object)prefab).name }); } } object obj = null; try { obj = Activator.CreateInstance(targetType, nonPublic: true); } catch { } if (obj != null && PopulatePrefabMembers(obj, targetType, prefab)) { return obj; } MethodInfo[] methods = targetType.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { ParameterInfo[] parameters2 = methodInfo.GetParameters(); if (parameters2.Length == 1 && parameters2[0].ParameterType == typeof(GameObject) && targetType.IsAssignableFrom(methodInfo.ReturnType)) { return methodInfo.Invoke(null, new object[1] { prefab }); } } return null; } private static bool PopulatePrefabMembers(object obj, Type t, GameObject prefab) { bool result = false; BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo[] fields = t.GetFields(bindingAttr); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsInitOnly && fieldInfo.FieldType == typeof(GameObject)) { fieldInfo.SetValue(obj, prefab); result = true; } } PropertyInfo[] properties = t.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.CanWrite && propertyInfo.PropertyType == typeof(GameObject)) { propertyInfo.SetValue(obj, prefab, null); result = true; } } return result; } private static List FindZombieEnemyPrefabs() { List list = new List(); foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle == (Object)null) { continue; } GameObject[] array; try { array = allLoadedAssetBundle.LoadAllAssets(); } catch { continue; } GameObject[] array2 = array; foreach (GameObject val in array2) { if (!((Object)(object)val == (Object)null) && (((Object)val).name ?? "").IndexOf("Enemy - MCZombie", StringComparison.OrdinalIgnoreCase) >= 0 && !list.Contains(val)) { list.Add(val); } } } return list; } private static string DescribeMembers(Type t) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; string text = string.Join(", ", (from f in t.GetFields(bindingAttr) select f.Name + ":" + f.FieldType.Name).ToArray()); string text2 = string.Join(", ", (from p in t.GetProperties(bindingAttr) where p.CanRead select p.Name + ":" + p.PropertyType.Name).ToArray()); return "fields=[" + text + "] props=[" + text2 + "]"; } catch { return ""; } } private static IEnumerable SafeGetTypes(Assembly asm) { try { return asm.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type x) => x != null); } } private static Assembly FindAssembly(string name) { return AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, name, StringComparison.OrdinalIgnoreCase)); } private static string Describe(MethodInfo m) { return m.DeclaringType.FullName + "." + m.Name + "(" + string.Join(", ", (from x in m.GetParameters() select x.ParameterType.Name).ToArray()) + ")"; } private static string Unwrap(Exception ex) { return ((ex is TargetInvocationException { InnerException: not null } ex2) ? ex2.InnerException : ex).ToString(); } private static void WarpLog(string path) { if (!_warpPathLogged) { _warpPathLogged = true; Info("MCZombie Warp compatibility route: " + path); } } private static void Info(string s) { if (Plugin.Log != null) { Plugin.Log.LogInfo((object)("[MCZOMBIEfix] " + s)); } else { Debug.Log((object)("[MCZOMBIEfix] " + s)); } } private static void Warn(string s) { if (Plugin.Log != null) { Plugin.Log.LogWarning((object)("[MCZOMBIEfix] " + s)); } else { Debug.LogWarning((object)("[MCZOMBIEfix] " + s)); } } private static void Error(string s) { if (Plugin.Log != null) { Plugin.Log.LogError((object)("[MCZOMBIEfix] " + s)); } else { Debug.LogError((object)("[MCZOMBIEfix] " + s)); } } } public sealed class VillageMinecraftDoorToggle : MonoBehaviour { private const float MotionDuration = 0.42f; private HingeJoint _joint; private Transform _interactionRoot; private Transform _motionTransform; private PhysGrabObject _grab; private PhysGrabHinge _hinge; private Rigidbody _body; private Rigidbody[] _allBodies = (Rigidbody[])(object)new Rigidbody[0]; private Vector3 _lockedMotionLocalPosition; private float _openTarget; private bool _configured; private bool _isOpen; private float _lastToggleAt = -1000f; private Quaternion _closedLocalRotation; private Quaternion _openLocalRotation; private Quaternion _motionFrom; private Quaternion _motionTo; private float _motionStartedAt; private bool _moving; private AudioSource _doorAudio; private AudioClip _openClip; private AudioClip _closeClip; public void Configure(HingeJoint joint, Transform interactionRoot, PhysGrabObject grab, PhysGrabHinge hinge) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) _joint = joint; _interactionRoot = interactionRoot; _grab = grab; _hinge = hinge; if ((Object)(object)_joint == (Object)null || (Object)(object)_interactionRoot == (Object)null) { ((Behaviour)this).enabled = false; return; } _motionTransform = ((Component)_joint).transform; if ((Object)(object)_motionTransform == (Object)null) { ((Behaviour)this).enabled = false; return; } _body = ((Component)_joint).GetComponent(); _allBodies = ((Component)_interactionRoot).GetComponentsInChildren(true); PhysGrabObject[] componentsInChildren = ((Component)_interactionRoot).GetComponentsInChildren(true); PhysGrabObject[] array = componentsInChildren; foreach (PhysGrabObject val in array) { Behaviour val2 = (Behaviour)(object)val; if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } PhysGrabHinge[] componentsInChildren2 = ((Component)_interactionRoot).GetComponentsInChildren(true); PhysGrabHinge[] array2 = componentsInChildren2; foreach (PhysGrabHinge val3 in array2) { Behaviour val4 = (Behaviour)(object)val3; if ((Object)(object)val4 != (Object)null) { val4.enabled = false; } } LockDoorRigidbodies(); _lockedMotionLocalPosition = _motionTransform.localPosition; _joint.useMotor = false; _joint.useSpring = false; JointLimits limits = _joint.limits; float min = ((JointLimits)(ref limits)).min; float max = ((JointLimits)(ref limits)).max; if (Mathf.Abs(max) >= Mathf.Abs(min)) { _openTarget = max * 0.92f; } else { _openTarget = min * 0.92f; } if (Mathf.Abs(_openTarget) < 35f) { _openTarget = 87f; } Vector3 val5 = ((Joint)_joint).axis; if (((Vector3)(ref val5)).sqrMagnitude < 0.0001f) { val5 = Vector3.up; } ((Vector3)(ref val5)).Normalize(); _closedLocalRotation = _motionTransform.localRotation; _openLocalRotation = _closedLocalRotation * Quaternion.AngleAxis(_openTarget, val5); _isOpen = false; ConfigureDoorAudio(); _configured = true; if (Plugin.Log != null) { Plugin.Log.LogInfo((object)("[MCZOMBIEfix] VILLAGE DOOR SOLID LOCK | " + ((Object)_interactionRoot).name + " | rigidbodies=" + ((_allBodies != null) ? _allBodies.Length : 0))); } } private void LockDoorRigidbodies() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (_allBodies == null) { return; } Rigidbody[] allBodies = _allBodies; foreach (Rigidbody val in allBodies) { if (!((Object)(object)val == (Object)null)) { if (!val.isKinematic) { val.velocity = Vector3.zero; val.angularVelocity = Vector3.zero; } val.useGravity = false; val.isKinematic = true; val.constraints = (RigidbodyConstraints)126; val.detectCollisions = true; } } } private void EnforceSolidDoorPose() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (_configured && !((Object)(object)_motionTransform == (Object)null)) { LockDoorRigidbodies(); _motionTransform.localPosition = _lockedMotionLocalPosition; if (!_moving) { _motionTransform.localRotation = (_isOpen ? _openLocalRotation : _closedLocalRotation); } } } private void FixedUpdate() { EnforceSolidDoorPose(); } private void LateUpdate() { EnforceSolidDoorPose(); } private void ConfigureDoorAudio() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) _openClip = Bridge.GetVillageWoodDoorAudioClip(opening: true); _closeClip = Bridge.GetVillageWoodDoorAudioClip(opening: false); if (!((Object)(object)_openClip == (Object)null) || !((Object)(object)_closeClip == (Object)null)) { AudioSource strongholdDoorAudioSource = Bridge.GetStrongholdDoorAudioSource(opening: true); AudioSource strongholdDoorAudioSource2 = Bridge.GetStrongholdDoorAudioSource(opening: false); GameObject val = new GameObject("LegacyREPOCompat Door Audio"); val.transform.SetParent(_interactionRoot, false); _doorAudio = val.AddComponent(); _doorAudio.playOnAwake = false; _doorAudio.loop = false; AudioSource val2 = (((Object)(object)strongholdDoorAudioSource != (Object)null) ? strongholdDoorAudioSource : strongholdDoorAudioSource2); if ((Object)(object)val2 != (Object)null) { _doorAudio.volume = val2.volume; _doorAudio.pitch = val2.pitch; _doorAudio.spatialBlend = val2.spatialBlend; _doorAudio.minDistance = val2.minDistance; _doorAudio.maxDistance = val2.maxDistance; _doorAudio.rolloffMode = val2.rolloffMode; _doorAudio.dopplerLevel = val2.dopplerLevel; _doorAudio.outputAudioMixerGroup = val2.outputAudioMixerGroup; } else { _doorAudio.volume = 0.75f; _doorAudio.pitch = 1f; _doorAudio.spatialBlend = 1f; _doorAudio.minDistance = 1f; _doorAudio.maxDistance = 12f; _doorAudio.rolloffMode = (AudioRolloffMode)0; _doorAudio.dopplerLevel = 0f; } } } private void Update() { //IL_0071: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0113: Unknown result type (might be due to invalid IL or missing references) if (!_configured || (Object)(object)_motionTransform == (Object)null || (Object)(object)_interactionRoot == (Object)null || Plugin.VillageClickToggleDoors == null || !Plugin.VillageClickToggleDoors.Value) { return; } UpdateMotion(); if (!Input.GetMouseButtonDown(0) || Time.realtimeSinceStartup - _lastToggleAt < 0.2f) { return; } Camera main = Camera.main; RaycastHit val = default(RaycastHit); if (!((Object)(object)main == (Object)null) && Physics.Raycast(((Component)main).transform.position, ((Component)main).transform.forward, ref val, 3.5f, -1, (QueryTriggerInteraction)1) && !((Object)(object)((RaycastHit)(ref val)).transform == (Object)null) && ((Object)(object)((RaycastHit)(ref val)).transform == (Object)(object)_interactionRoot || ((RaycastHit)(ref val)).transform.IsChildOf(_interactionRoot))) { _lastToggleAt = Time.realtimeSinceStartup; _isOpen = !_isOpen; _motionFrom = _motionTransform.localRotation; _motionTo = (_isOpen ? _openLocalRotation : _closedLocalRotation); _motionStartedAt = Time.realtimeSinceStartup; _moving = true; PlayDoorSound(_isOpen); if (Plugin.Log != null) { Plugin.Log.LogInfo((object)("[MCZOMBIEfix] VILLAGE DOOR TOGGLE | " + (_isOpen ? "OPEN" : "CLOSE") + " | " + ((Object)_interactionRoot).name)); } } } private void UpdateMotion() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0039: Unknown result type (might be due to invalid IL or missing references) if (_moving && !((Object)(object)_motionTransform == (Object)null)) { float num = (Time.realtimeSinceStartup - _motionStartedAt) / 0.42f; if (num >= 1f) { _motionTransform.localRotation = _motionTo; _moving = false; } else { num = Mathf.Clamp01(num); float num2 = num * num * (3f - 2f * num); _motionTransform.localRotation = Quaternion.Slerp(_motionFrom, _motionTo, num2); } } } private void PlayDoorSound(bool opening) { if (!((Object)(object)_doorAudio == (Object)null)) { AudioClip val = (opening ? _openClip : _closeClip); if (!((Object)(object)val == (Object)null)) { _doorAudio.Stop(); _doorAudio.clip = val; _doorAudio.Play(); } } } }