From a124ace0540ba3bf153d979fa86091623a5ad6ce Mon Sep 17 00:00:00 2001 From: Arys Date: Fri, 26 Jan 2024 08:28:29 +0000 Subject: [PATCH] Fixed exception caused by BTR not being destroyed at correct time (!68) Todo: * Make BTR spawn at random time during raid instead of at start * ~~Fix BTR trader services not working for subsequent raids in Streets~~ Drakia provided me with a fix and it's included in this PR TL;DR - It's ready for testing Co-authored-by: Nympfonic Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Modules/pulls/68 Co-authored-by: Arys Co-committed-by: Arys --- project/Aki.Custom/AkiCustomPlugin.cs | 1 + project/Aki.Custom/BTR/BTRManager.cs | 48 +++++++++---------- .../BTR/Patches/BTRBaseLocalGameStopPatch.cs | 34 +++++++++++++ .../BTR/Patches/BTRBotAttachPatch.cs | 1 - project/Aki.Custom/BTR/Patches/BTRPatch.cs | 3 +- .../TraderServices/TraderServicesManager.cs | 6 +++ 6 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 project/Aki.Custom/BTR/Patches/BTRBaseLocalGameStopPatch.cs diff --git a/project/Aki.Custom/AkiCustomPlugin.cs b/project/Aki.Custom/AkiCustomPlugin.cs index f2c19de..0d16b9d 100644 --- a/project/Aki.Custom/AkiCustomPlugin.cs +++ b/project/Aki.Custom/AkiCustomPlugin.cs @@ -63,6 +63,7 @@ namespace Aki.Custom new BTRPatch().Enable(); new BTRTransferItemsPatch().Enable(); new BTREndRaidItemDeliveryPatch().Enable(); + new BTRBaseLocalGameStopPatch().Enable(); } catch (Exception ex) { diff --git a/project/Aki.Custom/BTR/BTRManager.cs b/project/Aki.Custom/BTR/BTRManager.cs index d7f25ad..e23b216 100644 --- a/project/Aki.Custom/BTR/BTRManager.cs +++ b/project/Aki.Custom/BTR/BTRManager.cs @@ -57,7 +57,7 @@ namespace Aki.Custom.BTR _updateTaxiPriceMethod = AccessTools.GetDeclaredMethods(btrControllerType).Single(IsUpdateTaxiPriceMethod); } - public void Init() + private void Awake() { try { @@ -68,19 +68,19 @@ namespace Aki.Custom.BTR return; } - if (gameWorld.BtrController == null && !Singleton.Instantiated) + if (gameWorld.BtrController == null) { - Singleton.Create(new BTRControllerClass()); + gameWorld.BtrController = new BTRControllerClass(); } - gameWorld.BtrController = btrController = Singleton.Instance; + btrController = gameWorld.BtrController; InitBtr(); } catch { ConsoleScreen.LogError("[AKI-BTR] Unable to spawn BTR. Check logs."); - DestroyGameObjects(); + Destroy(this); throw; } } @@ -462,23 +462,18 @@ namespace Aki.Custom.BTR private void OnDestroy() { - DestroyGameObjects(); - } - - private void DestroyGameObjects() - { - if (btrController != null) + if (gameWorld == null) { - if (btrServerSide != null) - { - Destroy(btrServerSide.gameObject); - } - if (btrClientSide != null) - { - Destroy(btrClientSide.gameObject); - } + return; + } - btrController.Dispose(); + StaticManager.KillCoroutine(ref _shootingTargetCoroutine); + StaticManager.KillCoroutine(ref _coverFireTimerCoroutine); + + if (TraderServicesManager.Instance != null) + { + TraderServicesManager.Instance.OnTraderServicePurchased -= BtrTraderServicePurchased; + TraderServicesManager.Instance.Clear(); } if (gameWorld.MainPlayer != null) @@ -486,14 +481,17 @@ namespace Aki.Custom.BTR gameWorld.MainPlayer.OnBtrStateChanged -= HandleBtrDoorState; } - if (TraderServicesManager.Instance != null) + if (btrClientSide != null) { - TraderServicesManager.Instance.OnTraderServicePurchased -= BtrTraderServicePurchased; + Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrClientSide"); + Destroy(btrClientSide.gameObject); } - StaticManager.KillCoroutine(ref _shootingTargetCoroutine); - StaticManager.KillCoroutine(ref _coverFireTimerCoroutine); - Destroy(this); + if (btrServerSide != null) + { + Debug.LogWarning("[AKI-BTR] BTRManager - Destroying btrServerSide"); + Destroy(btrServerSide.gameObject); + } } } } diff --git a/project/Aki.Custom/BTR/Patches/BTRBaseLocalGameStopPatch.cs b/project/Aki.Custom/BTR/Patches/BTRBaseLocalGameStopPatch.cs new file mode 100644 index 0000000..d963b51 --- /dev/null +++ b/project/Aki.Custom/BTR/Patches/BTRBaseLocalGameStopPatch.cs @@ -0,0 +1,34 @@ +using Aki.Reflection.Patching; +using Comfort.Common; +using EFT; +using HarmonyLib; +using System.Reflection; +using Object = UnityEngine.Object; + +namespace Aki.Custom.BTR.Patches +{ + public class BTRBaseLocalGameStopPatch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(BaseLocalGame), nameof(BaseLocalGame.Stop)); + } + + [PatchPrefix] + private static void PatchPrefix() + { + var gameWorld = Singleton.Instance; + if (gameWorld == null) + { + return; + } + + var btrManager = gameWorld.GetComponent(); + if (btrManager != null) + { + Logger.LogWarning("[AKI-BTR] BTRBaseLocalGameStopPatch - Raid Ended: Destroying BTRManager"); + Object.Destroy(btrManager); + } + } + } +} diff --git a/project/Aki.Custom/BTR/Patches/BTRBotAttachPatch.cs b/project/Aki.Custom/BTR/Patches/BTRBotAttachPatch.cs index d1cce20..467fab9 100644 --- a/project/Aki.Custom/BTR/Patches/BTRBotAttachPatch.cs +++ b/project/Aki.Custom/BTR/Patches/BTRBotAttachPatch.cs @@ -29,7 +29,6 @@ namespace Aki.Custom.BTR.Patches var gameWorld = Singleton.Instance; if (gameWorld == null) { - Logger.LogError("[AKI-BTR] BTRBotAttachPatch - GameWorld is null"); return false; } diff --git a/project/Aki.Custom/BTR/Patches/BTRPatch.cs b/project/Aki.Custom/BTR/Patches/BTRPatch.cs index 765939d..8a5d782 100644 --- a/project/Aki.Custom/BTR/Patches/BTRPatch.cs +++ b/project/Aki.Custom/BTR/Patches/BTRPatch.cs @@ -35,8 +35,7 @@ namespace Aki.Custom.BTR.Patches return; } - var btrManager = gameWorld.gameObject.AddComponent(); - btrManager.Init(); + gameWorld.gameObject.AddComponent(); } catch (System.Exception) { diff --git a/project/Aki.SinglePlayer/Utils/TraderServices/TraderServicesManager.cs b/project/Aki.SinglePlayer/Utils/TraderServices/TraderServicesManager.cs index 14d225b..6f49a8a 100644 --- a/project/Aki.SinglePlayer/Utils/TraderServices/TraderServicesManager.cs +++ b/project/Aki.SinglePlayer/Utils/TraderServices/TraderServicesManager.cs @@ -40,6 +40,12 @@ namespace Aki.SinglePlayer.Utils.TraderServices _servicePurchased = new Dictionary>(); } + public void Clear() + { + _servicePurchased.Clear(); + _cachedTraders.Clear(); + } + public void GetTraderServicesDataFromServer(string traderId) { Dictionary servicesData = Singleton.Instance.ServicesData;