Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ExtractionAutoRevive v4.0.1
ExtractionAutoRevive.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.ExtractionAutoRevive { [BepInPlugin("REPOJP.ExtractionAutoRevive", "ExtractionAutoRevive", "4.0.1")] public sealed class ExtractionAutoRevivePlugin : BaseUnityPlugin { private sealed class PendingReviveEntry { public PlayerDeathHead DeathHead; public PlayerAvatar PlayerAvatar; public int Key; public float QueuedAt; public float GroundedStartedAt = -1f; public string LevelName; public string PlayerLabel; public string Source; } [CompilerGenerated] private sealed class <MonitorPendingRevives>d__39 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public ExtractionAutoRevivePlugin <>4__this; private float <interval>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MonitorPendingRevives>d__39(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } while (<>4__this._pendingRevives.Count > 0) { if (!<>4__this.IsModEnabled()) { <>4__this.ClearPendingRevives("mod disabled"); break; } if (!<>4__this.CanRunHostLogic()) { <>4__this.ClearPendingRevives("host lost"); break; } <>4__this.ProcessPendingRevives(); if (<>4__this._pendingRevives.Count > 0) { <interval>5__1 = 0.05f; if (<>4__this._configPendingCheckIntervalSeconds != null) { <interval>5__1 = Mathf.Clamp(<>4__this._configPendingCheckIntervalSeconds.Value, 0.02f, 1f); } <>2__current = (object)new WaitForSecondsRealtime(<interval>5__1); <>1__state = 1; return true; } } <>4__this._pendingMonitorCoroutine = null; <>4__this.WriteVerbose("Pending monitor stopped"); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "REPOJP.ExtractionAutoRevive"; public const string PluginName = "ExtractionAutoRevive"; public const string PluginVersion = "4.0.1"; internal static ExtractionAutoRevivePlugin Instance; internal static ManualLogSource LogSource; private Harmony _harmony; private static int _extractionCompleteContextDepth; private Coroutine _pendingMonitorCoroutine; private readonly Dictionary<int, PendingReviveEntry> _pendingRevives = new Dictionary<int, PendingReviveEntry>(); private ConfigEntry<bool> _configEnableMod; private ConfigEntry<bool> _configEnableLog; private ConfigEntry<bool> _configEnableVerboseLog; private ConfigEntry<bool> _configReviveOnShopExtraction; private ConfigEntry<float> _configRequiredGroundedSeconds; private ConfigEntry<float> _configGroundCheckDistance; private ConfigEntry<float> _configPendingCheckIntervalSeconds; private ConfigEntry<float> _configMaxPendingSeconds; private static readonly FieldInfo FieldPlayerAvatarDeathHead = AccessTools.Field(typeof(PlayerAvatar), "playerDeathHead"); private static readonly FieldInfo FieldPlayerAvatarDeadSet = AccessTools.Field(typeof(PlayerAvatar), "deadSet"); private static readonly FieldInfo FieldPlayerAvatarIsDisabled = AccessTools.Field(typeof(PlayerAvatar), "isDisabled"); private static readonly FieldInfo FieldPlayerDeathHeadTriggered = AccessTools.Field(typeof(PlayerDeathHead), "triggered"); private static readonly FieldInfo FieldPlayerDeathHeadPhysGrabObject = AccessTools.Field(typeof(PlayerDeathHead), "physGrabObject"); private void Awake() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown try { ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ExtractionAutoRevive] Persist setup failed\n" + ex)); } try { Instance = this; LogSource = ((BaseUnityPlugin)this).Logger; SetupConfig(); _harmony = new Harmony("REPOJP.ExtractionAutoRevive"); _harmony.PatchAll(typeof(ExtractionAutoRevivePlugin).Assembly); WriteLog("Loaded v4.0.1"); } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("[ExtractionAutoRevive] Awake failed\n" + ex2)); } } private void OnDestroy() { ClearPendingRevives("plugin destroy"); StopPendingMonitor(); try { if (_harmony != null) { _harmony.UnpatchSelf(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ExtractionAutoRevive] Unpatch failed\n" + ex)); } if (Instance == this) { Instance = null; } } private void SetupConfig() { //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown _configEnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable this mod. このMODを有効化"); _configReviveOnShopExtraction = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReviveOnShopExtraction", false, "Also revive dead players when the shop extraction tube completes purchases. ショップ購入チューブ完了時も蘇生"); _configEnableLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Log", "EnableLog", true, "Enable standard logs. 標準ログ有効化"); _configEnableVerboseLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Log", "EnableVerboseLog", false, "Enable verbose logs. 詳細ログ有効化"); _configRequiredGroundedSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("GroundCheck", "RequiredGroundedSeconds", 0f, new ConfigDescription("Required seconds that the death head must stay on the ground before revive. 蘇生前にデスヘッドが地面接触している必要秒数", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); _configGroundCheckDistance = ((BaseUnityPlugin)this).Config.Bind<float>("GroundCheck", "GroundCheckDistance", 0.35f, new ConfigDescription("Ground ray distance from the death head collider bounds. デスヘッドCollider境界からの地面判定距離", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 3f), Array.Empty<object>())); _configPendingCheckIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("GroundCheck", "PendingCheckIntervalSeconds", 0.05f, new ConfigDescription("Pending revive monitor interval. 遅延蘇生監視間隔", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.02f, 1f), Array.Empty<object>())); _configMaxPendingSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("GroundCheck", "MaxPendingSeconds", 0f, new ConfigDescription("Maximum seconds to wait for a death head to touch the ground. 0 means unlimited. デスヘッド地面接触待機最大秒数。0は無制限", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), Array.Empty<object>())); } private void WriteLog(string message) { if (_configEnableLog != null && _configEnableLog.Value && LogSource != null) { LogSource.LogInfo((object)("[ExtractionAutoRevive] " + message)); } } private void WriteVerbose(string message) { if (_configEnableVerboseLog != null && _configEnableVerboseLog.Value && LogSource != null) { LogSource.LogInfo((object)("[ExtractionAutoRevive] " + message)); } } private void WriteWarning(string message) { if (LogSource != null) { LogSource.LogWarning((object)("[ExtractionAutoRevive] " + message)); } } private bool IsModEnabled() { return _configEnableMod != null && _configEnableMod.Value; } private bool ShouldHandleShopExtraction() { return _configReviveOnShopExtraction != null && _configReviveOnShopExtraction.Value; } private bool CanRunHostLogic() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return false; } } internal static void EnterExtractionCompleteContext(string source) { ExtractionAutoRevivePlugin instance = Instance; if (!((Object)(object)instance == (Object)null) && instance.IsModEnabled() && instance.CanRunHostLogic() && (!string.Equals(source, "shop", StringComparison.Ordinal) || instance.ShouldHandleShopExtraction())) { _extractionCompleteContextDepth++; instance.WriteVerbose("Enter extraction context source=" + source + " depth=" + _extractionCompleteContextDepth); } } internal static void ExitExtractionCompleteContext(string source, Exception exception) { ExtractionAutoRevivePlugin instance = Instance; bool flag = _extractionCompleteContextDepth > 0; if (_extractionCompleteContextDepth > 0) { _extractionCompleteContextDepth--; } if (!((Object)(object)instance == (Object)null) && flag) { instance.WriteVerbose("Exit extraction context source=" + source + " depth=" + _extractionCompleteContextDepth); if (exception != null) { instance.WriteWarning("Skip queue because extraction method failed source=" + source + "\n" + exception); } else if (instance.IsModEnabled() && instance.CanRunHostLogic()) { instance.QueueAllDeadPlayers(source); } } } internal static bool IsExtractionCompleteContextActive() { return _extractionCompleteContextDepth > 0; } private void QueueAllDeadPlayers(string source) { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { WriteWarning("Skip queue reason=GameDirector PlayerList null source=" + source); return; } int num = 0; int num2 = 0; foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if ((Object)(object)player == (Object)null) { num2++; continue; } PlayerDeathHead playerDeathHead = GetPlayerDeathHead(player); if ((Object)(object)playerDeathHead == (Object)null) { num2++; WriteVerbose("Skip queue player=" + GetPlayerLabel(player) + " reason=deathHead null source=" + source); } else if (!IsPlayerDead(player, playerDeathHead)) { num2++; WriteVerbose("Skip queue player=" + GetPlayerLabel(player) + " reason=alive source=" + source); } else if (!IsDeathHeadTriggered(playerDeathHead)) { num2++; WriteVerbose("Skip queue player=" + GetPlayerLabel(player) + " reason=headNotTriggered source=" + source); } else { EnqueuePendingRevive(playerDeathHead, player, source); num++; } } WriteLog("Extraction complete source=" + source + " queued=" + num + " skipped=" + num2); StartPendingMonitorIfNeeded(); } private void EnqueuePendingRevive(PlayerDeathHead deathHead, PlayerAvatar playerAvatar, string source) { if (!((Object)(object)deathHead == (Object)null) && !((Object)(object)playerAvatar == (Object)null)) { int num = GetPendingKey(playerAvatar, deathHead); if (num == 0) { num = ((Object)playerAvatar).GetInstanceID(); } if (_pendingRevives.TryGetValue(num, out var value)) { value.DeathHead = deathHead; value.PlayerAvatar = playerAvatar; value.PlayerLabel = GetPlayerLabel(playerAvatar); value.LevelName = GetCurrentLevelName(); value.Source = source; WriteVerbose("Refresh pending revive player=" + value.PlayerLabel + " key=" + num + " source=" + source); } else { PendingReviveEntry pendingReviveEntry = new PendingReviveEntry { DeathHead = deathHead, PlayerAvatar = playerAvatar, Key = num, QueuedAt = Time.unscaledTime, GroundedStartedAt = -1f, LevelName = GetCurrentLevelName(), PlayerLabel = GetPlayerLabel(playerAvatar), Source = source }; _pendingRevives[num] = pendingReviveEntry; WriteLog("Queue ground-wait revive player=" + pendingReviveEntry.PlayerLabel + " key=" + num + " source=" + source); } } } private void StartPendingMonitorIfNeeded() { if (_pendingRevives.Count > 0 && _pendingMonitorCoroutine == null) { _pendingMonitorCoroutine = ((MonoBehaviour)this).StartCoroutine(MonitorPendingRevives()); WriteVerbose("Pending monitor started"); } } private void StopPendingMonitor() { if (_pendingMonitorCoroutine != null) { try { ((MonoBehaviour)this).StopCoroutine(_pendingMonitorCoroutine); } catch { } _pendingMonitorCoroutine = null; } } [IteratorStateMachine(typeof(<MonitorPendingRevives>d__39))] private IEnumerator MonitorPendingRevives() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MonitorPendingRevives>d__39(0) { <>4__this = this }; } private void ProcessPendingRevives() { if (_pendingRevives.Count <= 0) { return; } List<int> list = new List<int>(_pendingRevives.Keys); foreach (int item in list) { if (!_pendingRevives.TryGetValue(item, out var value)) { continue; } if (value == null || (Object)(object)value.PlayerAvatar == (Object)null || (Object)(object)value.DeathHead == (Object)null) { RemovePendingRevive(item, "invalid reference"); continue; } if (HasQueuedLevelChanged(value)) { RemovePendingRevive(item, "level changed"); continue; } if (!IsPlayerDead(value.PlayerAvatar, value.DeathHead)) { RemovePendingRevive(item, "already alive"); continue; } if (!IsDeathHeadTriggered(value.DeathHead)) { RemovePendingRevive(item, "head no longer triggered"); continue; } if (HasPendingTimedOut(value)) { RemovePendingRevive(item, "pending timeout"); continue; } if (!IsDeathHeadGrounded(value.DeathHead)) { value.GroundedStartedAt = -1f; WriteVerbose("Pending wait player=" + value.PlayerLabel + " reason=not grounded"); continue; } if (value.GroundedStartedAt < 0f) { value.GroundedStartedAt = Time.unscaledTime; WriteVerbose("Pending grounded start player=" + value.PlayerLabel); } float num = 0f; if (_configRequiredGroundedSeconds != null) { num = Mathf.Clamp(_configRequiredGroundedSeconds.Value, 0f, 10f); } float num2 = Time.unscaledTime - value.GroundedStartedAt; if (num2 < num) { WriteVerbose("Pending grounded wait player=" + value.PlayerLabel + " elapsed=" + num2.ToString("F2")); } else if (ReviveNow(value.PlayerAvatar, value.DeathHead, "source=" + value.Source + " grounded=" + num2.ToString("F2") + "s")) { RemovePendingRevive(item, "revived"); } else { RemovePendingRevive(item, "revive failed"); } } } private bool HasPendingTimedOut(PendingReviveEntry entry) { if (entry == null) { return true; } float num = 0f; if (_configMaxPendingSeconds != null) { num = Mathf.Clamp(_configMaxPendingSeconds.Value, 0f, 600f); } if (num <= 0f) { return false; } return Time.unscaledTime - entry.QueuedAt >= num; } private void RemovePendingRevive(int key, string reason) { if (_pendingRevives.TryGetValue(key, out var value)) { WriteVerbose("Pending remove player=" + value.PlayerLabel + " key=" + key + " reason=" + reason); _pendingRevives.Remove(key); } } internal void ClearPendingRevives(string reason) { if (_pendingRevives.Count > 0) { WriteLog("Clear pending revives count=" + _pendingRevives.Count + " reason=" + reason); _pendingRevives.Clear(); } } private bool IsPlayerDead(PlayerAvatar playerAvatar, PlayerDeathHead deathHead) { if ((Object)(object)playerAvatar == (Object)null) { return false; } bool boolField = GetBoolField(FieldPlayerAvatarDeadSet, playerAvatar, defaultValue: false); bool boolField2 = GetBoolField(FieldPlayerAvatarIsDisabled, playerAvatar, defaultValue: false); bool flag = (Object)(object)((Component)playerAvatar).gameObject != (Object)null && ((Component)playerAvatar).gameObject.activeSelf; bool flag2 = (Object)(object)deathHead != (Object)null && IsDeathHeadTriggered(deathHead); if (boolField) { return true; } if (boolField2) { return true; } if (!flag) { return true; } if (flag2) { return true; } return false; } private bool ReviveNow(PlayerAvatar playerAvatar, PlayerDeathHead deathHead, string reason) { if ((Object)(object)playerAvatar == (Object)null || (Object)(object)deathHead == (Object)null) { return false; } if (!IsPlayerDead(playerAvatar, deathHead)) { WriteVerbose("Skip revive player=" + GetPlayerLabel(playerAvatar) + " reason=alreadyAlive finalReason=" + reason); return true; } try { playerAvatar.Revive(false); WriteLog("Revive player=" + GetPlayerLabel(playerAvatar) + " " + reason); return true; } catch (Exception ex) { WriteWarning("Revive failed player=" + GetPlayerLabel(playerAvatar) + " " + reason + "\n" + ex); return false; } } private bool IsDeathHeadGrounded(PlayerDeathHead deathHead) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: 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_006d: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)deathHead == (Object)null) { return false; } PhysGrabObject playerDeathHeadPhysGrabObject = GetPlayerDeathHeadPhysGrabObject(deathHead); if ((Object)(object)playerDeathHeadPhysGrabObject == (Object)null) { return false; } float num = 0.35f; if (_configGroundCheckDistance != null) { num = Mathf.Clamp(_configGroundCheckDistance.Value, 0.05f, 3f); } try { Vector3 centerPoint = playerDeathHeadPhysGrabObject.centerPoint; if (SemiFunc.OnGroundCheck(centerPoint, num, playerDeathHeadPhysGrabObject)) { return true; } } catch { } try { if ((Object)(object)playerDeathHeadPhysGrabObject.rb != (Object)null) { Vector3 worldCenterOfMass = playerDeathHeadPhysGrabObject.rb.worldCenterOfMass; if (SemiFunc.OnGroundCheck(worldCenterOfMass, num, playerDeathHeadPhysGrabObject)) { return true; } } } catch { } try { Collider[] componentsInChildren = ((Component)deathHead).GetComponentsInChildren<Collider>(); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && !val.isTrigger) { Bounds bounds = val.bounds; Vector3 center = ((Bounds)(ref bounds)).center; float num2 = ((Bounds)(ref bounds)).extents.y + num; if (SemiFunc.OnGroundCheck(center, num2, playerDeathHeadPhysGrabObject)) { return true; } } } } catch { } return false; } private int GetPendingKey(PlayerAvatar playerAvatar, PlayerDeathHead deathHead) { try { if ((Object)(object)playerAvatar != (Object)null && (Object)(object)playerAvatar.photonView != (Object)null && playerAvatar.photonView.ViewID > 0) { return playerAvatar.photonView.ViewID; } } catch { } try { PhotonView val = null; if ((Object)(object)deathHead != (Object)null) { val = ((Component)deathHead).GetComponent<PhotonView>(); } if ((Object)(object)val != (Object)null && val.ViewID > 0) { return val.ViewID; } } catch { } if ((Object)(object)playerAvatar != (Object)null) { return ((Object)playerAvatar).GetInstanceID(); } return 0; } private string GetPlayerLabel(PlayerAvatar playerAvatar) { if ((Object)(object)playerAvatar == (Object)null) { return "null"; } try { if (!string.IsNullOrEmpty(((Object)playerAvatar).name)) { return ((Object)playerAvatar).name; } } catch { } return "PlayerAvatar"; } private static PlayerDeathHead GetPlayerDeathHead(PlayerAvatar playerAvatar) { if ((Object)(object)playerAvatar == (Object)null) { return null; } if (FieldPlayerAvatarDeathHead != null) { try { object? value = FieldPlayerAvatarDeathHead.GetValue(playerAvatar); return (PlayerDeathHead)((value is PlayerDeathHead) ? value : null); } catch { } } try { return ((Component)playerAvatar).GetComponentInChildren<PlayerDeathHead>(true); } catch { return null; } } private static bool IsDeathHeadTriggered(PlayerDeathHead deathHead) { return GetBoolField(FieldPlayerDeathHeadTriggered, deathHead, defaultValue: false); } private PhysGrabObject GetPlayerDeathHeadPhysGrabObject(PlayerDeathHead deathHead) { if ((Object)(object)deathHead == (Object)null) { return null; } PhysGrabObject val = null; if (FieldPlayerDeathHeadPhysGrabObject != null) { try { object? value = FieldPlayerDeathHeadPhysGrabObject.GetValue(deathHead); val = (PhysGrabObject)((value is PhysGrabObject) ? value : null); } catch { } } if ((Object)(object)val != (Object)null) { return val; } try { val = ((Component)deathHead).GetComponent<PhysGrabObject>(); } catch { val = null; } return val; } private bool HasQueuedLevelChanged(PendingReviveEntry entry) { if (entry == null) { return true; } string currentLevelName = GetCurrentLevelName(); if (!string.IsNullOrEmpty(entry.LevelName) && !string.IsNullOrEmpty(currentLevelName) && !string.Equals(entry.LevelName, currentLevelName, StringComparison.Ordinal)) { return true; } return false; } private string GetCurrentLevelName() { try { if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null) { return ((Object)RunManager.instance.levelCurrent).name ?? string.Empty; } } catch { } return string.Empty; } private static bool GetBoolField(FieldInfo fieldInfo, object instance, bool defaultValue) { if (fieldInfo == null || instance == null) { return defaultValue; } try { object value = fieldInfo.GetValue(instance); if (value is bool) { return (bool)value; } } catch { } return defaultValue; } } [HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInHaulList")] internal static class ExtractionPoint_DestroyAllPhysObjectsInHaulList_Patch { private static void Prefix() { ExtractionAutoRevivePlugin.EnterExtractionCompleteContext("haul"); } private static Exception Finalizer(Exception __exception) { ExtractionAutoRevivePlugin.ExitExtractionCompleteContext("haul", __exception); return __exception; } } [HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInShoppingList")] internal static class ExtractionPoint_DestroyAllPhysObjectsInShoppingList_Patch { private static void Prefix() { ExtractionAutoRevivePlugin.EnterExtractionCompleteContext("shop"); } private static Exception Finalizer(Exception __exception) { ExtractionAutoRevivePlugin.ExitExtractionCompleteContext("shop", __exception); return __exception; } } [HarmonyPatch(typeof(PlayerDeathHead), "Revive")] internal static class PlayerDeathHead_Revive_Patch { private static bool Prefix() { if (ExtractionAutoRevivePlugin.IsExtractionCompleteContextActive()) { return false; } return true; } } [HarmonyPatch(typeof(RunManager), "ChangeLevel")] internal static class RunManager_ChangeLevel_Patch { private static void Prefix() { if ((Object)(object)ExtractionAutoRevivePlugin.Instance != (Object)null) { ExtractionAutoRevivePlugin.Instance.ClearPendingRevives("run manager change level"); } } } [HarmonyPatch(typeof(RunManager), "RestartScene")] internal static class RunManager_RestartScene_Patch { private static void Prefix() { if ((Object)(object)ExtractionAutoRevivePlugin.Instance != (Object)null) { ExtractionAutoRevivePlugin.Instance.ClearPendingRevives("run manager restart scene"); } } } }