From 81b1ea8c89d6c8440d958780dbe63f9b9ac0b3a0 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:55:16 +0200 Subject: [PATCH 01/23] Initial changes for transit support --- Fika.Core/Coop/Components/CoopHandler.cs | 46 ++++++++++++------- .../Coop/Custom/FikaTransitController.cs | 45 ++++++++++++++++++ Fika.Core/Coop/GameMode/CoopGame.cs | 34 +++++++++++--- Fika.Core/Coop/Utils/FikaBackendUtils.cs | 1 + Fika.Core/Coop/Utils/NetManagerUtils.cs | 11 +++++ 5 files changed, 114 insertions(+), 23 deletions(-) create mode 100644 Fika.Core/Coop/Custom/FikaTransitController.cs diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index 507e06b3..45c58049 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -43,22 +43,7 @@ public CoopPlayer MyPlayer private bool ready; private bool isClient; private float charSyncCounter; - private bool requestQuitGame = false; - - public class SpawnObject(Profile profile, Vector3 position, bool isAlive, bool isAI, int netId, MongoID currentId, ushort firstOperationId) - { - public Profile Profile = profile; - public Vector3 Position = position; - public bool IsAlive = isAlive; - public bool IsAI = isAI; - public int NetId = netId; - public MongoID CurrentId = currentId; - public ushort FirstOperationId = firstOperationId; - public EHandsControllerType ControllerType; - public string ItemId; - public bool IsStationary; - public byte[] HealthBytes; - } + private bool requestQuitGame = false; #endregion public static bool TryGetCoopHandler(out CoopHandler coopHandler) @@ -85,6 +70,18 @@ public static string GetServerId() return FikaBackendUtils.GroupId; } + public void CleanUpForTransit() + { + Players.Clear(); + HumanPlayers.Clear(); + AmountOfHumans = 1; + ExtractedPlayers.Clear(); + queuedProfileIds.Clear(); + spawnQueue.Clear(); + ready = false; + LocalGameInstance = null; + } + protected void Awake() { Logger = BepInEx.Logging.Logger.CreateLogSource("CoopHandler"); @@ -126,7 +123,7 @@ protected private void Update() if (isClient) { charSyncCounter += Time.deltaTime; - int waitTime = LocalGameInstance.Status == GameStatus.Started ? 15 : 2; + int waitTime = LocalGameInstance.Status == GameStatus.Started ? 15 : 5; if (charSyncCounter > waitTime) { @@ -533,5 +530,20 @@ public enum EQuitState Dead, Extracted } + + public class SpawnObject(Profile profile, Vector3 position, bool isAlive, bool isAI, int netId, MongoID currentId, ushort firstOperationId) + { + public Profile Profile = profile; + public Vector3 Position = position; + public bool IsAlive = isAlive; + public bool IsAI = isAI; + public int NetId = netId; + public MongoID CurrentId = currentId; + public ushort FirstOperationId = firstOperationId; + public EHandsControllerType ControllerType; + public string ItemId; + public bool IsStationary; + public byte[] HealthBytes; + } } } \ No newline at end of file diff --git a/Fika.Core/Coop/Custom/FikaTransitController.cs b/Fika.Core/Coop/Custom/FikaTransitController.cs new file mode 100644 index 00000000..67ef4a90 --- /dev/null +++ b/Fika.Core/Coop/Custom/FikaTransitController.cs @@ -0,0 +1,45 @@ +using Comfort.Common; +using EFT; +using EFT.Interactive; +using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.Players; +using System.Collections.Generic; + +namespace Fika.Core.Coop.Custom +{ + public class FikaTransitController(BackendConfigSettingsClass.GClass1505 settings, LocationSettingsClass.Location.TransitParameters[] parameters, Profile profile, LocalRaidSettings localRaidSettings) + : GClass1617(settings, parameters, profile, localRaidSettings) + { + LocalRaidSettings localRaidSettings = localRaidSettings; + + public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) + { + string location = point.parameters.location; + ERaidMode eraidMode = ERaidMode.Local; + if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) + { + eraidMode = ERaidMode.Local; + tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); + } + string profileId = player.ProfileId; + GClass1883 gclass = new() + { + hash = hash, + playersCount = playersCount, + ip = "", + location = location, + profiles = keys, + transitionRaidId = summonedTransits[profileId].raidId, + raidMode = eraidMode, + side = player.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, + dayTime = localRaidSettings.timeVariant + }; + alreadyTransits.Add(profileId, gclass); + if (Singleton.Instance is CoopGame coopGame) + { + coopGame.Extract((CoopPlayer)player, null); + //coopGame.Stop(profileId, ExitStatus.Transit, point.parameters.name, 0f); + } + } + } +} diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index b89d5921..8ec7f91a 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -1801,9 +1801,10 @@ public void UpdateExfilPointFromServer(ExfiltrationPoint point, bool enable) /// When the local player successfully extracts, enable freecam, notify other players about the extract /// /// The local player to start the Coroutine on - /// The point that was used to extract + /// The exfiltration point that was used to extract + /// The transit point that was used to transit /// - public void Extract(CoopPlayer player, ExfiltrationPoint point) + public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, TransitPoint transitPoint = null) { PreloaderUI preloaderUI = Singleton.Instance; localTriggerZones = new(player.TriggerZones); @@ -1829,13 +1830,13 @@ public void Extract(CoopPlayer player, ExfiltrationPoint point) MyExitStatus = ExitStatus.Runner; } - if (point != null) + if (exfiltrationPoint != null) { - point.Disable(); + exfiltrationPoint.Disable(); - if (point.HasRequirements && point.TransferItemRequirement != null) + if (exfiltrationPoint.HasRequirements && exfiltrationPoint.TransferItemRequirement != null) { - if (point.TransferItemRequirement.Met(player, point) && player.IsYourPlayer) + if (exfiltrationPoint.TransferItemRequirement.Met(player, exfiltrationPoint) && player.IsYourPlayer) { // Seems to already be handled by SPT so we only add it visibly player.Profile.EftStats.SessionCounters.AddDouble(0.2, [CounterTag.FenceStanding, EFenceStandingSource.ExitStanding]); @@ -1849,6 +1850,17 @@ public void Extract(CoopPlayer player, ExfiltrationPoint point) player.Profile.EftStats.SessionCounters.AddDouble(0.01, [CounterTag.FenceStanding, EFenceStandingSource.ExitStanding]); } + FikaTransitController transitController = (FikaTransitController)Singleton.Instance.TransitController; + if (transitController != null) + { + if (transitController.alreadyTransits.TryGetValue(player.ProfileId, out GClass1883 data)) + { + MyExitStatus = ExitStatus.Transit; + MyExitLocation = transitPoint.parameters.name; + FikaBackendUtils.IsTransit = true; + } + } + GenericPacket genericPacket = new() { NetId = player.NetId, @@ -1993,6 +2005,11 @@ private async void HealthController_DiedEvent(EDamageType damageType) /// public override void Stop(string profileId, ExitStatus exitStatus, string exitName, float delay = 0f) { + if (exitStatus < ExitStatus.Transit) + { + FikaBackendUtils.IsTransit = false; + } + NetworkTimeSync.Reset(); Logger.LogDebug("Stop"); @@ -2203,6 +2220,11 @@ public Dictionary GetOwnBTRTransfers(string profileId) /// public void StopFromCancel(string profileId, ExitStatus exitStatus) { + if (exitStatus < ExitStatus.Transit) + { + FikaBackendUtils.IsTransit = false; + } + Logger.LogWarning("Game init was cancelled!"); CoopPlayer myPlayer = (CoopPlayer)Singleton.Instance.MainPlayer; diff --git a/Fika.Core/Coop/Utils/FikaBackendUtils.cs b/Fika.Core/Coop/Utils/FikaBackendUtils.cs index 862bcad3..0476dc71 100644 --- a/Fika.Core/Coop/Utils/FikaBackendUtils.cs +++ b/Fika.Core/Coop/Utils/FikaBackendUtils.cs @@ -27,6 +27,7 @@ public static class FikaBackendUtils public static bool IsDedicated = false; public static bool IsReconnect = false; public static bool IsDedicatedGame = false; + public static bool IsTransit = false; public static PlayersRaidReadyPanel PlayersRaidReadyPanel; public static MatchMakerGroupPreview MatchMakerGroupPreview; public static int HostExpectedNumberOfPlayers = 1; diff --git a/Fika.Core/Coop/Utils/NetManagerUtils.cs b/Fika.Core/Coop/Utils/NetManagerUtils.cs index 4fbf435b..726ac24c 100644 --- a/Fika.Core/Coop/Utils/NetManagerUtils.cs +++ b/Fika.Core/Coop/Utils/NetManagerUtils.cs @@ -60,6 +60,12 @@ public static void CreatePingingClient() public static void DestroyNetManager(bool isServer) { + if (FikaBackendUtils.IsTransit) + { + Singleton.Instance.CoopHandler.CleanUpForTransit(); + return; + } + if (FikaGameObject != null) { if (isServer) @@ -187,6 +193,11 @@ public static void StopPinger() public static Task CreateCoopHandler() { + if (FikaBackendUtils.IsTransit) + { + return Task.CompletedTask; + } + logger.LogInfo("Creating CoopHandler..."); IFikaNetworkManager networkManager = Singleton.Instance; if (networkManager != null) From 48c0a43f063ed4a03cbe2d29a728182f1335bb9f Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:56:45 +0200 Subject: [PATCH 02/23] Pass transit point to extract method --- Fika.Core/Coop/Custom/FikaTransitController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fika.Core/Coop/Custom/FikaTransitController.cs b/Fika.Core/Coop/Custom/FikaTransitController.cs index 67ef4a90..44b919c0 100644 --- a/Fika.Core/Coop/Custom/FikaTransitController.cs +++ b/Fika.Core/Coop/Custom/FikaTransitController.cs @@ -37,7 +37,7 @@ public override void Transit(TransitPoint point, int playersCount, string hash, alreadyTransits.Add(profileId, gclass); if (Singleton.Instance is CoopGame coopGame) { - coopGame.Extract((CoopPlayer)player, null); + coopGame.Extract((CoopPlayer)player, null, point); //coopGame.Stop(profileId, ExitStatus.Transit, point.parameters.name, 0f); } } From 569b99920ca38819a70210d6e19f29d6c9113da6 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sun, 6 Oct 2024 22:57:32 +0200 Subject: [PATCH 03/23] Revert char sync --- Fika.Core/Coop/Components/CoopHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index 45c58049..ebd2a553 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -123,7 +123,7 @@ protected private void Update() if (isClient) { charSyncCounter += Time.deltaTime; - int waitTime = LocalGameInstance.Status == GameStatus.Started ? 15 : 5; + int waitTime = LocalGameInstance.Status == GameStatus.Started ? 15 : 2; if (charSyncCounter > waitTime) { From db8813b01ddbcf257bf289add7702d1039ebd8fd Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sun, 6 Oct 2024 23:06:25 +0200 Subject: [PATCH 04/23] Re-init transit controller --- Fika.Core/Coop/GameMode/CoopGame.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 8ec7f91a..d47cb02a 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -1515,7 +1515,7 @@ public override async Task vmethod_1(BotControllerSettings controllerSettings, I gameWorld.BtrController = new BTRControllerClass(gameWorld); } - /*bool transitActive; + bool transitActive; if (instance == null) { transitActive = false; @@ -1527,15 +1527,13 @@ public override async Task vmethod_1(BotControllerSettings controllerSettings, I } if (transitActive) { - Singleton.Instance.TransitController = new GClass1617(instance.transitSettings, Location_0.transitParameters, + Singleton.Instance.TransitController = new FikaTransitController(instance.transitSettings, Location_0.transitParameters, Profile_0, localRaidSettings_0); } else { GClass1615.DisableTransitPoints(); - }*/ - - GClass1615.DisableTransitPoints(); + } if (WeatherController.Instance != null) { From ddb1cfcc58e4754348cbca04bff262ebaada9093 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 07:38:45 +0200 Subject: [PATCH 05/23] Update transit parameters --- Fika.Core/Coop/GameMode/CoopGame.cs | 2 +- .../LocalGame/TarkovApplication_LocalGameCreator_Patch.cs | 4 +++- Fika.Core/Networking/FikaClient.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index d47cb02a..422df2af 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -1523,7 +1523,7 @@ public override async Task vmethod_1(BotControllerSettings controllerSettings, I else { BackendConfigSettingsClass.GClass1505 transitSettings = instance.transitSettings; - transitActive = (transitSettings != null) && transitSettings.active; + transitActive = transitSettings != null && transitSettings.active; } if (transitActive) { diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs index 81259e12..e373a906 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs @@ -88,7 +88,8 @@ public static async Task CreateFikaGame(TarkovApplication instance, TimeAndWeath location = raidSettings.LocationId, timeVariant = raidSettings.SelectedDateTime, mode = ELocalMode.PVE_OFFLINE, - playerSide = raidSettings.Side + playerSide = raidSettings.Side, + isLocationTransition = raidSettings.isLocationTransition }; Traverse applicationTraverse = Traverse.Create(instance); applicationTraverse.Field("localRaidSettings_0").Value = localRaidSettings; @@ -96,6 +97,7 @@ public static async Task CreateFikaGame(TarkovApplication instance, TimeAndWeath LocalSettings localSettings = await instance.Session.LocalRaidStarted(localRaidSettings); applicationTraverse.Field("localRaidSettings_0").Value.serverId = localSettings.serverId; applicationTraverse.Field("localRaidSettings_0").Value.selectedLocation = localSettings.locationLoot; + applicationTraverse.Field("localRaidSettings_0").Value.transition = localSettings.transitionSettings; GClass1284 profileInsurance = localSettings.profileInsurance; if ((profileInsurance?.insuredItems) != null) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 29d4c83f..af68998e 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -252,7 +252,7 @@ private void OnResyncInventoryIdPacketReceived(ResyncInventoryIdPacket packet) { ResyncInventoryIdPacket response = new(playerToApply.NetId) { - MongoId = playerToApply.InventoryController.CurrentId.ToString() + MongoId = playerToApply.InventoryController.CurrentId }; SendData(ref response, DeliveryMethod.ReliableOrdered); } From 50af5b44e0708fc4c22d941d1a5ecd660a62129b Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 07:57:25 +0200 Subject: [PATCH 06/23] Update resync packet --- Fika.Core/Networking/FikaClient.cs | 2 +- Fika.Core/Networking/FikaServer.cs | 2 +- .../Packets/Communication/ResyncInventoryIdPacket.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index af68998e..c8f2d854 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -243,7 +243,7 @@ private void OnResyncInventoryIdPacketReceived(ResyncInventoryIdPacket packet) { if (observedPlayer.InventoryController is ObservedInventoryController observedController) { - observedController.SetNewID(packet.MongoId); + observedController.SetNewID(packet.MongoId.Value); } return; } diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 3ad0aa7d..d2efe6fc 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -405,7 +405,7 @@ private void OnResyncInventoryIdPacketReceived(ResyncInventoryIdPacket packet, N SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered, peer); if (observedPlayer.InventoryController is ObservedInventoryController observedController) { - observedController.SetNewID(packet.MongoId); + observedController.SetNewID(packet.MongoId.Value); } } } diff --git a/Fika.Core/Networking/Packets/Communication/ResyncInventoryIdPacket.cs b/Fika.Core/Networking/Packets/Communication/ResyncInventoryIdPacket.cs index 9e272db9..6afe7b6b 100644 --- a/Fika.Core/Networking/Packets/Communication/ResyncInventoryIdPacket.cs +++ b/Fika.Core/Networking/Packets/Communication/ResyncInventoryIdPacket.cs @@ -6,12 +6,12 @@ namespace Fika.Core.Networking public struct ResyncInventoryIdPacket(int netId) : INetSerializable { public int NetId = netId; - public MongoID MongoId = string.Empty; + public MongoID? MongoId; public void Deserialize(NetDataReader reader) { NetId = reader.GetInt(); - MongoId = reader.GetMongoID().Value; + MongoId = reader.GetMongoID(); } public void Serialize(NetDataWriter writer) From 234b884650c22eb77ce5a708c94368bde43a5dd3 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:10:27 +0200 Subject: [PATCH 07/23] Working transit system (I hate this game) --- .../Coop/ClientClasses/CoopClientGameWorld.cs | 1 - .../FikaClientTransitController.cs | 107 +++++++ Fika.Core/Coop/Components/CoopHandler.cs | 23 +- .../Coop/Custom/FikaTransitController.cs | 45 --- Fika.Core/Coop/GameMode/CoopGame.cs | 106 +++++-- .../Coop/HostClasses/CoopHostGameWorld.cs | 1 - .../HostClasses/FikaHostTransitController.cs | 275 ++++++++++++++++++ ...rkovApplication_LocalGamePreparer_Patch.cs | 21 +- Fika.Core/Coop/Players/CoopPlayer.cs | 24 ++ Fika.Core/Coop/Players/ObservedCoopPlayer.cs | 6 + Fika.Core/Coop/Utils/FikaGlobals.cs | 5 +- Fika.Core/Coop/Utils/NetManagerUtils.cs | 14 + Fika.Core/Networking/FikaClient.cs | 51 +++- .../Networking/FikaSerializationExtensions.cs | 2 - Fika.Core/Networking/FikaServer.cs | 43 ++- .../Communication/TransitEventPacket.cs | 194 ++++++++++++ .../Communication/TransitInteractPacket.cs | 31 ++ .../GameWorld/SyncTransitControllersPacket.cs | 28 ++ 18 files changed, 879 insertions(+), 98 deletions(-) create mode 100644 Fika.Core/Coop/ClientClasses/FikaClientTransitController.cs delete mode 100644 Fika.Core/Coop/Custom/FikaTransitController.cs create mode 100644 Fika.Core/Coop/HostClasses/FikaHostTransitController.cs create mode 100644 Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs create mode 100644 Fika.Core/Networking/Packets/Communication/TransitInteractPacket.cs create mode 100644 Fika.Core/Networking/Packets/GameWorld/SyncTransitControllersPacket.cs diff --git a/Fika.Core/Coop/ClientClasses/CoopClientGameWorld.cs b/Fika.Core/Coop/ClientClasses/CoopClientGameWorld.cs index 0087067f..46ec9c02 100644 --- a/Fika.Core/Coop/ClientClasses/CoopClientGameWorld.cs +++ b/Fika.Core/Coop/ClientClasses/CoopClientGameWorld.cs @@ -61,7 +61,6 @@ public override void Dispose() { base.Dispose(); NetManagerUtils.DestroyNetManager(false); - FikaBackendUtils.MatchingType = EMatchmakerType.Single; } public override void PlantTripwire(Item item, string profileId, Vector3 fromPosition, Vector3 toPosition) diff --git a/Fika.Core/Coop/ClientClasses/FikaClientTransitController.cs b/Fika.Core/Coop/ClientClasses/FikaClientTransitController.cs new file mode 100644 index 00000000..180c82ca --- /dev/null +++ b/Fika.Core/Coop/ClientClasses/FikaClientTransitController.cs @@ -0,0 +1,107 @@ +using Comfort.Common; +using EFT; +using EFT.Interactive; +using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.Players; +using Fika.Core.Coop.Utils; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Fika.Core.Coop.ClientClasses +{ + public class FikaClientTransitController : GClass1618 + { + public FikaClientTransitController(BackendConfigSettingsClass.GClass1505 settings, LocationSettingsClass.Location.TransitParameters[] parameters, Profile profile, LocalRaidSettings localRaidSettings) + : base(settings, parameters) + { + OnPlayerEnter += OnClientPlayerEnter; + OnPlayerExit += OnClientPlayerExit; + string[] array = localRaidSettings.transition.visitedLocations.EmptyIfNull().Append(localRaidSettings.location).ToArray(); + summonedTransits[profile.Id] = new GClass1614(localRaidSettings.transition.transitionRaidId, localRaidSettings.transition.transitionCount, array); + TransferItemsController.InitItemControllerServer(FikaGlobals.TransitTraderId, FikaGlobals.TransiterTraderName); + this.localRaidSettings = localRaidSettings; + } + public GStruct176 InteractPacket { get; set; } + + private readonly LocalRaidSettings localRaidSettings; + + private void OnClientPlayerEnter(TransitPoint point, Player player) + { + if (!transitPlayers.ContainsKey(player.ProfileId)) + { + TransferItemsController.InitPlayerStash(player); + if (player is CoopPlayer coopPlayer) + { + coopPlayer.UpdateBtrTraderServiceData().HandleExceptions(); + } + } + } + + private void OnClientPlayerExit(TransitPoint point, Player player) + { + + } + + public void Init() + { + method_1(dictionary_0.Values); + } + + public override void Dispose() + { + base.Dispose(); + OnPlayerEnter -= OnClientPlayerEnter; + OnPlayerExit -= OnClientPlayerExit; + } + + public void HandleClientExtract(int transitId, int playerId) + { + if (!smethod_0(playerId, out Player myPlayer)) + { + return; + } + + if (!dictionary_0.TryGetValue(transitId, out TransitPoint transitPoint)) + { + FikaPlugin.Instance.FikaLogger.LogError("FikaClientTransitController::HandleClientExtract: Could not find transit point with id: " + transitId); + return; + } + + string location = transitPoint.parameters.location; + ERaidMode eraidMode = ERaidMode.Local; + if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) + { + eraidMode = ERaidMode.Local; + tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); + } + string profileId = myPlayer.ProfileId; + Dictionary profileKeys = []; + profileKeys.Add(profileId, new() + { + _id = profileId, + keyId = InteractPacket.keyId, + isSolo = true + }); + + GClass1883 gclass = new() + { + hash = Guid.NewGuid().ToString(), + playersCount = 1, + ip = "", + location = location, + profiles = profileKeys, + transitionRaidId = summonedTransits[profileId].raidId, + raidMode = eraidMode, + side = myPlayer.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, + dayTime = localRaidSettings.timeVariant + }; + + alreadyTransits.Add(profileId, gclass); + if (Singleton.Instance is CoopGame coopGame) + { + coopGame.Extract((CoopPlayer)myPlayer, null, transitPoint); + } + } + } +} diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index ebd2a553..fa4704b5 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -80,6 +80,7 @@ public void CleanUpForTransit() spawnQueue.Clear(); ready = false; LocalGameInstance = null; + requestQuitGame = false; } protected void Awake() @@ -145,6 +146,11 @@ protected void OnDestroy() HumanPlayers.Clear(); } + public void ReInitInteractables() + { + Singleton.Instance.World_0.method_0(null); + } + public EQuitState GetQuitState() { EQuitState quitState = EQuitState.None; @@ -179,9 +185,13 @@ public EQuitState GetQuitState() /// private void ProcessQuitting() { - EQuitState quitState = GetQuitState(); + if (!FikaPlugin.ExtractKey.Value.IsDown()) + { + return; + } - if (FikaPlugin.ExtractKey.Value.IsDown() && quitState != EQuitState.None && !requestQuitGame) + EQuitState quitState = GetQuitState(); + if (quitState != EQuitState.None && !requestQuitGame) { //Log to both the in-game console as well as into the BepInEx logfile ConsoleScreen.Log($"{FikaPlugin.ExtractKey.Value} pressed, attempting to extract!"); @@ -191,15 +201,20 @@ private void ProcessQuitting() CoopGame coopGame = (CoopGame)Singleton.Instance; // If you are the server / host - if (FikaBackendUtils.IsServer) + if (!isClient) { + if (coopGame.MyExitStatus == ExitStatus.Transit && HumanPlayers.Count <= 1) + { + coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.MyExitStatus, coopGame.MyExitLocation, 0); + return; + } // A host needs to wait for the team to extract or die! if ((Singleton.Instance.NetServer.ConnectedPeersCount > 0) && quitState != EQuitState.None) { NotificationManagerClass.DisplayWarningNotification(LocaleUtils.HOST_CANNOT_EXTRACT.Localized()); requestQuitGame = false; return; - } + } else if (Singleton.Instance.NetServer.ConnectedPeersCount == 0 && Singleton.Instance.TimeSinceLastPeerDisconnected > DateTime.Now.AddSeconds(-5) && Singleton.Instance.HasHadPeer) diff --git a/Fika.Core/Coop/Custom/FikaTransitController.cs b/Fika.Core/Coop/Custom/FikaTransitController.cs deleted file mode 100644 index 44b919c0..00000000 --- a/Fika.Core/Coop/Custom/FikaTransitController.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Comfort.Common; -using EFT; -using EFT.Interactive; -using Fika.Core.Coop.GameMode; -using Fika.Core.Coop.Players; -using System.Collections.Generic; - -namespace Fika.Core.Coop.Custom -{ - public class FikaTransitController(BackendConfigSettingsClass.GClass1505 settings, LocationSettingsClass.Location.TransitParameters[] parameters, Profile profile, LocalRaidSettings localRaidSettings) - : GClass1617(settings, parameters, profile, localRaidSettings) - { - LocalRaidSettings localRaidSettings = localRaidSettings; - - public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) - { - string location = point.parameters.location; - ERaidMode eraidMode = ERaidMode.Local; - if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) - { - eraidMode = ERaidMode.Local; - tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); - } - string profileId = player.ProfileId; - GClass1883 gclass = new() - { - hash = hash, - playersCount = playersCount, - ip = "", - location = location, - profiles = keys, - transitionRaidId = summonedTransits[profileId].raidId, - raidMode = eraidMode, - side = player.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, - dayTime = localRaidSettings.timeVariant - }; - alreadyTransits.Add(profileId, gclass); - if (Singleton.Instance is CoopGame coopGame) - { - coopGame.Extract((CoopPlayer)player, null, point); - //coopGame.Stop(profileId, ExitStatus.Transit, point.parameters.name, 0f); - } - } - } -} diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 422df2af..0832775e 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -21,6 +21,7 @@ using Fika.Core.Coop.Components; using Fika.Core.Coop.Custom; using Fika.Core.Coop.FreeCamera; +using Fika.Core.Coop.HostClasses; using Fika.Core.Coop.ObservedClasses; using Fika.Core.Coop.ObservedClasses.Snapshotting; using Fika.Core.Coop.PacketHandlers; @@ -45,10 +46,10 @@ namespace Fika.Core.Coop.GameMode { - /// - /// Coop game used in Fika - /// - public sealed class CoopGame : BaseLocalGame, IBotGame, IFikaGame + /// + /// Coop game used in Fika + /// + public sealed class CoopGame : BaseLocalGame, IBotGame, IFikaGame { public string InfiltrationPoint; public ExitStatus MyExitStatus { get; set; } = ExitStatus.Survived; @@ -699,6 +700,40 @@ public override IEnumerator vmethod_2() { NetworkTimeSync.Start(); } + SyncTransitControllers(); + } + + private void SyncTransitControllers() + { + GClass1615 transitController = Singleton.Instance.TransitController; + if (transitController == null) + { + Logger.LogError("SyncTransitControllers: TransitController was null!"); + return; + } + + string profileId = Profile_0.Id; + if (transitController.summonedTransits.TryGetValue(profileId, out GClass1614 transitData)) + { + SyncTransitControllersPacket packet = new() + { + ProfileId = profileId, + RaidId = transitData.raidId, + Count = transitData.count, + Maps = transitData.maps + }; + + if (isServer) + { + Singleton.Instance.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + return; + } + + Singleton.Instance.SendData(ref packet, DeliveryMethod.ReliableOrdered); + return; + } + + Logger.LogError("SyncTransitControllers: Could not find TransitData in Summonedtransits!"); } /// @@ -727,7 +762,7 @@ private async Task WaitForOtherPlayers() SetMatchmakerStatus(LocaleUtils.UI_WAIT_FOR_OTHER_PLAYERS.Localized()); if (isServer) - { + { #if DEBUG Logger.LogWarning("Server: Waiting for coopHandler.AmountOfHumans < expected players, expected: " + expectedPlayers); #endif @@ -1045,6 +1080,10 @@ public async Task InitPlayer(BotControllerSettings botsSettings, string backendU if (CoopHandler.TryGetCoopHandler(out CoopHandler coopHandler)) { coopHandler.LocalGameInstance = this; + if (isServer && FikaBackendUtils.IsTransit) + { + coopHandler.ReInitInteractables(); + } } else { @@ -1527,7 +1566,8 @@ public override async Task vmethod_1(BotControllerSettings controllerSettings, I } if (transitActive) { - Singleton.Instance.TransitController = new FikaTransitController(instance.transitSettings, Location_0.transitParameters, + Singleton.Instance.TransitController = isServer ? new FikaHostTransitController(instance.transitSettings, Location_0.transitParameters, + Profile_0, localRaidSettings_0) : new FikaClientTransitController(instance.transitSettings, Location_0.transitParameters, Profile_0, localRaidSettings_0); } else @@ -1762,14 +1802,25 @@ public override void vmethod_6() else { exfilPoints = exfilController.EligiblePoints(Profile_0); - } + } - if (GClass1615.Exist(out GClass1617 gclass)) + GameUi.TimerPanel.SetTime(EFTDateTimeClass.UtcNow, Profile_0.Info.Side, GameTimer.EscapeTimeSeconds(), exfilPoints); + + if (isServer) { - gclass.Init(); + if (GClass1615.Exist(out FikaHostTransitController gclass)) + { + gclass.Init(); + // TODO: Sync to clients!!! + } + } + else + { + if (GClass1615.Exist(out FikaClientTransitController gclass)) + { + gclass.Init(); + } } - - GameUi.TimerPanel.SetTime(EFTDateTimeClass.UtcNow, Profile_0.Info.Side, GameTimer.EscapeTimeSeconds(), exfilPoints); exfilManager = gameObject.AddComponent(); exfilManager.Run(exfilPoints); @@ -1848,7 +1899,7 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran player.Profile.EftStats.SessionCounters.AddDouble(0.01, [CounterTag.FenceStanding, EFenceStandingSource.ExitStanding]); } - FikaTransitController transitController = (FikaTransitController)Singleton.Instance.TransitController; + GClass1615 transitController = Singleton.Instance.TransitController; if (transitController != null) { if (transitController.alreadyTransits.TryGetValue(player.ProfileId, out GClass1883 data)) @@ -1914,7 +1965,7 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran GameUi.TimerPanel.Close(); } - if (FikaPlugin.AutoExtract.Value) + if (FikaPlugin.AutoExtract.Value && !FikaBackendUtils.IsTransit) { if (!isServer) { @@ -1939,7 +1990,7 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran /// private IEnumerator ExtractRoutine(CoopPlayer player) { - while (true) + while (Status != GameStatus.Stopping) { if (player != null && player.ActiveHealthController != null) { @@ -2088,7 +2139,10 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa Logger.LogError("Stop: Could not find CoopHandler!"); } - Destroy(coopHandler); + if (!FikaBackendUtils.IsTransit) + { + Destroy(coopHandler); + } ExitManager stopManager = new() { @@ -2332,14 +2386,17 @@ public void ToggleDebug(bool enabled) /// public override MetricsClass vmethod_7() { - try - { - PlayerLeftRequest body = new(FikaBackendUtils.Profile.ProfileId); - FikaRequestHandler.RaidLeave(body); - } - catch (Exception ex) + if (!FikaBackendUtils.IsTransit) { - Logger.LogError("Unable to send RaidLeave request to server: " + ex.Message); + try + { + PlayerLeftRequest body = new(FikaBackendUtils.Profile.ProfileId); + FikaRequestHandler.RaidLeave(body); + } + catch (Exception ex) + { + Logger.LogError("Unable to send RaidLeave request to server: " + ex.Message); + } } using (CounterCreatorAbstractClass.StartWithToken("CollectMetrics")) { @@ -2391,7 +2448,10 @@ public override void CleanUp() FikaPlugin.DynamicAIRate.SettingChanged -= DynamicAIRate_SettingChanged; } - FikaBackendUtils.HostExpectedNumberOfPlayers = 1; + if (!FikaBackendUtils.IsTransit) + { + FikaBackendUtils.HostExpectedNumberOfPlayers = 1; + } FikaBackendUtils.RequestFikaWorld = false; FikaBackendUtils.IsReconnect = false; FikaBackendUtils.ReconnectPosition = Vector3.zero; diff --git a/Fika.Core/Coop/HostClasses/CoopHostGameWorld.cs b/Fika.Core/Coop/HostClasses/CoopHostGameWorld.cs index 94f95b59..097a0586 100644 --- a/Fika.Core/Coop/HostClasses/CoopHostGameWorld.cs +++ b/Fika.Core/Coop/HostClasses/CoopHostGameWorld.cs @@ -77,7 +77,6 @@ public override void Dispose() base.Dispose(); MineManager.OnExplosion -= OnMineExplode; NetManagerUtils.DestroyNetManager(true); - FikaBackendUtils.MatchingType = EMatchmakerType.Single; } public override void InitAirdrop(string lootTemplateId = null, bool takeNearbyPoint = false, Vector3 position = default) diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs new file mode 100644 index 00000000..56b79c70 --- /dev/null +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -0,0 +1,275 @@ +using Comfort.Common; +using EFT; +using EFT.Communications; +using EFT.GlobalEvents; +using EFT.Interactive; +using EFT.UI; +using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.Players; +using Fika.Core.Networking; +using LiteNetLib; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Fika.Core.Coop.HostClasses +{ + public class FikaHostTransitController : GClass1616 + { + public FikaHostTransitController(BackendConfigSettingsClass.GClass1505 settings, LocationSettingsClass.Location.TransitParameters[] parameters, Profile profile, LocalRaidSettings localRaidSettings) + : base(settings, parameters) + { + this.localRaidSettings = localRaidSettings; + OnPlayerEnter += OnHostPlayerEnter; + OnPlayerExit += OnHostPlayerExit; + string[] array = localRaidSettings.transition.visitedLocations.EmptyIfNull().Append(localRaidSettings.location).ToArray(); + summonedTransits[profile.Id] = new GClass1614(localRaidSettings.transition.transitionRaidId, localRaidSettings.transition.transitionCount, array); + TransferItemsController.InitItemControllerServer("656f0f98d80a697f855d34b1", "BTR"); + server = Singleton.Instance; + } + + private readonly LocalRaidSettings localRaidSettings; + private readonly FikaServer server; + + private void OnHostPlayerEnter(TransitPoint point, Player player) + { + if (!method_4(player, point.parameters.id, out string _)) + { + if (player.IsYourPlayer) + { + method_6(); + } + return; + } + else + { + if (!method_4(player, point.parameters.id, out string _)) + { + return; + } + } + if (!transitPlayers.ContainsKey(player.ProfileId)) + { + TransferItemsController.InitPlayerStash(player); + if (player is CoopPlayer coopPlayer) + { + coopPlayer.UpdateBtrTraderServiceData().HandleExceptions(); + } + if (player.IsYourPlayer) + { + method_7(point.parameters.id, player, method_9()); + return; + } + TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.Interaction, + TransitEvent = new TransitInteractionEvent() + { + PlayerId = player.Id, + PointId = point.parameters.id, + Type = TransitInteractionEvent.EType.Show + } + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + return; + } + dictionary_0[point.parameters.id].GroupEnter(player); + } + + private void OnHostPlayerExit(TransitPoint point, Player player) + { + if (transitPlayers.ContainsKey(player.ProfileId)) + { + point.GroupExit(player); + } + if (player.IsYourPlayer) + { + method_10(player); + return; + } + + TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.Interaction, + TransitEvent = new TransitInteractionEvent() + { + PlayerId = player.Id, + PointId = point.parameters.id, + Type = TransitInteractionEvent.EType.Hide + } + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + } + + public override void Sizes(Dictionary sizes) + { + foreach (KeyValuePair size in sizes) + { + if (GamePlayerOwner.MyPlayer.Id == size.Key) + { + MonoBehaviourSingleton.Instance.LocationTransitGroupSize.Display(); + MonoBehaviourSingleton.Instance.LocationTransitGroupSize.Show((int)size.Value); + } + } + + TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.GroupSize, + TransitEvent = new TransitGroupSizeEvent() + { + Sizes = sizes + } + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + } + + public override void Timers(int pointId, Dictionary timers) + { + foreach (KeyValuePair timer in timers) + { + if (GamePlayerOwner.MyPlayer.Id == timer.Key) + { + method_5(pointId); + MonoBehaviourSingleton.Instance.LocationTransitTimerPanel.Display(); + MonoBehaviourSingleton.Instance.LocationTransitTimerPanel.Show((float)timer.Value); + } + } + + TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.GroupTimer, + TransitEvent = new TransitGroupTimerEvent() + { + PointId = pointId, + Timers = timers + } + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + } + + public override void InactivePointNotification(int playerId, int pointId) + { + if (GamePlayerOwner.MyPlayer.Id == playerId) + { + NotificationManagerClass.DisplayWarningNotification("Transit/InactivePoint".Localized(null), ENotificationDurationType.Default); + method_5(pointId); + return; + } + + TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.Interaction, + TransitEvent = new TransitInteractionEvent() + { + PlayerId = playerId, + PointId = pointId, + Type = TransitInteractionEvent.EType.InactivePoint + } + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + } + + public override void InteractWithTransit(Player player, GStruct176 packet) + { + if (player.IsYourPlayer) + { + method_10(player); + transitPlayers.Add(player.ProfileId, player.Id); + profileKeys[player.ProfileId] = packet.keyId; + dictionary_0[packet.pointId].GroupEnter(player); + ExfiltrationControllerClass.Instance.BannedPlayers.Add(player.Id); + ExfiltrationControllerClass.Instance.CancelExtractionForPlayer(player); + ExfiltrationControllerClass.Instance.DisableExitsInteraction(); + return; + } + + transitPlayers[player.ProfileId] = player.Id; + profileKeys[player.ProfileId] = packet.keyId; + dictionary_0[packet.pointId].GroupEnter(player); + ExfiltrationControllerClass.Instance.BannedPlayers.Add(player.Id); + ExfiltrationControllerClass.Instance.CancelExtractionForPlayer(player); + + TransitEventPacket eventPacket = new() + { + EventType = TransitEventPacket.ETransitEventType.Interaction, + TransitEvent = new TransitInteractionEvent() + { + PlayerId = player.Id, + PointId = packet.pointId, + Type = TransitInteractionEvent.EType.Confirm + } + }; + + server.SendDataToAll(ref eventPacket, DeliveryMethod.ReliableOrdered); + } + + public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) + { + if (player.IsYourPlayer) + { + string location = point.parameters.location; + ERaidMode eraidMode = ERaidMode.Local; + if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) + { + eraidMode = ERaidMode.Local; + tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); + } + string profileId = player.ProfileId; + GClass1883 gclass = new() + { + hash = hash, + playersCount = playersCount, + ip = "", + location = location, + profiles = keys, + transitionRaidId = summonedTransits[profileId].raidId, + raidMode = eraidMode, + side = player.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, + dayTime = localRaidSettings.timeVariant + }; + alreadyTransits.Add(profileId, gclass); + if (Singleton.Instance is CoopGame coopGame) + { + coopGame.Extract((CoopPlayer)player, null, point); + } + } + + TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.Extract, + PlayerId = player.PlayerId, + TransitId = point.parameters.id + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + } + + public override void Dispose() + { + base.Dispose(); + OnPlayerEnter -= OnHostPlayerEnter; + OnPlayerExit -= OnHostPlayerExit; + } + + public void Init() + { + foreach (TransitPoint transitPoint in dictionary_0.Values) + { + transitPoint.Enabled = true; + } + method_1(dictionary_0.Values); + + /*TransitEventPacket packet = new() + { + EventType = TransitEventPacket.ETransitEventType.Init + }; + + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered);*/ + } + } +} diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs index 682884db..a5183a09 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs @@ -50,17 +50,20 @@ public static async void Prefix(TarkovApplication __instance, RaidSettings ____r } } - NetManagerUtils.CreateNetManager(FikaBackendUtils.IsServer); - if (isServer) + if (!FikaBackendUtils.IsTransit) { - NetManagerUtils.StartPinger(); - } - await NetManagerUtils.InitNetManager(isServer); + NetManagerUtils.CreateNetManager(FikaBackendUtils.IsServer); + if (isServer) + { + NetManagerUtils.StartPinger(); + } + await NetManagerUtils.InitNetManager(isServer); - if (isServer) - { - SetStatusModel status = new(FikaBackendUtils.GroupId, LobbyEntry.ELobbyStatus.COMPLETE); - await FikaRequestHandler.UpdateSetStatus(status); + if (isServer) + { + SetStatusModel status = new(FikaBackendUtils.GroupId, LobbyEntry.ELobbyStatus.COMPLETE); + await FikaRequestHandler.UpdateSetStatus(status); + } } } diff --git a/Fika.Core/Coop/Players/CoopPlayer.cs b/Fika.Core/Coop/Players/CoopPlayer.cs index 07675d6f..0b21242e 100644 --- a/Fika.Core/Coop/Players/CoopPlayer.cs +++ b/Fika.Core/Coop/Players/CoopPlayer.cs @@ -21,6 +21,7 @@ using Fika.Core.Networking; using Fika.Core.Networking.Http; using HarmonyLib; +using JsonType; using System; using System.Collections; using System.Collections.Generic; @@ -672,6 +673,29 @@ public override void OnMounting(GStruct179.EMountingCommand command) }); } + public override void vmethod_3(GClass1615 controller, int transitPointId, string keyId, EDateTime time) + { + GStruct176 packet = controller.GetInteractPacket(transitPointId, keyId, time); + if (FikaBackendUtils.IsServer) + { + controller.InteractWithTransit(this, packet); + } + else + { + TransitInteractPacket interactPacket = new() + { + NetId = NetId, + Data = packet + }; + Singleton.Instance.SendData(ref interactPacket, LiteNetLib.DeliveryMethod.ReliableOrdered); + if (Singleton.Instance.TransitController is FikaClientTransitController transitController) + { + transitController.InteractPacket = packet; + } + } + UpdateInteractionCast(); + } + public override void vmethod_4(TripwireSynchronizableObject tripwire) { base.vmethod_4(tripwire); diff --git a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs index 5ca13133..fbb56e71 100644 --- a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs +++ b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs @@ -17,6 +17,7 @@ using Fika.Core.Networking; using Fika.Core.Utils; using HarmonyLib; +using JsonType; using System; using System.Collections; using System.Collections.Generic; @@ -821,6 +822,11 @@ public override void OnDead(EDamageType damageType) CorpseSyncPacket = default; } + public override void vmethod_3(GClass1615 controller, int transitPointId, string keyId, EDateTime time) + { + // Do nothing + } + public override void HandleDamagePacket(ref DamagePacket packet) { DamageInfo damageInfo = new() diff --git a/Fika.Core/Coop/Utils/FikaGlobals.cs b/Fika.Core/Coop/Utils/FikaGlobals.cs index 4d5bfdaa..615783e3 100644 --- a/Fika.Core/Coop/Utils/FikaGlobals.cs +++ b/Fika.Core/Coop/Utils/FikaGlobals.cs @@ -1,13 +1,11 @@ using Comfort.Common; using EFT; -using EFT.Interactive; using EFT.InventoryLogic; using EFT.UI; using Fika.Core.Coop.Players; using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using UnityEngine; @@ -15,6 +13,9 @@ namespace Fika.Core.Coop.Utils { public static class FikaGlobals { + public const string TransitTraderId = "656f0f98d80a697f855d34b1"; + public const string TransiterTraderName = "BTR"; + public static readonly List BlockedInteractions = [ EInteraction.DropBackpack, EInteraction.NightVisionOffGear, EInteraction.NightVisionOnGear, diff --git a/Fika.Core/Coop/Utils/NetManagerUtils.cs b/Fika.Core/Coop/Utils/NetManagerUtils.cs index 726ac24c..506985c2 100644 --- a/Fika.Core/Coop/Utils/NetManagerUtils.cs +++ b/Fika.Core/Coop/Utils/NetManagerUtils.cs @@ -63,9 +63,23 @@ public static void DestroyNetManager(bool isServer) if (FikaBackendUtils.IsTransit) { Singleton.Instance.CoopHandler.CleanUpForTransit(); + if (isServer) + { + FikaServer server = Singleton.Instance; + server.RaidInitialized = false; + server.ReadyClients = 0; + return; + } + + FikaClient client = Singleton.Instance; + client.HostReady = false; + client.HostLoaded = false; + client.ReadyClients = 0; return; } + FikaBackendUtils.MatchingType = EMatchmakerType.Single; + if (FikaGameObject != null) { if (isServer) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index c8f2d854..fcf9a4c6 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -17,6 +17,7 @@ using Fika.Core.Coop.Custom; using Fika.Core.Coop.Factories; using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.HostClasses; using Fika.Core.Coop.ObservedClasses; using Fika.Core.Coop.ObservedClasses.Snapshotting; using Fika.Core.Coop.Players; @@ -38,10 +39,10 @@ namespace Fika.Core.Networking { - /// - /// Client used in P2P connections - /// - public class FikaClient : MonoBehaviour, INetEventListener, IFikaNetworkManager + /// + /// Client used in P2P connections + /// + public class FikaClient : MonoBehaviour, INetEventListener, IFikaNetworkManager { public CoopPlayer MyPlayer; public NetPacketProcessor packetProcessor = new(); @@ -153,6 +154,8 @@ public async void Init() packetProcessor.SubscribeNetSerializable(OnUsableItemPacketReceived); packetProcessor.SubscribeNetSerializable(OnNetworkSettingsPacketReceived); packetProcessor.SubscribeNetSerializable(OnArtilleryPacketReceived); + packetProcessor.SubscribeNetSerializable(OnSyncTransitControllersPacketReceived); + packetProcessor.SubscribeNetSerializable(OnTransitEventPacketReceived); #if DEBUG AddDebugPackets(); @@ -204,6 +207,46 @@ public async void Init() FikaEventDispatcher.DispatchEvent(new FikaClientCreatedEvent(this)); } + private void OnTransitEventPacketReceived(TransitEventPacket packet) + { + if (!(packet.EventType is TransitEventPacket.ETransitEventType.Init or TransitEventPacket.ETransitEventType.Extract)) + { + packet.TransitEvent.Invoke(); + return; + } + + if (packet.EventType is TransitEventPacket.ETransitEventType.Init) + { + if (coopHandler.LocalGameInstance.GameWorld_0.TransitController is FikaClientTransitController transitController) + { + transitController.Init(); + return; + } + } + + if (packet.EventType is TransitEventPacket.ETransitEventType.Extract) + { + if (coopHandler.LocalGameInstance.GameWorld_0.TransitController is FikaClientTransitController transitController) + { + transitController.HandleClientExtract(packet.TransitId, packet.PlayerId); + } + } + + logger.LogError("OnTransitEventPacketReceived: TransitController was not FikaClientTransitController!"); + } + + private void OnSyncTransitControllersPacketReceived(SyncTransitControllersPacket packet) + { + GClass1615 transitController = Singleton.Instance.TransitController; + if (transitController != null) + { + transitController.summonedTransits[packet.ProfileId] = new(packet.RaidId, packet.Count, packet.Maps); + return; + } + + logger.LogError("OnSyncTransitControllersPacketReceived: TransitController was null!"); + } + private void AddDebugPackets() { packetProcessor.SubscribeNetSerializable(OnSpawnItemPacketReceived); diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index 305978a3..12fc84a4 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -1629,7 +1629,5 @@ public static MountingPacket GetMountingPacket(this NetDataReader reader) } return packet; } - - } } \ No newline at end of file diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index d2efe6fc..ab65838c 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -15,6 +15,7 @@ using Fika.Core.Coop.Custom; using Fika.Core.Coop.Factories; using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.HostClasses; using Fika.Core.Coop.ObservedClasses; using Fika.Core.Coop.ObservedClasses.Snapshotting; using Fika.Core.Coop.Players; @@ -41,10 +42,10 @@ namespace Fika.Core.Networking { - /// - /// Server used in P2P connections - /// - public class FikaServer : MonoBehaviour, INetEventListener, INetLogger, INatPunchListener, GInterface231, IFikaNetworkManager + /// + /// Server used in P2P connections + /// + public class FikaServer : MonoBehaviour, INetEventListener, INetLogger, INatPunchListener, GInterface231, IFikaNetworkManager { public int ReadyClients = 0; public DateTime TimeSinceLastPeerDisconnected = DateTime.Now.AddDays(1); @@ -167,6 +168,8 @@ public async Task Init() packetProcessor.SubscribeNetSerializable(OnTraderServicesPacketReceived); packetProcessor.SubscribeNetSerializable(OnResyncInventoryIdPacketReceived); packetProcessor.SubscribeNetSerializable(OnUsableItemPacketReceived); + packetProcessor.SubscribeNetSerializable(OnSyncTransitControllersPacketReceived); + packetProcessor.SubscribeNetSerializable(OnSubscribeNetSerializableReceived); #if DEBUG AddDebugPackets(); @@ -274,6 +277,32 @@ public async Task Init() FikaEventDispatcher.DispatchEvent(new FikaServerCreatedEvent(this)); } + private void OnSubscribeNetSerializableReceived(TransitInteractPacket packet, NetPeer peer) + { + if (coopHandler.Players.TryGetValue(packet.NetId, out CoopPlayer playerToApply)) + { + GClass1615 transitController = Singleton.Instance.TransitController; + if (transitController != null) + { + transitController.InteractWithTransit(playerToApply, packet.Data); + } + } + } + + private void OnSyncTransitControllersPacketReceived(SyncTransitControllersPacket packet, NetPeer peer) + { + SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered, peer); + + GClass1615 transitController = Singleton.Instance.TransitController; + if (transitController != null) + { + transitController.summonedTransits[packet.ProfileId] = new(packet.RaidId, packet.Count, packet.Maps); + return; + } + + logger.LogError("OnSyncTransitControllersPacketReceived: TransitController was null!"); + } + private void AddDebugPackets() { packetProcessor.SubscribeNetSerializable(OnSpawnItemPacketReceived); @@ -942,7 +971,7 @@ private void OnInformationPacketReceived(InformationPacket packet, NetPeer peer) { ReadyClients += packet.ReadyPlayers; - bool hostReady = coopHandler != null && coopHandler.LocalGameInstance.Status == GameStatus.Started; + bool hostReady = coopHandler != null && coopHandler.LocalGameInstance != null && coopHandler.LocalGameInstance.Status == GameStatus.Started; InformationPacket respondPackage = new(false) { @@ -1104,9 +1133,9 @@ private void OnDamagePacketReceived(DamagePacket packet, NetPeer peer) playerToApply.PacketReceiver.DamagePackets.Enqueue(packet); return; } - + SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered, peer); - } + } } private void OnArmorDamagePacketReceived(ArmorDamagePacket packet, NetPeer peer) diff --git a/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs b/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs new file mode 100644 index 00000000..9addeff8 --- /dev/null +++ b/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs @@ -0,0 +1,194 @@ +using EFT.GlobalEvents; +using LiteNetLib.Utils; +using System.Collections.Generic; + +namespace Fika.Core.Networking +{ + public class TransitEventPacket : INetSerializable + { + public ETransitEventType EventType; + public BaseSyncEvent TransitEvent; + public int TransitId; + public int PlayerId; + + public void Deserialize(NetDataReader reader) + { + EventType = (ETransitEventType)reader.GetByte(); + switch (EventType) + { + case ETransitEventType.Init: + { + /*TransitInitEvent initEvent = new() + { + PlayerId = GamePlayerOwner.MyPlayer.Id + }; + int pointAmount = reader.GetInt(); + Dictionary points = []; + for (int i = 0; i < pointAmount; i++) + { + int key = reader.GetInt(); + ushort value = reader.GetUShort(); + points.Add(key, value); + } + initEvent.TransitionCount = reader.GetUShort(); + TransitEvent = initEvent;*/ + } + break; + case ETransitEventType.GroupTimer: + { + TransitGroupTimerEvent timerEvent = new() + { + PointId = reader.GetInt() + }; + int timerAmount = reader.GetInt(); + Dictionary timers = []; + for (int i = 0; i < timerAmount; i++) + { + int key = reader.GetInt(); + ushort value = reader.GetUShort(); + timers.Add(key, value); + } + timerEvent.Timers = timers; + TransitEvent = timerEvent; + } + break; + case ETransitEventType.GroupSize: + { + TransitGroupSizeEvent sizeEvent = new(); + int sizeAmount = reader.GetInt(); + Dictionary sizes = []; + for (int i = 0; i < sizeAmount; i++) + { + int key = reader.GetInt(); + byte value = reader.GetByte(); + sizes.Add(key, value); + } + sizeEvent.Sizes = sizes; + TransitEvent = sizeEvent; + } + break; + case ETransitEventType.Interaction: + { + TransitInteractionEvent interactionEvent = new() + { + PlayerId = reader.GetInt(), + PointId = reader.GetInt(), + Type = (TransitInteractionEvent.EType)reader.GetByte() + }; + TransitEvent = interactionEvent; + } + break; + case ETransitEventType.Messages: + { + TransitMessagesEvent messagesEvent = new(); + int messagesAmount = reader.GetInt(); + Dictionary messages = []; + for (int i = 0; i < messagesAmount; i++) + { + int key = reader.GetInt(); + TransitMessagesEvent.EType value = (TransitMessagesEvent.EType)reader.GetByte(); + messages.Add(key, value); + } + TransitEvent = messagesEvent; + } + break; + case ETransitEventType.Extract: + TransitId = reader.GetInt(); + PlayerId = reader.GetInt(); + break; + default: + break; + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put((byte)EventType); + switch (EventType) + { + case ETransitEventType.Init: + { + /*if (TransitEvent is TransitInitEvent initEvent) + { + writer.Put(initEvent.Points.Count); + foreach (KeyValuePair point in initEvent.Points) + { + writer.Put(point.Key); + writer.Put(point.Value); + } + writer.Put(initEvent.TransitionCount); + }*/ + } + break; + case ETransitEventType.GroupTimer: + { + if (TransitEvent is TransitGroupTimerEvent timerEvent) + { + writer.Put(timerEvent.PointId); + writer.Put(timerEvent.Timers.Count); + foreach (KeyValuePair timer in timerEvent.Timers) + { + writer.Put(timer.Key); + writer.Put(timer.Value); + } + } + } + break; + case ETransitEventType.GroupSize: + { + if (TransitEvent is TransitGroupSizeEvent sizeEvent) + { + writer.Put(sizeEvent.Sizes.Count); + foreach (KeyValuePair size in sizeEvent.Sizes) + { + writer.Put(size.Key); + writer.Put(size.Value); + } + } + } + break; + case ETransitEventType.Interaction: + { + if (TransitEvent is TransitInteractionEvent interactionEvent) + { + writer.Put(interactionEvent.PlayerId); + writer.Put(interactionEvent.PointId); + writer.Put((byte)interactionEvent.Type); + } + } + break; + case ETransitEventType.Messages: + { + if (TransitEvent is TransitMessagesEvent messagesEvent) + { + writer.Put(messagesEvent.Messages.Count); + foreach (KeyValuePair message in messagesEvent.Messages) + { + writer.Put(message.Key); + writer.Put((byte)message.Value); + } + } + } + break; + case ETransitEventType.Extract: + writer.Put(TransitId); + writer.Put(PlayerId); + break; + default: + break; + } + } + + public enum ETransitEventType + { + Init, + GroupTimer, + GroupSize, + Interaction, + Messages, + Extract + } + } + + +} diff --git a/Fika.Core/Networking/Packets/Communication/TransitInteractPacket.cs b/Fika.Core/Networking/Packets/Communication/TransitInteractPacket.cs new file mode 100644 index 00000000..3e720241 --- /dev/null +++ b/Fika.Core/Networking/Packets/Communication/TransitInteractPacket.cs @@ -0,0 +1,31 @@ +using JsonType; +using LiteNetLib.Utils; + +namespace Fika.Core.Networking +{ + public struct TransitInteractPacket : INetSerializable + { + public int NetId; + public GStruct176 Data; + + public void Deserialize(NetDataReader reader) + { + NetId = reader.GetInt(); + Data = new() + { + hasInteraction = true, + pointId = reader.GetInt(), + keyId = reader.GetString(), + time = (EDateTime)reader.GetByte() + }; + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(NetId); + writer.Put(Data.pointId); + writer.Put(Data.keyId); + writer.Put((byte)Data.time); + } + } +} diff --git a/Fika.Core/Networking/Packets/GameWorld/SyncTransitControllersPacket.cs b/Fika.Core/Networking/Packets/GameWorld/SyncTransitControllersPacket.cs new file mode 100644 index 00000000..b697071b --- /dev/null +++ b/Fika.Core/Networking/Packets/GameWorld/SyncTransitControllersPacket.cs @@ -0,0 +1,28 @@ +using LiteNetLib.Utils; + +namespace Fika.Core.Networking +{ + public struct SyncTransitControllersPacket : INetSerializable + { + public string ProfileId; + public string RaidId; + public int Count; + public string[] Maps; + + public void Deserialize(NetDataReader reader) + { + ProfileId = reader.GetString(); + RaidId = reader.GetString(); + Count = reader.GetInt(); + Maps = reader.GetStringArray(); + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(ProfileId); + writer.Put(RaidId); + writer.Put(Count); + writer.PutArray(Maps); + } + } +} From 8833c023294d8689cba3f9a5b6a0ded7658dab15 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:39:54 +0200 Subject: [PATCH 08/23] Add checks for transit --- Fika.Core/Coop/Components/CoopHandler.cs | 49 ++++----- .../HostClasses/FikaHostTransitController.cs | 99 ++++++++++++++++--- .../Communication/TransitEventPacket.cs | 1 + 3 files changed, 114 insertions(+), 35 deletions(-) diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index fa4704b5..b399fc34 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -25,11 +25,6 @@ public class CoopHandler : MonoBehaviour #region Fields/Properties public CoopGame LocalGameInstance { get; internal set; } public string ServerId { get; set; } = null; - public Dictionary Players = []; - public List HumanPlayers = []; - public int AmountOfHumans = 1; - public List ExtractedPlayers = []; - public List queuedProfileIds = []; public CoopPlayer MyPlayer { get @@ -38,7 +33,13 @@ public CoopPlayer MyPlayer } } - private ManualLogSource Logger; + public Dictionary Players = []; + public List HumanPlayers = []; + public int AmountOfHumans = 1; + public List ExtractedPlayers = []; + public List queuedProfileIds = []; + + private ManualLogSource logger; private readonly Queue spawnQueue = new(50); private bool ready; private bool isClient; @@ -85,7 +86,7 @@ public void CleanUpForTransit() protected void Awake() { - Logger = BepInEx.Logging.Logger.CreateLogSource("CoopHandler"); + logger = BepInEx.Logging.Logger.CreateLogSource("CoopHandler"); } protected void Start() @@ -195,7 +196,7 @@ private void ProcessQuitting() { //Log to both the in-game console as well as into the BepInEx logfile ConsoleScreen.Log($"{FikaPlugin.ExtractKey.Value} pressed, attempting to extract!"); - Logger.LogInfo($"{FikaPlugin.ExtractKey.Value} pressed, attempting to extract!"); + logger.LogInfo($"{FikaPlugin.ExtractKey.Value} pressed, attempting to extract!"); requestQuitGame = true; CoopGame coopGame = (CoopGame)Singleton.Instance; @@ -267,7 +268,7 @@ private async void SpawnPlayer(SpawnObject spawnObject) { if (spawnObject.Profile == null) { - Logger.LogError("SpawnPlayer: Profile was null!"); + logger.LogError("SpawnPlayer: Profile was null!"); queuedProfileIds.Remove(spawnObject.Profile.ProfileId); return; } @@ -285,7 +286,7 @@ private async void SpawnPlayer(SpawnObject spawnObject) IEnumerable allPrefabPaths = spawnObject.Profile.GetAllPrefabPaths(); if (allPrefabPaths.Count() == 0) { - Logger.LogError($"SpawnPlayer::{spawnObject.Profile.Info.Nickname}::PrefabPaths are empty!"); + logger.LogError($"SpawnPlayer::{spawnObject.Profile.Info.Nickname}::PrefabPaths are empty!"); return; } @@ -294,11 +295,11 @@ await Singleton.Instance.LoadBundlesAndCreatePools(PoolManager.Pool { if (x.IsFaulted) { - Logger.LogError($"SpawnPlayer::{spawnObject.Profile.Info.Nickname}::Load Failed"); + logger.LogError($"SpawnPlayer::{spawnObject.Profile.Info.Nickname}::Load Failed"); } else if (x.IsCanceled) { - Logger.LogError($"SpawnPlayer::{spawnObject.Profile.Info.Nickname}::Load Cancelled"); + logger.LogError($"SpawnPlayer::{spawnObject.Profile.Info.Nickname}::Load Cancelled"); } }); @@ -319,18 +320,18 @@ await Singleton.Instance.LoadBundlesAndCreatePools(PoolManager.Pool { // Start Coroutine as botController might need a while to start sometimes... #if DEBUG - Logger.LogInfo("Starting AddClientToBotEnemies routine."); + logger.LogInfo("Starting AddClientToBotEnemies routine."); #endif StartCoroutine(AddClientToBotEnemies(botController, otherPlayer)); } else { - Logger.LogError("botController was null when trying to add player to enemies!"); + logger.LogError("botController was null when trying to add player to enemies!"); } } else { - Logger.LogError("LocalGameInstance was null when trying to add player to enemies!"); + logger.LogError("LocalGameInstance was null when trying to add player to enemies!"); } } @@ -361,7 +362,7 @@ public void QueueProfile(Profile profile, byte[] healthByteArray, Vector3 positi queuedProfileIds.Add(profile.ProfileId); #if DEBUG - Logger.LogInfo($"Queueing profile: {profile.Nickname}, {profile.ProfileId}"); + logger.LogInfo($"Queueing profile: {profile.Nickname}, {profile.ProfileId}"); #endif SpawnObject spawnObject = new(profile, position, isAlive, isAI, netId, firstId, firstOperationId); if (controllerType != EHandsControllerType.None) @@ -410,7 +411,7 @@ private ObservedCoopPlayer SpawnObservedPlayer(SpawnObject spawnObject) otherPlayer.NetId = netId; #if DEBUG - Logger.LogInfo($"SpawnObservedPlayer: {profile.Nickname} spawning with NetId {netId}"); + logger.LogInfo($"SpawnObservedPlayer: {profile.Nickname} spawning with NetId {netId}"); #endif if (!isAi) { @@ -423,7 +424,7 @@ private ObservedCoopPlayer SpawnObservedPlayer(SpawnObject spawnObject) } else { - Logger.LogError($"Trying to add {otherPlayer.Profile.Nickname} to list of players but it was already there!"); + logger.LogError($"Trying to add {otherPlayer.Profile.Nickname} to list of players but it was already there!"); } if (!isAi && !isDedicatedProfile && !HumanPlayers.Contains(otherPlayer)) @@ -472,7 +473,7 @@ private ObservedCoopPlayer SpawnObservedPlayer(SpawnObject spawnObject) otherPlayer.InitObservedPlayer(isDedicatedProfile); #if DEBUG - Logger.LogInfo($"CreateLocalPlayer::{profile.Info.Nickname}::Spawned."); + logger.LogInfo($"CreateLocalPlayer::{profile.Info.Nickname}::Spawned."); #endif EHandsControllerType controllerType = spawnObject.ControllerType; @@ -482,7 +483,7 @@ private ObservedCoopPlayer SpawnObservedPlayer(SpawnObject spawnObject) { if (controllerType != EHandsControllerType.Empty && string.IsNullOrEmpty(itemId)) { - Logger.LogError($"CreateLocalPlayer: ControllerType was not Empty but itemId was null! ControllerType: {controllerType}"); + logger.LogError($"CreateLocalPlayer: ControllerType was not Empty but itemId was null! ControllerType: {controllerType}"); } else { @@ -496,7 +497,7 @@ private IEnumerator AddClientToBotEnemies(BotsController botController, LocalPla { CoopGame coopGame = LocalGameInstance; - Logger.LogInfo($"AddClientToBotEnemies: " + playerToAdd.Profile.Nickname); + logger.LogInfo($"AddClientToBotEnemies: " + playerToAdd.Profile.Nickname); while (coopGame.Status != GameStatus.Running && !botController.IsEnable) { @@ -509,7 +510,7 @@ private IEnumerator AddClientToBotEnemies(BotsController botController, LocalPla } #if DEBUG - Logger.LogInfo($"Adding Client {playerToAdd.Profile.Nickname} to enemy list"); + logger.LogInfo($"Adding Client {playerToAdd.Profile.Nickname} to enemy list"); #endif botController.AddActivePLayer(playerToAdd); @@ -527,12 +528,12 @@ private IEnumerator AddClientToBotEnemies(BotsController botController, LocalPla if (found) { #if DEBUG - Logger.LogInfo($"Verified that {playerToAdd.Profile.Nickname} was added to the enemy list."); + logger.LogInfo($"Verified that {playerToAdd.Profile.Nickname} was added to the enemy list."); #endif } else { - Logger.LogError($"Failed to add {playerToAdd.Profile.Nickname} to the enemy list."); + logger.LogError($"Failed to add {playerToAdd.Profile.Nickname} to the enemy list."); } } diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index 56b79c70..93e77fcd 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -4,18 +4,18 @@ using EFT.GlobalEvents; using EFT.Interactive; using EFT.UI; +using Fika.Core.Coop.Components; using Fika.Core.Coop.GameMode; using Fika.Core.Coop.Players; using Fika.Core.Networking; using LiteNetLib; -using System; using System.Collections.Generic; using System.Linq; namespace Fika.Core.Coop.HostClasses { - public class FikaHostTransitController : GClass1616 - { + public class FikaHostTransitController : GClass1616 + { public FikaHostTransitController(BackendConfigSettingsClass.GClass1505 settings, LocationSettingsClass.Location.TransitParameters[] parameters, Profile profile, LocalRaidSettings localRaidSettings) : base(settings, parameters) { @@ -26,10 +26,12 @@ public FikaHostTransitController(BackendConfigSettingsClass.GClass1505 settings, summonedTransits[profile.Id] = new GClass1614(localRaidSettings.transition.transitionRaidId, localRaidSettings.transition.transitionCount, array); TransferItemsController.InitItemControllerServer("656f0f98d80a697f855d34b1", "BTR"); server = Singleton.Instance; + playersInTransitZone = []; } private readonly LocalRaidSettings localRaidSettings; private readonly FikaServer server; + private readonly Dictionary playersInTransitZone; private void OnHostPlayerEnter(TransitPoint point, Player player) { @@ -37,17 +39,23 @@ private void OnHostPlayerEnter(TransitPoint point, Player player) { if (player.IsYourPlayer) { - method_6(); + method_6(); } return; } else - { + { if (!method_4(player, point.parameters.id, out string _)) { return; } } + + if (!playersInTransitZone.ContainsKey(player)) + { + playersInTransitZone.Add(player, point.parameters.id); + } + if (!transitPlayers.ContainsKey(player.ProfileId)) { TransferItemsController.InitPlayerStash(player); @@ -57,7 +65,7 @@ private void OnHostPlayerEnter(TransitPoint point, Player player) } if (player.IsYourPlayer) { - method_7(point.parameters.id, player, method_9()); + method_7(point.parameters.id, player, method_9()); return; } TransitEventPacket packet = new() @@ -79,6 +87,14 @@ private void OnHostPlayerEnter(TransitPoint point, Player player) private void OnHostPlayerExit(TransitPoint point, Player player) { + if (playersInTransitZone.TryGetValue(player, out int value)) + { + if (value == point.parameters.id) + { + playersInTransitZone.Remove(player); + } + } + if (transitPlayers.ContainsKey(player.ProfileId)) { point.GroupExit(player); @@ -110,7 +126,7 @@ public override void Sizes(Dictionary sizes) if (GamePlayerOwner.MyPlayer.Id == size.Key) { MonoBehaviourSingleton.Instance.LocationTransitGroupSize.Display(); - MonoBehaviourSingleton.Instance.LocationTransitGroupSize.Show((int)size.Value); + MonoBehaviourSingleton.Instance.LocationTransitGroupSize.Show((int)size.Value); } } @@ -134,7 +150,7 @@ public override void Timers(int pointId, Dictionary timers) { method_5(pointId); MonoBehaviourSingleton.Instance.LocationTransitTimerPanel.Display(); - MonoBehaviourSingleton.Instance.LocationTransitTimerPanel.Show((float)timer.Value); + MonoBehaviourSingleton.Instance.LocationTransitTimerPanel.Show((float)timer.Value); } } @@ -176,6 +192,17 @@ public override void InactivePointNotification(int playerId, int pointId) public override void InteractWithTransit(Player player, GStruct176 packet) { + TransitPoint point = dictionary_0[packet.pointId]; + if (point == null) + { + return; + } + + if (!CheckForPlayers(player, packet.pointId)) + { + return; + } + if (player.IsYourPlayer) { method_10(player); @@ -208,8 +235,58 @@ public override void InteractWithTransit(Player player, GStruct176 packet) server.SendDataToAll(ref eventPacket, DeliveryMethod.ReliableOrdered); } + private bool CheckForPlayers(Player player, int pointId) + { + int humanPlayers = 0; + foreach (CoopPlayer coopPlayer in Singleton.Instance.CoopHandler.HumanPlayers) + { + if (coopPlayer.HealthController.IsAlive) + { + humanPlayers++; + } + } + + int playersInPoint = 0; + foreach (KeyValuePair item in playersInTransitZone) + { + if (item.Key.HealthController.IsAlive) + { + if (item.Value == pointId) + { + playersInPoint++; + } + } + } + + if (playersInPoint < humanPlayers) + { + if (player.IsYourPlayer) + { + NotificationManagerClass.DisplayWarningNotification(TransitMessagesEvent.EType.NonAllTeammates.ToString(), ENotificationDurationType.Default); + return false; + } + + Dictionary messages = []; + messages.Add(player.Id, TransitMessagesEvent.EType.NonAllTeammates); + + TransitEventPacket messagePacket = new() + { + EventType = TransitEventPacket.ETransitEventType.Messages, + TransitEvent = new TransitMessagesEvent() + { + Messages = messages + } + }; + + server.SendDataToAll(ref messagePacket, DeliveryMethod.ReliableOrdered); + return false; + } + + return true; + } + public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) - { + { if (player.IsYourPlayer) { string location = point.parameters.location; @@ -236,7 +313,7 @@ public override void Transit(TransitPoint point, int playersCount, string hash, if (Singleton.Instance is CoopGame coopGame) { coopGame.Extract((CoopPlayer)player, null, point); - } + } } TransitEventPacket packet = new() @@ -247,7 +324,7 @@ public override void Transit(TransitPoint point, int playersCount, string hash, }; server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); - } + } public override void Dispose() { diff --git a/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs b/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs index 9addeff8..4d11a34a 100644 --- a/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs +++ b/Fika.Core/Networking/Packets/Communication/TransitEventPacket.cs @@ -89,6 +89,7 @@ public void Deserialize(NetDataReader reader) TransitMessagesEvent.EType value = (TransitMessagesEvent.EType)reader.GetByte(); messages.Add(key, value); } + messagesEvent.Messages = messages; TransitEvent = messagesEvent; } break; From 1db8fc33d3855067347f50948ab4024159179d24 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:44:38 +0200 Subject: [PATCH 09/23] Add debug patch --- .../Debug/UnityEngine_DebugLog_Patch.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 Fika.Core/Coop/Patches/Debug/UnityEngine_DebugLog_Patch.cs diff --git a/Fika.Core/Coop/Patches/Debug/UnityEngine_DebugLog_Patch.cs b/Fika.Core/Coop/Patches/Debug/UnityEngine_DebugLog_Patch.cs new file mode 100644 index 00000000..e8b998ed --- /dev/null +++ b/Fika.Core/Coop/Patches/Debug/UnityEngine_DebugLog_Patch.cs @@ -0,0 +1,54 @@ +using HarmonyLib; +using SPT.Reflection.Patching; +using System.Reflection; +using System.Threading.Tasks; + +namespace Fika.Core.Coop.Patches +{ + class TasksExtensions_HandleFinishedTask_Patches + { + public static void Enable() + { + new TasksExtensions_HandleFinishedTask_Patch1().Enable(); + new TasksExtensions_HandleFinishedTask_Patch2().Enable(); + } + + internal class TasksExtensions_HandleFinishedTask_Patch1 : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TasksExtensions), nameof(TasksExtensions.HandleFinishedTask), [typeof(Task)]); + } + + [PatchPrefix] + public static bool Prefix(Task task) + { + if (task.IsFaulted) + { + Logger.LogError($"TasksExtensions_HandleFinishedTask_Patch1: {task.Exception}"); + } + + return true; + } + } + + internal class TasksExtensions_HandleFinishedTask_Patch2 : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return AccessTools.Method(typeof(TasksExtensions), nameof(TasksExtensions.HandleFinishedTask), [typeof(Task), typeof(object)]); + } + + [PatchPrefix] + public static bool Prefix(Task task, object errorMessage) + { + if (task.IsFaulted) + { + Logger.LogError($"TasksExtensions_HandleFinishedTask_Patch2: {task.Exception}"); + } + + return true; + } + } + } +} \ No newline at end of file From a22eb27ae9aa03115960e523c109181c322ba9ff Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:45:20 +0200 Subject: [PATCH 10/23] Fix git --- .../Debug/GClass1615_method_0_Patch.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 Fika.Core/Coop/Patches/Debug/GClass1615_method_0_Patch.cs diff --git a/Fika.Core/Coop/Patches/Debug/GClass1615_method_0_Patch.cs b/Fika.Core/Coop/Patches/Debug/GClass1615_method_0_Patch.cs new file mode 100644 index 00000000..044dffe6 --- /dev/null +++ b/Fika.Core/Coop/Patches/Debug/GClass1615_method_0_Patch.cs @@ -0,0 +1,25 @@ +using SPT.Reflection.Patching; +using System.Reflection; + +namespace Fika.Core.Coop.Patches +{ + /// + /// Used to speed up debugging + /// + public class GClass1615_method_0_Patch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return typeof(GClass1615).GetMethod(nameof(GClass1615.method_0)); + } + + [PatchPrefix] + public static void Prefix(ref LocationSettingsClass.Location.TransitParameters[] parameters) + { + foreach (LocationSettingsClass.Location.TransitParameters parameter in parameters) + { + parameter.activateAfterSec = 10; + } + } + } +} From 1ff3877b2c15750c8b59f731e1477495db05c04c Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:45:25 +0200 Subject: [PATCH 11/23] Fix git --- .../Patches/UnityEngine_DebugLog_Patch.cs | 54 ------------------- Fika.Core/FikaPlugin.cs | 1 + 2 files changed, 1 insertion(+), 54 deletions(-) delete mode 100644 Fika.Core/Coop/Patches/UnityEngine_DebugLog_Patch.cs diff --git a/Fika.Core/Coop/Patches/UnityEngine_DebugLog_Patch.cs b/Fika.Core/Coop/Patches/UnityEngine_DebugLog_Patch.cs deleted file mode 100644 index af507d71..00000000 --- a/Fika.Core/Coop/Patches/UnityEngine_DebugLog_Patch.cs +++ /dev/null @@ -1,54 +0,0 @@ -using HarmonyLib; -using SPT.Reflection.Patching; -using System.Reflection; -using System.Threading.Tasks; - -namespace Fika.Core.Coop.Patches -{ - class TasksExtensions_HandleFinishedTask_Patches - { - public static void Enable() - { - new TasksExtensions_HandleFinishedTask_Patch1().Enable(); - new TasksExtensions_HandleFinishedTask_Patch2().Enable(); - } - - internal class TasksExtensions_HandleFinishedTask_Patch1 : ModulePatch - { - protected override MethodBase GetTargetMethod() - { - return AccessTools.Method(typeof(TasksExtensions), nameof(TasksExtensions.HandleFinishedTask), [typeof(Task)]); - } - - [PatchPrefix] - public static bool Prefix(Task task) - { - if (task.IsFaulted) - { - Logger.LogError($"TasksExtensions_HandleFinishedTask_Patch1: {task.Exception}"); - } - - return true; - } - } - - internal class TasksExtensions_HandleFinishedTask_Patch2 : ModulePatch - { - protected override MethodBase GetTargetMethod() - { - return AccessTools.Method(typeof(TasksExtensions), nameof(TasksExtensions.HandleFinishedTask), [typeof(Task), typeof(object)]); - } - - [PatchPrefix] - public static bool Prefix(Task task, object errorMessage) - { - if (task.IsFaulted) - { - Logger.LogError($"TasksExtensions_HandleFinishedTask_Patch2: {task.Exception}"); - } - - return true; - } - } - } -} \ No newline at end of file diff --git a/Fika.Core/FikaPlugin.cs b/Fika.Core/FikaPlugin.cs index 688ac9f1..f602c469 100644 --- a/Fika.Core/FikaPlugin.cs +++ b/Fika.Core/FikaPlugin.cs @@ -280,6 +280,7 @@ protected void Awake() #if DEBUG TasksExtensions_HandleFinishedTask_Patches.Enable(); + new GClass1615_method_0_Patch().Enable(); #endif gameObject.AddComponent(); From 12502a01db42c82bab50ae1ae7cf7b0a39f97012 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:48:54 +0200 Subject: [PATCH 12/23] Reuse raid settings when using transit --- .../TarkovApplication_LocalGameCreator_Patch.cs | 10 ++++++++++ Fika.Core/Coop/Utils/FikaBackendUtils.cs | 1 + 2 files changed, 11 insertions(+) diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs index e373a906..2f67df11 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs @@ -49,6 +49,16 @@ public static async Task CreateFikaGame(TarkovApplication instance, TimeAndWeath GameWorld gameWorld) { bool isServer = FikaBackendUtils.IsServer; + bool isTransit = FikaBackendUtils.IsTransit; + if (isServer && !isTransit) + { + FikaBackendUtils.TransitRaidSettings = raidSettings; + } + + if (isTransit) + { + raidSettings = FikaBackendUtils.TransitRaidSettings; + } metricsEvents.SetGamePrepared(); diff --git a/Fika.Core/Coop/Utils/FikaBackendUtils.cs b/Fika.Core/Coop/Utils/FikaBackendUtils.cs index 0476dc71..6ae09405 100644 --- a/Fika.Core/Coop/Utils/FikaBackendUtils.cs +++ b/Fika.Core/Coop/Utils/FikaBackendUtils.cs @@ -38,6 +38,7 @@ public static class FikaBackendUtils public static string HostLocationId; public static bool RequestFikaWorld = false; public static Vector3 ReconnectPosition = Vector3.zero; + public static RaidSettings TransitRaidSettings; public static bool IsServer { From 6aad2591f97b82bfa9e7553dd595770b33ca220a Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:49:55 +0200 Subject: [PATCH 13/23] Ignore dedicated when calculating players --- Fika.Core/Coop/HostClasses/FikaHostTransitController.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index 93e77fcd..81a7b98a 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -7,6 +7,7 @@ using Fika.Core.Coop.Components; using Fika.Core.Coop.GameMode; using Fika.Core.Coop.Players; +using Fika.Core.Coop.Utils; using Fika.Core.Networking; using LiteNetLib; using System.Collections.Generic; @@ -242,6 +243,11 @@ private bool CheckForPlayers(Player player, int pointId) { if (coopPlayer.HealthController.IsAlive) { + if (coopPlayer.IsYourPlayer && FikaBackendUtils.IsDedicated) + { + continue; + } + humanPlayers++; } } From 66eab145725991c78c6079a2e315755c955fac40 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:51:06 +0200 Subject: [PATCH 14/23] Add note --- Fika.Core/Coop/HostClasses/FikaHostTransitController.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index 81a7b98a..f3d5704c 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -293,6 +293,8 @@ private bool CheckForPlayers(Player player, int pointId) public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) { + // TODO: Handle dedi + if (player.IsYourPlayer) { string location = point.parameters.location; From f6c946f387d5a1dbf7a00e4dc13740fb7ad83f28 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:06:24 +0200 Subject: [PATCH 15/23] Self extract dedi --- .../HostClasses/FikaHostTransitController.cs | 65 +++++++++++++++++-- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index f3d5704c..e3436edb 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -4,12 +4,12 @@ using EFT.GlobalEvents; using EFT.Interactive; using EFT.UI; -using Fika.Core.Coop.Components; using Fika.Core.Coop.GameMode; using Fika.Core.Coop.Players; using Fika.Core.Coop.Utils; using Fika.Core.Networking; using LiteNetLib; +using System; using System.Collections.Generic; using System.Linq; @@ -28,11 +28,15 @@ public FikaHostTransitController(BackendConfigSettingsClass.GClass1505 settings, TransferItemsController.InitItemControllerServer("656f0f98d80a697f855d34b1", "BTR"); server = Singleton.Instance; playersInTransitZone = []; + dediTransit = false; + transittedPlayers = []; } private readonly LocalRaidSettings localRaidSettings; private readonly FikaServer server; private readonly Dictionary playersInTransitZone; + private bool dediTransit; + private List transittedPlayers; private void OnHostPlayerEnter(TransitPoint point, Player player) { @@ -54,7 +58,7 @@ private void OnHostPlayerEnter(TransitPoint point, Player player) if (!playersInTransitZone.ContainsKey(player)) { - playersInTransitZone.Add(player, point.parameters.id); + playersInTransitZone.Add(player, point.parameters.id); } if (!transitPlayers.ContainsKey(player.ProfileId)) @@ -288,15 +292,55 @@ private bool CheckForPlayers(Player player, int pointId) return false; } - return true; + return true; } public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) { - // TODO: Handle dedi + if (FikaBackendUtils.IsDedicated && !dediTransit) + { + dediTransit = true; + + Player dediPlayer = GamePlayerOwner.MyPlayer; + + string location = point.parameters.location; + ERaidMode eraidMode = ERaidMode.Local; + if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) + { + eraidMode = ERaidMode.Local; + tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); + } + string profileId = dediPlayer.ProfileId; + keys = []; + keys.Add(profileId, new() + { + isSolo = true, + keyId = "", + _id = profileId, + }); + + GClass1883 gclass = new() + { + hash = Guid.NewGuid().ToString(), + playersCount = 1, + ip = "", + location = location, + profiles = keys, + transitionRaidId = summonedTransits[profileId].raidId, + raidMode = eraidMode, + side = player.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, + dayTime = localRaidSettings.timeVariant + }; + alreadyTransits.Add(profileId, gclass); + if (Singleton.Instance is CoopGame coopGame) + { + coopGame.Extract((CoopPlayer)player, null, point); + } + } if (player.IsYourPlayer) { + dediTransit = true; string location = point.parameters.location; ERaidMode eraidMode = ERaidMode.Local; if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) @@ -322,6 +366,8 @@ public override void Transit(TransitPoint point, int playersCount, string hash, { coopGame.Extract((CoopPlayer)player, null, point); } + transittedPlayers.Add(player.Id); + return; } TransitEventPacket packet = new() @@ -331,7 +377,18 @@ public override void Transit(TransitPoint point, int playersCount, string hash, TransitId = point.parameters.id }; + transittedPlayers.Add(player.Id); + server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); + + if (FikaBackendUtils.IsDedicated) + { + if (transittedPlayers.Count >= (FikaBackendUtils.HostExpectedNumberOfPlayers - 1)) + { + CoopGame coopGame = (CoopGame)Singleton.Instance; + coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, ExitStatus.Transit, coopGame.MyExitLocation, 0); + } + } } public override void Dispose() From 5c5ab727a2ff71b4bf5e00c9404123d288ced53f Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:27:43 +0200 Subject: [PATCH 16/23] Add dedi functionality --- Fika.Core/Coop/Components/CoopExfilManager.cs | 4 +- Fika.Core/Coop/Components/CoopHandler.cs | 8 +- Fika.Core/Coop/Components/CoopTimeManager.cs | 2 +- Fika.Core/Coop/GameMode/CoopGame.cs | 31 ++--- Fika.Core/Coop/GameMode/IFikaGame.cs | 4 +- .../HostClasses/FikaHostTransitController.cs | 107 ++++++++++-------- ...arkovApplication_LocalGameCreator_Patch.cs | 9 -- Fika.Core/Coop/Utils/FikaBackendUtils.cs | 1 - Fika.Core/Networking/FikaServer.cs | 4 +- .../Networking/Packets/Player/DamagePacket.cs | 4 +- .../Packets/Player/HealthSyncPacket.cs | 24 ++-- Fika.Core/Networking/Packets/SubPackets.cs | 2 - 12 files changed, 103 insertions(+), 97 deletions(-) diff --git a/Fika.Core/Coop/Components/CoopExfilManager.cs b/Fika.Core/Coop/Components/CoopExfilManager.cs index 796f5cb7..1bbcf28d 100644 --- a/Fika.Core/Coop/Components/CoopExfilManager.cs +++ b/Fika.Core/Coop/Components/CoopExfilManager.cs @@ -42,7 +42,7 @@ protected void Update() if (playerHandler.startTime + playerHandler.point.Settings.ExfiltrationTime - game.PastTime <= 0) { playerHandlers.Remove(playerHandler); - game.MyExitLocation = playerHandler.point.Settings.Name; + game.ExitLocation = playerHandler.point.Settings.Name; game.Extract(playerHandler.player, playerHandler.point); } } @@ -71,7 +71,7 @@ protected void Update() if (!exfiltrationPoint.UnmetRequirements(player).Any()) { - game.MyExitLocation = exfiltrationPoint.Settings.Name; + game.ExitLocation = exfiltrationPoint.Settings.Name; game.Extract((CoopPlayer)player, exfiltrationPoint); } } diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index b399fc34..862f9317 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -204,9 +204,9 @@ private void ProcessQuitting() // If you are the server / host if (!isClient) { - if (coopGame.MyExitStatus == ExitStatus.Transit && HumanPlayers.Count <= 1) + if (coopGame.ExitStatus == ExitStatus.Transit && HumanPlayers.Count <= 1) { - coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.MyExitStatus, coopGame.MyExitLocation, 0); + coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.ExitStatus, coopGame.ExitLocation, 0); return; } // A host needs to wait for the team to extract or die! @@ -226,12 +226,12 @@ private void ProcessQuitting() } else { - coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.MyExitStatus, MyPlayer.ActiveHealthController.IsAlive ? coopGame.MyExitLocation : null, 0); + coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.ExitStatus, MyPlayer.ActiveHealthController.IsAlive ? coopGame.ExitLocation : null, 0); } } else { - coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.MyExitStatus, MyPlayer.ActiveHealthController.IsAlive ? coopGame.MyExitLocation : null, 0); + coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, coopGame.ExitStatus, MyPlayer.ActiveHealthController.IsAlive ? coopGame.ExitLocation : null, 0); } return; } diff --git a/Fika.Core/Coop/Components/CoopTimeManager.cs b/Fika.Core/Coop/Components/CoopTimeManager.cs index c10e2d05..0da95de4 100644 --- a/Fika.Core/Coop/Components/CoopTimeManager.cs +++ b/Fika.Core/Coop/Components/CoopTimeManager.cs @@ -23,7 +23,7 @@ protected void Update() { if (CoopGame.Status == GameStatus.Started && GameTimer != null && GameTimer.SessionTime != null && GameTimer.PastTime >= GameTimer.SessionTime) { - CoopGame.MyExitStatus = ExitStatus.MissingInAction; + CoopGame.ExitStatus = ExitStatus.MissingInAction; CoopPlayer coopPlayer = (CoopPlayer)Singleton.Instance.MainPlayer; CoopGame.Extract(coopPlayer, null); enabled = false; diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 0832775e..1e90101c 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -52,8 +52,8 @@ namespace Fika.Core.Coop.GameMode public sealed class CoopGame : BaseLocalGame, IBotGame, IFikaGame { public string InfiltrationPoint; - public ExitStatus MyExitStatus { get; set; } = ExitStatus.Survived; - public string MyExitLocation { get; set; } = null; + public ExitStatus ExitStatus { get; set; } = ExitStatus.Survived; + public string ExitLocation { get; set; } = null; public ISpawnSystem SpawnSystem; public Dictionary Bots = []; public List ExtractedPlayers { get; } = []; @@ -1863,7 +1863,7 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran position.y += 500; player.Teleport(position); - if (MyExitStatus == ExitStatus.MissingInAction) + if (ExitStatus == ExitStatus.MissingInAction) { NotificationManagerClass.DisplayMessageNotification(LocaleUtils.PLAYER_MIA.Localized(), iconType: EFT.Communications.ENotificationIconType.Alert, textColor: Color.red); } @@ -1876,7 +1876,7 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran BackendConfigSettingsClass.GClass1479.GClass1485 matchEndConfig = Singleton.Instance.Experience.MatchEnd; if (player.Profile.EftStats.SessionCounters.GetAllInt([CounterTag.Exp]) < matchEndConfig.SurvivedExpRequirement && PastTime < matchEndConfig.SurvivedTimeRequirement) { - MyExitStatus = ExitStatus.Runner; + ExitStatus = ExitStatus.Runner; } if (exfiltrationPoint != null) @@ -1904,8 +1904,8 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran { if (transitController.alreadyTransits.TryGetValue(player.ProfileId, out GClass1883 data)) { - MyExitStatus = ExitStatus.Transit; - MyExitLocation = transitPoint.parameters.name; + ExitStatus = ExitStatus.Transit; + ExitLocation = transitPoint.parameters.name; FikaBackendUtils.IsTransit = true; } } @@ -1965,15 +1965,15 @@ public void Extract(CoopPlayer player, ExfiltrationPoint exfiltrationPoint, Tran GameUi.TimerPanel.Close(); } - if (FikaPlugin.AutoExtract.Value && !FikaBackendUtils.IsTransit) + if (FikaPlugin.AutoExtract.Value || FikaBackendUtils.IsTransit) { if (!isServer) { - Stop(coopHandler.MyPlayer.ProfileId, MyExitStatus, coopHandler.MyPlayer.ActiveHealthController.IsAlive ? MyExitLocation : null, 0); + Stop(coopHandler.MyPlayer.ProfileId, ExitStatus, coopHandler.MyPlayer.ActiveHealthController.IsAlive ? ExitLocation : null, 0); } else if (Singleton.Instance.NetServer.ConnectedPeersCount == 0) { - Stop(coopHandler.MyPlayer.ProfileId, MyExitStatus, coopHandler.MyPlayer.ActiveHealthController.IsAlive ? MyExitLocation : null, 0); + Stop(coopHandler.MyPlayer.ProfileId, ExitStatus, coopHandler.MyPlayer.ActiveHealthController.IsAlive ? ExitLocation : null, 0); } } } @@ -2009,7 +2009,10 @@ private IEnumerator ExtractRoutine(CoopPlayer player) public void ClearHostAI(Player player) { - botsController_0.DestroyInfo(player); + if (botsController_0 != null) + { + botsController_0.DestroyInfo(player); + } } /// @@ -2036,12 +2039,12 @@ private async void HealthController_DiedEvent(EDamageType damageType) player.HealthController.DiedEvent -= HealthController_DiedEvent; PlayerOwner.vmethod_1(); - MyExitStatus = ExitStatus.Killed; - MyExitLocation = string.Empty; + ExitStatus = ExitStatus.Killed; + ExitLocation = string.Empty; if (FikaPlugin.Instance.ForceSaveOnDeath) { - await SavePlayer((CoopPlayer)player, MyExitStatus, string.Empty, true); + await SavePlayer((CoopPlayer)player, ExitStatus, string.Empty, true); } } @@ -2159,7 +2162,7 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa Status = GameStatus.Stopping; GameTimer.TryStop(); - if (gameUI.TimerPanel.enabled) + if (gameUI.TimerPanel.isActiveAndEnabled) { gameUI.TimerPanel.Close(); } diff --git a/Fika.Core/Coop/GameMode/IFikaGame.cs b/Fika.Core/Coop/GameMode/IFikaGame.cs index d4ce4162..6e1ffa5e 100644 --- a/Fika.Core/Coop/GameMode/IFikaGame.cs +++ b/Fika.Core/Coop/GameMode/IFikaGame.cs @@ -10,9 +10,9 @@ public interface IFikaGame { public List ExtractedPlayers { get; } - ExitStatus MyExitStatus { get; set; } + ExitStatus ExitStatus { get; set; } - string MyExitLocation { get; set; } + string ExitLocation { get; set; } public void Stop(string profileId, ExitStatus exitStatus, string exitName, float delay = 0f); } diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index e3436edb..974c10c2 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -5,6 +5,7 @@ using EFT.Interactive; using EFT.UI; using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.PacketHandlers; using Fika.Core.Coop.Players; using Fika.Core.Coop.Utils; using Fika.Core.Networking; @@ -30,13 +31,20 @@ public FikaHostTransitController(BackendConfigSettingsClass.GClass1505 settings, playersInTransitZone = []; dediTransit = false; transittedPlayers = []; + + if (FikaBackendUtils.IsDedicated) + { + CoopPlayer dediPlayer = (CoopPlayer)GamePlayerOwner.MyPlayer; + TransferItemsController.InitPlayerStash(dediPlayer); + dediPlayer.UpdateBtrTraderServiceData().HandleExceptions(); + } } private readonly LocalRaidSettings localRaidSettings; private readonly FikaServer server; private readonly Dictionary playersInTransitZone; private bool dediTransit; - private List transittedPlayers; + private readonly List transittedPlayers; private void OnHostPlayerEnter(TransitPoint point, Player player) { @@ -297,47 +305,6 @@ private bool CheckForPlayers(Player player, int pointId) public override void Transit(TransitPoint point, int playersCount, string hash, Dictionary keys, Player player) { - if (FikaBackendUtils.IsDedicated && !dediTransit) - { - dediTransit = true; - - Player dediPlayer = GamePlayerOwner.MyPlayer; - - string location = point.parameters.location; - ERaidMode eraidMode = ERaidMode.Local; - if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) - { - eraidMode = ERaidMode.Local; - tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); - } - string profileId = dediPlayer.ProfileId; - keys = []; - keys.Add(profileId, new() - { - isSolo = true, - keyId = "", - _id = profileId, - }); - - GClass1883 gclass = new() - { - hash = Guid.NewGuid().ToString(), - playersCount = 1, - ip = "", - location = location, - profiles = keys, - transitionRaidId = summonedTransits[profileId].raidId, - raidMode = eraidMode, - side = player.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, - dayTime = localRaidSettings.timeVariant - }; - alreadyTransits.Add(profileId, gclass); - if (Singleton.Instance is CoopGame coopGame) - { - coopGame.Extract((CoopPlayer)player, null, point); - } - } - if (player.IsYourPlayer) { dediTransit = true; @@ -381,12 +348,60 @@ public override void Transit(TransitPoint point, int playersCount, string hash, server.SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered); - if (FikaBackendUtils.IsDedicated) + if (FikaBackendUtils.IsDedicated && !dediTransit) + { + ExtractDedi(point); + } + } + + private void ExtractDedi(TransitPoint point) + { + Dictionary keys; + dediTransit = true; + + CoopPlayer dediPlayer = (CoopPlayer)GamePlayerOwner.MyPlayer; + + string location = point.parameters.location; + ERaidMode eraidMode = ERaidMode.Local; + if (TarkovApplication.Exist(out TarkovApplication tarkovApplication)) + { + eraidMode = ERaidMode.Local; + tarkovApplication.transitionStatus = new GStruct136(location, false, localRaidSettings.playerSide, eraidMode, localRaidSettings.timeVariant); + } + string profileId = dediPlayer.ProfileId; + keys = []; + keys.Add(profileId, new() { - if (transittedPlayers.Count >= (FikaBackendUtils.HostExpectedNumberOfPlayers - 1)) + isSolo = true, + keyId = "", + _id = profileId, + }); + + GClass1883 gclass = new() + { + hash = Guid.NewGuid().ToString(), + playersCount = 1, + ip = "", + location = location, + profiles = keys, + transitionRaidId = summonedTransits[profileId].raidId, + raidMode = eraidMode, + side = dediPlayer.Side is EPlayerSide.Savage ? ESideType.Savage : ESideType.Pmc, + dayTime = localRaidSettings.timeVariant + }; + alreadyTransits.Add(profileId, gclass); + + GClass1615 transitController = Singleton.Instance.TransitController; + if (transitController != null && Singleton.Instance is CoopGame coopGame) + { + if (transitController.alreadyTransits.TryGetValue(dediPlayer.ProfileId, out GClass1883 data)) { - CoopGame coopGame = (CoopGame)Singleton.Instance; - coopGame.Stop(Singleton.Instance.MainPlayer.ProfileId, ExitStatus.Transit, coopGame.MyExitLocation, 0); + coopGame.ExitStatus = ExitStatus.Transit; + coopGame.ExitLocation = point.parameters.name; + coopGame.ExtractedPlayers.Add(dediPlayer.NetId); + FikaBackendUtils.IsTransit = true; + + coopGame.Stop(dediPlayer.ProfileId, coopGame.ExitStatus, coopGame.ExitLocation, 0); } } } diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs index 2f67df11..45a97a1b 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs @@ -50,15 +50,6 @@ public static async Task CreateFikaGame(TarkovApplication instance, TimeAndWeath { bool isServer = FikaBackendUtils.IsServer; bool isTransit = FikaBackendUtils.IsTransit; - if (isServer && !isTransit) - { - FikaBackendUtils.TransitRaidSettings = raidSettings; - } - - if (isTransit) - { - raidSettings = FikaBackendUtils.TransitRaidSettings; - } metricsEvents.SetGamePrepared(); diff --git a/Fika.Core/Coop/Utils/FikaBackendUtils.cs b/Fika.Core/Coop/Utils/FikaBackendUtils.cs index 6ae09405..0476dc71 100644 --- a/Fika.Core/Coop/Utils/FikaBackendUtils.cs +++ b/Fika.Core/Coop/Utils/FikaBackendUtils.cs @@ -38,7 +38,6 @@ public static class FikaBackendUtils public static string HostLocationId; public static bool RequestFikaWorld = false; public static Vector3 ReconnectPosition = Vector3.zero; - public static RaidSettings TransitRaidSettings; public static bool IsServer { diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index ab65838c..aeb81eba 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -1332,8 +1332,8 @@ public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) // End the raid Singleton.Instance.Stop(Singleton.Instance.MainPlayer.ProfileId, - Singleton.Instance.MyExitStatus, - Singleton.Instance.MyExitLocation, 0); + Singleton.Instance.ExitStatus, + Singleton.Instance.ExitLocation, 0); } } } diff --git a/Fika.Core/Networking/Packets/Player/DamagePacket.cs b/Fika.Core/Networking/Packets/Player/DamagePacket.cs index 09257c6a..37457543 100644 --- a/Fika.Core/Networking/Packets/Player/DamagePacket.cs +++ b/Fika.Core/Networking/Packets/Player/DamagePacket.cs @@ -30,7 +30,7 @@ public struct DamagePacket(int netId) : INetSerializable public void Deserialize(NetDataReader reader) { NetId = reader.GetInt(); - DamageType = (EDamageType)reader.GetByte(); + DamageType = (EDamageType)reader.GetInt(); Damage = reader.GetFloat(); BodyPartType = (EBodyPart)reader.GetByte(); ColliderType = (EBodyPartColliderType)reader.GetByte(); @@ -52,7 +52,7 @@ public void Deserialize(NetDataReader reader) public void Serialize(NetDataWriter writer) { writer.Put(NetId); - writer.Put((byte)DamageType); + writer.Put((int)DamageType); writer.Put(Damage); writer.Put((byte)BodyPartType); writer.Put((byte)ColliderType); diff --git a/Fika.Core/Networking/Packets/Player/HealthSyncPacket.cs b/Fika.Core/Networking/Packets/Player/HealthSyncPacket.cs index b45793a4..7aa27870 100644 --- a/Fika.Core/Networking/Packets/Player/HealthSyncPacket.cs +++ b/Fika.Core/Networking/Packets/Player/HealthSyncPacket.cs @@ -17,7 +17,7 @@ public void Deserialize(NetDataReader reader) NetId = reader.GetInt(); GStruct358 packet = new() { - SyncType = (GStruct358.ESyncType)reader.GetInt() + SyncType = (GStruct358.ESyncType)reader.GetByte() }; switch (packet.SyncType) { @@ -27,13 +27,13 @@ public void Deserialize(NetDataReader reader) { EffectId = reader.GetInt(), Type = reader.GetByte(), - BodyPart = (EBodyPart)reader.GetInt(), + BodyPart = (EBodyPart)reader.GetByte(), DelayTime = reader.GetFloat(), BuildUpTime = reader.GetFloat(), WorkTime = reader.GetFloat(), ResidueTime = reader.GetFloat(), Strength = reader.GetFloat(), - ExtraDataType = (GStruct358.GStruct359.EExtraDataType)reader.GetInt() + ExtraDataType = (GStruct358.GStruct359.EExtraDataType)reader.GetByte() }; switch (packet.Data.AddEffect.ExtraDataType) { @@ -144,7 +144,7 @@ public void Deserialize(NetDataReader reader) { packet.Data.BodyHealth = new() { - BodyPart = (EBodyPart)reader.GetInt(), + BodyPart = (EBodyPart)reader.GetByte(), Value = reader.GetFloat() }; break; @@ -185,7 +185,7 @@ public void Deserialize(NetDataReader reader) { packet.Data.ApplyDamage = new() { - BodyPart = (EBodyPart)reader.GetInt(), + BodyPart = (EBodyPart)reader.GetByte(), Damage = reader.GetFloat(), DamageType = (EDamageType)reader.GetInt() }; @@ -195,7 +195,7 @@ public void Deserialize(NetDataReader reader) { packet.Data.DestroyedBodyPart = new() { - BodyPart = (EBodyPart)reader.GetInt(), + BodyPart = (EBodyPart)reader.GetByte(), IsDestroyed = reader.GetBool() }; if (packet.Data.DestroyedBodyPart.IsDestroyed) @@ -262,20 +262,20 @@ public void Serialize(NetDataWriter writer) { writer.Put(NetId); GStruct358.GStruct377 packet = Packet.Data; - writer.Put((int)Packet.SyncType); + writer.Put((byte)Packet.SyncType); switch (Packet.SyncType) { case GStruct358.ESyncType.AddEffect: { writer.Put(packet.AddEffect.EffectId); writer.Put(packet.AddEffect.Type); - writer.Put((int)packet.AddEffect.BodyPart); + writer.Put((byte)packet.AddEffect.BodyPart); writer.Put(packet.AddEffect.DelayTime); writer.Put(packet.AddEffect.BuildUpTime); writer.Put(packet.AddEffect.WorkTime); writer.Put(packet.AddEffect.ResidueTime); writer.Put(packet.AddEffect.Strength); - writer.Put((int)packet.AddEffect.ExtraDataType); + writer.Put((byte)packet.AddEffect.ExtraDataType); switch (packet.AddEffect.ExtraDataType) { case GStruct358.GStruct359.EExtraDataType.None: @@ -352,7 +352,7 @@ public void Serialize(NetDataWriter writer) } case GStruct358.ESyncType.BodyHealth: { - writer.Put((int)packet.BodyHealth.BodyPart); + writer.Put((byte)packet.BodyHealth.BodyPart); writer.Put(packet.BodyHealth.Value); break; } @@ -378,14 +378,14 @@ public void Serialize(NetDataWriter writer) } case GStruct358.ESyncType.ApplyDamage: { - writer.Put((int)packet.ApplyDamage.BodyPart); + writer.Put((byte)packet.ApplyDamage.BodyPart); writer.Put(packet.ApplyDamage.Damage); writer.Put((int)packet.ApplyDamage.DamageType); break; } case GStruct358.ESyncType.DestroyedBodyPart: { - writer.Put((int)packet.DestroyedBodyPart.BodyPart); + writer.Put((byte)packet.DestroyedBodyPart.BodyPart); writer.Put(packet.DestroyedBodyPart.IsDestroyed); if (packet.DestroyedBodyPart.IsDestroyed) { diff --git a/Fika.Core/Networking/Packets/SubPackets.cs b/Fika.Core/Networking/Packets/SubPackets.cs index 5f649bb1..8f4d3953 100644 --- a/Fika.Core/Networking/Packets/SubPackets.cs +++ b/Fika.Core/Networking/Packets/SubPackets.cs @@ -200,8 +200,6 @@ public struct VaultPacket public float VaultingSpeed; public float BehindObstacleHeight; public float AbsoluteForwardVelocity; - - } public struct CorpseSyncPacket From 6a8e337343928055bfaebaae0fdad4b6dabffcbc Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:10:59 +0200 Subject: [PATCH 17/23] Handle TransitionData locally --- Fika.Core/Coop/GameMode/CoopGame.cs | 13 ++++++++ .../HostClasses/FikaHostTransitController.cs | 1 - ...arkovApplication_LocalGameCreator_Patch.cs | 2 +- ...rkovApplication_LocalGamePreparer_Patch.cs | 2 +- Fika.Core/Coop/Players/ObservedCoopPlayer.cs | 2 +- Fika.Core/Coop/Utils/FikaBackendUtils.cs | 33 +++++++++++++++++-- Fika.Core/Coop/Utils/FikaGlobals.cs | 1 + 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 1e90101c..e7ca5afb 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -2062,6 +2062,19 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa FikaBackendUtils.IsTransit = false; } + if (FikaBackendUtils.IsTransit) + { + GClass1322 data = FikaBackendUtils.TransitData; + data.isLocationTransition = true; + data.transitionCount++; + data.visitedLocations = [.. data.visitedLocations, Location_0.Id]; + FikaBackendUtils.TransitData = data; + } + else + { + FikaBackendUtils.ResetTransitData(); + } + NetworkTimeSync.Reset(); Logger.LogDebug("Stop"); diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index 974c10c2..47eb759c 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -5,7 +5,6 @@ using EFT.Interactive; using EFT.UI; using Fika.Core.Coop.GameMode; -using Fika.Core.Coop.PacketHandlers; using Fika.Core.Coop.Players; using Fika.Core.Coop.Utils; using Fika.Core.Networking; diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs index 45a97a1b..79750a94 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs @@ -98,7 +98,7 @@ public static async Task CreateFikaGame(TarkovApplication instance, TimeAndWeath LocalSettings localSettings = await instance.Session.LocalRaidStarted(localRaidSettings); applicationTraverse.Field("localRaidSettings_0").Value.serverId = localSettings.serverId; applicationTraverse.Field("localRaidSettings_0").Value.selectedLocation = localSettings.locationLoot; - applicationTraverse.Field("localRaidSettings_0").Value.transition = localSettings.transitionSettings; + applicationTraverse.Field("localRaidSettings_0").Value.transition = FikaBackendUtils.TransitData; GClass1284 profileInsurance = localSettings.profileInsurance; if ((profileInsurance?.insuredItems) != null) diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs index a5183a09..c872608e 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGamePreparer_Patch.cs @@ -63,7 +63,7 @@ public static async void Prefix(TarkovApplication __instance, RaidSettings ____r { SetStatusModel status = new(FikaBackendUtils.GroupId, LobbyEntry.ELobbyStatus.COMPLETE); await FikaRequestHandler.UpdateSetStatus(status); - } + } } } diff --git a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs index fbb56e71..283a4469 100644 --- a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs +++ b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs @@ -887,7 +887,7 @@ public override void OnBeenKilledByAggressor(IPlayer aggressor, DamageInfo damag if (FikaPlugin.Instance.SharedQuestProgression && FikaPlugin.EasyKillConditions.Value) { - if (aggressor.Profile.Info.GroupId == "Fika" && !aggressor.IsYourPlayer) + if (aggressor.GroupId == "Fika" && !aggressor.IsYourPlayer) { CoopPlayer mainPlayer = (CoopPlayer)Singleton.Instance.MainPlayer; if (mainPlayer != null) diff --git a/Fika.Core/Coop/Utils/FikaBackendUtils.cs b/Fika.Core/Coop/Utils/FikaBackendUtils.cs index 0476dc71..12b26c78 100644 --- a/Fika.Core/Coop/Utils/FikaBackendUtils.cs +++ b/Fika.Core/Coop/Utils/FikaBackendUtils.cs @@ -37,7 +37,7 @@ public static class FikaBackendUtils public static bool IsHostNatPunch = false; public static string HostLocationId; public static bool RequestFikaWorld = false; - public static Vector3 ReconnectPosition = Vector3.zero; + public static Vector3 ReconnectPosition = Vector3.zero; public static bool IsServer { @@ -63,6 +63,35 @@ public static bool IsSinglePlayer } public static string GroupId { get; set; } public static string RaidCode { get; set; } + public static GClass1322 TransitData + { + get + { + if (transitData == null) + { + return new() + { + isLocationTransition = false, + transitionCount = 0, + transitionRaidId = FikaGlobals.DefaultTransitId, + visitedLocations = [] + }; + } + + return transitData; + } + set + { + transitData = value; + } + } + + private static GClass1322 transitData; + + public static void ResetTransitData() + { + TransitData = null; + } public static bool JoinMatch(string profileId, string serverId, out CreateMatch result, out string errorMessage) { @@ -123,6 +152,6 @@ public static string GenerateRaidCode(int length) } return raidCode; - } + } } } diff --git a/Fika.Core/Coop/Utils/FikaGlobals.cs b/Fika.Core/Coop/Utils/FikaGlobals.cs index 615783e3..e0f1b2df 100644 --- a/Fika.Core/Coop/Utils/FikaGlobals.cs +++ b/Fika.Core/Coop/Utils/FikaGlobals.cs @@ -15,6 +15,7 @@ public static class FikaGlobals { public const string TransitTraderId = "656f0f98d80a697f855d34b1"; public const string TransiterTraderName = "BTR"; + public const string DefaultTransitId = "66f5750951530ca5ae09876d"; public static readonly List BlockedInteractions = [ From 04a133a14678bf1eaac5f7e17570a1bfb6961d7d Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:20:36 +0200 Subject: [PATCH 18/23] Use cached settings between transitions --- .../TarkovApplication_LocalGameCreator_Patch.cs | 14 ++++++++++++++ Fika.Core/Coop/Utils/FikaBackendUtils.cs | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs index 79750a94..37b20728 100644 --- a/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs +++ b/Fika.Core/Coop/Patches/LocalGame/TarkovApplication_LocalGameCreator_Patch.cs @@ -51,6 +51,20 @@ public static async Task CreateFikaGame(TarkovApplication instance, TimeAndWeath bool isServer = FikaBackendUtils.IsServer; bool isTransit = FikaBackendUtils.IsTransit; + if (isServer && !isTransit) + { + FikaBackendUtils.CachedRaidSettings = raidSettings; + } + else if (isServer && isTransit && FikaBackendUtils.CachedRaidSettings != null) + { + Logger.LogInfo("Applying cached raid settings from previous raid"); + RaidSettings cachedSettings = FikaBackendUtils.CachedRaidSettings; + raidSettings.WavesSettings = cachedSettings.WavesSettings; + raidSettings.BotSettings = cachedSettings.BotSettings; + raidSettings.MetabolismDisabled = cachedSettings.MetabolismDisabled; + raidSettings.PlayersSpawnPlace = cachedSettings.PlayersSpawnPlace; + } + metricsEvents.SetGamePrepared(); LocationSettingsClass.Location location = raidSettings.SelectedLocation; diff --git a/Fika.Core/Coop/Utils/FikaBackendUtils.cs b/Fika.Core/Coop/Utils/FikaBackendUtils.cs index 12b26c78..77b1d869 100644 --- a/Fika.Core/Coop/Utils/FikaBackendUtils.cs +++ b/Fika.Core/Coop/Utils/FikaBackendUtils.cs @@ -37,7 +37,8 @@ public static class FikaBackendUtils public static bool IsHostNatPunch = false; public static string HostLocationId; public static bool RequestFikaWorld = false; - public static Vector3 ReconnectPosition = Vector3.zero; + public static Vector3 ReconnectPosition = Vector3.zero; + public static RaidSettings CachedRaidSettings; public static bool IsServer { From 676d6aaaad2746b71a57fb1725737205af30e34a Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:28:35 +0200 Subject: [PATCH 19/23] Add patch to get trader service for clients --- .../Coop/Patches/GClass1616_method_8_Patch.cs | 25 +++++++++++++++++++ Fika.Core/FikaPlugin.cs | 1 + 2 files changed, 26 insertions(+) create mode 100644 Fika.Core/Coop/Patches/GClass1616_method_8_Patch.cs diff --git a/Fika.Core/Coop/Patches/GClass1616_method_8_Patch.cs b/Fika.Core/Coop/Patches/GClass1616_method_8_Patch.cs new file mode 100644 index 00000000..c8dae832 --- /dev/null +++ b/Fika.Core/Coop/Patches/GClass1616_method_8_Patch.cs @@ -0,0 +1,25 @@ +using EFT; +using Fika.Core.Coop.Players; +using Fika.Core.Coop.Utils; +using SPT.Reflection.Patching; +using System.Reflection; + +namespace Fika.Core.Coop.Patches +{ + public class GClass1616_method_8_Patch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return typeof(GClass1616).GetMethod(nameof(GClass1616.method_8)); + } + + [PatchPrefix] + public static void Prefix(Player player) + { + if (FikaBackendUtils.IsClient && player.IsYourPlayer && player is CoopPlayer coopPlayer) + { + coopPlayer.InventoryController.GetTraderServicesDataFromServer(FikaGlobals.TransitTraderId); + } + } + } +} diff --git a/Fika.Core/FikaPlugin.cs b/Fika.Core/FikaPlugin.cs index f602c469..10905776 100644 --- a/Fika.Core/FikaPlugin.cs +++ b/Fika.Core/FikaPlugin.cs @@ -277,6 +277,7 @@ protected void Awake() new AchievementView_Show_Patch().Enable(); new GClass3224_IsValid_Patch().Enable(); new GClass3223_ExceptAI_Patch().Enable(); + new GClass1616_method_8_Patch().Enable(); #if DEBUG TasksExtensions_HandleFinishedTask_Patches.Enable(); From a9b008a32b94ba8c1861c4f22bd7cf3380e5b7ce Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:51:19 +0200 Subject: [PATCH 20/23] Update botcontroller --- Fika.Core/Coop/GameMode/CoopGame.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index e7ca5afb..b7304656 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -156,6 +156,7 @@ internal static CoopGame Create(IInputTree inputTree, Profile profile, GameWorld dateTime = EDateTime.CURR; } + raidSettings.BotSettings.BotAmount = raidSettings.WavesSettings.BotAmount; CoopGame coopGame = smethod_0(inputTree, profile, gameWorld, backendDateTime, insurance, menuUI, gameUI, location, timeAndWeather, wavesSettings, dateTime, callback, fixedDeltaTime, updateQueue, backEndSession, new TimeSpan?(sessionTime), metricsEvents, metricsCollector, localRaidSettings); From fb619ccc6000dbcda9ace193a30f36a8a354bca2 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:51:41 +0200 Subject: [PATCH 21/23] Update method name --- Fika.Core/Coop/HostClasses/FikaHostTransitController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs index 47eb759c..96f13ab4 100644 --- a/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs +++ b/Fika.Core/Coop/HostClasses/FikaHostTransitController.cs @@ -349,11 +349,11 @@ public override void Transit(TransitPoint point, int playersCount, string hash, if (FikaBackendUtils.IsDedicated && !dediTransit) { - ExtractDedi(point); + ExtractDedicatedClient(point); } } - private void ExtractDedi(TransitPoint point) + private void ExtractDedicatedClient(TransitPoint point) { Dictionary keys; dediTransit = true; From c896d62542fb4e391b36212ac9f11ea59dd2c609 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Tue, 8 Oct 2024 18:51:47 +0200 Subject: [PATCH 22/23] Update coopgame --- Fika.Core/Coop/GameMode/CoopGame.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index b7304656..a17842f3 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -157,6 +157,7 @@ internal static CoopGame Create(IInputTree inputTree, Profile profile, GameWorld } raidSettings.BotSettings.BotAmount = raidSettings.WavesSettings.BotAmount; + CoopGame coopGame = smethod_0(inputTree, profile, gameWorld, backendDateTime, insurance, menuUI, gameUI, location, timeAndWeather, wavesSettings, dateTime, callback, fixedDeltaTime, updateQueue, backEndSession, new TimeSpan?(sessionTime), metricsEvents, metricsCollector, localRaidSettings); From 583c11d5ec47c4e71d173ef6de538324158eabc4 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Wed, 9 Oct 2024 07:51:36 +0200 Subject: [PATCH 23/23] Massive rework to weapon packets - Should be faster - Use less memory - Less garbage --- .../CoopClientFirearmController.cs | 141 ++- .../CoopClientGrenadeController.cs | 54 +- .../CoopClientKnifeController.cs | 21 +- .../CoopClientQuickGrenadeController.cs | 15 +- .../CoopObservedFirearmController.cs | 423 ++----- .../Coop/PacketHandlers/PacketReceiver.cs | 2 +- Fika.Core/Coop/Players/CoopPlayer.cs | 132 +- Fika.Core/Networking/FikaClient.cs | 4 +- .../Networking/FikaSerializationExtensions.cs | 573 ++------- Fika.Core/Networking/FikaServer.cs | 4 +- .../FirearmController/FirearmSubPackets.cs | 1121 +++++++++++++++++ .../Packets/FirearmController/WeaponPacket.cs | 201 +-- Fika.Core/Networking/Packets/SubPackets.cs | 135 +- 13 files changed, 1472 insertions(+), 1354 deletions(-) create mode 100644 Fika.Core/Networking/Packets/FirearmController/FirearmSubPackets.cs diff --git a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientFirearmController.cs b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientFirearmController.cs index 3f6cbaf8..ef390ee6 100644 --- a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientFirearmController.cs +++ b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientFirearmController.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using UnityEngine; +using static Fika.Core.Networking.FirearmSubPackets; namespace Fika.Core.Coop.ClientClasses { @@ -103,7 +104,7 @@ public override bool ToggleBipod() { player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleBipod = true + Type = EFirearmSubPacketType.ToggleBipod }); } return success; @@ -116,7 +117,7 @@ public override bool CheckChamber() { player.PacketSender.FirearmPackets.Enqueue(new() { - CheckChamber = true + Type = EFirearmSubPacketType.CheckChamber }); } return flag; @@ -129,7 +130,7 @@ public override bool CheckAmmo() { player.PacketSender.FirearmPackets.Enqueue(new() { - CheckAmmo = true + Type = EFirearmSubPacketType.CheckAmmo }); } return flag; @@ -142,8 +143,11 @@ public override bool ChangeFireMode(Weapon.EFireMode fireMode) { player.PacketSender.FirearmPackets.Enqueue(new() { - ChangeFireMode = true, - FireMode = fireMode + Type = EFirearmSubPacketType.ChangeFireMode, + SubPacket = new ChangeFireModePacket() + { + FireMode = fireMode + } }); } return flag; @@ -154,8 +158,11 @@ public override void ChangeAimingMode() base.ChangeAimingMode(); player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleAim = true, - AimingIndex = IsAiming ? Item.AimIndex.Value : -1 + Type = EFirearmSubPacketType.ToggleAim, + SubPacket = new ToggleAimPacket() + { + AimingIndex = IsAiming ? Item.AimIndex.Value : -1 + } }); } @@ -168,8 +175,11 @@ public override void SetAim(bool value) { player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleAim = true, - AimingIndex = IsAiming ? Item.AimIndex.Value : -1 + Type = EFirearmSubPacketType.ToggleAim, + SubPacket = new ToggleAimPacket() + { + AimingIndex = IsAiming ? Item.AimIndex.Value : -1 + } }); } } @@ -181,8 +191,11 @@ public override void AimingChanged(bool newValue) { player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleAim = true, - AimingIndex = -1 + Type = EFirearmSubPacketType.ToggleAim, + SubPacket = new ToggleAimPacket() + { + AimingIndex = -1 + } }); } } @@ -194,7 +207,7 @@ public override bool CheckFireMode() { player.PacketSender.FirearmPackets.Enqueue(new() { - CheckFireMode = true + Type = EFirearmSubPacketType.CheckFireMode }); } return flag; @@ -205,8 +218,8 @@ public override void DryShot(int chamberIndex = 0, bool underbarrelShot = false) base.DryShot(chamberIndex, underbarrelShot); player.PacketSender.FirearmPackets.Enqueue(new() { - HasShotInfo = true, - ShotInfoPacket = new() + Type = EFirearmSubPacketType.ShotInfo, + SubPacket = new ShotInfoPacket() { ShotType = EShotType.DryFire, ChamberIndex = chamberIndex, @@ -222,7 +235,7 @@ public override bool ExamineWeapon() { player.PacketSender.FirearmPackets.Enqueue(new() { - ExamineWeapon = true + Type = EFirearmSubPacketType.ExamineWeapon }); } return flag; @@ -256,8 +269,8 @@ public override void InitiateShot(IWeapon weapon, BulletClass ammo, Vector3 shot player.PacketSender.FirearmPackets.Enqueue(new() { - HasShotInfo = true, - ShotInfoPacket = new() + Type = EFirearmSubPacketType.ShotInfo, + SubPacket = new ShotInfoPacket() { ShotType = shotType, ShotPosition = shotPosition, @@ -288,7 +301,8 @@ public override void QuickReloadMag(MagazineClass magazine, Callback callback) player.PacketSender.FirearmPackets.Enqueue(new() { - QuickReloadMagPacket = new() + Type = EFirearmSubPacketType.QuickReloadMag, + SubPacket = new QuickReloadMagPacket() { Reload = true, MagId = magazine.Id @@ -337,7 +351,8 @@ public override void ReloadGrenadeLauncher(AmmoPackReloadingClass ammoPack, Call string[] reloadingAmmoIds = ammoPack.GetReloadingAmmoIds(); player.PacketSender.FirearmPackets.Enqueue(new() { - ReloadLauncherPacket = new() + Type = EFirearmSubPacketType.ReloadLauncher, + SubPacket = new ReloadLauncherPacket() { Reload = true, AmmoIds = reloadingAmmoIds @@ -379,11 +394,11 @@ public override bool SetLightsState(FirearmLightStateStruct[] lightsStates, bool { player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleLightStates = true, - LightStatesPacket = new() + Type = EFirearmSubPacketType.ToggleLightStates, + SubPacket = new LightStatesPacket() { Amount = lightsStates.Length, - LightStates = lightsStates + States = lightsStates } }); } @@ -417,11 +432,11 @@ private void SendScopeStates(FirearmScopeStateStruct[] scopeStates) player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleScopeStates = true, - ScopeStatesPacket = new() + Type = EFirearmSubPacketType.ToggleScopeStates, + SubPacket = new ScopeStatesPacket() { Amount = scopeStates.Length, - FirearmScopeStateStruct = scopeStates + States = scopeStates } }); } @@ -451,8 +466,8 @@ public override void ShotMisfired(BulletClass ammo, Weapon.EMalfunctionState mal player.PacketSender.FirearmPackets.Enqueue(new() { - HasShotInfo = true, - ShotInfoPacket = new() + Type = EFirearmSubPacketType.ShotInfo, + SubPacket = new ShotInfoPacket() { ShotType = shotType, Overheat = overheat, @@ -470,7 +485,7 @@ public override bool ToggleLauncher() { player.PacketSender.FirearmPackets.Enqueue(new() { - ToggleLauncher = true + Type = EFirearmSubPacketType.ToggleLauncher }); } return flag; @@ -481,7 +496,7 @@ public override void Loot(bool p) base.Loot(p); player.PacketSender.FirearmPackets.Enqueue(new() { - Loot = p + Type = EFirearmSubPacketType.Loot }); } @@ -490,8 +505,11 @@ public override void SetInventoryOpened(bool opened) base.SetInventoryOpened(opened); player.PacketSender.FirearmPackets.Enqueue(new() { - EnableInventory = true, - InventoryStatus = opened + Type = EFirearmSubPacketType.ToggleInventory, + SubPacket = new ToggleInventoryPacket() + { + Open = opened + } }); } @@ -500,8 +518,11 @@ public override void ChangeLeftStance() base.ChangeLeftStance(); player.PacketSender.FirearmPackets.Enqueue(new() { - HasStanceChange = true, - LeftStanceState = player.MovementContext.LeftStanceEnabled + Type = EFirearmSubPacketType.LeftStanceChange, + SubPacket = new LeftStanceChangePacket() + { + LeftStance = player.MovementContext.LeftStanceEnabled + } }); } @@ -509,8 +530,8 @@ public override void SendStartOneShotFire() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasFlareShot = true, - FlareShotPacket = new() + Type = EFirearmSubPacketType.FlareShot, + SubPacket = new FlareShotPacket() { StartOneShotFire = true } @@ -521,8 +542,8 @@ public override void CreateFlareShot(BulletClass flareItem, Vector3 shotPosition { player.PacketSender.FirearmPackets.Enqueue(new() { - HasFlareShot = true, - FlareShotPacket = new() + Type = EFirearmSubPacketType.FlareShot, + SubPacket = new FlareShotPacket() { ShotPosition = shotPosition, ShotForward = forward, @@ -536,10 +557,11 @@ private void SendAbortReloadPacket(int amount) { player.PacketSender.FirearmPackets.Enqueue(new() { - ReloadWithAmmoPacket = new() + Type = EFirearmSubPacketType.ReloadWithAmmo, + SubPacket = new ReloadWithAmmoPacket() { Reload = true, - Status = SubPackets.EReloadWithAmmoStatus.AbortReload, + Status = EReloadWithAmmoStatus.AbortReload, AmmoLoadedToMag = amount } }); @@ -554,8 +576,11 @@ public override void RollCylinder(bool rollToZeroCamora) player.PacketSender.FirearmPackets.Enqueue(new() { - HasRollCylinder = true, - RollToZeroCamora = rollToZeroCamora + Type = EFirearmSubPacketType.RollCylinder, + SubPacket = new RollCylinderPacket() + { + RollToZeroCamora = rollToZeroCamora + } }); CurrentOperation.RollCylinder(null, rollToZeroCamora); @@ -567,10 +592,11 @@ private void SendEndReloadPacket(int amount) { player.PacketSender.FirearmPackets.Enqueue(new() { - ReloadWithAmmoPacket = new() + Type = EFirearmSubPacketType.ReloadWithAmmo, + SubPacket = new ReloadWithAmmoPacket() { Reload = true, - Status = SubPackets.EReloadWithAmmoStatus.EndReload, + Status = EReloadWithAmmoStatus.EndReload, AmmoLoadedToMag = amount } }); @@ -581,7 +607,7 @@ private void SendBoltActionReloadPacket() { player.PacketSender.FirearmPackets.Enqueue(new() { - ReloadBoltAction = true + Type = EFirearmSubPacketType.ReloadBoltAction }); } @@ -734,7 +760,8 @@ public void Process(IResult result) { coopPlayer.PacketSender.FirearmPackets.Enqueue(new() { - ReloadMagPacket = new() + Type = EFirearmSubPacketType.ReloadMag, + SubPacket = new ReloadMagPacket() { Reload = true, MagId = magazine.Id, @@ -760,17 +787,15 @@ public void Process(IResult result) { coopPlayer.PacketSender.FirearmPackets.Enqueue(new() { - ReloadWithAmmoPacket = new() - { - Reload = true, - Status = SubPackets.EReloadWithAmmoStatus.StartReload, - AmmoIds = ammoIds - }, - CylinderMagPacket = new() + Type = EFirearmSubPacketType.CylinderMag, + SubPacket = new CylinderMagPacket() { Changed = true, CamoraIndex = cylinderMagazine.CurrentCamoraIndex, - HammerClosed = coopClientFirearmController.Item.CylinderHammerClosed + HammerClosed = coopClientFirearmController.Item.CylinderHammerClosed, + Reload = true, + Status = EReloadWithAmmoStatus.StartReload, + AmmoIds = ammoIds } }); } @@ -805,11 +830,12 @@ public void Process(IResult result) { coopPlayer.PacketSender.FirearmPackets.Enqueue(new() { - ReloadBarrelsPacket = new() + Type = EFirearmSubPacketType.ReloadBarrels, + SubPacket = new ReloadBarrelsPacket() { Reload = true, AmmoIds = ammoIds, - LocationDescription = locationDescription, + LocationDescription = locationDescription } }); } @@ -827,10 +853,11 @@ public void Process(IResult result) { coopPlayer.PacketSender.FirearmPackets.Enqueue(new() { - ReloadWithAmmoPacket = new() + Type = EFirearmSubPacketType.ReloadWithAmmo, + SubPacket = new ReloadWithAmmoPacket() { Reload = true, - Status = SubPackets.EReloadWithAmmoStatus.StartReload, + Status = EReloadWithAmmoStatus.StartReload, AmmoIds = ammoIds } }); diff --git a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientGrenadeController.cs b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientGrenadeController.cs index 6a1d72fe..5a7f7142 100644 --- a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientGrenadeController.cs +++ b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientGrenadeController.cs @@ -4,13 +4,13 @@ using EFT; using EFT.InventoryLogic; using Fika.Core.Coop.Players; -using Fika.Core.Networking.Packets; using System; using UnityEngine; +using static Fika.Core.Networking.FirearmSubPackets; namespace Fika.Core.Coop.ClientClasses { - internal class CoopClientGrenadeController : Player.GrenadeHandsController + internal class CoopClientGrenadeController : Player.GrenadeHandsController { protected CoopPlayer player; @@ -25,10 +25,10 @@ public override void ExamineWeapon() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets.GrenadePacketType.ExamineWeapon + PacketType = EGrenadePacketType.ExamineWeapon } }); base.ExamineWeapon(); @@ -38,10 +38,10 @@ public override void HighThrow() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets.GrenadePacketType.HighThrow + PacketType = EGrenadePacketType.HighThrow } }); base.HighThrow(); @@ -51,10 +51,10 @@ public override void LowThrow() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets.GrenadePacketType.LowThrow + PacketType = EGrenadePacketType.LowThrow } }); base.LowThrow(); @@ -64,10 +64,10 @@ public override void PullRingForHighThrow() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets.GrenadePacketType.PullRingForHighThrow + PacketType = EGrenadePacketType.PullRingForHighThrow } }); base.PullRingForHighThrow(); @@ -77,10 +77,10 @@ public override void PullRingForLowThrow() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets.GrenadePacketType.PullRingForLowThrow + PacketType = EGrenadePacketType.PullRingForLowThrow } }); base.PullRingForLowThrow(); @@ -90,10 +90,10 @@ public override void vmethod_2(float timeSinceSafetyLevelRemoved, Vector3 positi { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets .GrenadePacketType.None, + PacketType = EGrenadePacketType.None, HasGrenade = true, GrenadeRotation = rotation, GrenadePosition = position, @@ -108,8 +108,8 @@ public override void PlantTripwire() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { PlantTripwire = true } @@ -133,8 +133,8 @@ public override void ChangeFireMode(Weapon.EFireMode fireMode) { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { ChangeToIdle = true } @@ -145,8 +145,8 @@ public override void ChangeFireMode(Weapon.EFireMode fireMode) { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { ChangeToPlant = true } @@ -162,7 +162,7 @@ public override void ActualDrop(Result controller, float player.PacketSender.FirearmPackets.Enqueue(new() { - CancelGrenade = true + Type = EFirearmSubPacketType.CancelGrenade }); base.ActualDrop(controller, animationSpeed, callback, fastDrop); } diff --git a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientKnifeController.cs b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientKnifeController.cs index d8d21b5f..61184d2a 100644 --- a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientKnifeController.cs +++ b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientKnifeController.cs @@ -2,6 +2,7 @@ using EFT.InventoryLogic; using Fika.Core.Coop.Players; +using static Fika.Core.Networking.FirearmSubPackets; namespace Fika.Core.Coop.ClientClasses { @@ -22,8 +23,8 @@ public override void ExamineWeapon() player.PacketSender.FirearmPackets.Enqueue(new() { - HasKnifePacket = true, - KnifePacket = new() + Type = EFirearmSubPacketType.Knife, + SubPacket = new KnifePacket() { Examine = true } @@ -38,10 +39,10 @@ public override bool MakeKnifeKick() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasKnifePacket = true, - KnifePacket = new() + Type = EFirearmSubPacketType.Knife, + SubPacket = new KnifePacket() { - Kick = knifeKick + Kick = true } }); } @@ -57,10 +58,10 @@ public override bool MakeAlternativeKick() { player.PacketSender.FirearmPackets.Enqueue(new() { - HasKnifePacket = true, - KnifePacket = new() + Type = EFirearmSubPacketType.Knife, + SubPacket = new KnifePacket() { - AltKick = alternateKnifeKick + AltKick = true } }); } @@ -74,8 +75,8 @@ public override void BrakeCombo() player.PacketSender.FirearmPackets.Enqueue(new() { - HasKnifePacket = true, - KnifePacket = new() + Type = EFirearmSubPacketType.Knife, + SubPacket = new KnifePacket() { BreakCombo = true } diff --git a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientQuickGrenadeController.cs b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientQuickGrenadeController.cs index 781bf84f..4b2a320a 100644 --- a/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientQuickGrenadeController.cs +++ b/Fika.Core/Coop/ClientClasses/HandsControllers/CoopClientQuickGrenadeController.cs @@ -1,15 +1,15 @@ // © 2024 Lacyway All Rights Reserved using Fika.Core.Coop.Players; -using Fika.Core.Networking.Packets; using UnityEngine; +using static Fika.Core.Networking.FirearmSubPackets; namespace Fika.Core.Coop.ClientClasses { - /// - /// This is only used by AI - /// - internal class CoopClientQuickGrenadeController : EFT.Player.QuickGrenadeThrowHandsController + /// + /// This is only used by AI + /// + internal class CoopClientQuickGrenadeController : EFT.Player.QuickGrenadeThrowHandsController { protected CoopPlayer player; @@ -24,10 +24,9 @@ public override void vmethod_2(float timeSinceSafetyLevelRemoved, Vector3 positi { player.PacketSender.FirearmPackets.Enqueue(new() { - HasGrenadePacket = true, - GrenadePacket = new() + Type = EFirearmSubPacketType.Grenade, + SubPacket = new GrenadePacket() { - PacketType = SubPackets.GrenadePacketType.None, HasGrenade = true, GrenadeRotation = rotation, GrenadePosition = position, diff --git a/Fika.Core/Coop/ObservedClasses/HandsControllers/CoopObservedFirearmController.cs b/Fika.Core/Coop/ObservedClasses/HandsControllers/CoopObservedFirearmController.cs index 838c5aef..091120e2 100644 --- a/Fika.Core/Coop/ObservedClasses/HandsControllers/CoopObservedFirearmController.cs +++ b/Fika.Core/Coop/ObservedClasses/HandsControllers/CoopObservedFirearmController.cs @@ -13,15 +13,28 @@ using UnityEngine; using static EFT.Player; using static EFT.Player.GrenadeHandsController; +using static Fika.Core.Networking.FirearmSubPackets; namespace Fika.Core.Coop.ObservedClasses { public class CoopObservedFirearmController : FirearmController { + public WeaponPrefab WeaponPrefab + { + get + { + return weaponPrefab; + } + set + { + weaponPrefab = value; + } + } + public CoopPlayer coopPlayer; - bool triggerPressed = false; - bool needsReset = false; - float lastFireTime = 0f; + private bool triggerPressed = false; + private bool needsReset = false; + private float lastFireTime = 0f; public override bool IsTriggerPressed { get @@ -64,7 +77,7 @@ public override Vector3 WeaponDirection { return -CurrentFireport.up; } - } + } public override Dictionary GetOperationFactoryDelegates() { @@ -88,7 +101,7 @@ protected void Start() { _objectInHandsAnimator.SetAiming(false); aimMovementSpeed = coopPlayer.Skills.GetWeaponInfo(Item).AimMovementSpeed; - weaponPrefab = ControllerGameObject.GetComponent(); + WeaponPrefab = ControllerGameObject.GetComponent(); if (UnderbarrelWeapon != null) { underBarrelManager = Traverse.Create(this).Field("GClass1723_0").Value; @@ -228,357 +241,74 @@ public override bool ToggleBipod() return HasBipod && CurrentOperation.ToggleBipod(); } - public void HandleFirearmPacket(ref WeaponPacket packet, InventoryController inventoryController) + public void HandleShotInfoPacket(ref ShotInfoPacket packet, InventoryController inventoryController) { - if (packet.HasShotInfo) - { - if (packet.ShotInfoPacket.ShotType != EShotType.RegularShot && packet.ShotInfoPacket.ShotType != EShotType.DryFire) - { - switch (packet.ShotInfoPacket.ShotType) - { - case EShotType.Misfire: - Weapon.MalfState.State = Weapon.EMalfunctionState.Misfire; - break; - case EShotType.Feed: - Weapon.MalfState.State = Weapon.EMalfunctionState.Feed; - break; - case EShotType.JamedShot: - Weapon.MalfState.State = Weapon.EMalfunctionState.Jam; - break; - case EShotType.SoftSlidedShot: - Weapon.MalfState.State = Weapon.EMalfunctionState.SoftSlide; - break; - case EShotType.HardSlidedShot: - Weapon.MalfState.State = Weapon.EMalfunctionState.HardSlide; - break; - } - - if (string.IsNullOrEmpty(packet.ShotInfoPacket.AmmoTemplate)) - { - FikaPlugin.Instance.FikaLogger.LogError("CoopObservedFirearmController::HandleFirearmPacket: AmmoTemplate was null or empty!"); - return; - } - - Weapon.MalfState.MalfunctionedAmmo = (BulletClass)Singleton.Instance.CreateItem(MongoID.Generate(), packet.ShotInfoPacket.AmmoTemplate, null); - if (weaponPrefab != null) - { - weaponPrefab.InitMalfunctionState(Weapon, false, false, out _); - } - else - { - FikaPlugin.Instance.FikaLogger.LogError("CoopObservedFirearmController::HandleFirearmPacket: WeaponPrefab was null!"); - } - } - else if (packet.ShotInfoPacket.ShotType == EShotType.DryFire) - { - FirearmsAnimator.SetFire(true); - DryShot(); - hasFired = true; - lastFireTime = Time.time; - } - else if (packet.ShotInfoPacket.ShotType == EShotType.RegularShot) - { - HandleObservedShot(ref packet, inventoryController); - } - } - - if (packet.ChangeFireMode) - { - ChangeFireMode(packet.FireMode); - } - - if (packet.ExamineWeapon) - { - ExamineWeapon(); - } - - if (packet.ToggleAim) - { - SetAim(packet.AimingIndex); - } - - if (packet.CheckAmmo) - { - CheckAmmo(); - } - - if (packet.CheckChamber) - { - CheckChamber(); - } - - if (packet.CheckFireMode) - { - CheckFireMode(); - } - - if (packet.ToggleLightStates) - { - SetLightsState(packet.LightStatesPacket.LightStates, true); - } - - if (packet.ToggleScopeStates) - { - SetScopeMode(packet.ScopeStatesPacket.FirearmScopeStateStruct); - } - - if (packet.ToggleLauncher) - { - ToggleLauncher(); - } - - if (packet.EnableInventory) - { - SetInventoryOpened(packet.InventoryStatus); - } - - if (packet.ReloadMagPacket.Reload) - { - MagazineClass magazine = null; - try - { - GStruct428 result = coopPlayer.FindItemById(packet.ReloadMagPacket.MagId); - if (!result.Succeeded) - { - FikaPlugin.Instance.FikaLogger.LogError(result.Error); - return; - } - if (result.Value is MagazineClass magazineClass) - { - magazine = magazineClass; - } - else - { - FikaPlugin.Instance.FikaLogger.LogError($"CoopObservedFirearmController::HandleFirearmPacket::ReloadMagPacket: Item was not MagazineClass, it was {result.Value.GetType()}"); - } - } - catch (Exception ex) - { - FikaPlugin.Instance.FikaLogger.LogError(ex); - FikaPlugin.Instance.FikaLogger.LogError($"CoopObservedFirearmController::HandleFirearmPacket: There is no item {packet.ReloadMagPacket.MagId} in profile {coopPlayer.ProfileId}"); - throw; - } - ItemAddress gridItemAddress = null; - if (packet.ReloadMagPacket.LocationDescription != null) - { - try - { - GClass1170 reader = new(packet.ReloadMagPacket.LocationDescription); - if (packet.ReloadMagPacket.LocationDescription.Length != 0) - { - GClass1664 descriptor = reader.ReadPolymorph(); - gridItemAddress = inventoryController.ToItemAddress(descriptor); - } - } - catch (GException4 exception2) - { - FikaPlugin.Instance.FikaLogger.LogError(exception2); - } - } - if (magazine != null) - { - ReloadMag(magazine, gridItemAddress, null); - } - else - { - FikaPlugin.Instance.FikaLogger.LogError($"CoopObservedFirearmController::HandleFirearmPacket::ReloadMag final variables were null! Mag: {magazine}, Address: {gridItemAddress}"); - } - } - - - if (packet.QuickReloadMagPacket.Reload) - { - try - { - GStruct428 result = coopPlayer.FindItemById(packet.QuickReloadMagPacket.MagId); - if (!result.Succeeded) - { - FikaPlugin.Instance.FikaLogger.LogError(result.Error); - return; - } - if (result.Value is MagazineClass magazine) - { - QuickReloadMag(magazine, null); - } - else - { - FikaPlugin.Instance.FikaLogger.LogError($"CoopObservedFirearmController::HandleFirearmPacket::QuickReloadMag item was not of type MagazineClass, was {result.Value.GetType()}"); - } - } - catch (Exception ex) - { - FikaPlugin.Instance.FikaLogger.LogError(ex); - FikaPlugin.Instance.FikaLogger.LogError($"CoopObservedFirearmController: There is no item {packet.ReloadMagPacket.MagId} in profile {coopPlayer.ProfileId}"); - throw; - } - } - - if (packet.ReloadWithAmmoPacket.Reload) + if (packet.ShotType >= EShotType.Misfire) { - if (packet.ReloadWithAmmoPacket.Status == SubPackets.EReloadWithAmmoStatus.AbortReload) + switch (packet.ShotType) { - CurrentOperation.SetTriggerPressed(true); + case EShotType.Misfire: + Weapon.MalfState.State = Weapon.EMalfunctionState.Misfire; + break; + case EShotType.Feed: + Weapon.MalfState.State = Weapon.EMalfunctionState.Feed; + break; + case EShotType.JamedShot: + Weapon.MalfState.State = Weapon.EMalfunctionState.Jam; + break; + case EShotType.SoftSlidedShot: + Weapon.MalfState.State = Weapon.EMalfunctionState.SoftSlide; + break; + case EShotType.HardSlidedShot: + Weapon.MalfState.State = Weapon.EMalfunctionState.HardSlide; + break; } - if (packet.ReloadWithAmmoPacket.Reload) + if (string.IsNullOrEmpty(packet.AmmoTemplate)) { - if (packet.ReloadWithAmmoPacket.Status == SubPackets.EReloadWithAmmoStatus.StartReload) - { - List bullets = FindAmmoByIds(packet.ReloadWithAmmoPacket.AmmoIds); - AmmoPackReloadingClass ammoPack = new(bullets); - if (!packet.CylinderMagPacket.Changed) - { - CurrentOperation.ReloadWithAmmo(ammoPack, null, null); - } - else - { - CurrentOperation.ReloadCylinderMagazine(ammoPack, null, null); - } - } - - if (packet.CylinderMagPacket.Changed && Weapon.GetCurrentMagazine() is CylinderMagazineClass cylinderMagazine) - { - cylinderMagazine.SetCurrentCamoraIndex(packet.CylinderMagPacket.CamoraIndex); - Weapon.CylinderHammerClosed = packet.CylinderMagPacket.HammerClosed; - } - } - } - - /*if (packet.HasCylinderMagPacket) - { - if (packet.ReloadWithAmmo.Reload && packet.CylinderMag.Changed) - { - if (packet.ReloadWithAmmo.Status == FikaSerialization.ReloadWithAmmoPacket.EReloadWithAmmoStatus.StartReload) - { - List bullets = FindAmmoByIds(packet.ReloadWithAmmo.AmmoIds); - AmmoPackReloadingClass ammoPack = new(bullets); - ReloadCylinderMagazine(ammoPack, null); - } - } - - if (packet.ReloadWithAmmo.Status == FikaSerialization.ReloadWithAmmoPacket.EReloadWithAmmoStatus.AbortReload) - { - CurrentOperation.SetTriggerPressed(true); - } - - - }*/ - - // Check for GClass increment - if (packet.HasRollCylinder && Weapon is GClass2973) - { - RollCylinder(packet.RollToZeroCamora); - } - - if (packet.ReloadLauncherPacket.Reload) - { - List ammo = FindAmmoByIds(packet.ReloadLauncherPacket.AmmoIds); - AmmoPackReloadingClass ammoPack = new(ammo); - ReloadGrenadeLauncher(ammoPack, null); - } - - if (packet.ReloadBarrelsPacket.Reload) - { - List ammo = FindAmmoByIds(packet.ReloadBarrelsPacket.AmmoIds); - - AmmoPackReloadingClass ammoPack = new(ammo); - - ItemAddress gridItemAddress = null; - - GClass1170 reader = new(packet.ReloadBarrelsPacket.LocationDescription); - try - { - if (packet.ReloadBarrelsPacket.LocationDescription.Length > 0) - { - GClass1664 descriptor = reader.ReadPolymorph(); - gridItemAddress = inventoryController.ToItemAddress(descriptor); - } - } - catch (GException4 exception2) - { - FikaPlugin.Instance.FikaLogger.LogError(exception2); + FikaPlugin.Instance.FikaLogger.LogError("CoopObservedFirearmController::HandleShotInfoPacket: AmmoTemplate was null or empty!"); + return; } - if (ammoPack != null) + Weapon.MalfState.MalfunctionedAmmo = (BulletClass)Singleton.Instance.CreateItem(MongoID.Generate(), packet.AmmoTemplate, null); + if (WeaponPrefab != null) { - ReloadBarrels(ammoPack, gridItemAddress, null); + WeaponPrefab.InitMalfunctionState(Weapon, false, false, out _); } else { - FikaPlugin.Instance.FikaLogger.LogError($"CoopObservedFirearmController::HandleFirearmPacket::ReloadBarrel final variables were null! Ammo: {ammoPack}, Address: {gridItemAddress}"); + FikaPlugin.Instance.FikaLogger.LogError("CoopObservedFirearmController::HandleShotInfoPacket: WeaponPrefab was null!"); } + return; } - if (packet.HasStanceChange) - { - if (coopPlayer.MovementContext.LeftStanceEnabled != packet.LeftStanceState) - { - ChangeLeftStance(); - } - } - - if (packet.HasFlareShot) - { - if (packet.FlareShotPacket.StartOneShotFire) - { - FirearmsAnimator.SetFire(true); - // Check for GClass increments - if (Weapon is not GClass2973) - { - FirearmsAnimator.Animator.Play(FirearmsAnimator.FullFireStateName, 1, 0f); - Weapon.Repairable.Durability = 0; - } - else - { - FirearmsAnimator.Animator.Play(FirearmsAnimator.FullDoubleActionFireStateName, 1, 0f); - } - } - else - { - BulletClass bulletClass = (BulletClass)Singleton.Instance.CreateItem(MongoID.Generate(), packet.FlareShotPacket.AmmoTemplateId, null); - InitiateFlare(bulletClass, packet.FlareShotPacket.ShotPosition, packet.FlareShotPacket.ShotForward); - bulletClass.IsUsed = true; - if (weaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) - { - weaponEffectsManager.MoveAmmoFromChamberToShellPort(bulletClass.IsUsed, 0); - } - bulletClass = null; - FirearmsAnimator.SetFire(false); - } - } - - if (packet.ReloadBoltAction) - { - StartCoroutine(ObservedBoltAction(FirearmsAnimator, this, inventoryController)); - } - - if (packet.UnderbarrelSightingRangeUp) - { - UnderbarrelSightingRangeUp(); - } - - if (packet.UnderbarrelSightingRangeDown) + if (packet.ShotType == EShotType.DryFire) { - UnderbarrelSightingRangeDown(); + FirearmsAnimator.SetFire(true); + DryShot(); + hasFired = true; + lastFireTime = Time.time; + return; } - if (packet.ToggleBipod) + if (packet.ShotType == EShotType.RegularShot) { - ToggleBipod(); + HandleObservedShot(ref packet, inventoryController); + return; } } - private void HandleObservedShot(ref WeaponPacket packet, InventoryController inventoryController) + private void HandleObservedShot(ref ShotInfoPacket packet, InventoryController inventoryController) { - if (string.IsNullOrEmpty(packet.ShotInfoPacket.AmmoTemplate)) + if (string.IsNullOrEmpty(packet.AmmoTemplate)) { - FikaPlugin.Instance.FikaLogger.LogError("CoopObservedFirearmController::HandleFirearmPacket: AmmoTemplate was null or empty!"); + FikaPlugin.Instance.FikaLogger.LogError("CoopObservedFirearmController::HandleShotInfoPacket: AmmoTemplate was null or empty!"); return; } - BulletClass ammo = (BulletClass)Singleton.Instance.CreateItem(MongoID.Generate(), packet.ShotInfoPacket.AmmoTemplate, null); - InitiateShot(Item, ammo, packet.ShotInfoPacket.ShotPosition, packet.ShotInfoPacket.ShotDirection, - CurrentFireport.position, packet.ShotInfoPacket.ChamberIndex, packet.ShotInfoPacket.Overheat); + BulletClass ammo = (BulletClass)Singleton.Instance.CreateItem(MongoID.Generate(), packet.AmmoTemplate, null); + InitiateShot(Item, ammo, packet.ShotPosition, packet.ShotDirection, + CurrentFireport.position, packet.ChamberIndex, packet.Overheat); if (Weapon.SelectedFireMode == Weapon.EFireMode.fullauto) { @@ -586,12 +316,12 @@ private void HandleObservedShot(ref WeaponPacket packet, InventoryController inv } float pitchMult = method_60(); - WeaponSoundPlayer.FireBullet(ammo, packet.ShotInfoPacket.ShotPosition, packet.ShotInfoPacket.ShotDirection, + WeaponSoundPlayer.FireBullet(ammo, packet.ShotPosition, packet.ShotDirection, pitchMult, Malfunction, false, IsBirstOf2Start); - Weapon.MalfState.LastShotOverheat = packet.ShotInfoPacket.LastShotOverheat; - Weapon.MalfState.LastShotTime = packet.ShotInfoPacket.LastShotTime; - Weapon.MalfState.SlideOnOverheatReached = packet.ShotInfoPacket.SlideOnOverheatReached; + Weapon.MalfState.LastShotOverheat = packet.LastShotOverheat; + Weapon.MalfState.LastShotTime = packet.LastShotTime; + Weapon.MalfState.SlideOnOverheatReached = packet.SlideOnOverheatReached; triggerPressed = false; hasFired = true; @@ -605,7 +335,7 @@ private void HandleObservedShot(ref WeaponPacket packet, InventoryController inv FirearmsAnimator.SetFire(true); - if (packet.ShotInfoPacket.UnderbarrelShot) + if (packet.UnderbarrelShot) { if (UnderbarrelWeapon.Chamber.ContainedItem is BulletClass grenadeBullet && !grenadeBullet.IsUsed) { @@ -626,7 +356,7 @@ private void HandleObservedShot(ref WeaponPacket packet, InventoryController inv if (Weapon.Chambers[i].ContainedItem is BulletClass bClass && !bClass.IsUsed) { bClass.IsUsed = true; - if (weaponPrefab != null && weaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) + if (WeaponPrefab != null && WeaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) { if (!bClass.AmmoTemplate.RemoveShellAfterFire) { @@ -648,9 +378,9 @@ private void HandleObservedShot(ref WeaponPacket packet, InventoryController inv else { Weapon.Chambers[0].RemoveItem(false); - if (weaponPrefab != null && weaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) + if (WeaponPrefab != null && WeaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) { - HandleShellEvent(weaponEffectsManager, packet, ammo, magazine); + HandleShellEvent(weaponEffectsManager, ref packet, ammo, magazine); } } } @@ -704,12 +434,17 @@ private void HandleObservedShot(ref WeaponPacket packet, InventoryController inv if (ammo.AmmoTemplate.IsLightAndSoundShot) { - method_61(packet.ShotInfoPacket.ShotPosition, packet.ShotInfoPacket.ShotDirection); - LightAndSoundShot(packet.ShotInfoPacket.ShotPosition, packet.ShotInfoPacket.ShotDirection, ammo.AmmoTemplate); + method_61(packet.ShotPosition, packet.ShotDirection); + LightAndSoundShot(packet.ShotPosition, packet.ShotDirection, ammo.AmmoTemplate); } } - private List FindAmmoByIds(string[] ammoIds) + public void HandleObservedBoltAction() + { + StartCoroutine(ObservedBoltAction(FirearmsAnimator, this, coopPlayer.InventoryController)); + } + + public List FindAmmoByIds(string[] ammoIds) { _preallocatedAmmoList.Clear(); foreach (string id in ammoIds) @@ -730,7 +465,7 @@ private IEnumerator ObservedBoltAction(FirearmsAnimator animator, FirearmControl yield return new WaitForSeconds(0.75f); - if (weaponPrefab != null && weaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) + if (WeaponPrefab != null && WeaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) { weaponEffectsManager.StartSpawnShell(coopPlayer.Velocity * 0.66f, 0); } @@ -747,12 +482,12 @@ private IEnumerator ObservedBoltAction(FirearmsAnimator animator, FirearmControl animator.SetFire(false); } - private void HandleShellEvent(WeaponManagerClass weaponEffectsManager, WeaponPacket packet, BulletClass ammo, MagazineClass magazine) + private void HandleShellEvent(WeaponManagerClass weaponEffectsManager, ref ShotInfoPacket packet, BulletClass ammo, MagazineClass magazine) { - weaponEffectsManager.DestroyPatronInWeapon(packet.ShotInfoPacket.ChamberIndex); + weaponEffectsManager.DestroyPatronInWeapon(packet.ChamberIndex); if (!ammo.AmmoTemplate.RemoveShellAfterFire) { - weaponEffectsManager.CreatePatronInShellPort(ammo, packet.ShotInfoPacket.ChamberIndex); + weaponEffectsManager.CreatePatronInShellPort(ammo, packet.ChamberIndex); FirearmsAnimator.SetShellsInWeapon(1); } else diff --git a/Fika.Core/Coop/PacketHandlers/PacketReceiver.cs b/Fika.Core/Coop/PacketHandlers/PacketReceiver.cs index d89716ae..8d428b10 100644 --- a/Fika.Core/Coop/PacketHandlers/PacketReceiver.cs +++ b/Fika.Core/Coop/PacketHandlers/PacketReceiver.cs @@ -93,7 +93,7 @@ protected void Update() { for (int i = 0; i < firearmPackets; i++) { - player.HandleWeaponPacket(FirearmPackets.Dequeue()); + FirearmPackets.Dequeue().SubPacket.Handle(player); } } int damagePackets = DamagePackets.Count; diff --git a/Fika.Core/Coop/Players/CoopPlayer.cs b/Fika.Core/Coop/Players/CoopPlayer.cs index 0b21242e..08796fff 100644 --- a/Fika.Core/Coop/Players/CoopPlayer.cs +++ b/Fika.Core/Coop/Players/CoopPlayer.cs @@ -29,6 +29,7 @@ using System.Threading.Tasks; using UnityEngine; using static Fika.Core.Coop.ClientClasses.CoopClientInventoryController; +using static Fika.Core.Networking.FirearmSubPackets; using static Fika.Core.Networking.Packets.SubPackets; namespace Fika.Core.Coop.Players @@ -508,8 +509,11 @@ public override void SetCompassState(bool value) base.SetCompassState(value); PacketSender.FirearmPackets.Enqueue(new() { - HasCompassChange = true, - CompassState = value + Type = EFirearmSubPacketType.CompassChange, + SubPacket = new CompassChangePacket() + { + Enabled = value + } }); } @@ -1221,130 +1225,6 @@ public void HandleCallbackFromServer(OperationCallbackPacket operationCallbackPa } } - public virtual void HandleWeaponPacket(WeaponPacket packet) - { - if (HandsController is CoopObservedFirearmController firearmController) - { - firearmController.HandleFirearmPacket(ref packet, _inventoryController); - } - - if (packet.Loot) - { - HandsController.Loot(packet.Loot); - } - - if (packet.HasGrenadePacket) - { - if (HandsController is CoopObservedGrenadeController grenadeController) - { - switch (packet.GrenadePacket.PacketType) - { - case GrenadePacketType.ExamineWeapon: - { - grenadeController.ExamineWeapon(); - break; - } - case GrenadePacketType.HighThrow: - { - grenadeController.HighThrow(); - break; - } - case GrenadePacketType.LowThrow: - { - grenadeController.LowThrow(); - break; - } - case GrenadePacketType.PullRingForHighThrow: - { - grenadeController.PullRingForHighThrow(); - break; - } - case GrenadePacketType.PullRingForLowThrow: - { - grenadeController.PullRingForLowThrow(); - break; - } - } - if (packet.GrenadePacket.HasGrenade) - { - grenadeController.SpawnGrenade(0f, packet.GrenadePacket.GrenadePosition, packet.GrenadePacket.GrenadeRotation, packet.GrenadePacket.ThrowForce, packet.GrenadePacket.LowThrow); - } - - if (packet.GrenadePacket.PlantTripwire) - { - grenadeController.PlantTripwire(); - } - - if (packet.GrenadePacket.ChangeToIdle) - { - grenadeController.ChangeFireMode(Weapon.EFireMode.grenadeThrowing); - } - - if (packet.GrenadePacket.ChangeToPlant) - { - grenadeController.ChangeFireMode(Weapon.EFireMode.greanadePlanting); - } - } - else if (HandsController is CoopObservedQuickGrenadeController quickGrenadeController) - { - if (packet.GrenadePacket.HasGrenade) - { - quickGrenadeController.SpawnGrenade(0f, packet.GrenadePacket.GrenadePosition, packet.GrenadePacket.GrenadeRotation, packet.GrenadePacket.ThrowForce, packet.GrenadePacket.LowThrow); - } - } - else - { - FikaPlugin.Instance.FikaLogger.LogError($"HandleFirearmPacket::GrenadePacket: HandsController was not of type CoopObservedGrenadeController! Was {HandsController.GetType().Name}"); - } - } - - if (packet.CancelGrenade) - { - if (HandsController is CoopObservedGrenadeController grenadeController) - { - grenadeController.vmethod_3(); - } - } - - if (packet.HasCompassChange) - { - if (HandsController is ItemHandsController handsController) - { - handsController.CompassState.Value = packet.CompassState; - } - } - - if (packet.HasKnifePacket) - { - if (HandsController is CoopObservedKnifeController knifeController) - { - if (packet.KnifePacket.Examine) - { - knifeController.ExamineWeapon(); - } - - if (packet.KnifePacket.Kick) - { - knifeController.MakeKnifeKick(); - } - - if (packet.KnifePacket.AltKick) - { - knifeController.MakeAlternativeKick(); - } - - if (packet.KnifePacket.BreakCombo) - { - knifeController.BrakeCombo(); - } - } - else - { - FikaPlugin.Instance.FikaLogger.LogError($"HandleFirearmPacket::KnifePacket: HandsController was not of type CoopObservedKnifeController! Was {HandsController.GetType().Name}"); - } - } - } - public override void ApplyExplosionDamageToArmor(Dictionary armorDamage, DamageInfo damageInfo) { if (IsYourPlayer) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index fcf9a4c6..445205b7 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -114,7 +114,7 @@ public async void Init() myProfileId = FikaBackendUtils.Profile.ProfileId; packetProcessor.SubscribeNetSerializable(OnPlayerStatePacketReceived); - packetProcessor.SubscribeNetSerializable(OnFirearmPacketReceived); + packetProcessor.SubscribeNetSerializable(OnWeaponPacketReceived); packetProcessor.SubscribeNetSerializable(OnDamagePacketReceived); packetProcessor.SubscribeNetSerializable(OnArmorDamagePacketReceived); packetProcessor.SubscribeNetSerializable(OnInventoryPacketReceived); @@ -1187,7 +1187,7 @@ private void OnArmorDamagePacketReceived(ArmorDamagePacket packet) } } - private void OnFirearmPacketReceived(WeaponPacket packet) + private void OnWeaponPacketReceived(WeaponPacket packet) { if (coopHandler.Players.TryGetValue(packet.NetId, out CoopPlayer playerToApply)) { diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index 12fc84a4..2e931e25 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -12,6 +12,7 @@ using System.Linq; using UnityEngine; using static BasePhysicalClass; +using static Fika.Core.Networking.FirearmSubPackets; using static Fika.Core.Networking.Packets.SubPackets; namespace Fika.Core.Networking @@ -647,52 +648,6 @@ public static PlayerInfoPacket GetPlayerInfoPacket(this NetDataReader reader) return packet; } - /// - /// Serializes a - /// - /// - /// - public static void PutLightStatesPacket(this NetDataWriter writer, LightStatesPacket packet) - { - writer.Put(packet.Amount); - if (packet.Amount > 0) - { - for (int i = 0; i < packet.Amount; i++) - { - writer.Put(packet.LightStates[i].Id); - writer.Put(packet.LightStates[i].IsActive); - writer.Put(packet.LightStates[i].LightMode); - } - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static LightStatesPacket GetLightStatesPacket(this NetDataReader reader) - { - LightStatesPacket packet = new() - { - Amount = reader.GetInt() - }; - if (packet.Amount > 0) - { - packet.LightStates = new FirearmLightStateStruct[packet.Amount]; - for (int i = 0; i < packet.Amount; i++) - { - packet.LightStates[i] = new() - { - Id = reader.GetString(), - IsActive = reader.GetBool(), - LightMode = reader.GetInt() - }; - } - } - return packet; - } - /// /// Serializes a /// @@ -741,314 +696,6 @@ public static HeadLightsPacket GetHeadLightsPacket(this NetDataReader reader) return packet; } - /// - /// Serializes a - /// - /// - /// - public static void PutScopeStatesPacket(this NetDataWriter writer, ScopeStatesPacket packet) - { - writer.Put(packet.Amount); - if (packet.Amount > 0) - { - for (int i = 0; i < packet.Amount; i++) - { - writer.Put(packet.FirearmScopeStateStruct[i].Id); - writer.Put(packet.FirearmScopeStateStruct[i].ScopeMode); - writer.Put(packet.FirearmScopeStateStruct[i].ScopeIndexInsideSight); - writer.Put(packet.FirearmScopeStateStruct[i].ScopeCalibrationIndex); - } - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static ScopeStatesPacket GetScopeStatesPacket(this NetDataReader reader) - { - ScopeStatesPacket packet = new() - { - Amount = reader.GetInt() - }; - if (packet.Amount > 0) - { - packet.FirearmScopeStateStruct = new FirearmScopeStateStruct[packet.Amount]; - for (int i = 0; i < packet.Amount; i++) - { - packet.FirearmScopeStateStruct[i] = new() - { - Id = reader.GetString(), - ScopeMode = reader.GetInt(), - ScopeIndexInsideSight = reader.GetInt(), - ScopeCalibrationIndex = reader.GetInt() - }; - } - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutReloadMagPacket(this NetDataWriter writer, ReloadMagPacket packet) - { - writer.Put(packet.Reload); - if (packet.Reload) - { - writer.Put(packet.MagId); - writer.PutByteArray(packet.LocationDescription); - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static ReloadMagPacket GetReloadMagPacket(this NetDataReader reader) - { - ReloadMagPacket packet = new() - { - Reload = reader.GetBool() - }; - if (packet.Reload) - { - packet.MagId = reader.GetString(); - packet.LocationDescription = reader.GetByteArray(); - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutQuickReloadMagPacket(this NetDataWriter writer, QuickReloadMagPacket packet) - { - writer.Put(packet.Reload); - if (packet.Reload) - { - writer.Put(packet.MagId); - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static QuickReloadMagPacket GetQuickReloadMagPacket(this NetDataReader reader) - { - QuickReloadMagPacket packet = new() - { - Reload = reader.GetBool() - }; - if (packet.Reload) - { - packet.MagId = reader.GetString(); - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutReloadWithAmmoPacket(this NetDataWriter writer, ReloadWithAmmoPacket packet) - { - writer.Put(packet.Reload); - if (packet.Reload) - { - writer.Put((byte)packet.Status); - if (packet.Status == EReloadWithAmmoStatus.StartReload) - { - writer.PutArray(packet.AmmoIds); - } - if (packet.AmmoLoadedToMag > 0) - { - writer.Put(packet.AmmoLoadedToMag); - } - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static ReloadWithAmmoPacket GetReloadWithAmmoPacket(this NetDataReader reader) - { - ReloadWithAmmoPacket packet = new() - { - Reload = reader.GetBool() - }; - if (packet.Reload) - { - packet.Status = (EReloadWithAmmoStatus)reader.GetByte(); - if (packet.Status == EReloadWithAmmoStatus.StartReload) - { - packet.AmmoIds = reader.GetStringArray(); - } - if (packet.Status is EReloadWithAmmoStatus.EndReload or EReloadWithAmmoStatus.AbortReload) - { - packet.AmmoLoadedToMag = reader.GetInt(); - } - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutCylinderMagPacket(this NetDataWriter writer, CylinderMagPacket packet) - { - writer.Put(packet.Changed); - if (packet.Changed) - { - writer.Put(packet.CamoraIndex); - writer.Put(packet.HammerClosed); - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static CylinderMagPacket GetCylinderMagPacket(this NetDataReader reader) - { - CylinderMagPacket packet = new() - { - Changed = reader.GetBool() - }; - if (packet.Changed) - { - packet.CamoraIndex = reader.GetInt(); - packet.HammerClosed = reader.GetBool(); - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutReloadLauncherPacket(this NetDataWriter writer, ReloadLauncherPacket packet) - { - writer.Put(packet.Reload); - if (packet.Reload) - { - writer.PutArray(packet.AmmoIds); - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static ReloadLauncherPacket GetReloadLauncherPacket(this NetDataReader reader) - { - ReloadLauncherPacket packet = new() - { - Reload = reader.GetBool() - }; - if (packet.Reload) - { - packet.AmmoIds = reader.GetStringArray(); - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutReloadBarrelsPacket(this NetDataWriter writer, ReloadBarrelsPacket packet) - { - writer.Put(packet.Reload); - if (packet.Reload) - { - writer.PutArray(packet.AmmoIds); - writer.PutByteArray(packet.LocationDescription); - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static ReloadBarrelsPacket GetReloadBarrelsPacket(this NetDataReader reader) - { - ReloadBarrelsPacket packet = new() - { - Reload = reader.GetBool() - }; - if (packet.Reload) - { - packet.AmmoIds = reader.GetStringArray(); - packet.LocationDescription = reader.GetByteArray(); - } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutGrenadePacket(this NetDataWriter writer, GrenadePacket packet) - { - writer.Put((int)packet.PacketType); - writer.Put(packet.HasGrenade); - if (packet.HasGrenade) - { - writer.Put(packet.GrenadeRotation); - writer.Put(packet.GrenadePosition); - writer.Put(packet.ThrowForce); - writer.Put(packet.LowThrow); - } - writer.Put(packet.PlantTripwire); - writer.Put(packet.ChangeToIdle); - writer.Put(packet.ChangeToPlant); - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static GrenadePacket GetGrenadePacket(this NetDataReader reader) - { - GrenadePacket packet = new() - { - PacketType = (GrenadePacketType)reader.GetInt(), - HasGrenade = reader.GetBool() - }; - if (packet.HasGrenade) - { - packet.GrenadeRotation = reader.GetQuaternion(); - packet.GrenadePosition = reader.GetVector3(); - packet.ThrowForce = reader.GetVector3(); - packet.LowThrow = reader.GetBool(); - } - packet.PlantTripwire = reader.GetBool(); - packet.ChangeToIdle = reader.GetBool(); - packet.ChangeToPlant = reader.GetBool(); - return packet; - } - /// /// Serializes a /// @@ -1225,77 +872,6 @@ public static StationaryPacket GetStationaryPacket(this NetDataReader reader) packet.Id = reader.GetString(); } - return packet; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutKnifePacket(this NetDataWriter writer, KnifePacket packet) - { - writer.Put(packet.Examine); - writer.Put(packet.Kick); - writer.Put(packet.AltKick); - writer.Put(packet.BreakCombo); - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static KnifePacket GetKnifePacket(this NetDataReader reader) - { - return new KnifePacket() - { - Examine = reader.GetBool(), - Kick = reader.GetBool(), - AltKick = reader.GetBool(), - BreakCombo = reader.GetBool() - }; - } - - /// - /// Serializes a - /// - /// - /// - public static void PutShotInfoPacket(this NetDataWriter writer, ShotInfoPacket packet) - { - writer.Put((int)packet.ShotType); - writer.Put(packet.ShotPosition); - writer.Put(packet.ShotDirection); - writer.Put(packet.ChamberIndex); - writer.Put(packet.Overheat); - writer.Put(packet.UnderbarrelShot); - writer.Put(packet.AmmoTemplate); - writer.Put(packet.LastShotOverheat); - writer.Put(packet.LastShotTime); - writer.Put(packet.SlideOnOverheatReached); - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static ShotInfoPacket GetShotInfoPacket(this NetDataReader reader) - { - ShotInfoPacket packet = new() - { - ShotType = (EShotType)reader.GetInt(), - ShotPosition = reader.GetVector3(), - ShotDirection = reader.GetVector3(), - ChamberIndex = reader.GetInt(), - Overheat = reader.GetFloat(), - UnderbarrelShot = reader.GetBool(), - AmmoTemplate = reader.GetString(), - LastShotOverheat = reader.GetFloat(), - LastShotTime = reader.GetFloat(), - SlideOnOverheatReached = reader.GetBool() - }; return packet; } @@ -1356,42 +932,6 @@ public static WeatherClass GetWeatherClass(this NetDataReader reader) }; } - /// - /// Serializes a - /// - /// - /// - public static void PutFlareShotPacket(this NetDataWriter writer, FlareShotPacket packet) - { - writer.Put(packet.StartOneShotFire); - if (!packet.StartOneShotFire) - { - writer.Put(packet.ShotPosition); - writer.Put(packet.ShotForward); - writer.Put(packet.AmmoTemplateId); - } - } - - /// - /// Deserializes a - /// - /// - /// A with data - public static FlareShotPacket GetFlareShotPacket(this NetDataReader reader) - { - FlareShotPacket packet = new() - { - StartOneShotFire = reader.GetBool() - }; - if (!packet.StartOneShotFire) - { - packet.ShotPosition = reader.GetVector3(); - packet.ShotForward = reader.GetVector3(); - packet.AmmoTemplateId = reader.GetString(); - } - return packet; - } - /// /// Serializes a /// @@ -1629,5 +1169,116 @@ public static MountingPacket GetMountingPacket(this NetDataReader reader) } return packet; } + + public static void PutFirearmSubPacket(this NetDataWriter writer, IFirearmSubPacket packet, EFirearmSubPacketType type) + { + switch (type) + { + case EFirearmSubPacketType.ShotInfo: + case EFirearmSubPacketType.ChangeFireMode: + case EFirearmSubPacketType.ToggleAim: + case EFirearmSubPacketType.ToggleLightStates: + case EFirearmSubPacketType.ToggleScopeStates: + case EFirearmSubPacketType.ToggleInventory: + case EFirearmSubPacketType.LeftStanceChange: + case EFirearmSubPacketType.ReloadMag: + case EFirearmSubPacketType.QuickReloadMag: + case EFirearmSubPacketType.ReloadWithAmmo: + case EFirearmSubPacketType.CylinderMag: + case EFirearmSubPacketType.ReloadLauncher: + case EFirearmSubPacketType.ReloadBarrels: + case EFirearmSubPacketType.Grenade: + case EFirearmSubPacketType.CompassChange: + case EFirearmSubPacketType.Knife: + case EFirearmSubPacketType.FlareShot: + case EFirearmSubPacketType.RollCylinder: + packet.Serialize(writer); + break; + + case EFirearmSubPacketType.ToggleLauncher: + case EFirearmSubPacketType.CancelGrenade: + case EFirearmSubPacketType.ReloadBoltAction: + case EFirearmSubPacketType.UnderbarrelSightingRangeUp: + case EFirearmSubPacketType.UnderbarrelSightingRangeDown: + case EFirearmSubPacketType.ToggleBipod: + case EFirearmSubPacketType.ExamineWeapon: + case EFirearmSubPacketType.CheckAmmo: + case EFirearmSubPacketType.CheckChamber: + case EFirearmSubPacketType.CheckFireMode: + case EFirearmSubPacketType.Loot: + break; + default: + FikaPlugin.Instance.FikaLogger.LogError("IFirearmSubPacket: type was outside of bounds!"); + break; + } + } + + public static IFirearmSubPacket GetFirearmSubPacket(this NetDataReader reader, EFirearmSubPacketType type) + { + switch (type) + { + case EFirearmSubPacketType.ShotInfo: + return new ShotInfoPacket(reader); + case EFirearmSubPacketType.ChangeFireMode: + return new ChangeFireModePacket(reader); + case EFirearmSubPacketType.ToggleAim: + return new ToggleAimPacket(reader); + case EFirearmSubPacketType.ExamineWeapon: + return new ExamineWeaponPacket(); + case EFirearmSubPacketType.CheckAmmo: + return new CheckAmmoPacket(); + case EFirearmSubPacketType.CheckChamber: + return new CheckChamberPacket(); + case EFirearmSubPacketType.CheckFireMode: + return new CheckFireModePacket(); + case EFirearmSubPacketType.ToggleLightStates: + return new LightStatesPacket(reader); + case EFirearmSubPacketType.ToggleScopeStates: + return new ScopeStatesPacket(reader); + case EFirearmSubPacketType.ToggleLauncher: + return new ToggleLauncherPacket(); + case EFirearmSubPacketType.ToggleInventory: + return new ToggleInventoryPacket(reader); + case EFirearmSubPacketType.Loot: + return new FirearmLootPacket(); + case EFirearmSubPacketType.ReloadMag: + return new ReloadMagPacket(reader); + case EFirearmSubPacketType.QuickReloadMag: + return new QuickReloadMagPacket(reader); + case EFirearmSubPacketType.ReloadWithAmmo: + return new ReloadWithAmmoPacket(reader); + case EFirearmSubPacketType.CylinderMag: + return new CylinderMagPacket(reader); + case EFirearmSubPacketType.ReloadLauncher: + return new ReloadLauncherPacket(reader); + case EFirearmSubPacketType.ReloadBarrels: + return new ReloadBarrelsPacket(reader); + case EFirearmSubPacketType.Grenade: + return new GrenadePacket(reader); + case EFirearmSubPacketType.CancelGrenade: + return new CancelGrenadePacket(); + case EFirearmSubPacketType.CompassChange: + return new CompassChangePacket(reader); + case EFirearmSubPacketType.Knife: + return new KnifePacket(reader); + case EFirearmSubPacketType.FlareShot: + return new FlareShotPacket(reader); + case EFirearmSubPacketType.ReloadBoltAction: + return new ReloadBoltActionPacket(); + case EFirearmSubPacketType.RollCylinder: + return new RollCylinderPacket(reader); + case EFirearmSubPacketType.UnderbarrelSightingRangeUp: + return new UnderbarrelSightingRangeUpPacket(); + case EFirearmSubPacketType.UnderbarrelSightingRangeDown: + return new UnderbarrelSightingRangeDownPacket(); + case EFirearmSubPacketType.ToggleBipod: + return new ToggleBipodPacket(); + case EFirearmSubPacketType.LeftStanceChange: + return new LeftStanceChangePacket(reader); + default: + FikaPlugin.Instance.FikaLogger.LogError("IFirearmSubPacket: type was outside of bounds!"); + return null; + } + } } } \ No newline at end of file diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index aeb81eba..3de55efa 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -140,7 +140,7 @@ public async Task Init() currentNetId = 1; packetProcessor.SubscribeNetSerializable(OnPlayerStatePacketReceived); - packetProcessor.SubscribeNetSerializable(OnFirearmPacketReceived); + packetProcessor.SubscribeNetSerializable(OnWeaponPacketReceived); packetProcessor.SubscribeNetSerializable(OnDamagePacketReceived); packetProcessor.SubscribeNetSerializable(OnArmorDamagePacketReceived); packetProcessor.SubscribeNetSerializable(OnInventoryPacketReceived); @@ -1148,7 +1148,7 @@ private void OnArmorDamagePacketReceived(ArmorDamagePacket packet, NetPeer peer) SendDataToAll(ref packet, DeliveryMethod.ReliableOrdered, peer); } - private void OnFirearmPacketReceived(WeaponPacket packet, NetPeer peer) + private void OnWeaponPacketReceived(WeaponPacket packet, NetPeer peer) { if (coopHandler.Players.TryGetValue(packet.NetId, out CoopPlayer playerToApply)) { diff --git a/Fika.Core/Networking/Packets/FirearmController/FirearmSubPackets.cs b/Fika.Core/Networking/Packets/FirearmController/FirearmSubPackets.cs new file mode 100644 index 00000000..8ca810f9 --- /dev/null +++ b/Fika.Core/Networking/Packets/FirearmController/FirearmSubPackets.cs @@ -0,0 +1,1121 @@ +using Comfort.Common; +using EFT; +using EFT.InventoryLogic; +using Fika.Core.Coop.ObservedClasses; +using Fika.Core.Coop.Players; +using LiteNetLib.Utils; +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using UnityEngine; +using static EFT.Player; + +namespace Fika.Core.Networking +{ + public class FirearmSubPackets + { + public enum EFirearmSubPacketType + { + ShotInfo, + ChangeFireMode, + ToggleAim, + ExamineWeapon, + CheckAmmo, + CheckChamber, + CheckFireMode, + ToggleLightStates, + ToggleScopeStates, + ToggleLauncher, + ToggleInventory, + Loot, + ReloadMag, + QuickReloadMag, + ReloadWithAmmo, + CylinderMag, + ReloadLauncher, + ReloadBarrels, + Grenade, + CancelGrenade, + CompassChange, + Knife, + FlareShot, + ReloadBoltAction, + RollCylinder, + UnderbarrelSightingRangeUp, + UnderbarrelSightingRangeDown, + ToggleBipod, + LeftStanceChange + } + + public struct ToggleAimPacket : IFirearmSubPacket + { + public int AimingIndex; + + public ToggleAimPacket(NetDataReader reader) + { + AimingIndex = reader.GetInt(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.SetAim(AimingIndex); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(AimingIndex); + } + } + + public struct ChangeFireModePacket(NetDataReader reader) : IFirearmSubPacket + { + public Weapon.EFireMode FireMode = (Weapon.EFireMode)reader.GetByte(); + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.ChangeFireMode(FireMode); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put((byte)FireMode); + } + } + + public struct ExamineWeaponPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.ExamineWeapon(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct CheckAmmoPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.CheckAmmo(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct ToggleLauncherPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.ToggleLauncher(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct ToggleInventoryPacket : IFirearmSubPacket + { + public bool Open; + + public ToggleInventoryPacket(NetDataReader reader) + { + Open = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.SetInventoryOpened(Open); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Open); + } + } + + public struct FirearmLootPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + player.HandsController.Loot(true); + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct CancelGrenadePacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedGrenadeController grenadeController) + { + grenadeController.vmethod_3(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct CompassChangePacket : IFirearmSubPacket + { + public bool Enabled; + + public CompassChangePacket(NetDataReader reader) + { + Enabled = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is ItemHandsController handsController) + { + handsController.CompassState.Value = Enabled; + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Enabled); + } + } + + public struct LeftStanceChangePacket : IFirearmSubPacket + { + public bool LeftStance; + + public LeftStanceChangePacket(NetDataReader reader) + { + LeftStance = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + if (player.MovementContext.LeftStanceEnabled != LeftStance) + { + controller.ChangeLeftStance(); + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(LeftStance); + } + } + + public struct RollCylinderPacket : IFirearmSubPacket + { + public bool RollToZeroCamora; + + public RollCylinderPacket(NetDataReader reader) + { + RollToZeroCamora = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + // Check for GClass increments + if (player.HandsController is CoopObservedFirearmController controller && controller.Weapon is GClass2973) + { + controller.RollCylinder(RollToZeroCamora); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(RollToZeroCamora); + } + } + + public struct ReloadBoltActionPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.HandleObservedBoltAction(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct CheckChamberPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.CheckChamber(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct CheckFireModePacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.CheckFireMode(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct UnderbarrelSightingRangeUpPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.UnderbarrelSightingRangeUp(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct UnderbarrelSightingRangeDownPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.UnderbarrelSightingRangeDown(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct ToggleBipodPacket : IFirearmSubPacket + { + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.ToggleBipod(); + } + } + + public void Serialize(NetDataWriter writer) + { + throw new NotImplementedException(); + } + } + + public struct ShotInfoPacket : IFirearmSubPacket + { + public EShotType ShotType; + public Vector3 ShotPosition; + public Vector3 ShotDirection; + public int ChamberIndex; + public float Overheat; + public bool UnderbarrelShot; + public string AmmoTemplate; + public float LastShotOverheat; + public float LastShotTime; + public bool SlideOnOverheatReached; + + public ShotInfoPacket(NetDataReader reader) + { + ShotType = (EShotType)reader.GetInt(); + ShotPosition = reader.GetVector3(); + ShotDirection = reader.GetVector3(); + ChamberIndex = reader.GetInt(); + Overheat = reader.GetFloat(); + UnderbarrelShot = reader.GetBool(); + AmmoTemplate = reader.GetString(); + LastShotOverheat = reader.GetFloat(); + LastShotTime = reader.GetFloat(); + SlideOnOverheatReached = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.HandleShotInfoPacket(ref this, player.InventoryController); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put((int)ShotType); + writer.Put(ShotPosition); + writer.Put(ShotDirection); + writer.Put(ChamberIndex); + writer.Put(Overheat); + writer.Put(UnderbarrelShot); + writer.Put(AmmoTemplate); + writer.Put(LastShotOverheat); + writer.Put(LastShotTime); + writer.Put(SlideOnOverheatReached); + } + } + + public struct KnifePacket : IFirearmSubPacket + { + public bool Examine; + public bool Kick; + public bool AltKick; + public bool BreakCombo; + + public KnifePacket(NetDataReader reader) + { + Examine = reader.GetBool(); + Kick = reader.GetBool(); + AltKick = reader.GetBool(); + BreakCombo = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedKnifeController knifeController) + { + if (Examine) + { + knifeController.ExamineWeapon(); + } + + if (Kick) + { + knifeController.MakeKnifeKick(); + } + + if (AltKick) + { + knifeController.MakeAlternativeKick(); + } + + if (BreakCombo) + { + knifeController.BrakeCombo(); + } + } + else + { + FikaPlugin.Instance.FikaLogger.LogError($"KnifePacket: HandsController was not of type CoopObservedKnifeController! Was {player.HandsController.GetType().Name}"); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Examine); + writer.Put(Kick); + writer.Put(AltKick); + writer.Put(BreakCombo); + } + } + + public struct GrenadePacket : IFirearmSubPacket + { + public EGrenadePacketType PacketType; + public bool HasGrenade; + public Quaternion GrenadeRotation; + public Vector3 GrenadePosition; + public Vector3 ThrowForce; + public bool LowThrow; + public bool PlantTripwire; + public bool ChangeToIdle; + public bool ChangeToPlant; + + public GrenadePacket(NetDataReader reader) + { + PacketType = (EGrenadePacketType)reader.GetInt(); + HasGrenade = reader.GetBool(); + if (HasGrenade) + { + GrenadeRotation = reader.GetQuaternion(); + GrenadePosition = reader.GetVector3(); + ThrowForce = reader.GetVector3(); + LowThrow = reader.GetBool(); + } + PlantTripwire = reader.GetBool(); + ChangeToIdle = reader.GetBool(); + ChangeToPlant = reader.GetBool(); + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedGrenadeController controller) + { + switch (PacketType) + { + case EGrenadePacketType.ExamineWeapon: + { + controller.ExamineWeapon(); + break; + } + case EGrenadePacketType.HighThrow: + { + controller.HighThrow(); + break; + } + case EGrenadePacketType.LowThrow: + { + controller.LowThrow(); + break; + } + case EGrenadePacketType.PullRingForHighThrow: + { + controller.PullRingForHighThrow(); + break; + } + case EGrenadePacketType.PullRingForLowThrow: + { + controller.PullRingForLowThrow(); + break; + } + } + if (HasGrenade) + { + controller.SpawnGrenade(0f, GrenadePosition, GrenadeRotation, ThrowForce, LowThrow); + } + + if (PlantTripwire) + { + controller.PlantTripwire(); + } + + if (ChangeToIdle) + { + controller.ChangeFireMode(Weapon.EFireMode.grenadeThrowing); + } + + if (ChangeToPlant) + { + controller.ChangeFireMode(Weapon.EFireMode.greanadePlanting); + } + } + else if (player.HandsController is CoopObservedQuickGrenadeController quickGrenadeController) + { + if (HasGrenade) + { + quickGrenadeController.SpawnGrenade(0f, GrenadePosition, GrenadeRotation, ThrowForce, LowThrow); + } + } + else + { + FikaPlugin.Instance.FikaLogger.LogError($"GrenadePacket: HandsController was not of type CoopObservedGrenadeController! Was {player.HandsController.GetType().Name}"); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put((int)PacketType); + writer.Put(HasGrenade); + if (HasGrenade) + { + writer.Put(GrenadeRotation); + writer.Put(GrenadePosition); + writer.Put(ThrowForce); + writer.Put(LowThrow); + } + writer.Put(PlantTripwire); + writer.Put(ChangeToIdle); + writer.Put(ChangeToPlant); + } + } + + public struct LightStatesPacket : IFirearmSubPacket + { + public int Amount; + public FirearmLightStateStruct[] States; + + public LightStatesPacket(NetDataReader reader) + { + Amount = reader.GetInt(); + if (Amount > 0) + { + States = new FirearmLightStateStruct[Amount]; + for (int i = 0; i < Amount; i++) + { + States[i] = new() + { + Id = reader.GetString(), + IsActive = reader.GetBool(), + LightMode = reader.GetInt() + }; + } + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.SetLightsState(States, true); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Amount); + if (Amount > 0) + { + for (int i = 0; i < Amount; i++) + { + writer.Put(States[i].Id); + writer.Put(States[i].IsActive); + writer.Put(States[i].LightMode); + } + } + } + } + + public struct ScopeStatesPacket : IFirearmSubPacket + { + public int Amount; + public FirearmScopeStateStruct[] States; + + public ScopeStatesPacket(NetDataReader reader) + { + Amount = reader.GetInt(); + if (Amount > 0) + { + States = new FirearmScopeStateStruct[Amount]; + for (int i = 0; i < Amount; i++) + { + States[i] = new() + { + Id = reader.GetString(), + ScopeMode = reader.GetInt(), + ScopeIndexInsideSight = reader.GetInt(), + ScopeCalibrationIndex = reader.GetInt() + }; + } + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + controller.SetScopeMode(States); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Amount); + if (Amount > 0) + { + for (int i = 0; i < Amount; i++) + { + writer.Put(States[i].Id); + writer.Put(States[i].ScopeMode); + writer.Put(States[i].ScopeIndexInsideSight); + writer.Put(States[i].ScopeCalibrationIndex); + } + } + } + } + + public struct ReloadMagPacket : IFirearmSubPacket + { + public bool Reload; + public string MagId; + public byte[] LocationDescription; + + public ReloadMagPacket(NetDataReader reader) + { + Reload = reader.GetBool(); + if (Reload) + { + MagId = reader.GetString(); + LocationDescription = reader.GetByteArray(); + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + MagazineClass magazine = null; + try + { + GStruct428 result = player.FindItemById(MagId); + if (!result.Succeeded) + { + FikaPlugin.Instance.FikaLogger.LogError(result.Error); + return; + } + if (result.Value is MagazineClass magazineClass) + { + magazine = magazineClass; + } + else + { + FikaPlugin.Instance.FikaLogger.LogError($"ReloadMagPacket: Item was not MagazineClass, it was {result.Value.GetType()}"); + } + } + catch (Exception ex) + { + FikaPlugin.Instance.FikaLogger.LogError(ex); + FikaPlugin.Instance.FikaLogger.LogError($"ReloadMagPacket: There is no item {MagId} in profile {player.ProfileId}"); + throw; + } + ItemAddress gridItemAddress = null; + if (LocationDescription != null) + { + try + { + GClass1170 reader = new(LocationDescription); + if (LocationDescription.Length != 0) + { + GClass1664 descriptor = reader.ReadPolymorph(); + gridItemAddress = player.InventoryController.ToItemAddress(descriptor); + } + } + catch (GException4 exception2) + { + FikaPlugin.Instance.FikaLogger.LogError(exception2); + } + } + if (magazine != null) + { + controller.ReloadMag(magazine, gridItemAddress, null); + } + else + { + FikaPlugin.Instance.FikaLogger.LogError($"ReloadMagPacket: final variables were null! Mag: {magazine}, Address: {gridItemAddress}"); + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Reload); + if (Reload) + { + writer.Put(MagId); + writer.PutByteArray(LocationDescription); + } + } + } + + public struct QuickReloadMagPacket : IFirearmSubPacket + { + public bool Reload; + public string MagId; + + public QuickReloadMagPacket(NetDataReader reader) + { + Reload = reader.GetBool(); + if (Reload) + { + MagId = reader.GetString(); + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + try + { + GStruct428 result = player.FindItemById(MagId); + if (!result.Succeeded) + { + FikaPlugin.Instance.FikaLogger.LogError(result.Error); + return; + } + if (result.Value is MagazineClass magazine) + { + controller.QuickReloadMag(magazine, null); + } + else + { + FikaPlugin.Instance.FikaLogger.LogError($"QuickReloadMagPacket: item was not of type MagazineClass, was {result.Value.GetType()}"); + } + } + catch (Exception ex) + { + FikaPlugin.Instance.FikaLogger.LogError(ex); + FikaPlugin.Instance.FikaLogger.LogError($"QuickReloadMagPacket: There is no item {MagId} in profile {player.ProfileId}"); + throw; + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Reload); + if (Reload) + { + writer.Put(MagId); + } + } + } + + public struct ReloadWithAmmoPacket : IFirearmSubPacket + { + public bool Reload; + public EReloadWithAmmoStatus Status; + public int AmmoLoadedToMag; + public string[] AmmoIds; + + public ReloadWithAmmoPacket(NetDataReader reader) + { + Reload = reader.GetBool(); + if (Reload) + { + Status = (EReloadWithAmmoStatus)reader.GetByte(); + if (Status == EReloadWithAmmoStatus.StartReload) + { + AmmoIds = reader.GetStringArray(); + } + if (Status is EReloadWithAmmoStatus.EndReload or EReloadWithAmmoStatus.AbortReload) + { + AmmoLoadedToMag = reader.GetInt(); + } + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + if (Status == EReloadWithAmmoStatus.AbortReload) + { + controller.CurrentOperation.SetTriggerPressed(true); + } + + if (Reload) + { + if (Status == EReloadWithAmmoStatus.StartReload) + { + List bullets = controller.FindAmmoByIds(AmmoIds); + AmmoPackReloadingClass ammoPack = new(bullets); + controller.CurrentOperation.ReloadWithAmmo(ammoPack, null, null); + } + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Reload); + if (Reload) + { + writer.Put((byte)Status); + if (Status == EReloadWithAmmoStatus.StartReload) + { + writer.PutArray(AmmoIds); + } + if (AmmoLoadedToMag > 0) + { + writer.Put(AmmoLoadedToMag); + } + } + } + } + + public struct CylinderMagPacket : IFirearmSubPacket + { + public bool Changed; + public int CamoraIndex; + public bool HammerClosed; + public bool Reload; + public EReloadWithAmmoStatus Status; + public int AmmoLoadedToMag; + public string[] AmmoIds; + + public CylinderMagPacket(NetDataReader reader) + { + Changed = reader.GetBool(); + if (Changed) + { + CamoraIndex = reader.GetInt(); + HammerClosed = reader.GetBool(); + } + Reload = reader.GetBool(); + if (Reload) + { + Status = (EReloadWithAmmoStatus)reader.GetByte(); + AmmoLoadedToMag = reader.GetInt(); + AmmoIds = reader.GetStringArray(); + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + if (Status == EReloadWithAmmoStatus.AbortReload) + { + controller.CurrentOperation.SetTriggerPressed(true); + } + + if (Reload) + { + if (Status == EReloadWithAmmoStatus.StartReload) + { + List bullets = controller.FindAmmoByIds(AmmoIds); + AmmoPackReloadingClass ammoPack = new(bullets); + controller.CurrentOperation.ReloadCylinderMagazine(ammoPack, null, null); + } + } + + if (Changed && controller.Weapon.GetCurrentMagazine() is CylinderMagazineClass cylinder) + { + cylinder.SetCurrentCamoraIndex(CamoraIndex); + controller.Weapon.CylinderHammerClosed = HammerClosed; + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Changed); + if (Changed) + { + writer.Put(CamoraIndex); + writer.Put(HammerClosed); + } + writer.Put(Reload); + if (Reload) + { + writer.Put((byte)Status); + writer.Put(AmmoLoadedToMag); + writer.PutArray(AmmoIds); + } + } + } + + public struct ReloadLauncherPacket : IFirearmSubPacket + { + public bool Reload; + public string[] AmmoIds; + + public ReloadLauncherPacket(NetDataReader reader) + { + Reload = reader.GetBool(); + if (Reload) + { + AmmoIds = reader.GetStringArray(); + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + List ammo = controller.FindAmmoByIds(AmmoIds); + AmmoPackReloadingClass ammoPack = new(ammo); + controller.ReloadGrenadeLauncher(ammoPack, null); + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Reload); + if (Reload) + { + writer.PutArray(AmmoIds); + } + } + } + + public struct ReloadBarrelsPacket : IFirearmSubPacket + { + public bool Reload; + public string[] AmmoIds; + public byte[] LocationDescription; + + public ReloadBarrelsPacket(NetDataReader reader) + { + Reload = reader.GetBool(); + if (Reload) + { + AmmoIds = reader.GetStringArray(); + LocationDescription = reader.GetByteArray(); + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + List ammo = controller.FindAmmoByIds(AmmoIds); + AmmoPackReloadingClass ammoPack = new(ammo); + ItemAddress gridItemAddress = null; + + GClass1170 reader = new(LocationDescription); + try + { + if (LocationDescription.Length > 0) + { + GClass1664 descriptor = reader.ReadPolymorph(); + gridItemAddress = player.InventoryController.ToItemAddress(descriptor); + } + } + catch (GException4 exception2) + { + FikaPlugin.Instance.FikaLogger.LogError(exception2); + } + + if (ammoPack != null) + { + controller.ReloadBarrels(ammoPack, gridItemAddress, null); + } + else + { + FikaPlugin.Instance.FikaLogger.LogError($"ReloadBarrelsPacket: final variables were null! Ammo: {ammoPack}, Address: {gridItemAddress}"); + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Reload); + if (Reload) + { + writer.PutArray(AmmoIds); + writer.PutByteArray(LocationDescription); + } + } + } + + public struct FlareShotPacket : IFirearmSubPacket + { + public bool StartOneShotFire; + public Vector3 ShotPosition; + public Vector3 ShotForward; + public string AmmoTemplateId; + + public FlareShotPacket(NetDataReader reader) + { + StartOneShotFire = reader.GetBool(); + if (!StartOneShotFire) + { + ShotPosition = reader.GetVector3(); + ShotForward = reader.GetVector3(); + AmmoTemplateId = reader.GetString(); + } + } + + public void Handle(CoopPlayer player) + { + if (player.HandsController is CoopObservedFirearmController controller) + { + if (StartOneShotFire) + { + controller.FirearmsAnimator.SetFire(true); + // Check for GClass increments + if (controller.Weapon is not GClass2973) + { + controller.FirearmsAnimator.Animator.Play(controller.FirearmsAnimator.FullFireStateName, 1, 0f); + controller.Weapon.Repairable.Durability = 0; + } + else + { + controller.FirearmsAnimator.Animator.Play(controller.FirearmsAnimator.FullDoubleActionFireStateName, 1, 0f); + } + } + else + { + BulletClass bulletClass = (BulletClass)Singleton.Instance.CreateItem(MongoID.Generate(), AmmoTemplateId, null); + controller.InitiateFlare(bulletClass, ShotPosition, ShotForward); + bulletClass.IsUsed = true; + if (controller.WeaponPrefab.ObjectInHands is WeaponManagerClass weaponEffectsManager) + { + weaponEffectsManager.MoveAmmoFromChamberToShellPort(bulletClass.IsUsed, 0); + } + bulletClass = null; + controller.FirearmsAnimator.SetFire(false); + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(StartOneShotFire); + if (!StartOneShotFire) + { + writer.Put(ShotPosition); + writer.Put(ShotForward); + writer.Put(AmmoTemplateId); + } + } + } + + public interface IFirearmSubPacket + { + public void Handle(CoopPlayer player); + public void Serialize(NetDataWriter writer); + } + + public enum EGrenadePacketType + { + None, + ExamineWeapon, + HighThrow, + LowThrow, + PullRingForHighThrow, + PullRingForLowThrow + }; + + public enum EReloadWithAmmoStatus + { + None = 0, + StartReload, + EndReload, + AbortReload + } + } +} diff --git a/Fika.Core/Networking/Packets/FirearmController/WeaponPacket.cs b/Fika.Core/Networking/Packets/FirearmController/WeaponPacket.cs index 37c9daed..55946cab 100644 --- a/Fika.Core/Networking/Packets/FirearmController/WeaponPacket.cs +++ b/Fika.Core/Networking/Packets/FirearmController/WeaponPacket.cs @@ -1,207 +1,26 @@ -// © 2024 Lacyway All Rights Reserved - -using EFT.InventoryLogic; -using LiteNetLib.Utils; -using static Fika.Core.Networking.Packets.SubPackets; +using LiteNetLib.Utils; +using static Fika.Core.Networking.FirearmSubPackets; namespace Fika.Core.Networking { - public struct WeaponPacket(int netId) : INetSerializable + public struct WeaponPacket : INetSerializable { - public int NetId = netId; - public bool HasShotInfo = false; - public ShotInfoPacket ShotInfoPacket; - public bool ChangeFireMode = false; - public Weapon.EFireMode FireMode; - public bool ToggleAim = false; - public int AimingIndex; - public bool ExamineWeapon = false; - public bool CheckAmmo = false; - public bool CheckChamber = false; - public bool CheckFireMode = false; - public bool ToggleLightStates = false; - public LightStatesPacket LightStatesPacket; - public bool ToggleScopeStates = false; - public ScopeStatesPacket ScopeStatesPacket; - public bool ToggleLauncher = false; - public bool EnableInventory = false; - public bool InventoryStatus = false; - public bool Loot = false; - public ReloadMagPacket ReloadMagPacket; - public QuickReloadMagPacket QuickReloadMagPacket; - public ReloadWithAmmoPacket ReloadWithAmmoPacket; - public CylinderMagPacket CylinderMagPacket; - public ReloadLauncherPacket ReloadLauncherPacket; - public ReloadBarrelsPacket ReloadBarrelsPacket; - public bool HasGrenadePacket = false; - public GrenadePacket GrenadePacket; - public bool CancelGrenade = false; - public bool HasCompassChange = false; - public bool CompassState; - public bool HasKnifePacket = false; - public KnifePacket KnifePacket; - public bool HasStanceChange = false; - public bool LeftStanceState; - public bool HasFlareShot = false; - public FlareShotPacket FlareShotPacket; - public bool ReloadBoltAction = false; - public bool HasRollCylinder = false; - public bool RollToZeroCamora = false; - public bool UnderbarrelSightingRangeUp = false; - public bool UnderbarrelSightingRangeDown = false; - public bool ToggleBipod = false; + public int NetId; + public EFirearmSubPacketType Type; + public IFirearmSubPacket SubPacket; public void Deserialize(NetDataReader reader) { NetId = reader.GetInt(); - HasShotInfo = reader.GetBool(); - if (HasShotInfo) - { - ShotInfoPacket = reader.GetShotInfoPacket(); - } - ChangeFireMode = reader.GetBool(); - FireMode = (Weapon.EFireMode)reader.GetInt(); - ToggleAim = reader.GetBool(); - if (ToggleAim) - { - AimingIndex = reader.GetInt(); - } - ExamineWeapon = reader.GetBool(); - CheckAmmo = reader.GetBool(); - CheckChamber = reader.GetBool(); - CheckFireMode = reader.GetBool(); - ToggleLightStates = reader.GetBool(); - if (ToggleLightStates) - { - LightStatesPacket = reader.GetLightStatesPacket(); - } - - ToggleScopeStates = reader.GetBool(); - if (ToggleScopeStates) - { - ScopeStatesPacket = reader.GetScopeStatesPacket(); - } - ToggleLauncher = reader.GetBool(); - EnableInventory = reader.GetBool(); - InventoryStatus = reader.GetBool(); - Loot = reader.GetBool(); - ReloadMagPacket = reader.GetReloadMagPacket(); - QuickReloadMagPacket = reader.GetQuickReloadMagPacket(); - ReloadWithAmmoPacket = reader.GetReloadWithAmmoPacket(); - CylinderMagPacket = reader.GetCylinderMagPacket(); - ReloadLauncherPacket = reader.GetReloadLauncherPacket(); - ReloadBarrelsPacket = reader.GetReloadBarrelsPacket(); - HasGrenadePacket = reader.GetBool(); - if (HasGrenadePacket) - { - GrenadePacket = reader.GetGrenadePacket(); - } - CancelGrenade = reader.GetBool(); - HasCompassChange = reader.GetBool(); - if (HasCompassChange) - { - CompassState = reader.GetBool(); - } - HasKnifePacket = reader.GetBool(); - if (HasKnifePacket) - { - KnifePacket = reader.GetKnifePacket(); - } - HasStanceChange = reader.GetBool(); - if (HasStanceChange) - { - LeftStanceState = reader.GetBool(); - } - HasFlareShot = reader.GetBool(); - if (HasFlareShot) - { - FlareShotPacket = reader.GetFlareShotPacket(); - } - ReloadBoltAction = reader.GetBool(); - HasRollCylinder = reader.GetBool(); - if (HasRollCylinder) - { - RollToZeroCamora = reader.GetBool(); - } - UnderbarrelSightingRangeUp = reader.GetBool(); - UnderbarrelSightingRangeDown = reader.GetBool(); - ToggleBipod = reader.GetBool(); + Type = (EFirearmSubPacketType)reader.GetByte(); + SubPacket = reader.GetFirearmSubPacket(Type); } public void Serialize(NetDataWriter writer) { writer.Put(NetId); - writer.Put(HasShotInfo); - if (HasShotInfo) - { - writer.PutShotInfoPacket(ShotInfoPacket); - } - writer.Put(ChangeFireMode); - writer.Put((int)FireMode); - writer.Put(ToggleAim); - if (ToggleAim) - { - writer.Put(AimingIndex); - } - writer.Put(ExamineWeapon); - writer.Put(CheckAmmo); - writer.Put(CheckChamber); - writer.Put(CheckFireMode); - writer.Put(ToggleLightStates); - if (ToggleLightStates) - { - writer.PutLightStatesPacket(LightStatesPacket); - } - writer.Put(ToggleScopeStates); - if (ToggleScopeStates) - { - writer.PutScopeStatesPacket(ScopeStatesPacket); - } - writer.Put(ToggleLauncher); - writer.Put(EnableInventory); - writer.Put(InventoryStatus); - writer.Put(Loot); - writer.PutReloadMagPacket(ReloadMagPacket); - writer.PutQuickReloadMagPacket(QuickReloadMagPacket); - writer.PutReloadWithAmmoPacket(ReloadWithAmmoPacket); - writer.PutCylinderMagPacket(CylinderMagPacket); - writer.PutReloadLauncherPacket(ReloadLauncherPacket); - writer.PutReloadBarrelsPacket(ReloadBarrelsPacket); - writer.Put(HasGrenadePacket); - if (HasGrenadePacket) - { - writer.PutGrenadePacket(GrenadePacket); - } - writer.Put(CancelGrenade); - writer.Put(HasCompassChange); - if (HasCompassChange) - { - writer.Put(CompassState); - } - writer.Put(HasKnifePacket); - if (HasKnifePacket) - { - writer.PutKnifePacket(KnifePacket); - } - writer.Put(HasStanceChange); - if (HasStanceChange) - { - writer.Put(LeftStanceState); - } - writer.Put(HasFlareShot); - if (HasFlareShot) - { - writer.PutFlareShotPacket(FlareShotPacket); - } - writer.Put(ReloadBoltAction); - writer.Put(HasRollCylinder); - if (HasRollCylinder) - { - writer.Put(RollToZeroCamora); - } - writer.Put(UnderbarrelSightingRangeUp); - writer.Put(UnderbarrelSightingRangeDown); - writer.Put(ToggleBipod); + writer.Put((byte)Type); + writer.PutFirearmSubPacket(SubPacket, Type); } } } diff --git a/Fika.Core/Networking/Packets/SubPackets.cs b/Fika.Core/Networking/Packets/SubPackets.cs index 8f4d3953..a2f03088 100644 --- a/Fika.Core/Networking/Packets/SubPackets.cs +++ b/Fika.Core/Networking/Packets/SubPackets.cs @@ -24,79 +24,6 @@ public struct PlayerInfoPacket(Profile profile, MongoID? controllerId, ushort fi public bool IsStationary; } - public struct LightStatesPacket - { - public int Amount; - public FirearmLightStateStruct[] LightStates; - } - - public struct HeadLightsPacket - { - public int Amount; - public bool IsSilent; - public FirearmLightStateStruct[] LightStates; - } - - public struct ScopeStatesPacket - { - public int Amount; - public FirearmScopeStateStruct[] FirearmScopeStateStruct; - } - - public struct ReloadMagPacket - { - public bool Reload; - public string MagId; - public byte[] LocationDescription; - } - - public struct QuickReloadMagPacket - { - public bool Reload; - public string MagId; - } - - public struct ReloadWithAmmoPacket - { - public bool Reload; - public EReloadWithAmmoStatus Status; - public int AmmoLoadedToMag; - public string[] AmmoIds; - } - - public struct CylinderMagPacket - { - public bool Changed; - public int CamoraIndex; - public bool HammerClosed; - } - - public struct ReloadLauncherPacket - { - public bool Reload; - public string[] AmmoIds; - } - - public struct ReloadBarrelsPacket - { - public bool Reload; - public string[] AmmoIds; - public byte[] LocationDescription; - } - - public struct GrenadePacket() - { - public GrenadePacketType PacketType; - public bool HasGrenade = false; - public Quaternion GrenadeRotation; - public Vector3 GrenadePosition; - public Vector3 ThrowForce; - public bool LowThrow; - public bool PlantTripwire = false; - public bool ChangeToIdle = false; - public bool ChangeToPlant = false; - } - public struct ItemControllerExecutePacket { public uint CallbackId; @@ -117,6 +44,13 @@ public struct ContainerInteractionPacket public EInteractionType InteractionType; } + public struct HeadLightsPacket + { + public int Amount; + public bool IsSilent; + public FirearmLightStateStruct[] LightStates; + } + public struct ProceedPacket() { public EProceedType ProceedType; @@ -138,29 +72,6 @@ public struct StationaryPacket public string Id; } - public struct KnifePacket() - { - public bool Examine = false; - public bool Kick = false; - public bool AltKick = false; - public bool BreakCombo = false; - } - - public struct ShotInfoPacket() - { - - public EShotType ShotType = EShotType.Unknown; - public Vector3 ShotPosition = Vector3.zero; - public Vector3 ShotDirection = Vector3.zero; - public int ChamberIndex = 0; - public float Overheat = 0f; - public bool UnderbarrelShot = false; - public string AmmoTemplate; - public float LastShotOverheat; - public float LastShotTime; - public bool SlideOnOverheatReached; - } - public struct WeatherClassPacket { public float AtmospherePressure; @@ -181,15 +92,7 @@ public struct WeatherClassPacket public float Turbulence; public float Wind; public int WindDirection; - } - - public struct FlareShotPacket - { - public bool StartOneShotFire; - public Vector3 ShotPosition; - public Vector3 ShotForward; - public string AmmoTemplateId; - } + } public struct VaultPacket { @@ -246,32 +149,14 @@ public struct MountingPacket(GStruct179.EMountingCommand command) public float CurrentMountingPointVerticalOffset; public short MountingDirection; public float TransitionTime; - } - - public enum GrenadePacketType - { - None, - ExamineWeapon, - HighThrow, - LowThrow, - PullRingForHighThrow, - PullRingForLowThrow - }; + } public enum EStationaryCommand { Occupy, Leave, Denied - } - - public enum EReloadWithAmmoStatus - { - None = 0, - StartReload, - EndReload, - AbortReload - } + } public enum EProceedType {