using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Peak.Afflictions; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.SceneManagement; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("WatchEgg")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("WatchEgg")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("217b75f9-9ff7-4920-8cee-9e5a99f9861d")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] [BepInPlugin("Sapphire009.StaminaFull", "StaminaFull", "1.0.0")] public sealed class StaminaFull : BaseUnityPlugin { [HarmonyPatch(typeof(Character), "UseStamina", new Type[] { typeof(float), typeof(bool) })] private static class CharacterUseStaminaPatch { [HarmonyPrefix] private static bool Prefix(Character __instance, float __0, bool __1, ref bool __result) { if (__0 <= 0f) { return true; } if (!CanApplyProtection(__instance)) { return true; } FillAndPreserveStamina(__instance); __instance.data.sinceUseStamina = 0f; __result = true; return false; } } [HarmonyPatch(typeof(Character), "AddStamina", new Type[] { typeof(float) })] private static class CharacterAddStaminaPatch { [HarmonyPrefix] private static bool Prefix(Character __instance, float __0) { if (__0 >= 0f) { return true; } return !CanApplyProtection(__instance); } } [HarmonyPatch(typeof(Character), "SetExtraStamina", new Type[] { typeof(float) })] private static class CharacterSetExtraStaminaPatch { [HarmonyPrefix] private static bool Prefix(Character __instance, float __0) { if (!CanApplyProtection(__instance)) { return true; } if (__0 >= __instance.data.extraStamina) { return true; } return false; } } [HarmonyPatch(typeof(Character), "AddExtraStamina", new Type[] { typeof(float) })] private static class CharacterAddExtraStaminaPatch { [HarmonyPrefix] private static bool Prefix(Character __instance, float __0) { if (__0 >= 0f) { return true; } return !CanApplyProtection(__instance); } } [HarmonyPatch(typeof(CharacterAfflictions), "AddStatus", new Type[] { typeof(STATUSTYPE), typeof(float), typeof(bool), typeof(bool), typeof(bool) })] private static class CharacterAfflictionsAddStatusPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, STATUSTYPE __0, float __1, bool __2, bool __3, bool __4, ref bool __result) { //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_0026: Unknown result type (might be due to invalid IL or missing references) if (__1 <= 0f || !CanApplyProtection(__instance)) { return true; } __result = false; LogBlockedStatus(__0, __1, "AddStatus"); return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "AdjustStatus", new Type[] { typeof(STATUSTYPE), typeof(float), typeof(bool) })] private static class CharacterAfflictionsAdjustStatusPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, STATUSTYPE __0, float __1, bool __2) { //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_0022: Unknown result type (might be due to invalid IL or missing references) if (__1 <= 0f || !CanApplyProtection(__instance)) { return true; } LogBlockedStatus(__0, __1, "AdjustStatus"); return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "SetStatus", new Type[] { typeof(STATUSTYPE), typeof(float), typeof(bool) })] private static class CharacterAfflictionsSetStatusPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, STATUSTYPE __0, float __1, bool __2) { //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_0019: 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) if (!CanApplyProtection(__instance)) { return true; } float currentStatus = __instance.GetCurrentStatus(__0); if (__1 <= currentStatus) { return true; } LogBlockedStatus(__0, __1 - currentStatus, "SetStatus"); return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "AddAffliction", new Type[] { typeof(Affliction), typeof(bool) })] private static class CharacterAfflictionsAddAfflictionPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, Affliction __0, bool __1) { //IL_00a3: 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) if (!CanApplyProtection(__instance)) { return true; } if (blockedAfflictionLogCount < 50) { blockedAfflictionLogCount++; string text = ((__0 != null) ? ((object)__0).GetType().Name : "null"); ManualLogSource modLogger = ModLogger; if (modLogger != null) { string[] obj = new string[7] { "[StaminaFull] Affliction blocked ", $"({blockedAfflictionLogCount}/", $"{50}). ", "Affliction=", text, ", Scene=", null }; Scene activeScene = SceneManager.GetActiveScene(); obj[6] = ((Scene)(ref activeScene)).name; modLogger.LogInfo((object)string.Concat(obj)); } } return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "AddThorn", new Type[] { typeof(Vector3) })] private static class CharacterAfflictionsAddThornPositionPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, Vector3 __0) { if (!CanApplyProtection(__instance)) { return true; } LogBlockedThorn(); return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "AddThorn", new Type[] { typeof(ushort) })] private static class CharacterAfflictionsAddThornIndexPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, ushort __0) { if (!CanApplyProtection(__instance)) { return true; } LogBlockedThorn(); return false; } } [HarmonyPatch(typeof(CharacterAfflictions), "RPC_EnableThorn", new Type[] { typeof(int) })] private static class CharacterAfflictionsEnableThornPatch { [HarmonyPrefix] private static bool Prefix(CharacterAfflictions __instance, int __0) { if (!CanApplyProtection(__instance)) { return true; } LogBlockedThorn(); return false; } } [HarmonyPatch(typeof(Character), "FixedUpdate")] private static class CharacterFixedUpdatePatch { [HarmonyPostfix] private static void Postfix(Character __instance) { if (!CanApplyProtection(__instance)) { if ((Object)(object)__instance != (Object)null) { PreservedExtraStamina.Remove(((Object)__instance).GetInstanceID()); } } else { ClearAllNegativeStates(__instance); FillAndPreserveStamina(__instance); } } } public const string PluginGUID = "Sapphire009.StaminaFull"; public const string PluginName = "StaminaFull"; public const string PluginVersion = "1.0.0"; private const string BuildMarker = "InfiniteStamina-AllStatusBlock-R2"; private const int MaximumLogCount = 50; internal static ManualLogSource ModLogger; private static readonly Dictionary PreservedExtraStamina = new Dictionary(); private static int blockedStatusLogCount; private static int blockedAfflictionLogCount; private static int blockedThornLogCount; private Harmony harmony; private void Awake() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; harmony = new Harmony("Sapphire009.StaminaFull"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"StaminaFull 1.0.0 loaded. Build: InfiniteStamina-AllStatusBlock-R2. Infinite stamina and complete status protection are enabled outside Airport."); } private void OnDestroy() { PreservedExtraStamina.Clear(); blockedStatusLogCount = 0; blockedAfflictionLogCount = 0; blockedThornLogCount = 0; if (harmony != null) { harmony.UnpatchSelf(); harmony = null; } ModLogger = null; } internal static bool IsAirportScene() { //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) Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (string.IsNullOrEmpty(name)) { return false; } return name.IndexOf("Airport", StringComparison.OrdinalIgnoreCase) >= 0; } internal static bool CanApplyProtection(Character character) { if ((Object)(object)character == (Object)null || !character.IsLocal || (Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)character.refs.afflictions == (Object)null) { return false; } if (IsAirportScene()) { return false; } return true; } internal static bool CanApplyProtection(CharacterAfflictions afflictions) { if ((Object)(object)afflictions == (Object)null) { return false; } return CanApplyProtection(afflictions.character); } internal static void FillAndPreserveStamina(Character character) { if (!CanApplyProtection(character)) { if ((Object)(object)character != (Object)null) { PreservedExtraStamina.Remove(((Object)character).GetInstanceID()); } return; } float maxStamina = character.GetMaxStamina(); maxStamina = Mathf.Max(maxStamina, 1f); bool flag = false; if (Mathf.Abs(character.data.currentStamina - maxStamina) > 0.0001f) { character.data.currentStamina = maxStamina; flag = true; } int instanceID = ((Object)character).GetInstanceID(); if (!PreservedExtraStamina.TryGetValue(instanceID, out var value)) { value = character.data.extraStamina; PreservedExtraStamina.Add(instanceID, value); } else if (character.data.extraStamina > value) { value = character.data.extraStamina; PreservedExtraStamina[instanceID] = value; } else if (character.data.extraStamina < value) { character.data.extraStamina = value; flag = true; } if (flag && (Object)(object)GUIManager.instance != (Object)null && (Object)(object)GUIManager.instance.bar != (Object)null) { GUIManager.instance.bar.ChangeBar(); } } internal static void ClearAllNegativeStates(Character character) { //IL_0030: 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_004e: Unknown result type (might be due to invalid IL or missing references) if (!CanApplyProtection(character)) { return; } CharacterAfflictions afflictions = character.refs.afflictions; bool flag = false; int numStatusTypes = CharacterAfflictions.NumStatusTypes; for (int i = 0; i < numStatusTypes; i++) { STATUSTYPE val = (STATUSTYPE)i; if (!(afflictions.GetCurrentStatus(val) <= 0f)) { afflictions.SetStatus(val, 0f, false); flag = true; } } if (afflictions.isWebbed) { afflictions.SetStatus((STATUSTYPE)11, 0f, false); afflictions.isWebbed = false; flag = true; } if (flag) { afflictions.PushStatuses((Player)null); } if (afflictions.afflictionList != null && afflictions.afflictionList.Count > 0) { afflictions.ClearAllAfflictions(); } if (afflictions.physicalThorns == null) { return; } for (int num = afflictions.physicalThorns.Count - 1; num >= 0; num--) { ThornOnMe val2 = afflictions.physicalThorns[num]; if (!((Object)(object)val2 == (Object)null) && val2.stuckIn) { afflictions.RemoveThorn(val2); } } } private static void LogBlockedStatus(STATUSTYPE statusType, float amount, string source) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (blockedStatusLogCount < 50) { blockedStatusLogCount++; ManualLogSource modLogger = ModLogger; if (modLogger != null) { string[] obj = new string[8] { "[StaminaFull] Status blocked ", $"({blockedStatusLogCount}/{50}). ", $"Status={statusType}, ", $"Amount={amount:0.0000}, ", "Source=", source, ", Scene=", null }; Scene activeScene = SceneManager.GetActiveScene(); obj[7] = ((Scene)(ref activeScene)).name; modLogger.LogInfo((object)string.Concat(obj)); } } } private static void LogBlockedThorn() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (blockedThornLogCount < 50) { blockedThornLogCount++; ManualLogSource modLogger = ModLogger; if (modLogger != null) { string text = $"({blockedThornLogCount}/{50}). "; Scene activeScene = SceneManager.GetActiveScene(); modLogger.LogInfo((object)("[StaminaFull] Thorn blocked " + text + "Scene=" + ((Scene)(ref activeScene)).name)); } } } } namespace Sapphire009.WatchEgg; [HarmonyPatch(typeof(CharacterItems), "EquipSlot")] public static class AutoDrop { [HarmonyPatch(typeof(CharacterItems), "DropItemRpc")] private static class DropItemRpcPatch { [HarmonyPrefix] private unsafe static void Prefix(CharacterItems __instance, float throwCharge, byte slotID, Vector3 spawnPos) { //IL_0096: 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) Character localCharacter = Character.localCharacter; string text = "null"; bool flag = false; if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && (Object)(object)localCharacter.data.currentItem != (Object)null) { Item currentItem = localCharacter.data.currentItem; text = ((Object)((Component)currentItem).gameObject).name; flag = IsNestEggName(text); } string[] obj = new string[10] { "DropItemRpc CALLED | SlotID=", slotID.ToString(), " | ThrowCharge=", throwCharge.ToString(), " | SpawnPosition=", null, null, null, null, null }; Vector3 val = spawnPos; obj[5] = ((object)(*(Vector3*)(&val))/*cast due to .constrained prefix*/).ToString(); obj[6] = " | CurrentItem="; obj[7] = text; obj[8] = " | IsNestEgg="; obj[9] = flag.ToString(); LogWarning(string.Concat(obj)); } } public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; private const string LogPrefix = "[AutoDrop] "; private static ManualLogSource logger; public static void SetLogger(ManualLogSource pluginLogger) { logger = pluginLogger; LogInfo("AutoDrop initialized. Target prefab: NestEgg"); } [HarmonyPrepare] private static bool Prepare() { LogInfo("PATCH READY: CharacterItems.EquipSlot"); return true; } [HarmonyPrefix] private static void Prefix(CharacterItems __instance, Optionable slotID) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) LogInfo("EquipSlot PREFIX entered. | RequestedSlot=" + FormatSlot(slotID)); if ((Object)(object)__instance == (Object)null) { LogError("CharacterItems instance is null."); return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null) { LogWarning("Character.localCharacter is null."); return; } if (localCharacter.refs == null || (Object)(object)localCharacter.refs.items == (Object)null) { LogWarning("Local CharacterItems reference is null."); return; } if ((Object)(object)localCharacter.refs.items != (Object)(object)__instance) { LogInfo("Non-local CharacterItems ignored."); return; } if ((Object)(object)localCharacter.data == (Object)null) { LogWarning("Character.data is null."); return; } if ((Object)(object)localCharacter.player == (Object)null) { LogWarning("Character.player is null."); return; } if (slotID.IsNone) { LogInfo("Requested slot is None. Ignored."); return; } if (__instance.currentSelectedSlot.IsNone) { LogWarning("CurrentSelectedSlot is None."); return; } byte value = __instance.currentSelectedSlot.Value; byte value2 = slotID.Value; if (value == value2) { LogInfo("Same slot selected. Ignored. | Slot=" + value); return; } Item currentItem = localCharacter.data.currentItem; if ((Object)(object)currentItem == (Object)null) { LogWarning("Current held Item is null."); return; } ItemSlot itemSlot = localCharacter.player.GetItemSlot(value); if (itemSlot == null) { LogError("Current ItemSlot is null. | SlotID=" + value); return; } string text = NormalizePrefabName(((Object)((Component)currentItem).gameObject).name); string text2 = (itemSlot.IsEmpty() ? string.Empty : NormalizePrefabName(itemSlot.GetPrefabName())); string text3 = ((currentItem.UIData != null) ? currentItem.UIData.itemName : "UIData null"); bool flag = IsNestEggName(text); bool flag2 = IsNestEggName(text2); LogInfo("Detection result | CurrentSlot=" + value + " | RequestedSlot=" + value2 + " | HeldObject=" + text + " | SlotPrefab=" + text2 + " | UIItemName=" + text3 + " | HeldIsNestEgg=" + flag + " | SlotIsNestEgg=" + flag2); if (!flag && !flag2) { LogInfo("Current item is not NestEgg."); return; } if (currentItem.UIData == null) { LogError("NestEgg detected, but currentItem.UIData is null."); return; } bool canPocket = currentItem.UIData.canPocket; bool canDrop = currentItem.UIData.canDrop; currentItem.UIData.canPocket = false; currentItem.UIData.canDrop = true; Item prefab = itemSlot.prefab; if ((Object)(object)prefab != (Object)null && prefab.UIData != null) { prefab.UIData.canPocket = false; prefab.UIData.canDrop = true; } LogWarning("NEST EGG CONFIRMED. Auto-drop setting applied. | canPocket: " + canPocket + " -> " + currentItem.UIData.canPocket + " | canDrop: " + canDrop + " -> " + currentItem.UIData.canDrop); } [HarmonyPostfix] private static void Postfix(CharacterItems __instance, Optionable slotID) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = Character.localCharacter; string text = "null"; if ((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null && (Object)(object)localCharacter.data.currentItem != (Object)null) { text = ((Object)((Component)localCharacter.data.currentItem).gameObject).name; } LogInfo("EquipSlot POSTFIX | RequestedSlot=" + FormatSlot(slotID) + " | CurrentItemAfter=" + text); } private static bool IsNestEggName(string objectName) { return string.Equals(NormalizePrefabName(objectName), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizePrefabName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } private static string FormatSlot(Optionable slotID) { if (slotID.IsSome) { return slotID.Value.ToString(); } return "None"; } private static void LogInfo(string message) { if (logger != null) { logger.LogInfo((object)("[AutoDrop] " + message)); } } private static void LogWarning(string message) { if (logger != null) { logger.LogWarning((object)("[AutoDrop] " + message)); } } private static void LogError(string message) { if (logger != null) { logger.LogError((object)("[AutoDrop] " + message)); } } } [DisallowMultipleComponent] public sealed class BrighteningEgg : MonoBehaviour { [HarmonyPatch(typeof(Item), "Awake")] private static class ItemAwakePatch { [HarmonyPostfix] private static void Postfix(Item __instance) { if (IsNestEgg(__instance) && !((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { ((Component)__instance).gameObject.AddComponent(); } } } public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; private const string LogPrefix = "[BrighteningEgg] "; private const float MaximumMarkerSize = 34f; private const float MinimumMarkerSize = 23f; private const float NearDistance = 4f; private const float FarDistance = 120f; private const float ScreenEdgeMargin = 40f; private const float BottomScreenMargin = 72f; private const float LabelWidth = 100f; private const float LabelHeight = 30f; private const float LabelSpacing = 3f; private const float BaseLightIntensity = 2.3f; private const float LightPulseAmount = 0.55f; private const float LightPulseSpeed = 2.2f; private const float LightRange = 4.5f; private const float CameraSearchInterval = 1f; private static readonly Color MarkerColor = new Color(1f, 0.72f, 0.08f, 1f); private static readonly Color MarkerCenterColor = new Color(1f, 0.95f, 0.45f, 1f); private static readonly Color LabelColor = new Color(1f, 0.86f, 0.2f, 1f); private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.BrighteningEgg"); private static Texture2D circleTexture; private Item item; private GameObject lightObject; private Light eggLight; private Camera cachedCamera; private float nextCameraSearchTime; private GUIStyle labelStyle; private GUIStyle labelShadowStyle; private int cachedFontSize = -1; private void Awake() { item = ((Component)this).GetComponent(); if (!IsNestEgg(item)) { ((Behaviour)this).enabled = false; return; } CreateCircleTexture(); CreateEggLight(); Logger.LogInfo((object)("[BrighteningEgg] Always-visible marker attached. | Object=" + ((Object)((Component)item).gameObject).name)); } private void Update() { if (!((Object)(object)item == (Object)null)) { UpdateEggLight(); } } private void OnGUI() { //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) //IL_0068: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (!((Behaviour)this).enabled || (Object)(object)item == (Object)null || !((Component)this).gameObject.activeInHierarchy || IsHeldByLocalPlayer()) { return; } Camera viewCamera = GetViewCamera(); if (!((Object)(object)viewCamera == (Object)null)) { Vector3 val = CalculateWorldMarkerPosition(); Vector3 val2 = viewCamera.WorldToScreenPoint(val); if (!(val2.z <= 0f)) { float x = val2.x; float num = (float)Screen.height - val2.y; x = Mathf.Clamp(x, 40f, (float)Screen.width - 40f); num = Mathf.Clamp(num, 40f, (float)Screen.height - 72f); float num2 = Vector3.Distance(((Component)viewCamera).transform.position, val); float num3 = Mathf.InverseLerp(4f, 120f, num2); float markerSize = Mathf.Lerp(34f, 23f, num3); DrawMarker(x, num, markerSize); DrawEggLabel(x, num, markerSize); } } } private static void DrawMarker(float centerX, float centerY, float markerSize) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)circleTexture == (Object)null)) { Color color = GUI.color; float num = markerSize + 7f; Rect val = default(Rect); ((Rect)(ref val))..ctor(centerX - num * 0.5f, centerY - num * 0.5f, num, num); GUI.color = new Color(0f, 0f, 0f, 0.88f); GUI.DrawTexture(val, (Texture)(object)circleTexture, (ScaleMode)0, true); Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(centerX - markerSize * 0.5f, centerY - markerSize * 0.5f, markerSize, markerSize); GUI.color = MarkerColor; GUI.DrawTexture(val2, (Texture)(object)circleTexture, (ScaleMode)0, true); float num2 = markerSize * 0.35f; Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(centerX - num2 * 0.5f, centerY - num2 * 0.5f, num2, num2); GUI.color = MarkerCenterColor; GUI.DrawTexture(val3, (Texture)(object)circleTexture, (ScaleMode)0, true); GUI.color = color; } } private void DrawEggLabel(float centerX, float centerY, float markerSize) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_0098: Unknown result type (might be due to invalid IL or missing references) int fontSize = Mathf.RoundToInt(Mathf.Clamp(markerSize * 0.68f, 16f, 23f)); PrepareLabelStyles(fontSize); float num = centerX - 50f; float num2 = centerY + markerSize * 0.5f + 3f; Rect val = default(Rect); ((Rect)(ref val))..ctor(num, num2, 100f, 30f); DrawLabelShadow(val, -2f, 0f); DrawLabelShadow(val, 2f, 0f); DrawLabelShadow(val, 0f, -2f); DrawLabelShadow(val, 0f, 2f); GUI.Label(val, "Egg", labelStyle); } private void DrawLabelShadow(Rect originalRect, float offsetX, float offsetY) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) Rect val = default(Rect); ((Rect)(ref val))..ctor(((Rect)(ref originalRect)).x + offsetX, ((Rect)(ref originalRect)).y + offsetY, ((Rect)(ref originalRect)).width, ((Rect)(ref originalRect)).height); GUI.Label(val, "Egg", labelShadowStyle); } private void PrepareLabelStyles(int fontSize) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (labelStyle == null || labelShadowStyle == null || cachedFontSize != fontSize) { cachedFontSize = fontSize; labelStyle = new GUIStyle(GUI.skin.label); labelStyle.alignment = (TextAnchor)1; labelStyle.fontSize = fontSize; labelStyle.fontStyle = (FontStyle)1; labelStyle.wordWrap = false; labelStyle.clipping = (TextClipping)0; labelStyle.normal.textColor = LabelColor; labelShadowStyle = new GUIStyle(labelStyle); labelShadowStyle.normal.textColor = new Color(0f, 0f, 0f, 1f); } } private Camera GetViewCamera() { if ((Object)(object)cachedCamera != (Object)null && ((Behaviour)cachedCamera).isActiveAndEnabled) { return cachedCamera; } if (Time.unscaledTime < nextCameraSearchTime) { return null; } nextCameraSearchTime = Time.unscaledTime + 1f; Camera main = Camera.main; if ((Object)(object)main != (Object)null && ((Behaviour)main).isActiveAndEnabled) { cachedCamera = main; return cachedCamera; } Camera[] allCameras = Camera.allCameras; foreach (Camera val in allCameras) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled) { cachedCamera = val; return cachedCamera; } } return null; } private Vector3 CalculateWorldMarkerPosition() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010d: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_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_004a: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); bool flag = false; Bounds val = default(Bounds); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || !val2.enabled) { continue; } Bounds bounds = val2.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f)) { if (!flag) { val = bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(bounds); } } } if (!flag) { return ((Component)this).transform.position + Vector3.up * 0.65f; } float num = Mathf.Clamp(((Bounds)(ref val)).extents.y * 0.35f, 0.12f, 0.45f); return new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).max.y + num, ((Bounds)(ref val)).center.z); } private void CreateEggLight() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) lightObject = new GameObject("WatchEgg_NestEgg_AlwaysLight"); lightObject.transform.SetParent(((Component)this).transform, false); lightObject.transform.localPosition = CalculateLightLocalPosition(); lightObject.transform.localRotation = Quaternion.identity; eggLight = lightObject.AddComponent(); eggLight.type = (LightType)2; eggLight.color = MarkerColor; eggLight.intensity = 2.3f; eggLight.range = 4.5f; eggLight.shadows = (LightShadows)0; eggLight.renderMode = (LightRenderMode)0; eggLight.bounceIntensity = 0f; } private void UpdateEggLight() { if (!((Object)(object)eggLight == (Object)null) && !((Object)(object)lightObject == (Object)null)) { if (!lightObject.activeSelf) { lightObject.SetActive(true); } float num = (Mathf.Sin(Time.unscaledTime * 2.2f) + 1f) * 0.5f; eggLight.intensity = 2.3f + num * 0.55f; } } private Vector3 CalculateLightLocalPosition() { //IL_0029: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_0094: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); if (componentsInChildren == null || componentsInChildren.Length == 0) { return Vector3.zero; } bool flag = false; Bounds val = default(Bounds); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || !val2.enabled) { continue; } Bounds bounds = val2.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f)) { if (!flag) { val = bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(bounds); } } } if (!flag) { return Vector3.zero; } return ((Component)this).transform.InverseTransformPoint(((Bounds)(ref val)).center); } private bool IsHeldByLocalPlayer() { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null) { return false; } return localCharacter.IsLocal && (Object)(object)localCharacter.data.currentItem == (Object)(object)item; } private static void CreateCircleTexture() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)circleTexture != (Object)null) { return; } circleTexture = new Texture2D(64, 64, (TextureFormat)4, false); ((Object)circleTexture).name = "WatchEgg_AlwaysVisibleCircle"; ((Texture)circleTexture).wrapMode = (TextureWrapMode)1; ((Texture)circleTexture).filterMode = (FilterMode)1; ((Object)circleTexture).hideFlags = (HideFlags)61; Color[] array = (Color[])(object)new Color[4096]; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(31.5f, 31.5f); float num = 30.08f; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num2 = Vector2.Distance(new Vector2((float)j, (float)i), val); float num3 = Mathf.Clamp01((num - num2) * 0.8f); array[i * 64 + j] = new Color(1f, 1f, 1f, num3); } } circleTexture.SetPixels(array); circleTexture.Apply(false, true); } private void OnDestroy() { if ((Object)(object)lightObject != (Object)null) { Object.Destroy((Object)(object)lightObject); lightObject = null; } eggLight = null; cachedCamera = null; } public static bool IsNestEgg(Item targetItem) { if ((Object)(object)targetItem == (Object)null) { return false; } return IsNestEggName(((Object)((Component)targetItem).gameObject).name); } public static bool IsNestEggName(string objectName) { return string.Equals(NormalizePrefabName(objectName), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizePrefabName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } } [DisallowMultipleComponent] public sealed class CountUI : MonoBehaviour { [HarmonyPatch(typeof(CharacterSpawner), "Update")] private static class CharacterSpawnerUpdatePatch { [HarmonyPostfix] private static void Postfix() { EnsureCountUIExists(); } } public const string DeveloperName = "Sapphire009"; private const string LogPrefix = "[CountUI] "; private const float ReferenceScreenHeight = 1080f; private const float ReferenceWidth = 360f; private const float ReferenceHeight = 48f; private const float ReferenceBottomMargin = 115f; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.CountUI"); private static CountUI instance; private GUIStyle textStyle; private GUIStyle shadowStyle; private int cachedFontSize = -1; private void Awake() { if ((Object)(object)instance != (Object)null && (Object)(object)instance != (Object)(object)this) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); Logger.LogInfo((object)"[CountUI] Broken egg counter UI created."); } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } } private void OnGUI() { //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if (ShouldDisplay()) { PrepareStyles(); float num = Mathf.Clamp((float)Screen.height / 1080f, 0.75f, 1.5f); float num2 = 360f * num; float num3 = 48f * num; float num4 = ((float)Screen.width - num2) * 0.5f; float num5 = (float)Screen.height - 115f * num - num3; Rect val = default(Rect); ((Rect)(ref val))..ctor(num4, num5, num2, num3); string text = "BROKEN EGGS : " + EggCheckpoint.BrokenEggCount; Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(((Rect)(ref val)).x + 2f * num, ((Rect)(ref val)).y + 2f * num, ((Rect)(ref val)).width, ((Rect)(ref val)).height); GUI.Label(val2, text, shadowStyle); GUI.Label(val, text, textStyle); } } private static bool ShouldDisplay() { Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal) { return false; } if (!EggCheckpoint.HasCheckpoint && EggCheckpoint.BrokenEggCount <= 0) { return false; } return true; } private void PrepareStyles() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.RoundToInt(Mathf.Clamp((float)Screen.height / 1080f * 26f, 19f, 34f)); if (textStyle == null || shadowStyle == null || cachedFontSize != num) { cachedFontSize = num; textStyle = new GUIStyle(GUI.skin.label); textStyle.alignment = (TextAnchor)4; textStyle.fontSize = num; textStyle.fontStyle = (FontStyle)1; textStyle.normal.textColor = Color.white; textStyle.wordWrap = false; textStyle.clipping = (TextClipping)0; shadowStyle = new GUIStyle(textStyle); shadowStyle.normal.textColor = new Color(0f, 0f, 0f, 0.9f); } } private static void EnsureCountUIExists() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)instance != (Object)null)) { GameObject val = new GameObject("WatchEgg_BrokenEgg_CountUI"); val.AddComponent(); } } } [DisallowMultipleComponent] public sealed class EggCheckpoint : MonoBehaviour { [HarmonyPatch(typeof(Item), "Awake")] private static class ItemAwakePatch { [HarmonyPostfix] private static void Postfix(Item __instance) { if (IsNestEgg(__instance) && !((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(Breakable), "Break")] private static class BreakableBreakPatch { [HarmonyPrefix] private static void Prefix(Breakable __instance) { if ((Object)(object)__instance == (Object)null) { return; } Item val = ((Component)__instance).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)__instance).GetComponentInParent(); } if ((Object)(object)val == (Object)null) { val = ((Component)__instance).GetComponentInChildren(true); } if (IsNestEgg(val)) { int item = (((Object)(object)((MonoBehaviourPun)val).photonView != (Object)null) ? ((MonoBehaviourPun)val).photonView.ViewID : ((Object)((Component)val).gameObject).GetInstanceID()); if (!CountedBrokenViewIds.Contains(item)) { CountedBrokenViewIds.Add(item); BrokenEggCount++; Logger.LogWarning((object)("[EggCheckpoint] NestEgg broken. | BrokenCount=" + BrokenEggCount + " | ViewID=" + item)); } } } } public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; public const float TargetCheckpointDistance = 25f; public const float DistanceTolerance = 2f; public const float MinimumCheckpointDistance = 23f; public const float MaximumCheckpointDistance = 27f; private const float MaximumAcceptedFrameTravelDistance = 3f; private const float RequiredStableTime = 0.55f; private const float MaximumStableGroundSpeed = 0.45f; private const float MinimumGroundNormalY = 0.55f; private const float GroundCastStartHeight = 2.5f; private const float GroundCastDistance = 5f; private const float InitialGroundCastDistance = 12f; private const float GroundCastRadius = 0.18f; private const float GroundSurfacePadding = 0.015f; private const float MaximumEggGroundDistanceFromPlayer = 1.6f; private const string LogPrefix = "[EggCheckpoint] "; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.EggCheckpoint"); private static readonly HashSet CountedBrokenViewIds = new HashSet(); private static int activeSceneHandle = int.MinValue; private Item item; private Quaternion eggRestRotation; private float pivotToEggBottom = 0.2f; private Vector3 previousTrackedPosition; private bool hasPreviousTrackedPosition; private bool waitingForStableCheckpoint; private bool wasHeldByLocalPlayer; private Vector3 previousGroundPosition; private bool hasPreviousGroundPosition; private float stableGroundTimer; public static bool HasCheckpoint { get; private set; } public static Vector3 CheckpointPosition { get; private set; } public static Quaternion CheckpointRotation { get; private set; } public static int CheckpointNumber { get; private set; } public static int BrokenEggCount { get; private set; } public static float DistanceFromLastCheckpoint { get; private set; } private void Awake() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) ResetStaticDataWhenSceneChanged(); item = ((Component)this).GetComponent(); if (!IsNestEgg(item)) { ((Behaviour)this).enabled = false; return; } eggRestRotation = ((Component)this).transform.rotation; CacheEggBottomOffset(); CacheInitialCheckpoint(); Logger.LogInfo((object)("[EggCheckpoint] Attached to " + ((Object)((Component)item).gameObject).name + " | BottomOffset=" + pivotToEggBottom + " | DistanceMode=Accumulated3D")); } private void Update() { ResetStaticDataWhenSceneChanged(); if ((Object)(object)item == (Object)null) { return; } if (!IsHeldByLocalPlayer(out var localCharacter)) { HandleNotHeld(); return; } HandleHeld(localCharacter); UpdateAccumulatedTravelDistance(localCharacter); bool flag = UpdateStableGroundState(localCharacter); if (!HasCheckpoint) { DistanceFromLastCheckpoint = 0f; if (flag) { SaveCheckpoint(localCharacter, initialCheckpoint: true); } return; } if (DistanceFromLastCheckpoint >= 23f) { waitingForStableCheckpoint = true; } if (waitingForStableCheckpoint && flag) { SaveCheckpoint(localCharacter, initialCheckpoint: false); } } private bool IsHeldByLocalPlayer(out Character localCharacter) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Invalid comparison between Unknown and I4 localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || !localCharacter.IsLocal || (Object)(object)item == (Object)null) { return false; } return (Object)(object)localCharacter.data.currentItem == (Object)(object)item && (int)item.itemState == 1; } private void HandleHeld(Character localCharacter) { //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) if (!wasHeldByLocalPlayer) { wasHeldByLocalPlayer = true; stableGroundTimer = 0f; hasPreviousGroundPosition = false; hasPreviousTrackedPosition = false; if ((Object)(object)localCharacter != (Object)null) { previousTrackedPosition = ((Component)localCharacter).transform.position; hasPreviousTrackedPosition = true; } Logger.LogInfo((object)("[EggCheckpoint] NestEgg tracking started. | AccumulatedDistance=" + DistanceFromLastCheckpoint)); } } private void HandleNotHeld() { if (wasHeldByLocalPlayer) { wasHeldByLocalPlayer = false; stableGroundTimer = 0f; hasPreviousGroundPosition = false; hasPreviousTrackedPosition = false; Logger.LogInfo((object)("[EggCheckpoint] NestEgg tracking paused. | AccumulatedDistance=" + DistanceFromLastCheckpoint)); } } private void UpdateAccumulatedTravelDistance(Character localCharacter) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_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) if ((Object)(object)localCharacter == (Object)null) { hasPreviousTrackedPosition = false; return; } Vector3 position = ((Component)localCharacter).transform.position; if (!hasPreviousTrackedPosition) { previousTrackedPosition = position; hasPreviousTrackedPosition = true; return; } float num = Vector3.Distance(previousTrackedPosition, position); previousTrackedPosition = position; if (!float.IsNaN(num) && !float.IsInfinity(num)) { if (num > 3f) { Logger.LogWarning((object)("[EggCheckpoint] Large position jump ignored. | FrameDistance=" + num)); } else { DistanceFromLastCheckpoint += num; } } } private bool UpdateStableGroundState(Character character) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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) if ((Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { ResetStableGroundState(); return false; } if (!character.data.isGrounded || character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing || character.data.dead || character.data.fullyPassedOut || !(character.data.groundNormal.y >= 0.55f)) { ResetStableGroundState(); return false; } Vector3 groundPos = character.data.groundPos; if (!hasPreviousGroundPosition) { previousGroundPosition = groundPos; hasPreviousGroundPosition = true; stableGroundTimer = 0f; return false; } float num = Mathf.Max(Time.deltaTime, 0.0001f); float num2 = Vector3.Distance(previousGroundPosition, groundPos) / num; previousGroundPosition = groundPos; if (num2 <= 0.45f) { stableGroundTimer += Time.deltaTime; } else { stableGroundTimer = 0f; } return stableGroundTimer >= 0.55f; } private void ResetStableGroundState() { stableGroundTimer = 0f; hasPreviousGroundPosition = false; } private void SaveCheckpoint(Character localCharacter, bool initialCheckpoint) { //IL_002d: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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) if (!TryGetGroundAttachedEggPosition(localCharacter, out var result)) { Logger.LogWarning((object)"[EggCheckpoint] Checkpoint save delayed: safe ground was not found."); return; } float distanceFromLastCheckpoint = DistanceFromLastCheckpoint; CheckpointPosition = result; CheckpointRotation = eggRestRotation; HasCheckpoint = true; CheckpointNumber++; DistanceFromLastCheckpoint = 0f; waitingForStableCheckpoint = false; stableGroundTimer = 0f; hasPreviousGroundPosition = false; if ((Object)(object)localCharacter != (Object)null) { previousTrackedPosition = ((Component)localCharacter).transform.position; hasPreviousTrackedPosition = true; } else { hasPreviousTrackedPosition = false; } Logger.LogWarning((object)("[EggCheckpoint] " + (initialCheckpoint ? "Initial checkpoint saved." : "Travel checkpoint saved.") + " | Number=" + CheckpointNumber + " | TravelDistance=" + distanceFromLastCheckpoint + " | Position=" + ((object)CheckpointPosition/*cast due to .constrained prefix*/).ToString())); } private bool TryGetGroundAttachedEggPosition(Character localCharacter, out Vector3 result) { //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_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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: 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_0086: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) result = Vector3.zero; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null) { return false; } if (TryCastGroundBelowEgg(localCharacter, out var groundHit)) { result = ((RaycastHit)(ref groundHit)).point + Vector3.up * (pivotToEggBottom + 0.015f); return true; } if (!TryCastGroundAtPlayer(localCharacter, out groundHit)) { return false; } result = ((RaycastHit)(ref groundHit)).point + Vector3.up * (pivotToEggBottom + 0.015f); return true; } private bool TryCastGroundBelowEgg(Character localCharacter, out RaycastHit groundHit) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) Vector3 groundPos = localCharacter.data.groundPos; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(((Component)this).transform.position.x, groundPos.y + 2.5f, ((Component)this).transform.position.z); if (!Physics.SphereCast(val, 0.18f, Vector3.down, ref groundHit, 5f, LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)1)), (QueryTriggerInteraction)1)) { return false; } if (((RaycastHit)(ref groundHit)).normal.y < 0.55f) { return false; } Vector3 val2 = ((RaycastHit)(ref groundHit)).point - groundPos; val2.y = 0f; return ((Vector3)(ref val2)).magnitude <= 1.6f; } private bool TryCastGroundAtPlayer(Character localCharacter, out RaycastHit groundHit) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0027: 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_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 val = localCharacter.data.groundPos + Vector3.up * 2.5f; if (!Physics.SphereCast(val, 0.18f, Vector3.down, ref groundHit, 5f, LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)1)), (QueryTriggerInteraction)1)) { return false; } return ((RaycastHit)(ref groundHit)).normal.y >= 0.55f; } private void CacheInitialCheckpoint() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if (!HasCheckpoint) { Vector3 val = ((Component)this).transform.position + Vector3.up * 2.5f; RaycastHit val2 = default(RaycastHit); if (Physics.SphereCast(val, 0.18f, Vector3.down, ref val2, 12f, LayerMask.op_Implicit(HelperFunctions.GetMask((LayerType)1)), (QueryTriggerInteraction)1) && !(((RaycastHit)(ref val2)).normal.y < 0.55f)) { CheckpointPosition = ((RaycastHit)(ref val2)).point + Vector3.up * (pivotToEggBottom + 0.015f); CheckpointRotation = eggRestRotation; HasCheckpoint = true; CheckpointNumber = 1; DistanceFromLastCheckpoint = 0f; waitingForStableCheckpoint = false; Logger.LogWarning((object)("[EggCheckpoint] Initial spawn checkpoint cached. | Position=" + ((object)CheckpointPosition/*cast due to .constrained prefix*/).ToString())); } } } private void CacheEggBottomOffset() { //IL_016a: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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_00f4: 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_0112: 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) Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); float num = float.PositiveInfinity; bool flag = false; Vector3 size; foreach (Collider val in componentsInChildren) { if ((Object)(object)val == (Object)null || !val.enabled || val.isTrigger) { continue; } Bounds bounds = val.bounds; size = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f)) { if (((Bounds)(ref bounds)).min.y < num) { num = ((Bounds)(ref bounds)).min.y; } flag = true; } } if (!flag) { Renderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren2) { if ((Object)(object)val2 == (Object)null) { continue; } Bounds bounds2 = val2.bounds; size = ((Bounds)(ref bounds2)).size; if (!(((Vector3)(ref size)).sqrMagnitude <= 0.0001f)) { if (((Bounds)(ref bounds2)).min.y < num) { num = ((Bounds)(ref bounds2)).min.y; } flag = true; } } } if (!flag) { pivotToEggBottom = 0.2f; return; } float num2 = ((Component)this).transform.position.y - num; if (num2 <= 0.01f || num2 >= 3f) { pivotToEggBottom = 0.2f; } else { pivotToEggBottom = num2; } } public static bool TryGetCheckpoint(out Vector3 position, out Quaternion rotation) { //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_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) position = CheckpointPosition; rotation = CheckpointRotation; return HasCheckpoint; } public static void ResetCheckpoint() { //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) HasCheckpoint = false; CheckpointPosition = Vector3.zero; CheckpointRotation = Quaternion.identity; CheckpointNumber = 0; BrokenEggCount = 0; DistanceFromLastCheckpoint = 0f; CountedBrokenViewIds.Clear(); } private static void ResetStaticDataWhenSceneChanged() { //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) Scene activeScene = SceneManager.GetActiveScene(); int handle = ((Scene)(ref activeScene)).handle; if (activeSceneHandle != handle) { activeSceneHandle = handle; ResetCheckpoint(); Logger.LogInfo((object)"[EggCheckpoint] Scene changed. Checkpoint data reset."); } } public static bool IsNestEgg(Item targetItem) { if ((Object)(object)targetItem == (Object)null) { return false; } return IsNestEggName(((Object)((Component)targetItem).gameObject).name); } public static bool IsNestEggName(string objectName) { return string.Equals(NormalizePrefabName(objectName), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizePrefabName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } } [HarmonyPatch(typeof(Breakable), "OnCollisionEnter")] public static class NoBody { public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; private const string LogPrefix = "[NoBody] "; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.NoBody"); [HarmonyPrepare] private static bool Prepare() { Logger.LogInfo((object)"[NoBody] PATCH READY: Breakable.OnCollisionEnter"); return true; } [HarmonyPrefix] private static bool Prefix(Breakable __instance, Collision collision) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || collision == null) { return true; } Item item = FindItem(((Component)__instance).gameObject); if (!IsNestEgg(item)) { return true; } if (!TryGetCollidedCharacter(collision, out var character)) { return true; } ManualLogSource logger = Logger; string[] obj = new string[6] { "[NoBody] NestEgg body collision ignored. | Player=", GetCharacterName(character), " | RelativeVelocity=", null, null, null }; Vector3 relativeVelocity = collision.relativeVelocity; obj[3] = ((Vector3)(ref relativeVelocity)).magnitude.ToString(); obj[4] = " | Collider="; obj[5] = GetColliderName(collision); logger.LogInfo((object)string.Concat(obj)); return false; } private static bool TryGetCollidedCharacter(Collision collision, out Character character) { character = null; if (collision == null) { return false; } if ((Object)(object)collision.collider != (Object)null) { character = ((Component)collision.collider).GetComponentInParent(); if ((Object)(object)character != (Object)null) { return true; } } if ((Object)(object)collision.rigidbody != (Object)null) { character = ((Component)collision.rigidbody).GetComponentInParent(); if ((Object)(object)character != (Object)null) { return true; } } if ((Object)(object)collision.transform != (Object)null) { character = ((Component)collision.transform).GetComponentInParent(); if ((Object)(object)character != (Object)null) { return true; } } return false; } private static Item FindItem(GameObject sourceObject) { if ((Object)(object)sourceObject == (Object)null) { return null; } Item component = sourceObject.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = sourceObject.GetComponentInParent(); if ((Object)(object)component != (Object)null) { return component; } return sourceObject.GetComponentInChildren(true); } private static bool IsNestEgg(Item item) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null) { return false; } return string.Equals(NormalizePrefabName(((Object)((Component)item).gameObject).name), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizePrefabName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } private static string GetCharacterName(Character character) { if ((Object)(object)character == (Object)null) { return "Unknown"; } if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && ((MonoBehaviourPun)character).photonView.Owner != null && !string.IsNullOrEmpty(((MonoBehaviourPun)character).photonView.Owner.NickName)) { return ((MonoBehaviourPun)character).photonView.Owner.NickName; } return ((Object)((Component)character).gameObject).name; } private static string GetColliderName(Collision collision) { if (collision == null || (Object)(object)collision.collider == (Object)null || (Object)(object)((Component)collision.collider).gameObject == (Object)null) { return "Unknown"; } return ((Object)((Component)collision.collider).gameObject).name; } } public static class NoEat { private sealed class PendingNestEggBreak { public Vector3 BreakPosition; public float ExpireTime; public readonly HashSet ItemIDs = new HashSet(); public readonly HashSet ObjectNames = new HashSet(StringComparer.OrdinalIgnoreCase); public readonly HashSet ItemNames = new HashSet(StringComparer.OrdinalIgnoreCase); } [HarmonyPatch(typeof(Breakable), "Break")] private static class BreakableBreakPatch { [HarmonyPrefix] private unsafe static void Prefix(Breakable __instance) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) if (IsNestEggBreakable(__instance, out var eggItem)) { RemoveExpiredBreakRecords(); PendingNestEggBreak pendingNestEggBreak = new PendingNestEggBreak(); pendingNestEggBreak.BreakPosition = ((Component)eggItem).transform.position; pendingNestEggBreak.ExpireTime = Time.time + 4f; RegisterSpawnList(__instance.instantiateOnBreak, pendingNestEggBreak); RegisterSpawnList(__instance.alternateInstantiateOnBreak, pendingNestEggBreak); RegisterSpawnList(__instance.instantiateNonItemOnBreak, pendingNestEggBreak); if (pendingNestEggBreak.ItemIDs.Count == 0 && pendingNestEggBreak.ObjectNames.Count == 0 && pendingNestEggBreak.ItemNames.Count == 0) { Logger.LogWarning((object)"[NoEat] NestEgg break detected, but no spawned Item prefab was found."); return; } PendingBreaks.Add(pendingNestEggBreak); ManualLogSource logger = Logger; string[] obj = new string[6] { "[NoEat] NestEgg break registered. | Position=", null, null, null, null, null }; Vector3 breakPosition = pendingNestEggBreak.BreakPosition; obj[1] = ((object)(*(Vector3*)(&breakPosition))/*cast due to .constrained prefix*/).ToString(); obj[2] = " | SpawnItemIDs="; obj[3] = pendingNestEggBreak.ItemIDs.Count.ToString(); obj[4] = " | SpawnNames="; obj[5] = pendingNestEggBreak.ObjectNames.Count.ToString(); logger.LogInfo((object)string.Concat(obj)); } } } [HarmonyPatch(typeof(Item), "Awake")] private static class ItemAwakePatch { [HarmonyPostfix] private static void Postfix(Item __instance) { if (!((Object)(object)__instance == (Object)null)) { if (IsNestEgg(__instance)) { EnsureTimedDespawn(__instance, "NestEgg"); } TryMarkSpawnedItem(__instance); } } } [HarmonyPatch(typeof(Item), "StartUsePrimary")] private static class StartUsePrimaryPatch { [HarmonyPrefix] private static bool Prefix(Item __instance) { if (!IsBlockedItem(__instance)) { return true; } LogBlocked(__instance, "StartUsePrimary"); return false; } } [HarmonyPatch(typeof(Item), "ContinueUsePrimary")] private static class ContinueUsePrimaryPatch { [HarmonyPrefix] private static bool Prefix(Item __instance) { return !IsBlockedItem(__instance); } } [HarmonyPatch(typeof(Item), "StartUseSecondary")] private static class StartUseSecondaryPatch { [HarmonyPrefix] private static bool Prefix(Item __instance) { if (!IsBlockedItem(__instance)) { return true; } LogBlocked(__instance, "StartUseSecondary"); return false; } } [HarmonyPatch(typeof(Item), "ContinueUseSecondary")] private static class ContinueUseSecondaryPatch { [HarmonyPrefix] private static bool Prefix(Item __instance) { return !IsBlockedItem(__instance); } } [HarmonyPatch(typeof(Item), "FinishCastSecondary")] private static class FinishCastSecondaryPatch { [HarmonyPrefix] private static bool Prefix(Item __instance) { if (!IsBlockedItem(__instance)) { return true; } LogBlocked(__instance, "FinishCastSecondary"); return false; } } [HarmonyPatch(typeof(Item), "ConsumeDelayed")] private static class ConsumeDelayedPatch { [HarmonyPrefix] private static bool Prefix(Item __instance, ref IEnumerator __result) { if (!IsBlockedItem(__instance)) { return true; } LogBlocked(__instance, "ConsumeDelayed"); __result = EmptyRoutine(); return false; } } private const string LogPrefix = "[NoEat] "; private const string TargetPrefabName = "NestEgg"; private const float PendingLifetime = 4f; private const float SpawnDetectionRadius = 6f; public const float GroundDespawnLifetime = 30f; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.NoEat"); private static readonly List PendingBreaks = new List(); private static bool IsNestEggBreakable(Breakable breakable, out Item eggItem) { eggItem = null; if ((Object)(object)breakable == (Object)null) { return false; } eggItem = FindItem(((Component)breakable).gameObject); if ((Object)(object)eggItem == (Object)null) { return false; } return IsNestEgg(eggItem); } private static bool IsNestEgg(Item item) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null) { return false; } string a = NormalizeObjectName(((Object)((Component)item).gameObject).name); return string.Equals(a, "NestEgg", StringComparison.OrdinalIgnoreCase); } private static Item FindItem(GameObject sourceObject) { if ((Object)(object)sourceObject == (Object)null) { return null; } Item component = sourceObject.GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = sourceObject.GetComponentInParent(); if ((Object)(object)component != (Object)null) { return component; } return sourceObject.GetComponentInChildren(true); } private static void RegisterSpawnList(List spawnList, PendingNestEggBreak pendingBreak) { if (spawnList == null || pendingBreak == null) { return; } for (int i = 0; i < spawnList.Count; i++) { GameObject val = spawnList[i]; if ((Object)(object)val == (Object)null) { continue; } Item val2 = FindItem(val); if (!((Object)(object)val2 == (Object)null)) { pendingBreak.ItemIDs.Add(val2.itemID); AddObjectName(pendingBreak, ((Object)val).name); AddObjectName(pendingBreak, ((Object)((Component)val2).gameObject).name); if (val2.UIData != null) { AddItemName(pendingBreak, val2.UIData.itemName); } } } } private static void AddObjectName(PendingNestEggBreak pendingBreak, string objectName) { string text = NormalizeObjectName(objectName); if (!string.IsNullOrEmpty(text)) { pendingBreak.ObjectNames.Add(text); } } private static void AddItemName(PendingNestEggBreak pendingBreak, string itemName) { if (!string.IsNullOrWhiteSpace(itemName)) { pendingBreak.ItemNames.Add(itemName.Trim()); } } private static bool MatchesPendingBreak(Item item, PendingNestEggBreak pendingBreak) { //IL_0023: 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 ((Object)(object)item == (Object)null || pendingBreak == null) { return false; } float num = Vector3.Distance(((Component)item).transform.position, pendingBreak.BreakPosition); if (num > 6f) { return false; } if (pendingBreak.ItemIDs.Contains(item.itemID)) { return true; } string item2 = NormalizeObjectName(((Object)((Component)item).gameObject).name); if (pendingBreak.ObjectNames.Contains(item2)) { return true; } if (item.UIData != null && !string.IsNullOrWhiteSpace(item.UIData.itemName) && pendingBreak.ItemNames.Contains(item.UIData.itemName.Trim())) { return true; } return false; } private static void EnsureTimedDespawn(Item item, string sourceName) { if (!((Object)(object)item == (Object)null) && !((Object)(object)((Component)item).gameObject == (Object)null)) { WatchEggTimedDespawn watchEggTimedDespawn = ((Component)item).GetComponent(); if ((Object)(object)watchEggTimedDespawn == (Object)null) { watchEggTimedDespawn = ((Component)item).gameObject.AddComponent(); } watchEggTimedDespawn.Configure(sourceName); } } private static void TryMarkSpawnedItem(Item item) { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return; } RemoveExpiredBreakRecords(); if (PendingBreaks.Count == 0) { return; } if ((Object)(object)((Component)item).GetComponent() != (Object)null) { EnsureTimedDespawn(item, "NestEgg break product"); return; } for (int num = PendingBreaks.Count - 1; num >= 0; num--) { PendingNestEggBreak pendingBreak = PendingBreaks[num]; if (MatchesPendingBreak(item, pendingBreak)) { ((Component)item).gameObject.AddComponent(); EnsureTimedDespawn(item, "NestEgg break product"); Logger.LogInfo((object)("[NoEat] NestEgg spawned item marked as non-edible. | Object=" + ((Object)((Component)item).gameObject).name + " | ItemID=" + item.itemID + " | Position=" + ((object)((Component)item).transform.position/*cast due to .constrained prefix*/).ToString() + " | GroundDespawnSeconds=" + 30f)); break; } } } private static bool IsBlockedItem(Item item) { if ((Object)(object)item == (Object)null) { return false; } return (Object)(object)((Component)item).GetComponent() != (Object)null; } private static void RemoveExpiredBreakRecords() { float time = Time.time; for (int num = PendingBreaks.Count - 1; num >= 0; num--) { if (!(PendingBreaks[num].ExpireTime > time)) { PendingBreaks.RemoveAt(num); } } } private static string NormalizeObjectName(string objectName) { if (string.IsNullOrWhiteSpace(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length); text = text.Trim(); } return text; } private static void LogBlocked(Item item, string actionName) { string text = (((Object)(object)item != (Object)null) ? ((Object)((Component)item).gameObject).name : "null"); Logger.LogWarning((object)("[NoEat] Consumption blocked. | Action=" + actionName + " | Object=" + text)); } private static IEnumerator EmptyRoutine() { yield break; } } [DisallowMultipleComponent] public sealed class NoEatMarker : MonoBehaviour { } [DisallowMultipleComponent] public sealed class WatchEggTimedDespawn : MonoBehaviour { private const string LogPrefix = "[TimedDespawn] "; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.TimedDespawn"); private Item item; private float accumulatedGroundTime; private bool lifetimeExpired; private bool destroyIssued; private string sourceName = "Unknown"; public float AccumulatedGroundTime => accumulatedGroundTime; public float RemainingGroundTime => Mathf.Max(0f, 30f - accumulatedGroundTime); private void Awake() { item = ((Component)this).GetComponent(); if ((Object)(object)item == (Object)null) { ((Behaviour)this).enabled = false; } } public void Configure(string configuredSourceName) { if (!string.IsNullOrWhiteSpace(configuredSourceName)) { sourceName = configuredSourceName; } } private void Update() { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if (destroyIssued || (Object)(object)item == (Object)null || (int)item.itemState > 0) { return; } if (!lifetimeExpired) { accumulatedGroundTime += Time.deltaTime; if (accumulatedGroundTime < 30f) { return; } lifetimeExpired = true; } TryDestroyExpiredObject(); } private void TryDestroyExpiredObject() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 if (!destroyIssued && !((Object)(object)item == (Object)null) && (int)item.itemState <= 0) { PhotonView photonView = ((MonoBehaviourPun)item).photonView; if (!PhotonNetwork.InRoom || (Object)(object)photonView == (Object)null || photonView.ViewID <= 0) { destroyIssued = true; Logger.LogInfo((object)("[TimedDespawn] Destroying expired local object. | Object=" + ((Object)((Component)this).gameObject).name + " | Source=" + sourceName + " | GroundSeconds=" + accumulatedGroundTime)); Object.Destroy((Object)(object)((Component)this).gameObject); } else if (photonView.IsMine || photonView.AmController) { destroyIssued = true; Logger.LogWarning((object)("[TimedDespawn] Destroying expired network object. | Object=" + ((Object)((Component)this).gameObject).name + " | Source=" + sourceName + " | ViewID=" + photonView.ViewID + " | GroundSeconds=" + accumulatedGroundTime)); PhotonNetwork.Destroy(((Component)this).gameObject); } } } } public static class NoInventory { private sealed class PendingSlotBreak { public byte SlotId; public float StartedAt; public float NextEquipAttemptAt; public float HeldDetectedAt = -1f; } [HarmonyPatch(typeof(CharacterItems), "EquipSlot", new Type[] { typeof(Optionable) })] private static class CharacterItemsEquipSlotPatch { [HarmonyPrefix] private static bool Prefix(CharacterItems __instance, Optionable __0) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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) Character val = ResolveCharacter(__instance); if (!IsValidLocalCharacter(val)) { return true; } Item currentItem = val.data.currentItem; if (!IsNestEgg(currentItem) || (int)currentItem.itemState != 1) { return true; } if (__0.IsSome && __instance.currentSelectedSlot.IsSome && __0.Value == __instance.currentSelectedSlot.Value) { return true; } int instanceID = ((Object)val).GetInstanceID(); PendingSlotBreaks.Remove(instanceID); Optionable backingSlot = FindHeldEggBackingSlot(__instance, val); BreakHeldEgg(__instance, backingSlot, __0, "EggLeftPlayerHand"); return false; } } [HarmonyPatch(typeof(CharacterItems), "Update")] private static class CharacterItemsUpdatePatch { [HarmonyPostfix] private static void Postfix(CharacterItems __instance) { Character character = ResolveCharacter(__instance); if (IsValidLocalCharacter(character)) { ScanWorldBackpackedEggs(); if (!ProcessPendingSlotBreak(__instance, character) && TryFindIllegalEggSlot(__instance, character, out var illegalSlotId)) { StartPendingSlotBreak(__instance, character, illegalSlotId); } } } } [HarmonyPatch(typeof(Item), "PutInBackpackRPC", new Type[] { typeof(byte), typeof(BackpackReference) })] private static class ItemPutInBackpackRpcPatch { [HarmonyPostfix] private static void Postfix(Item __instance, byte __0, BackpackReference __1) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (IsNestEgg(__instance)) { BreakBackpackedEgg(__instance, __1, "PutInBackpackRPC"); } } } private const string LogPrefix = "[NoInventory] "; private const string TargetPrefabName = "NestEgg"; private const float HeldAttachSafetyDelay = 0.06f; private const float NormalEquipGraceSeconds = 0.75f; private const float PendingBreakTimeoutSeconds = 3f; private const float EquipRetryIntervalSeconds = 0.2f; private const float BackpackScanIntervalSeconds = 0.1f; private const int MaximumLogCount = 100; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.NoInventory"); private static readonly Dictionary PendingSlotBreaks = new Dictionary(); private static readonly HashSet BreakingEggInstanceIds = new HashSet(); private static float nextBackpackScanAt; private static int inventoryBreakLogCount; private static int backpackBreakLogCount; private static int rejectedBreakLogCount; private static bool IsNestEgg(Item item) { if ((Object)(object)item == (Object)null) { return false; } string a = NormalizeObjectName(((Object)((Component)item).gameObject).name); return string.Equals(a, "NestEgg", StringComparison.OrdinalIgnoreCase); } private static bool SlotContainsNestEgg(ItemSlot slot) { return slot != null && !slot.IsEmpty() && IsNestEgg(slot.prefab); } private static string NormalizeObjectName(string objectName) { if (string.IsNullOrWhiteSpace(objectName)) { return string.Empty; } string text = objectName.Trim(); if (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length); text = text.Trim(); } return text; } private static Character ResolveCharacter(CharacterItems items) { if ((Object)(object)items == (Object)null) { return null; } Character val = ((Component)items).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)items).GetComponentInParent(); } return val; } private static bool IsValidLocalCharacter(Character character) { return (Object)(object)character != (Object)null && character.IsLocal && (Object)(object)character.data != (Object)null && (Object)(object)character.player != (Object)null; } private static bool IsEggLegallyHeldFromSlot(CharacterItems items, Character character, byte slotId) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 if ((Object)(object)items == (Object)null || (Object)(object)character == (Object)null || (Object)(object)character.data == (Object)null) { return false; } if (!items.currentSelectedSlot.IsSome || items.currentSelectedSlot.Value != slotId) { return false; } Item currentItem = character.data.currentItem; return IsNestEgg(currentItem) && (int)currentItem.itemState == 1; } private static bool IsRecentNormalEquip(CharacterItems items, byte slotId) { if ((Object)(object)items == (Object)null || !items.lastSelectedSlot.IsSome || items.lastSelectedSlot.Value != slotId) { return false; } return Time.time - items.lastEquippedSlotTime < 0.75f; } private static Optionable FindHeldEggBackingSlot(CharacterItems items, Character character) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)items == (Object)null || (Object)(object)character == (Object)null || (Object)(object)character.player == (Object)null) { return Optionable.None; } if (items.currentSelectedSlot.IsSome) { byte value = items.currentSelectedSlot.Value; ItemSlot itemSlot = character.player.GetItemSlot(value); if (SlotContainsNestEgg(itemSlot)) { return Optionable.Some(value); } } ItemSlot[] itemSlots = character.player.itemSlots; if (itemSlots != null) { for (byte b = 0; b < itemSlots.Length; b++) { if (SlotContainsNestEgg(itemSlots[b])) { return Optionable.Some(b); } } } if (SlotContainsNestEgg(character.player.tempFullSlot)) { return Optionable.Some((byte)250); } return Optionable.None; } private static bool TryFindIllegalEggSlot(CharacterItems items, Character character, out byte illegalSlotId) { illegalSlotId = 0; if ((Object)(object)items == (Object)null || (Object)(object)character == (Object)null || (Object)(object)character.player == (Object)null) { return false; } ItemSlot[] itemSlots = character.player.itemSlots; if (itemSlots != null) { for (byte b = 0; b < itemSlots.Length; b++) { ItemSlot slot = itemSlots[b]; if (SlotContainsNestEgg(slot) && !IsEggLegallyHeldFromSlot(items, character, b) && !IsRecentNormalEquip(items, b)) { illegalSlotId = b; return true; } } } if (SlotContainsNestEgg(character.player.tempFullSlot) && !IsEggLegallyHeldFromSlot(items, character, 250) && !IsRecentNormalEquip(items, 250)) { illegalSlotId = 250; return true; } return false; } private static bool CanBreakLocally(Item egg) { if ((Object)(object)egg == (Object)null) { return false; } if (!PhotonNetwork.InRoom || (Object)(object)((MonoBehaviourPun)egg).photonView == (Object)null) { return true; } return ((MonoBehaviourPun)egg).photonView.IsMine; } private static void PrepareEggForForcedBreak(Item egg, Vector3 dropPosition) { //IL_0026: 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_004a: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)egg == (Object)null) { return; } ((Component)egg).transform.SetParent((Transform)null, true); ((Component)egg).transform.position = dropPosition; egg.itemState = (ItemState)0; egg.holderCharacter = null; egg.backpackSlotTransform = null; egg.backpackReference = Optionable<(byte, BackpackReference)>.None; if ((Object)(object)egg.rig != (Object)null) { egg.rig.position = dropPosition; egg.rig.useGravity = true; egg.rig.isKinematic = false; egg.rig.interpolation = (RigidbodyInterpolation)1; egg.rig.collisionDetectionMode = (CollisionDetectionMode)2; egg.rig.excludeLayers = LayerMask.op_Implicit(0); egg.rig.linearVelocity = Vector3.down * 1.5f; egg.rig.angularVelocity = new Vector3(1.5f, 0.75f, -1f); } Collider[] array = egg.colliders; if (array == null || array.Length == 0) { array = ((Component)egg).GetComponentsInChildren(true); } foreach (Collider val in array) { if (!((Object)(object)val == (Object)null)) { val.enabled = true; val.isTrigger = false; } } Renderer[] componentsInChildren = ((Component)egg).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren.Length; j++) { if ((Object)(object)componentsInChildren[j] != (Object)null) { componentsInChildren[j].enabled = true; } } } private unsafe static bool ForceBreakEgg(Item egg, Vector3 dropPosition, string reason) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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) if (!IsNestEgg(egg)) { return false; } int instanceID = ((Object)egg).GetInstanceID(); if (!BreakingEggInstanceIds.Add(instanceID)) { return false; } if (!CanBreakLocally(egg)) { BreakingEggInstanceIds.Remove(instanceID); LogRejected(egg, reason, "Local client does not own the egg PhotonView."); return false; } BreakableEgg val = ((Component)egg).GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)egg).GetComponentInChildren(true); } if ((Object)(object)val == (Object)null) { BreakingEggInstanceIds.Remove(instanceID); LogRejected(egg, reason, "BreakableEgg component was not found."); return false; } try { PrepareEggForForcedBreak(egg, dropPosition); ((Breakable)val).spawnsItemsKinematic = false; ((Breakable)val).ragdollCharacterOnBreak = false; ((Breakable)val).Break((Collision)null); ManualLogSource logger = Logger; string[] obj = new string[6] { "[NoInventory] NestEgg was forcibly broken. Reason=", reason, " | Position=", null, null, null }; Vector3 val2 = dropPosition; obj[3] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[4] = " | ViewID="; obj[5] = (((Object)(object)((MonoBehaviourPun)egg).photonView != (Object)null) ? ((MonoBehaviourPun)egg).photonView.ViewID.ToString() : "None"); logger.LogWarning((object)string.Concat(obj)); return true; } catch (Exception ex) { BreakingEggInstanceIds.Remove(instanceID); Logger.LogError((object)("[NoInventory] Failed to forcibly break NestEgg. Reason=" + reason + " | Exception=" + ex)); return false; } } private static Vector3 GetHandDropPosition(Character character, Item egg) { //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) //IL_0023: 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) //IL_0028: 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_007c: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)character == (Object)null) { return ((Object)(object)egg != (Object)null) ? ((Component)egg).transform.position : Vector3.zero; } Vector3 val = ((Component)character).transform.forward; if ((Object)(object)character.data != (Object)null && ((Vector3)(ref character.data.lookDirection)).sqrMagnitude > 0.001f) { val = ((Vector3)(ref character.data.lookDirection)).normalized; } return character.Center + val * 0.3f + Vector3.down * 0.15f; } private static Vector3 GetBackpackDropPosition(Item egg, BackpackReference backpackReference) { //IL_0001: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_0091: 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_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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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)backpackReference.view != (Object)null) { Character component = ((Component)backpackReference.view).GetComponent(); if ((Object)(object)component != (Object)null) { return component.Center + ((Component)component).transform.forward * 0.25f + Vector3.down * 0.1f; } return ((Component)backpackReference.view).transform.position + Vector3.up * 0.25f; } return ((Object)(object)egg != (Object)null) ? (((Component)egg).transform.position + Vector3.down * 0.1f) : Vector3.zero; } private static void BreakHeldEgg(CharacterItems items, Optionable backingSlot, Optionable slotToEquipAfterBreak, string reason) { //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) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)items == (Object)null) { return; } Character val = ResolveCharacter(items); if (!IsValidLocalCharacter(val)) { return; } Item currentItem = val.data.currentItem; if (!IsNestEgg(currentItem)) { return; } if (backingSlot.IsNone) { backingSlot = FindHeldEggBackingSlot(items, val); } if (backingSlot.IsSome) { ItemSlot itemSlot = val.player.GetItemSlot(backingSlot.Value); if (SlotContainsNestEgg(itemSlot)) { val.player.EmptySlot(backingSlot); } } Vector3 handDropPosition = GetHandDropPosition(val, currentItem); items.UnAttachEquippedItem(); if (ForceBreakEgg(currentItem, handDropPosition, reason) && inventoryBreakLogCount < 100) { inventoryBreakLogCount++; Logger.LogInfo((object)("[NoInventory] Inventory egg violation handled. Count=" + inventoryBreakLogCount + "/" + 100 + " | Reason=" + reason + " | BackingSlot=" + (backingSlot.IsSome ? backingSlot.Value.ToString() : "None"))); } ((MonoBehaviour)items).StartCoroutine(ContinueEquipAfterBreak(items, slotToEquipAfterBreak)); } private static IEnumerator ContinueEquipAfterBreak(CharacterItems items, Optionable requestedSlot) { //IL_000e: 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) yield return null; if (!((Object)(object)items == (Object)null)) { Character character = ResolveCharacter(items); if (IsValidLocalCharacter(character)) { items.EquipSlot(requestedSlot); } } } private static bool ProcessPendingSlotBreak(CharacterItems items, Character character) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Invalid comparison between Unknown and I4 //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)character).GetInstanceID(); if (!PendingSlotBreaks.TryGetValue(instanceID, out var value)) { return false; } if (Time.time - value.StartedAt > 3f) { PendingSlotBreaks.Remove(instanceID); LogRejected(character.data.currentItem, "InventorySlot", "Timed out while equipping stored NestEgg."); return false; } ItemSlot itemSlot = character.player.GetItemSlot(value.SlotId); if (!SlotContainsNestEgg(itemSlot)) { PendingSlotBreaks.Remove(instanceID); return false; } Item currentItem = character.data.currentItem; if (IsNestEgg(currentItem) && (int)currentItem.itemState == 1) { if (value.HeldDetectedAt < 0f) { value.HeldDetectedAt = Time.time; return true; } if (Time.time - value.HeldDetectedAt < 0.06f) { return true; } byte slotId = value.SlotId; PendingSlotBreaks.Remove(instanceID); BreakHeldEgg(items, Optionable.Some(slotId), Optionable.None, "StoredInInventorySlot"); return true; } if (Time.time >= value.NextEquipAttemptAt) { value.NextEquipAttemptAt = Time.time + 0.2f; items.EquipSlot(Optionable.Some(value.SlotId)); } return true; } private static void StartPendingSlotBreak(CharacterItems items, Character character, byte slotId) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)character).GetInstanceID(); if (!PendingSlotBreaks.ContainsKey(instanceID)) { PendingSlotBreak pendingSlotBreak = new PendingSlotBreak(); pendingSlotBreak.SlotId = slotId; pendingSlotBreak.StartedAt = Time.time; pendingSlotBreak.NextEquipAttemptAt = Time.time + 0.2f; PendingSlotBreaks.Add(instanceID, pendingSlotBreak); items.EquipSlot(Optionable.Some(slotId)); } } private static void BreakBackpackedEgg(Item egg, BackpackReference backpackReference, string reason) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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 (IsNestEgg(egg) && (int)egg.itemState == 2 && CanBreakLocally(egg)) { Vector3 backpackDropPosition = GetBackpackDropPosition(egg, backpackReference); egg.ClearDataFromBackpack(); if (ForceBreakEgg(egg, backpackDropPosition, reason) && backpackBreakLogCount < 100) { backpackBreakLogCount++; Logger.LogInfo((object)("[NoInventory] Backpack egg violation handled. Count=" + backpackBreakLogCount + "/" + 100 + " | Reason=" + reason)); } } } private static void ScanWorldBackpackedEggs() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (Time.time < nextBackpackScanAt) { return; } nextBackpackScanAt = Time.time + 0.1f; List list = new List(Item.ALL_ITEMS); for (int i = 0; i < list.Count; i++) { Item val = list[i]; if (IsNestEgg(val) && (int)val.itemState == 2 && val.backpackReference.IsSome) { BreakBackpackedEgg(val, val.backpackReference.Value.Item2, "BackpackStateDetected"); } } } private static void LogRejected(Item egg, string reason, string detail) { if (rejectedBreakLogCount < 100) { rejectedBreakLogCount++; Logger.LogWarning((object)("[NoInventory] NestEgg break request was rejected. Count=" + rejectedBreakLogCount + "/" + 100 + " | Reason=" + reason + " | Detail=" + detail + " | Object=" + (((Object)(object)egg != (Object)null) ? ((Object)((Component)egg).gameObject).name : "null"))); } } } [HarmonyPatch(typeof(CharacterSpawner), "Update")] public static class RandomStartEgg { public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; private const float RequiredStableTime = 1.5f; private const string LogPrefix = "[RandomStartEgg] "; private const string RoomPropertyKey = "Sapphire009.WatchEgg.StartEggGranted"; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.RandomStartEgg"); private static int currentSceneHandle = int.MinValue; private static bool routineStarted; private static bool eggGranted; private static bool airportPropertyReset; private static int lastLoggedReadyCount = -1; [HarmonyPrepare] private static bool Prepare() { Logger.LogInfo((object)"[RandomStartEgg] PATCH READY: CharacterSpawner.Update"); return true; } [HarmonyPostfix] private static void Postfix(CharacterSpawner __instance) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Invalid comparison between Unknown and I4 //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) ResetStateWhenSceneChanged(); if ((Object)(object)__instance == (Object)null || !PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { return; } if (!GameHandler.IsOnIsland) { ResetRoomPropertyInAirport(); } else if ((int)MapHandler.CurrentSegmentNumber <= 0) { if (IsEggAlreadyGrantedInRoom()) { eggGranted = true; } else if (PhotonNetwork.IsMasterClient && !eggGranted && !routineStarted) { routineStarted = true; Scene activeScene = SceneManager.GetActiveScene(); int handle = ((Scene)(ref activeScene)).handle; ((MonoBehaviour)__instance).StartCoroutine(WaitForAllPlayersAndGrantEgg(handle)); } } } private static IEnumerator WaitForAllPlayersAndGrantEgg(int startedSceneHandle) { float stableTime = 0f; int stablePlayerCount = -1; Logger.LogInfo((object)"[RandomStartEgg] Waiting for all connected players to finish spawning."); while (true) { if (!CanContinueWaiting(startedSceneHandle)) { routineStarted = false; yield break; } if (IsEggAlreadyGrantedInRoom()) { eggGranted = true; routineStarted = false; yield break; } if (!TryGetAllSpawnedCharacters(out var _, out var roomPlayerCount)) { stableTime = 0f; stablePlayerCount = -1; yield return null; } else if (roomPlayerCount != stablePlayerCount) { stablePlayerCount = roomPlayerCount; stableTime = 0f; if (lastLoggedReadyCount != roomPlayerCount) { lastLoggedReadyCount = roomPlayerCount; Logger.LogInfo((object)("[RandomStartEgg] All current player characters are ready. | PlayerCount=" + roomPlayerCount)); } yield return null; } else { stableTime += Time.unscaledDeltaTime; if (!(stableTime < 1.5f)) { break; } yield return null; } } if (!TryGetAllSpawnedCharacters(out var finalCharacters, out var finalPlayerCount)) { routineStarted = false; yield break; } if (finalCharacters.Count == 0) { Logger.LogError((object)"[RandomStartEgg] Egg grant failed: no spawned character was found."); routineStarted = false; yield break; } if (!TryGetNestEggPrefab(out var nestEggPrefab)) { Logger.LogError((object)"[RandomStartEgg] Egg grant failed: NestEgg was not found in ItemDatabase."); routineStarted = false; yield break; } List eligibleCharacters = new List(); for (int i = 0; i < finalCharacters.Count; i++) { Character character = finalCharacters[i]; if (!((Object)(object)character == (Object)null) && !((Object)(object)character.player == (Object)null)) { if (!character.player.HasEmptySlot(nestEggPrefab.itemID)) { Logger.LogWarning((object)("[RandomStartEgg] Player excluded because inventory is full. | Player=" + GetCharacterName(character))); } else { eligibleCharacters.Add(character); } } } if (eligibleCharacters.Count == 0) { Logger.LogError((object)"[RandomStartEgg] Egg grant failed: all player inventories are full."); routineStarted = false; yield break; } int randomIndex = Random.Range(0, eligibleCharacters.Count); Character selectedCharacter = eligibleCharacters[randomIndex]; ItemSlot addedSlot = default(ItemSlot); if (!selectedCharacter.player.AddItem(nestEggPrefab.itemID, (ItemInstanceData)null, ref addedSlot) || addedSlot == null) { Logger.LogError((object)("[RandomStartEgg] NestEgg could not be added to " + GetCharacterName(selectedCharacter) + "'s inventory.")); routineStarted = false; yield break; } eggGranted = true; routineStarted = false; SetRoomEggGranted(value: true); int actorNumber = GetActorNumber(selectedCharacter); Logger.LogWarning((object)("[RandomStartEgg] NestEgg granted to one random player. | SelectedPlayer=" + GetCharacterName(selectedCharacter) + " | ActorNumber=" + actorNumber + " | ConnectedPlayers=" + finalPlayerCount + " | SlotID=" + addedSlot.itemSlotID + " | ItemID=" + nestEggPrefab.itemID)); } private static bool TryGetAllSpawnedCharacters(out List characters, out int roomPlayerCount) { characters = new List(); Player[] playerList = PhotonNetwork.PlayerList; roomPlayerCount = ((playerList != null) ? playerList.Length : 0); if (playerList == null || playerList.Length == 0) { return false; } Character val2 = default(Character); foreach (Player val in playerList) { if (val == null) { return false; } if (!PlayerHandler.TryGetCharacter(val.ActorNumber, ref val2)) { return false; } if ((Object)(object)val2 == (Object)null || (Object)(object)val2.data == (Object)null || val2.refs == null || (Object)(object)val2.refs.items == (Object)null || (Object)(object)val2.player == (Object)null) { return false; } characters.Add(val2); } return characters.Count == playerList.Length; } private static bool CanContinueWaiting(int startedSceneHandle) { //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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Invalid comparison between Unknown and I4 Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).handle != startedSceneHandle) { return false; } if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || !PhotonNetwork.IsMasterClient) { return false; } if (!GameHandler.IsOnIsland) { return false; } return (int)MapHandler.CurrentSegmentNumber == 0; } private static bool TryGetNestEggPrefab(out Item nestEggPrefab) { nestEggPrefab = null; ItemDatabase instance = SingletonAsset.Instance; if ((Object)(object)instance != (Object)null && instance.itemLookup != null) { foreach (KeyValuePair item in instance.itemLookup) { Item value = item.Value; if ((Object)(object)value == (Object)null || !IsNestEggName(((Object)((Component)value).gameObject).name)) { continue; } nestEggPrefab = value; return true; } } GameObject val = Resources.Load("0_Items/NestEgg"); if ((Object)(object)val == (Object)null) { return false; } nestEggPrefab = val.GetComponent(); if ((Object)(object)nestEggPrefab == (Object)null) { nestEggPrefab = val.GetComponentInChildren(true); } return (Object)(object)nestEggPrefab != (Object)null; } private static bool IsNestEggName(string objectName) { return string.Equals(NormalizeObjectName(objectName), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizeObjectName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } private static void ResetRoomPropertyInAirport() { if (!airportPropertyReset && PhotonNetwork.IsMasterClient && PhotonNetwork.CurrentRoom != null) { airportPropertyReset = true; SetRoomEggGranted(value: false); Logger.LogInfo((object)"[RandomStartEgg] Airport detected. Start egg room state reset."); } } private static bool IsEggAlreadyGrantedInRoom() { if (PhotonNetwork.CurrentRoom == null || ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties == null) { return false; } if (!((Dictionary)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)"Sapphire009.WatchEgg.StartEggGranted")) { return false; } if (!(((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties[(object)"Sapphire009.WatchEgg.StartEggGranted"] is bool result)) { return false; } return result; } private static void SetRoomEggGranted(bool value) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if (PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.IsMasterClient) { Hashtable val = new Hashtable(); val[(object)"Sapphire009.WatchEgg.StartEggGranted"] = value; PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null); } } private static string GetCharacterName(Character character) { if ((Object)(object)character == (Object)null) { return "Unknown"; } if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && ((MonoBehaviourPun)character).photonView.Owner != null) { return ((MonoBehaviourPun)character).photonView.Owner.NickName; } return ((Object)((Component)character).gameObject).name; } private static int GetActorNumber(Character character) { if ((Object)(object)character == (Object)null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null || ((MonoBehaviourPun)character).photonView.Owner == null) { return -1; } return ((MonoBehaviourPun)character).photonView.Owner.ActorNumber; } private static void ResetStateWhenSceneChanged() { //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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); int handle = ((Scene)(ref activeScene)).handle; if (currentSceneHandle != handle) { currentSceneHandle = handle; routineStarted = false; eggGranted = false; airportPropertyReset = false; lastLoggedReadyCount = -1; ManualLogSource logger = Logger; activeScene = SceneManager.GetActiveScene(); logger.LogInfo((object)("[RandomStartEgg] Scene state reset. | Scene=" + ((Scene)(ref activeScene)).name)); } } } [DisallowMultipleComponent] public sealed class Timer : MonoBehaviour { [HarmonyPatch(typeof(Item), "Awake")] private static class ItemAwakePatch { [HarmonyPostfix] private static void Postfix(Item __instance) { if (IsNestEgg(__instance) && !((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(Item), "RPC_SetThrownData")] private static class SetThrownDataPatch { [HarmonyPostfix] private static void Postfix(Item __instance, int characterID, float thrownAmount) { if (IsNestEgg(__instance)) { Timer timer = ((Component)__instance).GetComponent(); if ((Object)(object)timer == (Object)null) { timer = ((Component)__instance).gameObject.AddComponent(); } timer.ArmThrowerPickupBlock(characterID); } } } [HarmonyPatch(typeof(Item), "Interact")] private static class ItemInteractPatch { [HarmonyPrefix] private static bool Prefix(Item __instance, Character interactor) { if (!IsNestEgg(__instance)) { return true; } Timer component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } return component.CanInteract(interactor); } } public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; public const float MaximumHoldTime = 20f; private const float MinimumAirborneTime = 0.15f; private const float MinimumGroundNormalY = 0.35f; private const string LogPrefix = "[Timer] "; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.Timer"); private Item item; private float heldTime; private bool wasHeldByLocalPlayer; private bool automaticDropRequested; private int blockedThrowerViewId = -1; private bool blockThrowerPickupUntilGrounded; private float airborneBlockStartTime; public float HeldTime => heldTime; public float RemainingTime => Mathf.Max(0f, 20f - heldTime); public bool IsThrowerPickupBlocked => blockThrowerPickupUntilGrounded; private void Awake() { item = ((Component)this).GetComponent(); if (!IsNestEgg(item)) { ((Behaviour)this).enabled = false; } else { Logger.LogInfo((object)("[Timer] Timer attached to " + ((Object)((Component)item).gameObject).name)); } } private void Update() { if (!((Object)(object)item == (Object)null)) { UpdateLocalHoldTimer(); } } private void UpdateLocalHoldTimer() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Invalid comparison between Unknown and I4 Character localCharacter = Character.localCharacter; if (!((Object)(object)localCharacter != (Object)null) || !((Object)(object)localCharacter.data != (Object)null) || !localCharacter.IsLocal || !((Object)(object)localCharacter.data.currentItem == (Object)(object)item) || (int)item.itemState != 1) { ResetHoldTimer(); return; } if (!wasHeldByLocalPlayer) { wasHeldByLocalPlayer = true; heldTime = 0f; automaticDropRequested = false; Logger.LogInfo((object)"[Timer] NestEgg hold timer started."); } if (!automaticDropRequested) { heldTime += Time.deltaTime; if (!(heldTime < 20f)) { RequestAutomaticDrop(localCharacter); } } } private void RequestAutomaticDrop(Character holder) { //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: 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_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_01a0: 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_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: 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) if ((Object)(object)holder == (Object)null || (Object)(object)holder.data == (Object)null || holder.refs == null || (Object)(object)holder.refs.items == (Object)null || (Object)(object)holder.player == (Object)null) { Logger.LogError((object)"[Timer] Automatic drop failed: holder reference is missing."); return; } if ((Object)(object)holder.data.currentItem != (Object)(object)item) { Logger.LogWarning((object)"[Timer] Automatic drop cancelled: NestEgg is no longer held."); ResetHoldTimer(); return; } CharacterItems items = holder.refs.items; if (items.currentSelectedSlot.IsNone) { Logger.LogError((object)"[Timer] Automatic drop failed: currentSelectedSlot is None."); return; } byte value = items.currentSelectedSlot.Value; ItemSlot itemSlot = holder.player.GetItemSlot(value); if (itemSlot == null || itemSlot.IsEmpty()) { Logger.LogError((object)"[Timer] Automatic drop failed: current ItemSlot is null or empty."); return; } string text = NormalizePrefabName(itemSlot.GetPrefabName()); if (!IsNestEggName(text)) { Logger.LogError((object)("[Timer] Automatic drop failed: slot prefab is not NestEgg. Prefab=" + text)); return; } PhotonView component = ((Component)items).GetComponent(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)"[Timer] Automatic drop failed: CharacterItems PhotonView is null."); return; } automaticDropRequested = true; Vector3 val = ((Component)item).transform.position + Vector3.down * 0.2f; Vector3 zero = Vector3.zero; Quaternion rotation = ((Component)item).transform.rotation; component.RPC("DropItemRpc", (RpcTarget)0, new object[7] { 0f, value, val, zero, rotation, itemSlot.data, false }); Logger.LogWarning((object)"[Timer] NestEgg automatically dropped after 20 seconds."); } private void ResetHoldTimer() { if (wasHeldByLocalPlayer || !(heldTime <= 0f) || automaticDropRequested) { wasHeldByLocalPlayer = false; heldTime = 0f; automaticDropRequested = false; } } private void ArmThrowerPickupBlock(int throwerCharacterViewId) { if (throwerCharacterViewId > 0) { blockedThrowerViewId = throwerCharacterViewId; blockThrowerPickupUntilGrounded = true; airborneBlockStartTime = Time.time; Logger.LogInfo((object)("[Timer] Air catch blocked for thrower. | ThrowerViewID=" + blockedThrowerViewId)); } } private bool CanInteract(Character interactor) { if (!blockThrowerPickupUntilGrounded) { return true; } if ((Object)(object)interactor == (Object)null) { return true; } PhotonView component = ((Component)interactor).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } if (component.ViewID != blockedThrowerViewId) { return true; } Logger.LogWarning((object)"[Timer] Thrower pickup blocked while NestEgg is airborne."); return false; } private void OnCollisionEnter(Collision collision) { CheckGroundContact(collision); } private void OnCollisionStay(Collision collision) { CheckGroundContact(collision); } private void CheckGroundContact(Collision collision) { //IL_0045: 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_004e: Unknown result type (might be due to invalid IL or missing references) if (!blockThrowerPickupUntilGrounded || collision == null || Time.time - airborneBlockStartTime < 0.15f || CollisionBelongsToCharacter(collision)) { return; } for (int i = 0; i < collision.contactCount; i++) { ContactPoint contact = collision.GetContact(i); if (!(((ContactPoint)(ref contact)).normal.y < 0.35f)) { MarkAsGrounded(); break; } } } private static bool CollisionBelongsToCharacter(Collision collision) { if ((Object)(object)collision.collider != (Object)null) { Character componentInParent = ((Component)collision.collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { return true; } } if ((Object)(object)collision.rigidbody != (Object)null) { Character componentInParent2 = ((Component)collision.rigidbody).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null) { return true; } } return false; } private void MarkAsGrounded() { if (blockThrowerPickupUntilGrounded) { blockThrowerPickupUntilGrounded = false; blockedThrowerViewId = -1; Logger.LogInfo((object)"[Timer] NestEgg touched the ground. The thrower can pick it up again."); } } public static bool IsNestEgg(Item targetItem) { if ((Object)(object)targetItem == (Object)null) { return false; } return IsNestEggName(((Object)((Component)targetItem).gameObject).name); } public static bool IsNestEggName(string objectName) { return string.Equals(NormalizePrefabName(objectName), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizePrefabName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } } [DisallowMultipleComponent] public sealed class TimerSound : MonoBehaviour { [HarmonyPatch(typeof(Item), "Awake")] private static class ItemAwakePatch { [HarmonyPostfix] private static void Postfix(Item __instance) { if (Timer.IsNestEgg(__instance)) { if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } if (!((Object)(object)((Component)__instance).GetComponent() != (Object)null)) { ((Component)__instance).gameObject.AddComponent(); } } } } public const string DeveloperName = "Sapphire009"; public const float DoubleSpeedStartRemainingTime = 5f; public const float FinalSpeedStartRemainingTime = 2f; private const float NormalTickInterval = 1f; private const float DoubleSpeedTickInterval = 0.5f; private const float FinalSpeedTickInterval = 0.25f; private const float NormalVolume = 0.42f; private const float MaximumVolume = 1f; private const int SampleRate = 44100; private const string LogPrefix = "[TimerSound] "; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.TimerSound"); private static AudioClip tickClip; private static AudioClip tockClip; private Item item; private Timer timer; private AudioSource audioSource; private bool wasHeldByLocalPlayer; private bool doubleSpeedPhaseStarted; private bool finalSpeedPhaseStarted; private bool playTickNext = true; private float nextTickHeldTime; private bool gameMixerApplied; private void Awake() { item = ((Component)this).GetComponent(); if (!Timer.IsNestEgg(item)) { ((Behaviour)this).enabled = false; return; } timer = ((Component)this).GetComponent(); if ((Object)(object)timer == (Object)null) { timer = ((Component)this).gameObject.AddComponent(); } CreateSharedAudioClips(); CreateAudioSource(); Logger.LogInfo((object)("[TimerSound] TimerSound attached to " + ((Object)((Component)item).gameObject).name + " | NormalInterval=" + 1f + " | DoubleSpeedInterval=" + 0.5f + " | FinalSpeedInterval=" + 0.25f)); } private void Update() { if ((Object)(object)item == (Object)null) { return; } ApplyGameAudioMixer(); if (!IsHeldByLocalPlayer()) { StopAndResetSound(); return; } if (!wasHeldByLocalPlayer) { BeginNewHold(); } if ((Object)(object)timer == (Object)null) { timer = ((Component)this).GetComponent(); if ((Object)(object)timer == (Object)null) { return; } } float heldTime = timer.HeldTime; float remainingTime = timer.RemainingTime; if (!(remainingTime <= 0f)) { if (remainingTime <= 5f && !doubleSpeedPhaseStarted) { doubleSpeedPhaseStarted = true; nextTickHeldTime = Mathf.Min(nextTickHeldTime, heldTime); Logger.LogWarning((object)("[TimerSound] Double-speed phase started. | RemainingTime=" + remainingTime.ToString("F2") + " | Speed=2.0 | Interval=" + 0.5f)); } if (remainingTime <= 2f && !finalSpeedPhaseStarted) { finalSpeedPhaseStarted = true; nextTickHeldTime = Mathf.Min(nextTickHeldTime, heldTime); Logger.LogWarning((object)("[TimerSound] Final-speed phase started. | RemainingTime=" + remainingTime.ToString("F2") + " | Speed=4.0 | Interval=" + 0.25f)); } if (!(heldTime < nextTickHeldTime)) { PlayCurrentTick(remainingTime); float num = CalculateTickInterval(remainingTime); nextTickHeldTime = heldTime + num; } } } private bool IsHeldByLocalPlayer() { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Invalid comparison between Unknown and I4 Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.data == (Object)null || (Object)(object)item == (Object)null) { return false; } return localCharacter.IsLocal && (Object)(object)localCharacter.data.currentItem == (Object)(object)item && (int)item.itemState == 1; } private void BeginNewHold() { wasHeldByLocalPlayer = true; doubleSpeedPhaseStarted = false; finalSpeedPhaseStarted = false; playTickNext = true; nextTickHeldTime = 0f; if ((Object)(object)audioSource != (Object)null) { audioSource.Stop(); } Logger.LogInfo((object)"[TimerSound] NestEgg timer sound started."); } private void PlayCurrentTick(float remainingTime) { if (!((Object)(object)audioSource == (Object)null)) { AudioClip val = (playTickNext ? tickClip : tockClip); if (!((Object)(object)val == (Object)null)) { float num = CalculateTickVolume(remainingTime); audioSource.pitch = 1f; audioSource.PlayOneShot(val, num); playTickNext = !playTickNext; } } } private static float CalculateTickInterval(float remainingTime) { if (remainingTime <= 2f) { return 0.25f; } if (remainingTime <= 5f) { return 0.5f; } return 1f; } private static float CalculateTickVolume(float remainingTime) { if (remainingTime > 5f) { return 0.42f; } float num = 1f - Mathf.Clamp01(remainingTime / 5f); float num2 = Mathf.Pow(num, 1.35f); return Mathf.Lerp(0.42f, 1f, num2); } private void StopAndResetSound() { if (wasHeldByLocalPlayer) { wasHeldByLocalPlayer = false; doubleSpeedPhaseStarted = false; finalSpeedPhaseStarted = false; playTickNext = true; nextTickHeldTime = 0f; if ((Object)(object)audioSource != (Object)null) { audioSource.Stop(); } Logger.LogInfo((object)"[TimerSound] NestEgg timer sound stopped."); } } private void OnDisable() { StopAndResetSound(); } private void OnDestroy() { if ((Object)(object)audioSource != (Object)null) { audioSource.Stop(); } } private void CreateAudioSource() { audioSource = ((Component)this).gameObject.AddComponent(); audioSource.playOnAwake = false; audioSource.loop = false; audioSource.spatialBlend = 0f; audioSource.dopplerLevel = 0f; audioSource.volume = 1f; audioSource.pitch = 1f; audioSource.priority = 32; audioSource.bypassEffects = false; audioSource.bypassListenerEffects = false; audioSource.bypassReverbZones = true; } private void ApplyGameAudioMixer() { if (!gameMixerApplied && !((Object)(object)audioSource == (Object)null) && !((Object)(object)SFX_Player.instance == (Object)null)) { audioSource.outputAudioMixerGroup = SFX_Player.instance.defaultMixerGroup; gameMixerApplied = true; Logger.LogInfo((object)"[TimerSound] PEAK SFX mixer applied."); } } private static void CreateSharedAudioClips() { if ((Object)(object)tickClip == (Object)null) { tickClip = CreateClockClickClip("WatchEgg_NestEgg_TimerTick", 1750f, 0.065f, 0.78f); } if ((Object)(object)tockClip == (Object)null) { tockClip = CreateClockClickClip("WatchEgg_NestEgg_TimerTock", 1050f, 0.085f, 0.72f); } } private static AudioClip CreateClockClickClip(string clipName, float frequency, float duration, float strength) { int num = Mathf.Max(1, Mathf.CeilToInt(44100f * duration)); float[] array = new float[num]; uint num2 = 2463534242u; for (int i = 0; i < num; i++) { float num3 = (float)i / 44100f; float num4 = num3 / duration; float num5 = Mathf.Clamp01(num3 / 0.0025f); float num6 = Mathf.Exp((0f - num4) * 8.5f); float num7 = num5 * num6; float num8 = Mathf.Sin((float)Math.PI * 2f * frequency * num3); float num9 = Mathf.Sin((float)Math.PI * 2f * frequency * 2.17f * num3); num2 = num2 * 1664525 + 1013904223; float num10 = (float)(num2 >> 8) / 16777215f * 2f - 1f; float num11 = num8 * 0.58f + num9 * 0.2f + num10 * 0.22f; array[i] = Mathf.Clamp(num11 * num7 * strength, -1f, 1f); } return CreateAudioClipFromSamples(clipName, array); } private static AudioClip CreateAudioClipFromSamples(string clipName, float[] sourceSamples) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (sourceSamples == null || sourceSamples.Length == 0) { return null; } AudioClip val = AudioClip.Create(clipName, sourceSamples.Length, 1, 44100, false, (PCMReaderCallback)delegate(float[] outputSamples) { if (outputSamples != null) { int num = Mathf.Min(outputSamples.Length, sourceSamples.Length); Array.Copy(sourceSamples, 0, outputSamples, 0, num); for (int i = num; i < outputSamples.Length; i++) { outputSamples[i] = 0f; } } }); if ((Object)(object)val != (Object)null) { ((Object)val).hideFlags = (HideFlags)61; } return val; } } [BepInPlugin("sapphire009.watchegg", "WatchEgg", "1.0.1")] public sealed class WatchEggPlugin : BaseUnityPlugin { public const string PluginGuid = "sapphire009.watchegg"; public const string PluginName = "WatchEgg"; public const string PluginVersion = "1.0.1"; private const string BuildMarker = "AUTODROP_BREAKABLEEGG_DEBUG_001"; private Harmony harmony; private void Awake() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Sapphire009] WatchEgg 1.0.1 loading..."); ((BaseUnityPlugin)this).Logger.LogWarning((object)"[Sapphire009] Build marker: AUTODROP_BREAKABLEEGG_DEBUG_001"); AutoDrop.SetLogger(((BaseUnityPlugin)this).Logger); harmony = new Harmony("sapphire009.watchegg"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Sapphire009] Harmony PatchAll completed."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Sapphire009] WatchEgg 1.0.1 loaded successfully."); } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); harmony = null; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[Sapphire009] WatchEgg patches removed."); } } } public static class WithEgg { [HarmonyPatch(typeof(Item), "Awake")] private static class ItemAwakePatch { [HarmonyPostfix] private static void Postfix(Item __instance) { RegisterNestEgg(__instance); } } [HarmonyPatch(typeof(Campfire), "GetInteractionText")] private static class CampfireGetInteractionTextPatch { [HarmonyPostfix] private static void Postfix(Campfire __instance, ref string __result) { if (!((Object)(object)__instance == (Object)null) && !__instance.Lit && !IsNestEggInCampfireRange(__instance, out var _)) { if (string.IsNullOrEmpty(__result)) { __result = "BRING THE EGG TO THE CAMPFIRE"; } else { __result = "BRING THE EGG TO THE CAMPFIRE\n" + __result; } } } } [HarmonyPatch(typeof(Campfire), "Interact_CastFinished")] private static class CampfireInteractCastFinishedPatch { [HarmonyPrepare] private static bool Prepare() { Logger.LogInfo((object)("[WithEgg] PATCH READY: Campfire.Interact_CastFinished | RequiredEggRange=" + 15f)); return true; } [HarmonyPrefix] private static bool Prefix(Campfire __instance, Character interactor) { if ((Object)(object)__instance == (Object)null) { return true; } if (__instance.Lit) { return true; } if (IsNestEggInCampfireRange(__instance, out var nearestDistance)) { Logger.LogInfo((object)("[WithEgg] Campfire lighting allowed. | EggDistance=" + nearestDistance + " | Campfire=" + ((Object)((Component)__instance).gameObject).name)); return true; } string characterName = GetCharacterName(interactor); string text = (float.IsPositiveInfinity(nearestDistance) ? "No NestEgg found" : nearestDistance.ToString("F2")); Logger.LogWarning((object)("[WithEgg] Campfire lighting blocked. Bring the NestEgg closer. | Player=" + characterName + " | NearestEggDistance=" + text + " | RequiredRange=" + 15f + " | Campfire=" + ((Object)((Component)__instance).gameObject).name)); if ((Object)(object)GUIManager.instance != (Object)null) { GUIManager.instance.RefreshInteractablePrompt(); } return false; } } public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; public const float RequiredEggRange = 15f; private const string RequirementText = "BRING THE EGG TO THE CAMPFIRE"; private const string LogPrefix = "[WithEgg] "; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.WithEgg"); private static readonly List ActiveNestEggs = new List(); private static void RegisterNestEgg(Item item) { if (IsNestEgg(item)) { if (!ActiveNestEggs.Contains(item)) { ActiveNestEggs.Add(item); } WithEggTracker withEggTracker = ((Component)item).GetComponent(); if ((Object)(object)withEggTracker == (Object)null) { withEggTracker = ((Component)item).gameObject.AddComponent(); } withEggTracker.Initialize(item); Logger.LogInfo((object)("[WithEgg] NestEgg registered. | Object=" + ((Object)((Component)item).gameObject).name)); } } internal static void UnregisterNestEgg(Item item) { for (int num = ActiveNestEggs.Count - 1; num >= 0; num--) { Item val = ActiveNestEggs[num]; if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)item) { ActiveNestEggs.RemoveAt(num); } } } private static bool IsNestEggInCampfireRange(Campfire campfire, out float nearestDistance) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Invalid comparison between Unknown and I4 //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0191: 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) nearestDistance = float.PositiveInfinity; if ((Object)(object)campfire == (Object)null) { return false; } Vector3 position = ((Component)campfire).transform.position; if (PlayerHandler.GetAllPlayerCharacters() != null) { foreach (Character allPlayerCharacter in PlayerHandler.GetAllPlayerCharacters()) { if ((Object)(object)allPlayerCharacter == (Object)null || (Object)(object)allPlayerCharacter.data == (Object)null) { continue; } Item currentItem = allPlayerCharacter.data.currentItem; if (IsNestEgg(currentItem)) { float num = Vector3.Distance(position, allPlayerCharacter.Center); if (num < nearestDistance) { nearestDistance = num; } if (num <= 15f) { return true; } } } } for (int num2 = ActiveNestEggs.Count - 1; num2 >= 0; num2--) { Item val = ActiveNestEggs[num2]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { ActiveNestEggs.RemoveAt(num2); } else if (!IsNestEgg(val)) { ActiveNestEggs.RemoveAt(num2); } else if ((int)val.itemState != 1 && ((Component)val).gameObject.activeInHierarchy) { float num3 = Vector3.Distance(position, ((Component)val).transform.position); if (num3 < nearestDistance) { nearestDistance = num3; } if (num3 <= 15f) { return true; } } } return false; } private static bool IsNestEgg(Item item) { if ((Object)(object)item == (Object)null || (Object)(object)((Component)item).gameObject == (Object)null) { return false; } return string.Equals(NormalizePrefabName(((Object)((Component)item).gameObject).name), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizePrefabName(string objectName) { if (string.IsNullOrWhiteSpace(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } private static string GetCharacterName(Character character) { if ((Object)(object)character == (Object)null) { return "Unknown"; } if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && ((MonoBehaviourPun)character).photonView.Owner != null && !string.IsNullOrEmpty(((MonoBehaviourPun)character).photonView.Owner.NickName)) { return ((MonoBehaviourPun)character).photonView.Owner.NickName; } return ((Object)((Component)character).gameObject).name; } } [DisallowMultipleComponent] public sealed class WithEggTracker : MonoBehaviour { private Item trackedItem; public void Initialize(Item item) { trackedItem = item; } private void OnDestroy() { WithEgg.UnregisterNestEgg(trackedItem); trackedItem = null; } } [HarmonyPatch(typeof(CharacterSpawner), "Update")] public static class YSpawn { public const string DeveloperName = "Sapphire009"; public const string TargetPrefabName = "NestEgg"; public const KeyCode EmergencySpawnKey = (KeyCode)121; private const string LogPrefix = "[YSpawn] "; private const float AutomaticInitialDelay = 1.25f; private const float AutomaticRetryInterval = 0.5f; private const float AutomaticRetryTimeout = 10f; private const float EmergencyInputCooldown = 0.75f; private static readonly ManualLogSource Logger = Logger.CreateLogSource("WatchEgg.YSpawn"); private static int handledBrokenEggCount; private static int automaticAttemptedBrokenEggCount; private static int currentSceneHandle = int.MinValue; private static int lastProcessedFrame = -1; private static float nextAllowedEmergencyInputTime; private static bool automaticRespawnRoutineRunning; [HarmonyPrepare] private static bool Prepare() { Logger.LogInfo((object)"[YSpawn] PATCH READY: CharacterSpawner.Update"); return true; } [HarmonyPostfix] private static void Postfix(CharacterSpawner __instance) { ResetWhenSceneChanged(); if (lastProcessedFrame != Time.frameCount) { lastProcessedFrame = Time.frameCount; TryStartAutomaticRespawn(__instance); if (Input.GetKeyDown((KeyCode)121) && !(Time.unscaledTime < nextAllowedEmergencyInputTime)) { nextAllowedEmergencyInputTime = Time.unscaledTime + 0.75f; TrySpawnNestEgg(emergencyRequest: true, EggCheckpoint.BrokenEggCount); } } } private static void TryStartAutomaticRespawn(CharacterSpawner coroutineOwner) { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)coroutineOwner == (Object)null) && !automaticRespawnRoutineRunning && PhotonNetwork.InRoom && PhotonNetwork.CurrentRoom != null && PhotonNetwork.IsMasterClient && EggCheckpoint.HasCheckpoint) { int brokenEggCount = EggCheckpoint.BrokenEggCount; if (brokenEggCount > 0 && brokenEggCount > handledBrokenEggCount && brokenEggCount > automaticAttemptedBrokenEggCount) { automaticAttemptedBrokenEggCount = brokenEggCount; automaticRespawnRoutineRunning = true; Scene activeScene = SceneManager.GetActiveScene(); int handle = ((Scene)(ref activeScene)).handle; ((MonoBehaviour)coroutineOwner).StartCoroutine(AutomaticRespawnRoutine(handle, brokenEggCount)); } } } private static IEnumerator AutomaticRespawnRoutine(int startedSceneHandle, int triggeringBrokenEggCount) { Logger.LogWarning((object)("[YSpawn] NestEgg break detected. Automatic checkpoint respawn scheduled. | BrokenCount=" + triggeringBrokenEggCount)); yield return (object)new WaitForSecondsRealtime(1.25f); float timeoutTime = Time.unscaledTime + 10f; bool existingEggFound; string existingEggLocation; while (true) { if (!CanContinueAutomaticRespawn(startedSceneHandle)) { automaticRespawnRoutineRunning = false; yield break; } if (handledBrokenEggCount >= triggeringBrokenEggCount) { automaticRespawnRoutineRunning = false; yield break; } existingEggFound = TryFindExistingNestEgg(out existingEggLocation); if (!existingEggFound && TrySpawnNestEgg(emergencyRequest: false, triggeringBrokenEggCount)) { automaticRespawnRoutineRunning = false; yield break; } if (Time.unscaledTime >= timeoutTime) { break; } yield return (object)new WaitForSecondsRealtime(0.5f); existingEggLocation = null; } Logger.LogError((object)("[YSpawn] Automatic checkpoint respawn timed out. Use Y for emergency recovery. | BrokenCount=" + triggeringBrokenEggCount + " | ExistingEgg=" + (existingEggFound ? existingEggLocation : "None"))); automaticRespawnRoutineRunning = false; } private static bool CanContinueAutomaticRespawn(int startedSceneHandle) { //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) Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).handle != startedSceneHandle) { return false; } if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null || !PhotonNetwork.IsMasterClient) { return false; } if (!EggCheckpoint.HasCheckpoint) { return false; } return true; } private unsafe static bool TrySpawnNestEgg(bool emergencyRequest, int triggeringBrokenEggCount) { //IL_0135: 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_01e6: 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_024b: Unknown result type (might be due to invalid IL or missing references) //IL_0254: 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_02d0: 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_0215: Unknown result type (might be due to invalid IL or missing references) string text = (emergencyRequest ? "Emergency Y" : "Automatic"); if (!PhotonNetwork.InRoom || PhotonNetwork.CurrentRoom == null) { Logger.LogWarning((object)("[YSpawn] " + text + " spawn cancelled: Photon room is not ready.")); return false; } if (!PhotonNetwork.IsMasterClient) { if (emergencyRequest) { Logger.LogWarning((object)"[YSpawn] Emergency Y spawn cancelled: only the host can restore the egg."); } return false; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || !localCharacter.IsLocal) { Logger.LogWarning((object)("[YSpawn] " + text + " spawn cancelled: local character is not ready.")); return false; } if (!EggCheckpoint.TryGetCheckpoint(out var position, out var rotation)) { Logger.LogWarning((object)("[YSpawn] " + text + " spawn cancelled: no checkpoint has been saved.")); return false; } if (TryFindExistingNestEgg(out var existingLocation)) { if (emergencyRequest) { Logger.LogWarning((object)("[YSpawn] Emergency Y spawn cancelled: a NestEgg still exists. | Location=" + existingLocation)); } return false; } GameObject val; try { val = PhotonNetwork.InstantiateItemRoom("NestEgg", position, rotation); } catch (Exception ex) { Logger.LogError((object)("[YSpawn] " + text + " Photon spawn failed. | Exception=" + ex)); return false; } if ((Object)(object)val == (Object)null) { Logger.LogError((object)("[YSpawn] " + text + " spawn returned null.")); return false; } PhotonView component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Logger.LogError((object)"[YSpawn] Spawned NestEgg has no PhotonView."); PhotonNetwork.Destroy(val); return false; } val.transform.SetPositionAndRotation(position, rotation); Rigidbody component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.linearVelocity = Vector3.zero; component2.angularVelocity = Vector3.zero; component2.isKinematic = true; component2.Sleep(); } component.RPC("SetKinematicRPC", (RpcTarget)3, new object[3] { true, position, rotation }); handledBrokenEggCount = Mathf.Max(handledBrokenEggCount, Mathf.Max(triggeringBrokenEggCount, EggCheckpoint.BrokenEggCount)); ManualLogSource logger = Logger; string[] obj = new string[10] { "[YSpawn] ", text, " NestEgg spawned at checkpoint. | BrokenCount=", EggCheckpoint.BrokenEggCount.ToString(), " | CheckpointNumber=", EggCheckpoint.CheckpointNumber.ToString(), " | Position=", null, null, null }; Vector3 val2 = position; obj[7] = ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString(); obj[8] = " | ViewID="; obj[9] = component.ViewID.ToString(); logger.LogWarning((object)string.Concat(obj)); return true; } private static bool TryFindExistingNestEgg(out string existingLocation) { existingLocation = string.Empty; if (TryFindWorldNestEgg(out existingLocation)) { return true; } if (TryFindInventoryNestEgg(out existingLocation)) { return true; } return false; } private static bool TryFindWorldNestEgg(out string existingLocation) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) existingLocation = string.Empty; Item[] array = Object.FindObjectsOfType(); if (array == null) { return false; } foreach (Item val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { Scene scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid() && IsNestEggName(((Object)((Component)val).gameObject).name)) { existingLocation = "World: " + ((Object)((Component)val).gameObject).name + " at " + ((object)((Component)val).transform.position/*cast due to .constrained prefix*/).ToString(); return true; } } } return false; } private static bool TryFindInventoryNestEgg(out string existingLocation) { existingLocation = string.Empty; if (Character.AllCharacters == null) { return false; } BackpackData val2 = default(BackpackData); foreach (Character allCharacter in Character.AllCharacters) { if ((Object)(object)allCharacter == (Object)null || (Object)(object)allCharacter.player == (Object)null) { continue; } string characterName = GetCharacterName(allCharacter); ItemSlot[] itemSlots = allCharacter.player.itemSlots; if (itemSlots != null) { foreach (ItemSlot val in itemSlots) { if (val != null && !((Object)(object)val.prefab == (Object)null) && IsNestEggName(((Object)((Component)val.prefab).gameObject).name)) { existingLocation = "Inventory: " + characterName + " Slot=" + val.itemSlotID; return true; } } } ItemSlot backpackSlot = (ItemSlot)(object)allCharacter.player.backpackSlot; if (backpackSlot == null || backpackSlot.IsEmpty() || backpackSlot.data == null || !backpackSlot.data.TryGetDataEntry((DataEntryKey)7, ref val2) || val2 == null || val2.itemSlots == null) { continue; } for (int j = 0; j < val2.itemSlots.Length; j++) { ItemSlot val3 = val2.itemSlots[j]; if (val3 != null && !((Object)(object)val3.prefab == (Object)null) && IsNestEggName(((Object)((Component)val3.prefab).gameObject).name)) { existingLocation = "Backpack: " + characterName + " Slot=" + val3.itemSlotID; return true; } } } return false; } private static bool IsNestEggName(string objectName) { return string.Equals(NormalizeObjectName(objectName), "NestEgg", StringComparison.OrdinalIgnoreCase); } private static string NormalizeObjectName(string objectName) { if (string.IsNullOrEmpty(objectName)) { return string.Empty; } string text = objectName.Trim(); while (text.EndsWith("(Clone)", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(0, text.Length - "(Clone)".Length).Trim(); } return text; } private static string GetCharacterName(Character character) { if ((Object)(object)character == (Object)null) { return "Unknown"; } if ((Object)(object)((MonoBehaviourPun)character).photonView != (Object)null && ((MonoBehaviourPun)character).photonView.Owner != null) { string nickName = ((MonoBehaviourPun)character).photonView.Owner.NickName; if (!string.IsNullOrEmpty(nickName)) { return nickName; } } return ((Object)((Component)character).gameObject).name; } private static void ResetWhenSceneChanged() { //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) Scene activeScene = SceneManager.GetActiveScene(); if (currentSceneHandle == ((Scene)(ref activeScene)).handle) { if (EggCheckpoint.BrokenEggCount < handledBrokenEggCount) { handledBrokenEggCount = 0; automaticAttemptedBrokenEggCount = 0; } } else { currentSceneHandle = ((Scene)(ref activeScene)).handle; handledBrokenEggCount = 0; automaticAttemptedBrokenEggCount = 0; lastProcessedFrame = -1; nextAllowedEmergencyInputTime = 0f; automaticRespawnRoutineRunning = false; Logger.LogInfo((object)("[YSpawn] Scene changed. Respawn state reset. | Scene=" + ((Scene)(ref activeScene)).name)); } } }