From b03d0019517cc73ad42e48b4f42aa116ae6932fa Mon Sep 17 00:00:00 2001 From: Paulov Date: Tue, 30 Apr 2024 19:21:24 +0100 Subject: [PATCH 1/3] Refactored Player Extraction and Fixed issues with host --- .../CoopGameComponents/SITGameComponent.cs | 98 +---------- .../SITGameExtractionComponent.cs | 154 ++++++++++++++++++ .../Raid/ExtractedPlayerPacket.cs | 33 ++++ Source/Coop/SITGameModes/CoopSITGame.cs | 21 ++- Source/Coop/SITGameModes/ISITGame.cs | 2 +- .../Coop/SITGameModes/MultiplayerSITGame.cs | 1 + 6 files changed, 206 insertions(+), 103 deletions(-) create mode 100644 Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs create mode 100644 Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs diff --git a/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs b/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs index 64ad6fc3e..c6a0b12db 100644 --- a/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs +++ b/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs @@ -360,6 +360,7 @@ private void GameWorld_AfterGameStarted() this.GetOrAddComponent(); this.GetOrAddComponent(); + this.GetOrAddComponent(); StartCoroutine(SendPlayerStatePacket()); @@ -414,105 +415,8 @@ private IEnumerator EverySecondCoroutine() var coopGame = Singleton.Instance; - var playersToExtract = new HashSet(); - foreach (var exfilPlayer in coopGame.ExtractingPlayers) - { - var exfilTime = new TimeSpan(0, 0, (int)exfilPlayer.Value.Item1); - var timeInExfil = new TimeSpan(DateTime.Now.Ticks - exfilPlayer.Value.Item2); - if (timeInExfil >= exfilTime) - { - if (!playersToExtract.Contains(exfilPlayer.Key)) - { - Logger.LogDebug(exfilPlayer.Key + " should extract"); - playersToExtract.Add(exfilPlayer.Key); - } - } - else - { - Logger.LogDebug(exfilPlayer.Key + " extracting " + timeInExfil); - - } - } - - // Trigger all countdown exfils (e.g. car), clients are responsible for their own extract - // since exfilpoint.Entered is local because of collision logic being local - // we start from the end because we remove as we go in `CoopSITGame.ExfiltrationPoint_OnStatusChanged` - for (int i = coopGame.EnabledCountdownExfils.Count - 1; i >= 0; i--) - { - var ep = coopGame.EnabledCountdownExfils[i]; - if (coopGame.PastTime - ep.ExfiltrationStartTime >= ep.Settings.ExfiltrationTime) - { - var game = Singleton.Instance; - foreach (var player in ep.Entered) - { - var hasUnmetRequirements = ep.UnmetRequirements(player).Any(); - if (player != null && player.HealthController.IsAlive && !hasUnmetRequirements) - { - game.ExtractingPlayers.Remove(player.ProfileId); - game.ExtractedPlayers.Add(player.ProfileId); - } - } - ep.SetStatusLogged(ep.Reusable ? EExfiltrationStatus.UncompleteRequirements : EExfiltrationStatus.NotPresent, nameof(EverySecondCoroutine)); - } - } - - foreach (var player in playersToExtract) - { - coopGame.ExtractingPlayers.Remove(player); - coopGame.ExtractedPlayers.Add(player); - } - var world = Singleton.Instance; - // Hide extracted Players - foreach (var profileId in coopGame.ExtractedPlayers) - { - var player = world.RegisteredPlayers.Find(x => x.ProfileId == profileId) as EFT.Player; - if (player == null) - continue; - - if (!ExtractedProfilesSent.Contains(profileId)) - { - ExtractedProfilesSent.Add(profileId); - if (player.Profile.Side == EPlayerSide.Savage) - { - player.Profile.EftStats.SessionCounters.AddDouble(0.01, - [ - CounterTag.FenceStanding, - EFenceStandingSource.ExitStanding - ]); - } - AkiBackendCommunicationCoop.PostLocalPlayerData(player - , new Dictionary() { { "m", "Extraction" }, { "Extracted", true } } - ); - } - - if (player.ActiveHealthController != null) - { - if (!player.ActiveHealthController.MetabolismDisabled) - { - player.ActiveHealthController.AddDamageMultiplier(0); - player.ActiveHealthController.SetDamageCoeff(0); - player.ActiveHealthController.DisableMetabolism(); - player.ActiveHealthController.PauseAllEffects(); - - //player.SwitchRenderer(false); - - // TODO: Currently. Destroying your own Player just breaks the game and it appears to be "frozen". Need to learn a new way to do a FreeCam! - //if (Singleton.Instance.MainPlayer.ProfileId != profileId) - // Destroy(player); - } - } - //force close all screens to disallow looting open crates after extract - if (profileId == world.MainPlayer.ProfileId) - { - ScreenManager instance = ScreenManager.Instance; - instance.CloseAllScreensForced(); - } - - PlayerUtils.MakeVisible(player, false); - } - // Add players who have joined to the AI Enemy Lists var botController = (BotsController)ReflectionHelpers.GetFieldFromTypeByFieldType(typeof(BaseLocalGame), typeof(BotsController)).GetValue(Singleton.Instance); if (botController != null) diff --git a/Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs b/Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs new file mode 100644 index 000000000..b67ffd8dc --- /dev/null +++ b/Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs @@ -0,0 +1,154 @@ +using BepInEx.Logging; +using Comfort.Common; +using EFT.Counters; +using EFT; +using EFT.Interactive; +using HarmonyLib.Tools; +using StayInTarkov.Coop.Players; +using StayInTarkov.Coop.SITGameModes; +using StayInTarkov.Coop.Web; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using StayInTarkov.Networking; +using StayInTarkov.Coop.NetworkPacket.Raid; + +namespace StayInTarkov.Coop.Components.CoopGameComponents +{ + public sealed class SITGameExtractionComponent : MonoBehaviour + { + ManualLogSource Logger { get; set; } + HashSet ExtractedProfilesSent {get;set;} = new HashSet(); + + + void Awake() + { + Logger = BepInEx.Logging.Logger.CreateLogSource(nameof(SITGameExtractionComponent)); + } + + void Update() + { + if (!Singleton.Instantiated) + return; + + if (!Singleton.Instantiated) + return; + + ProcessExtractingPlayers(); + ProcessExtractionRequirements(); + HideExtractedPlayers(); + + } + + private void HideExtractedPlayers() + { + var world = Singleton.Instance; + var gameInstance = Singleton.Instance; + + // Hide extracted Players + foreach (var profileId in gameInstance.ExtractedPlayers) + { + var player = world.RegisteredPlayers.Find(x => x.ProfileId == profileId) as EFT.Player; + if (player == null) + continue; + + if (!ExtractedProfilesSent.Contains(profileId)) + { + ExtractedProfilesSent.Add(profileId); + if (player.Profile.Side == EPlayerSide.Savage) + { + player.Profile.EftStats.SessionCounters.AddDouble(0.01, + [ + CounterTag.FenceStanding, + EFenceStandingSource.ExitStanding + ]); + } + // Send the Extracted Packet to other Clients + GameClient.SendData(new ExtractedPlayerPacket(profileId).Serialize()); + } + + if (player.ActiveHealthController != null) + { + if (!player.ActiveHealthController.MetabolismDisabled) + { + player.ActiveHealthController.AddDamageMultiplier(0); + player.ActiveHealthController.SetDamageCoeff(0); + player.ActiveHealthController.DisableMetabolism(); + player.ActiveHealthController.PauseAllEffects(); + } + } + + //force close all screens to disallow looting open crates after extract + if (profileId == world.MainPlayer.ProfileId) + { + ScreenManager instance = ScreenManager.Instance; + instance.CloseAllScreensForced(); + } + + PlayerUtils.MakeVisible(player, false); + } + } + + private void ProcessExtractionRequirements() + { + var gameInstance = Singleton.Instance; + // Trigger all countdown exfils (e.g. car), clients are responsible for their own extract + // since exfilpoint.Entered is local because of collision logic being local + // we start from the end because we remove as we go in `CoopSITGame.ExfiltrationPoint_OnStatusChanged` + for (int i = gameInstance.EnabledCountdownExfils.Count - 1; i >= 0; i--) + { + var ep = gameInstance.EnabledCountdownExfils[i]; + if (gameInstance.PastTime - ep.ExfiltrationStartTime >= ep.Settings.ExfiltrationTime) + { + var game = Singleton.Instance; + foreach (var player in ep.Entered) + { + var hasUnmetRequirements = ep.UnmetRequirements(player).Any(); + if (player != null && player.HealthController.IsAlive && !hasUnmetRequirements) + { + game.ExtractingPlayers.Remove(player.ProfileId); + game.ExtractedPlayers.Add(player.ProfileId); + } + } + ep.SetStatusLogged(ep.Reusable ? EExfiltrationStatus.UncompleteRequirements : EExfiltrationStatus.NotPresent, nameof(ProcessExtractionRequirements)); + } + } + } + + private void ProcessExtractingPlayers() + { + var gameInstance = Singleton.Instance; + var playersToExtract = new HashSet(); + foreach (var exfilPlayer in gameInstance.ExtractingPlayers) + { + var exfilTime = new TimeSpan(0, 0, (int)exfilPlayer.Value.Item1); + var timeInExfil = new TimeSpan(DateTime.Now.Ticks - exfilPlayer.Value.Item2); + if (timeInExfil >= exfilTime) + { + if (!playersToExtract.Contains(exfilPlayer.Key)) + { +#if DEBUG + Logger.LogDebug(exfilPlayer.Key + " should extract"); +#endif + playersToExtract.Add(exfilPlayer.Key); + } + } +#if DEBUG + else + { + Logger.LogDebug(exfilPlayer.Key + " extracting " + timeInExfil); + } +#endif + } + + foreach (var player in playersToExtract) + { + gameInstance.ExtractingPlayers.Remove(player); + gameInstance.ExtractedPlayers.Add(player); + } + } + } +} diff --git a/Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs b/Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs new file mode 100644 index 000000000..da50d001c --- /dev/null +++ b/Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs @@ -0,0 +1,33 @@ +using Comfort.Common; +using EFT; +using StayInTarkov.Coop.NetworkPacket.Player; +using StayInTarkov.Coop.Players; +using StayInTarkov.Coop.SITGameModes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StayInTarkov.Coop.NetworkPacket.Raid +{ + public sealed class ExtractedPlayerPacket : BasePlayerPacket + { + public ExtractedPlayerPacket() : base("", nameof(ExtractedPlayerPacket)) + { + } + + public ExtractedPlayerPacket(string profileId) : base(profileId, nameof(ExtractedPlayerPacket)) + { + this.ProfileId = profileId; + } + + protected override void Process(CoopPlayerClient client) + { + StayInTarkovHelperConstants.Logger.LogDebug($"{nameof(ExtractedPlayerPacket)}:Process({client.ProfileId})"); + var gameInstance = Singleton.Instance; + if (!gameInstance.ExtractedPlayers.Contains(client.ProfileId)) + gameInstance.ExtractedPlayers.Add(client.ProfileId); + } + } +} diff --git a/Source/Coop/SITGameModes/CoopSITGame.cs b/Source/Coop/SITGameModes/CoopSITGame.cs index ecfa82943..835f6638c 100644 --- a/Source/Coop/SITGameModes/CoopSITGame.cs +++ b/Source/Coop/SITGameModes/CoopSITGame.cs @@ -41,6 +41,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using UnityEngine; @@ -209,9 +210,11 @@ InputTree inputTree return coopGame; } + void OnDestroy() { Logger.LogDebug("OnDestroy()"); + Singleton.Instance.AfterGameStarted -= Instance_AfterGameStarted; Comfort.Common.Singleton.TryRelease(this); } @@ -1180,9 +1183,6 @@ private void ExfiltrationPoint_OnCancelExtraction(ExfiltrationPoint point, EFT.P private void ExfiltrationPoint_OnStartExtraction(ExfiltrationPoint point, EFT.Player player) { - if (!player.IsYourPlayer) - return; - Logger.LogDebug($"{nameof(ExfiltrationPoint_OnStartExtraction)} {point.Settings.Name} {point.Status} {point.Settings.ExfiltrationTime}"); bool playerHasMetRequirements = !point.UnmetRequirements(player).Any(); if (!ExtractingPlayers.ContainsKey(player.ProfileId) && !ExtractedPlayers.Contains(player.ProfileId)) @@ -1191,8 +1191,12 @@ private void ExfiltrationPoint_OnStartExtraction(ExfiltrationPoint point, EFT.Pl Logger.LogDebug($"Added {player.ProfileId} to {nameof(ExtractingPlayers)}"); } - MyExitLocation = point.Settings.Name; - MyExitStatus = ExitStatus.Survived; + // Setup MyExitLocation and MyExitStatus only if this is My Player + if (player.IsYourPlayer) + { + MyExitLocation = point.Settings.Name; + MyExitStatus = ExitStatus.Survived; + } } private void ExfiltrationPoint_OnStatusChanged(ExfiltrationPoint point, EExfiltrationStatus prevStatus) @@ -1429,6 +1433,7 @@ private IEnumerator DisposingCo() public BossLocationSpawn[] BossWaves { get; private set; } public int ReadyPlayers { get; set; } public bool HostReady { get; set; } + public bool GameWorldStarted { get; set; } private NonWavesSpawnScenario nonWavesSpawnScenario_0; @@ -1445,6 +1450,7 @@ public async Task Run(BotControllerSettings botsSettings, string backendUrl, Inv { Logger.LogDebug(nameof(Run)); + Singleton.Instance.AfterGameStarted += Instance_AfterGameStarted; base.Status = GameStatus.Running; UnityEngine.Random.InitState((int)DateTime.UtcNow.Ticks); LocationSettingsClass.Location location; @@ -1483,6 +1489,11 @@ public async Task Run(BotControllerSettings botsSettings, string backendUrl, Inv method_5(botsSettings, SpawnSystem, runCallback); } + private void Instance_AfterGameStarted() + { + GameWorldStarted = true; + } + class PlayerLoopSystemType { public PlayerLoopSystemType() diff --git a/Source/Coop/SITGameModes/ISITGame.cs b/Source/Coop/SITGameModes/ISITGame.cs index 2f416d676..94e0fc27f 100644 --- a/Source/Coop/SITGameModes/ISITGame.cs +++ b/Source/Coop/SITGameModes/ISITGame.cs @@ -43,7 +43,7 @@ public interface ISITGame public Task Run(BotControllerSettings botsSettings, string backendUrl, InventoryControllerClass inventoryController, Callback runCallback); - + public bool GameWorldStarted { get; set; } //Task WaitForPlayersToSpawn(); //Task WaitForPlayersToBeReady(); diff --git a/Source/Coop/SITGameModes/MultiplayerSITGame.cs b/Source/Coop/SITGameModes/MultiplayerSITGame.cs index 63f6591bc..1aa68ef1a 100644 --- a/Source/Coop/SITGameModes/MultiplayerSITGame.cs +++ b/Source/Coop/SITGameModes/MultiplayerSITGame.cs @@ -41,6 +41,7 @@ public sealed class MultiplayerSITGame : BaseLocalGame, IBotGam public int ReadyPlayers { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public bool HostReady { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public bool GameWorldStarted { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public Task Run(BotControllerSettings botsSettings, string backendUrl, InventoryControllerClass inventoryController, Callback runCallback) { From 2f2c473ad3871bc441bb94db7e71093486a255fc Mon Sep 17 00:00:00 2001 From: Paulov Date: Tue, 30 Apr 2024 19:21:24 +0100 Subject: [PATCH 2/3] Refactored Player Extraction and Fixed issues with host --- .../CoopGameComponents/SITGameComponent.cs | 98 +---------- .../SITGameExtractionComponent.cs | 154 ++++++++++++++++++ .../Raid/ExtractedPlayerPacket.cs | 33 ++++ Source/Coop/SITGameModes/CoopSITGame.cs | 21 ++- Source/Coop/SITGameModes/ISITGame.cs | 2 +- .../Coop/SITGameModes/MultiplayerSITGame.cs | 1 + 6 files changed, 206 insertions(+), 103 deletions(-) create mode 100644 Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs create mode 100644 Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs diff --git a/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs b/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs index 8673754ba..d56fffd84 100644 --- a/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs +++ b/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs @@ -356,6 +356,7 @@ private void GameWorld_AfterGameStarted() this.GetOrAddComponent(); this.GetOrAddComponent(); + this.GetOrAddComponent(); StartCoroutine(SendPlayerStatePacket()); @@ -410,105 +411,8 @@ private IEnumerator EverySecondCoroutine() var coopGame = Singleton.Instance; - var playersToExtract = new HashSet(); - foreach (var exfilPlayer in coopGame.ExtractingPlayers) - { - var exfilTime = new TimeSpan(0, 0, (int)exfilPlayer.Value.Item1); - var timeInExfil = new TimeSpan(DateTime.Now.Ticks - exfilPlayer.Value.Item2); - if (timeInExfil >= exfilTime) - { - if (!playersToExtract.Contains(exfilPlayer.Key)) - { - Logger.LogDebug(exfilPlayer.Key + " should extract"); - playersToExtract.Add(exfilPlayer.Key); - } - } - else - { - Logger.LogDebug(exfilPlayer.Key + " extracting " + timeInExfil); - - } - } - - // Trigger all countdown exfils (e.g. car), clients are responsible for their own extract - // since exfilpoint.Entered is local because of collision logic being local - // we start from the end because we remove as we go in `CoopSITGame.ExfiltrationPoint_OnStatusChanged` - for (int i = coopGame.EnabledCountdownExfils.Count - 1; i >= 0; i--) - { - var ep = coopGame.EnabledCountdownExfils[i]; - if (coopGame.PastTime - ep.ExfiltrationStartTime >= ep.Settings.ExfiltrationTime) - { - var game = Singleton.Instance; - foreach (var player in ep.Entered) - { - var hasUnmetRequirements = ep.UnmetRequirements(player).Any(); - if (player != null && player.HealthController.IsAlive && !hasUnmetRequirements) - { - game.ExtractingPlayers.Remove(player.ProfileId); - game.ExtractedPlayers.Add(player.ProfileId); - } - } - ep.SetStatusLogged(ep.Reusable ? EExfiltrationStatus.UncompleteRequirements : EExfiltrationStatus.NotPresent, nameof(EverySecondCoroutine)); - } - } - - foreach (var player in playersToExtract) - { - coopGame.ExtractingPlayers.Remove(player); - coopGame.ExtractedPlayers.Add(player); - } - var world = Singleton.Instance; - // Hide extracted Players - foreach (var profileId in coopGame.ExtractedPlayers) - { - var player = world.RegisteredPlayers.Find(x => x.ProfileId == profileId) as EFT.Player; - if (player == null) - continue; - - if (!ExtractedProfilesSent.Contains(profileId)) - { - ExtractedProfilesSent.Add(profileId); - if (player.Profile.Side == EPlayerSide.Savage) - { - player.Profile.EftStats.SessionCounters.AddDouble(0.01, - [ - CounterTag.FenceStanding, - EFenceStandingSource.ExitStanding - ]); - } - AkiBackendCommunicationCoop.PostLocalPlayerData(player - , new Dictionary() { { "m", "Extraction" }, { "Extracted", true } } - ); - } - - if (player.ActiveHealthController != null) - { - if (!player.ActiveHealthController.MetabolismDisabled) - { - player.ActiveHealthController.AddDamageMultiplier(0); - player.ActiveHealthController.SetDamageCoeff(0); - player.ActiveHealthController.DisableMetabolism(); - player.ActiveHealthController.PauseAllEffects(); - - //player.SwitchRenderer(false); - - // TODO: Currently. Destroying your own Player just breaks the game and it appears to be "frozen". Need to learn a new way to do a FreeCam! - //if (Singleton.Instance.MainPlayer.ProfileId != profileId) - // Destroy(player); - } - } - //force close all screens to disallow looting open crates after extract - if (profileId == world.MainPlayer.ProfileId) - { - ScreenManager instance = ScreenManager.Instance; - instance.CloseAllScreensForced(); - } - - PlayerUtils.MakeVisible(player, false); - } - // Add players who have joined to the AI Enemy Lists var botController = (BotsController)ReflectionHelpers.GetFieldFromTypeByFieldType(typeof(BaseLocalGame), typeof(BotsController)).GetValue(Singleton.Instance); if (botController != null) diff --git a/Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs b/Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs new file mode 100644 index 000000000..b67ffd8dc --- /dev/null +++ b/Source/Coop/Components/CoopGameComponents/SITGameExtractionComponent.cs @@ -0,0 +1,154 @@ +using BepInEx.Logging; +using Comfort.Common; +using EFT.Counters; +using EFT; +using EFT.Interactive; +using HarmonyLib.Tools; +using StayInTarkov.Coop.Players; +using StayInTarkov.Coop.SITGameModes; +using StayInTarkov.Coop.Web; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using StayInTarkov.Networking; +using StayInTarkov.Coop.NetworkPacket.Raid; + +namespace StayInTarkov.Coop.Components.CoopGameComponents +{ + public sealed class SITGameExtractionComponent : MonoBehaviour + { + ManualLogSource Logger { get; set; } + HashSet ExtractedProfilesSent {get;set;} = new HashSet(); + + + void Awake() + { + Logger = BepInEx.Logging.Logger.CreateLogSource(nameof(SITGameExtractionComponent)); + } + + void Update() + { + if (!Singleton.Instantiated) + return; + + if (!Singleton.Instantiated) + return; + + ProcessExtractingPlayers(); + ProcessExtractionRequirements(); + HideExtractedPlayers(); + + } + + private void HideExtractedPlayers() + { + var world = Singleton.Instance; + var gameInstance = Singleton.Instance; + + // Hide extracted Players + foreach (var profileId in gameInstance.ExtractedPlayers) + { + var player = world.RegisteredPlayers.Find(x => x.ProfileId == profileId) as EFT.Player; + if (player == null) + continue; + + if (!ExtractedProfilesSent.Contains(profileId)) + { + ExtractedProfilesSent.Add(profileId); + if (player.Profile.Side == EPlayerSide.Savage) + { + player.Profile.EftStats.SessionCounters.AddDouble(0.01, + [ + CounterTag.FenceStanding, + EFenceStandingSource.ExitStanding + ]); + } + // Send the Extracted Packet to other Clients + GameClient.SendData(new ExtractedPlayerPacket(profileId).Serialize()); + } + + if (player.ActiveHealthController != null) + { + if (!player.ActiveHealthController.MetabolismDisabled) + { + player.ActiveHealthController.AddDamageMultiplier(0); + player.ActiveHealthController.SetDamageCoeff(0); + player.ActiveHealthController.DisableMetabolism(); + player.ActiveHealthController.PauseAllEffects(); + } + } + + //force close all screens to disallow looting open crates after extract + if (profileId == world.MainPlayer.ProfileId) + { + ScreenManager instance = ScreenManager.Instance; + instance.CloseAllScreensForced(); + } + + PlayerUtils.MakeVisible(player, false); + } + } + + private void ProcessExtractionRequirements() + { + var gameInstance = Singleton.Instance; + // Trigger all countdown exfils (e.g. car), clients are responsible for their own extract + // since exfilpoint.Entered is local because of collision logic being local + // we start from the end because we remove as we go in `CoopSITGame.ExfiltrationPoint_OnStatusChanged` + for (int i = gameInstance.EnabledCountdownExfils.Count - 1; i >= 0; i--) + { + var ep = gameInstance.EnabledCountdownExfils[i]; + if (gameInstance.PastTime - ep.ExfiltrationStartTime >= ep.Settings.ExfiltrationTime) + { + var game = Singleton.Instance; + foreach (var player in ep.Entered) + { + var hasUnmetRequirements = ep.UnmetRequirements(player).Any(); + if (player != null && player.HealthController.IsAlive && !hasUnmetRequirements) + { + game.ExtractingPlayers.Remove(player.ProfileId); + game.ExtractedPlayers.Add(player.ProfileId); + } + } + ep.SetStatusLogged(ep.Reusable ? EExfiltrationStatus.UncompleteRequirements : EExfiltrationStatus.NotPresent, nameof(ProcessExtractionRequirements)); + } + } + } + + private void ProcessExtractingPlayers() + { + var gameInstance = Singleton.Instance; + var playersToExtract = new HashSet(); + foreach (var exfilPlayer in gameInstance.ExtractingPlayers) + { + var exfilTime = new TimeSpan(0, 0, (int)exfilPlayer.Value.Item1); + var timeInExfil = new TimeSpan(DateTime.Now.Ticks - exfilPlayer.Value.Item2); + if (timeInExfil >= exfilTime) + { + if (!playersToExtract.Contains(exfilPlayer.Key)) + { +#if DEBUG + Logger.LogDebug(exfilPlayer.Key + " should extract"); +#endif + playersToExtract.Add(exfilPlayer.Key); + } + } +#if DEBUG + else + { + Logger.LogDebug(exfilPlayer.Key + " extracting " + timeInExfil); + } +#endif + } + + foreach (var player in playersToExtract) + { + gameInstance.ExtractingPlayers.Remove(player); + gameInstance.ExtractedPlayers.Add(player); + } + } + } +} diff --git a/Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs b/Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs new file mode 100644 index 000000000..da50d001c --- /dev/null +++ b/Source/Coop/NetworkPacket/Raid/ExtractedPlayerPacket.cs @@ -0,0 +1,33 @@ +using Comfort.Common; +using EFT; +using StayInTarkov.Coop.NetworkPacket.Player; +using StayInTarkov.Coop.Players; +using StayInTarkov.Coop.SITGameModes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StayInTarkov.Coop.NetworkPacket.Raid +{ + public sealed class ExtractedPlayerPacket : BasePlayerPacket + { + public ExtractedPlayerPacket() : base("", nameof(ExtractedPlayerPacket)) + { + } + + public ExtractedPlayerPacket(string profileId) : base(profileId, nameof(ExtractedPlayerPacket)) + { + this.ProfileId = profileId; + } + + protected override void Process(CoopPlayerClient client) + { + StayInTarkovHelperConstants.Logger.LogDebug($"{nameof(ExtractedPlayerPacket)}:Process({client.ProfileId})"); + var gameInstance = Singleton.Instance; + if (!gameInstance.ExtractedPlayers.Contains(client.ProfileId)) + gameInstance.ExtractedPlayers.Add(client.ProfileId); + } + } +} diff --git a/Source/Coop/SITGameModes/CoopSITGame.cs b/Source/Coop/SITGameModes/CoopSITGame.cs index cbf57c78d..51b46e2d9 100644 --- a/Source/Coop/SITGameModes/CoopSITGame.cs +++ b/Source/Coop/SITGameModes/CoopSITGame.cs @@ -41,6 +41,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Security.Permissions; using System.Text; using System.Threading.Tasks; using UnityEngine; @@ -209,9 +210,11 @@ InputTree inputTree return coopGame; } + void OnDestroy() { Logger.LogDebug("OnDestroy()"); + Singleton.Instance.AfterGameStarted -= Instance_AfterGameStarted; Comfort.Common.Singleton.TryRelease(this); } @@ -1193,9 +1196,6 @@ private void ExfiltrationPoint_OnCancelExtraction(ExfiltrationPoint point, EFT.P private void ExfiltrationPoint_OnStartExtraction(ExfiltrationPoint point, EFT.Player player) { - if (!player.IsYourPlayer) - return; - Logger.LogDebug($"{nameof(ExfiltrationPoint_OnStartExtraction)} {point.Settings.Name} {point.Status} {point.Settings.ExfiltrationTime}"); bool playerHasMetRequirements = !point.UnmetRequirements(player).Any(); if (!ExtractingPlayers.ContainsKey(player.ProfileId) && !ExtractedPlayers.Contains(player.ProfileId)) @@ -1204,8 +1204,12 @@ private void ExfiltrationPoint_OnStartExtraction(ExfiltrationPoint point, EFT.Pl Logger.LogDebug($"Added {player.ProfileId} to {nameof(ExtractingPlayers)}"); } - MyExitLocation = point.Settings.Name; - MyExitStatus = ExitStatus.Survived; + // Setup MyExitLocation and MyExitStatus only if this is My Player + if (player.IsYourPlayer) + { + MyExitLocation = point.Settings.Name; + MyExitStatus = ExitStatus.Survived; + } } private void ExfiltrationPoint_OnStatusChanged(ExfiltrationPoint point, EExfiltrationStatus prevStatus) @@ -1446,6 +1450,7 @@ private IEnumerator DisposingCo() public BossLocationSpawn[] BossWaves { get; private set; } public int ReadyPlayers { get; set; } public bool HostReady { get; set; } + public bool GameWorldStarted { get; set; } private NonWavesSpawnScenario nonWavesSpawnScenario_0; @@ -1462,6 +1467,7 @@ public async Task Run(BotControllerSettings botsSettings, string backendUrl, Inv { Logger.LogDebug(nameof(Run)); + Singleton.Instance.AfterGameStarted += Instance_AfterGameStarted; base.Status = GameStatus.Running; UnityEngine.Random.InitState((int)DateTime.UtcNow.Ticks); LocationSettingsClass.Location location; @@ -1500,6 +1506,11 @@ public async Task Run(BotControllerSettings botsSettings, string backendUrl, Inv method_5(botsSettings, SpawnSystem, runCallback); } + private void Instance_AfterGameStarted() + { + GameWorldStarted = true; + } + class PlayerLoopSystemType { public PlayerLoopSystemType() diff --git a/Source/Coop/SITGameModes/ISITGame.cs b/Source/Coop/SITGameModes/ISITGame.cs index 2f416d676..94e0fc27f 100644 --- a/Source/Coop/SITGameModes/ISITGame.cs +++ b/Source/Coop/SITGameModes/ISITGame.cs @@ -43,7 +43,7 @@ public interface ISITGame public Task Run(BotControllerSettings botsSettings, string backendUrl, InventoryControllerClass inventoryController, Callback runCallback); - + public bool GameWorldStarted { get; set; } //Task WaitForPlayersToSpawn(); //Task WaitForPlayersToBeReady(); diff --git a/Source/Coop/SITGameModes/MultiplayerSITGame.cs b/Source/Coop/SITGameModes/MultiplayerSITGame.cs index 63f6591bc..1aa68ef1a 100644 --- a/Source/Coop/SITGameModes/MultiplayerSITGame.cs +++ b/Source/Coop/SITGameModes/MultiplayerSITGame.cs @@ -41,6 +41,7 @@ public sealed class MultiplayerSITGame : BaseLocalGame, IBotGam public int ReadyPlayers { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public bool HostReady { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public bool GameWorldStarted { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } public Task Run(BotControllerSettings botsSettings, string backendUrl, InventoryControllerClass inventoryController, Callback runCallback) { From dad9f867b25d54edb44968c5f67dc9fee4ca50d8 Mon Sep 17 00:00:00 2001 From: Paulov Date: Wed, 1 May 2024 08:10:27 +0100 Subject: [PATCH 3/3] Remove unused fields/properties --- .../Coop/Components/CoopGameComponents/SITGameComponent.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs b/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs index d56fffd84..5c5b5dd7d 100644 --- a/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs +++ b/Source/Coop/Components/CoopGameComponents/SITGameComponent.cs @@ -456,8 +456,6 @@ private void ProcessOtherModsSpawnedPlayers() } } - private HashSet ExtractedProfilesSent = new(); - void OnDestroy() { StayInTarkovHelperConstants.Logger.LogDebug($"CoopGameComponent:OnDestroy"); @@ -475,9 +473,6 @@ void OnDestroy() Instance = null; } - TimeSpan LateUpdateSpan = TimeSpan.Zero; - Stopwatch swActionPackets { get; } = new Stopwatch(); - bool PerformanceCheck_ActionPackets { get; set; } = false; public bool RequestQuitGame { get; set; } int ForceQuitGamePressed = 0;