From f3688ff680273a2dfcf84a8815b5650bcdc4d152 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:07:09 +0100 Subject: [PATCH 01/34] Add Rejoin to Enum --- Fika.Core/UI/Models/LobbyEntry.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Fika.Core/UI/Models/LobbyEntry.cs b/Fika.Core/UI/Models/LobbyEntry.cs index 5b7ef5dd..f20bf229 100644 --- a/Fika.Core/UI/Models/LobbyEntry.cs +++ b/Fika.Core/UI/Models/LobbyEntry.cs @@ -43,7 +43,8 @@ public enum ELobbyStatus { LOADING = 0, IN_GAME = 1, - COMPLETE = 2 + COMPLETE = 2, + REJOIN = 3 } } } \ No newline at end of file From 738a1fcc5ae52a65060363ceda249f8c348c3500 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:08:06 +0100 Subject: [PATCH 02/34] add Rejoin option to UIscript (still says join for now, tooltip mentions rejoin) --- Fika.Core/UI/Custom/MatchMakerUIScript.cs | 39 ++++++++++++++--------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/Fika.Core/UI/Custom/MatchMakerUIScript.cs b/Fika.Core/UI/Custom/MatchMakerUIScript.cs index 8c8ec3b6..4cce2b3a 100644 --- a/Fika.Core/UI/Custom/MatchMakerUIScript.cs +++ b/Fika.Core/UI/Custom/MatchMakerUIScript.cs @@ -375,23 +375,32 @@ private void RefreshUI() switch (entry.Status) { - case LobbyEntry.ELobbyStatus.LOADING: + case LobbyEntry.ELobbyStatus.LOADING: + tooltipTextGetter = new() { - tooltipTextGetter = new() - { - TooltipText = "Host is still loading." - }; - - button.enabled = false; - if (image != null) - { - image.color = new(0.5f, image.color.g / 2, image.color.b / 2, 0.75f); - } - - tooltipArea = joinButton.GetOrAddComponent(); - tooltipArea.enabled = true; - tooltipArea.SetMessageText(new Func(tooltipTextGetter.GetText)); + TooltipText = "Host is still loading." + }; + + button.enabled = false; + if (image != null) + { + image.color = new(0.5f, image.color.g / 2, image.color.b / 2, 0.75f); } + + tooltipArea = joinButton.GetOrAddComponent(); + tooltipArea.enabled = true; + tooltipArea.SetMessageText(new Func(tooltipTextGetter.GetText)); + break; + case LobbyEntry.ELobbyStatus.REJOIN: + MatchmakerAcceptPatches.IsReconnect = true; + tooltipTextGetter = new() + { + TooltipText = "Click to Rejoin raid." + }; + + tooltipArea = joinButton.GetOrAddComponent(); + tooltipArea.enabled = true; + tooltipArea.SetMessageText(new Func(tooltipTextGetter.GetText)); break; case LobbyEntry.ELobbyStatus.IN_GAME: tooltipTextGetter = new() From c04b63b4f1bee3b100c3c76d7b260382e7babdc3 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:08:35 +0100 Subject: [PATCH 03/34] Add reconnect packets (to make into one packet) --- .../Packets/Player/ReconnectRequestPacket.cs | 19 ++++ .../Packets/Player/ReconnectResponsePacket.cs | 98 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs create mode 100644 Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs diff --git a/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs new file mode 100644 index 00000000..a7f4b1d1 --- /dev/null +++ b/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs @@ -0,0 +1,19 @@ +using LiteNetLib.Utils; + +namespace Fika.Core.Networking +{ + public struct ReconnectRequestPacket(int netId): INetSerializable + { + public int NetId = netId; + + public void Deserialize(NetDataReader reader) + { + NetId = reader.GetInt(); + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(NetId); + } + } +} \ No newline at end of file diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs new file mode 100644 index 00000000..70a3ecab --- /dev/null +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -0,0 +1,98 @@ +using EFT.Interactive; +using LiteNetLib.Utils; +using UnityEngine; + +namespace Fika.Core.Networking +{ + public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, bool isProne, + WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights): INetSerializable + { + public int NetId = netId; + public Vector3 Position = position; + public Quaternion Rotation = rotation; + public bool IsProne = isProne; + public int InteractiveObjectAmount; + public WorldInteractiveObject.GStruct385[] InteractiveObjects; + public int WindowBreakerAmount; + public WindowBreaker[] Windows; + public int LightAmount; + public LampController[] Lights; + + public void Deserialize(NetDataReader reader) + { + NetId = reader.GetInt(); + Position = reader.GetVector3(); + Rotation = reader.GetQuaternion(); + IsProne = reader.GetBool(); + InteractiveObjectAmount = reader.GetInt(); + + if (InteractiveObjectAmount > 0) + { + InteractiveObjects = new WorldInteractiveObject.GStruct385[InteractiveObjectAmount]; + for (int i = 0; i < InteractiveObjectAmount; i++) + { + InteractiveObjects[i] = reader.GetInteractiveObjectState(); + } + } + + WindowBreakerAmount = reader.GetInt(); + + if (WindowBreakerAmount > 0) + { + Windows = new WindowBreaker[WindowBreakerAmount]; + for (int i = 0; i < WindowBreakerAmount; i++) + { + Windows[i] = reader.GetWindowBreakerState(); + } + } + + LightAmount = reader.GetInt(); + + if (LightAmount > 0) + { + Lights = new LampController[LightAmount]; + for (int i = 0; i < LightAmount; i++) + { + Lights[i] = reader.GetLightState(); + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(NetId); + writer.Put(Position); + writer.Put(Rotation); + writer.Put(IsProne); + writer.Put(interactiveObjects.Length); + + if (interactiveObjects.Length > 0) + { + for (int i = 0; i < interactiveObjects.Length; i++) + { + writer.PutInteractiveObjectState(interactiveObjects[i]); + } + } + + writer.Put(windows.Length); + + if (windows.Length > 0) + { + for (int i = 0; i < windows.Length; i++) + { + writer.PutWindowBreakerState(windows[i]); + } + } + + writer.Put(lights.Length); + + if (lights.Length > 0) + { + for (int i = 0; i < lights.Length; i++) + { + writer.PutLightState(lights[i]); + } + } + } + } +} \ No newline at end of file From 1b0d597a5bd7ab617a7572311399f91b1bd148b5 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:09:42 +0100 Subject: [PATCH 04/34] add de/serialize for interactiveObjects/windows/lights --- .../Networking/FikaSerializationExtensions.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index 2a3ce5b6..c6e7a72f 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -1,5 +1,6 @@ using Comfort.Common; using EFT; +using EFT.Interactive; using EFT.InventoryLogic; using EFT.SynchronizableObjects; using LiteNetLib.Utils; @@ -239,5 +240,54 @@ public static Item GetItem(this NetDataReader reader) return GClass1524.DeserializeItem(Singleton.Instance, [], binaryReader.ReadEFTItemDescriptor()); } + + public static void PutInteractiveObjectState(this NetDataWriter writer, WorldInteractiveObject worldInteractiveObject) + { + writer.Put(worldInteractiveObject.Id); + writer.Put((byte) worldInteractiveObject.DoorState); + writer.Put(Mathf.FloorToInt(worldInteractiveObject.CurrentAngle)); + writer.Put(worldInteractiveObject as Door is Door door ? door.IsBroken: false); + } + + public static WorldInteractiveObject.GStruct385 GetInteractiveObjectState(this NetDataReader reader) + { + return new() + { + Id = reader.GetString(), + State = reader.GetByte(), + Angle = reader.GetInt(), + IsBroken = reader.GetBool() + }; + } + + public static void PutWindowBreakerState(this NetDataWriter writer, WindowBreaker windowBreaker) + { + writer.Put(windowBreaker.Id); + writer.Put(windowBreaker.FirstHitPosition.Value); + } + + public static WindowBreaker GetWindowBreakerState(this NetDataReader reader) + { + return new() + { + Id = reader.GetString(), + FirstHitPosition = reader.GetVector3(), + }; + } + + public static void PutLightState(this NetDataWriter writer, LampController windowBreaker) + { + writer.Put(windowBreaker.NetId); + writer.Put((byte) windowBreaker.LampState); + } + + public static LampController GetLightState(this NetDataReader reader) + { + return new() + { + NetId = reader.GetInt(), + LampState = (Turnable.EState) reader.GetByte() + }; + } } } From 17235412dffe7132a6e34ce9327b73f2efd31053 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:10:39 +0100 Subject: [PATCH 05/34] add reconnect flag and easy access packet location --- .../Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs b/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs index fa521a98..49f75041 100644 --- a/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs +++ b/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs @@ -1,5 +1,6 @@ using EFT; using EFT.UI.Matchmaker; +using Fika.Core.Networking; using Fika.Core.Networking.Http; using Fika.Core.Networking.Http.Models; using System; @@ -32,6 +33,9 @@ public static class MatchmakerAcceptPatches public static WeatherClass[] Nodes { get; set; } = null; private static string groupId; private static long timestamp; + public static bool IsReconnect = false; + public static ReconnectResponsePacket ReconnectPacket; + #endregion #region Static Fields From 5f741044c3601eebce441b995c2dc26aa8a63b40 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:11:16 +0100 Subject: [PATCH 06/34] add reconnecting to CoopGame --- Fika.Core/Coop/GameMode/CoopGame.cs | 31 ++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 45e49632..098f4c5f 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -653,11 +653,40 @@ public override async Task vmethod_2(int playerId, Vector3 position } } - LocalPlayer myPlayer = await CoopPlayer.Create(playerId, spawnPoint.Position, spawnPoint.Rotation, "Player", "Main_", EPointOfView.FirstPerson, profile, + Vector3 PosToSpawn = spawnPoint.Position; + Quaternion RotToSpawn = spawnPoint.Rotation; + if (MatchmakerAcceptPatches.IsReconnect) + { + ReconnectRequestPacket reconnectPacket = new(ProfileId); + Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); + Logger.LogError($"reconnectRequest packet sent"); + + do + { + Logger.LogError("Waiting for ReconnectResponse packet from Host..."); + await Task.Delay(100); + } + while (MatchmakerAcceptPatches.ReconnectPacket.Position == Vector3.zero); + + Logger.LogError($"setting pos to {MatchmakerAcceptPatches.ReconnectPacket.Position}"); + PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Position; + Logger.LogError($"Setting rot to {MatchmakerAcceptPatches.ReconnectPacket.Rotation}"); + RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Rotation; + } + + LocalPlayer myPlayer = await CoopPlayer.Create(playerId, PosToSpawn, RotToSpawn, "Player", "Main_", EPointOfView.FirstPerson, profile, false, UpdateQueue, Player.EUpdateMode.Auto, Player.EUpdateMode.Auto, GClass549.Config.CharacterController.ClientPlayerMode, () => Singleton.Instance.Control.Settings.MouseSensitivity, () => Singleton.Instance.Control.Settings.MouseAimingSensitivity, new GClass1445(), MatchmakerAcceptPatches.IsServer ? 0 : 1000, questController); + if (MatchmakerAcceptPatches.IsReconnect) + { + // finish off setting client up + // currently only prone + // TODO: get pose from server + myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.IsProne; + } + profile.SetSpawnedInSession(profile.Side == EPlayerSide.Savage); if (!CoopHandler.TryGetCoopHandler(out CoopHandler coopHandler)) From 986c5ed3ecc5285256d7877c53af449c7f676f84 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:11:51 +0100 Subject: [PATCH 07/34] Add gathering of things to sync and apply changes on clientside --- Fika.Core/Networking/FikaClient.cs | 35 ++++++++++++++++++++++++++++++ Fika.Core/Networking/FikaServer.cs | 23 ++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index ac6d798b..32986a7f 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -82,6 +82,7 @@ protected void Start() packetProcessor.SubscribeNetSerializable(OnAssignNetIdPacketReceived); packetProcessor.SubscribeNetSerializable(OnSyncNetIdPacketReceived); packetProcessor.SubscribeNetSerializable(OnOperationCallbackPacketReceived); + packetProcessor.SubscribeNetSerializable(OnReconnectResponsePacketReceived); _netClient = new NetManager(this) { @@ -188,6 +189,40 @@ private void OnAssignNetIdPacketReceived(AssignNetIdPacket packet, NetPeer peer) Players[packet.NetId] = MyPlayer; } + private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, NetPeer peer) + { + ClientGameWorld gameWorld = Singleton.Instance as ClientGameWorld; + + MatchmakerAcceptPatches.IsReconnect = true; + MatchmakerAcceptPatches.ReconnectPacket = packet; + + // TODO: turn into Coroutine for server/client + // doors/keycard doors/trunks + WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting).ToArray(); + for (int i = 0; i < packet.InteractiveObjectAmount; i++) + { + interactiveObjects[i].SetFromStatusInfo(packet.InteractiveObjects[i]); + } + + // Windows + for (int i = 0; i < packet.WindowBreakerAmount; i++) + { + gameWorld.method_20(packet.Windows[i].Id.GetHashCode(), packet.Windows[i].FirstHitPosition.Value); + } + + // lights + LampController[]lights = LocationScene.GetAllObjects(true).ToArray(); + for (int i = 0; i < packet.LightAmount; i++) + { + lights[i].Switch(packet.Lights[i].LampState); + } + + // TODO: smokes + // serialize - World.method_8 + // deserialize - ClientWorld.method_28 + // GStruct34 for packet + } + private void OnSendCharacterPacketReceived(SendCharacterPacket packet, NetPeer peer) { if (packet.PlayerInfo.Profile.ProfileId != MyPlayer.ProfileId) diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 1b2b15cb..f86bc4df 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -80,6 +80,7 @@ public async void Start() packetProcessor.SubscribeNetSerializable(OnMinePacketReceived); packetProcessor.SubscribeNetSerializable(OnBorderZonePacketReceived); packetProcessor.SubscribeNetSerializable(OnSendCharacterPacketReceived); + packetProcessor.SubscribeNetSerializable(OnReconnectRequestPacketReceived); _netServer = new NetManager(this) { @@ -161,6 +162,7 @@ await Task.Run(async () => ServerReady = true; } + public int PopNetId() { int netId = _currentNetId; @@ -169,6 +171,27 @@ public int PopNetId() return netId; } + private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, NetPeer peer) + { + serverLogger.LogError($"Player Wanting to reconnect {packet.ProfileId}"); + + var player = Players.TryGetValue(packet.ProfileId, out CoopPlayer playerToApply); + + if (!player) + { + serverLogger.LogError($"Player was not found"); + } + + // TODO: double check doors are working + WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting).ToArray(); + WindowBreaker[] windows = Singleton.Instance?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); + LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); + + ReconnectResponsePacket responsePacket = new(packet.ProfileId, playerToApply.Transform.position, playerToApply.Transform.rotation, playerToApply.IsInPronePose, interactiveObjects, windows, lights); + _dataWriter.Reset(); + SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); + } + private void OnSendCharacterPacketReceived(SendCharacterPacket packet, NetPeer peer) { int netId = PopNetId(); From 2c9b474fa1135926bf25cab376bf94374abdb023 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:22:21 +0100 Subject: [PATCH 08/34] change to be NetID instead of profileID --- Fika.Core/Networking/FikaServer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index f86bc4df..a226cfed 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -173,9 +173,9 @@ public int PopNetId() private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, NetPeer peer) { - serverLogger.LogError($"Player Wanting to reconnect {packet.ProfileId}"); + serverLogger.LogError($"Player Wanting to reconnect {packet.NetId}"); - var player = Players.TryGetValue(packet.ProfileId, out CoopPlayer playerToApply); + var player = Players.TryGetValue(packet.NetId, out CoopPlayer playerToApply); if (!player) { @@ -187,7 +187,7 @@ private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, Net WindowBreaker[] windows = Singleton.Instance?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); - ReconnectResponsePacket responsePacket = new(packet.ProfileId, playerToApply.Transform.position, playerToApply.Transform.rotation, playerToApply.IsInPronePose, interactiveObjects, windows, lights); + ReconnectResponsePacket responsePacket = new(packet.NetId, playerToApply.Transform.position, playerToApply.Transform.rotation, playerToApply.IsInPronePose, interactiveObjects, windows, lights); _dataWriter.Reset(); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } From 6a9aa6a06c886f637f82918180942ae0cde7ac24 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 11:35:38 +0100 Subject: [PATCH 09/34] to Fix logic --- Fika.Core/Networking/FikaClient.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 32986a7f..f4908d60 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -201,6 +201,7 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, N WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting).ToArray(); for (int i = 0; i < packet.InteractiveObjectAmount; i++) { + // TODO: this is totally wrong logic, to fix interactiveObjects[i].SetFromStatusInfo(packet.InteractiveObjects[i]); } @@ -214,6 +215,7 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, N LampController[]lights = LocationScene.GetAllObjects(true).ToArray(); for (int i = 0; i < packet.LightAmount; i++) { + // TODO: this is totally wrong logic, to fix lights[i].Switch(packet.Lights[i].LampState); } From fa54e94591142b63d9faefd669558b837efe4b6f Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 12:35:57 +0100 Subject: [PATCH 10/34] commented out syncing code for now since updating to latest Dev, lost the ability to reconnect and see syncing on both host/client, client syncs to host, Host does not for client --- Fika.Core/Coop/GameMode/CoopGame.cs | 2 +- Fika.Core/Networking/FikaClient.cs | 57 +++++++++++++++-------------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 098f4c5f..031115c0 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -657,7 +657,7 @@ public override async Task vmethod_2(int playerId, Vector3 position Quaternion RotToSpawn = spawnPoint.Rotation; if (MatchmakerAcceptPatches.IsReconnect) { - ReconnectRequestPacket reconnectPacket = new(ProfileId); + ReconnectRequestPacket reconnectPacket = new(playerId); Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); Logger.LogError($"reconnectRequest packet sent"); diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index f4908d60..eae35880 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -196,33 +196,36 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, N MatchmakerAcceptPatches.IsReconnect = true; MatchmakerAcceptPatches.ReconnectPacket = packet; - // TODO: turn into Coroutine for server/client - // doors/keycard doors/trunks - WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting).ToArray(); - for (int i = 0; i < packet.InteractiveObjectAmount; i++) - { - // TODO: this is totally wrong logic, to fix - interactiveObjects[i].SetFromStatusInfo(packet.InteractiveObjects[i]); - } - - // Windows - for (int i = 0; i < packet.WindowBreakerAmount; i++) - { - gameWorld.method_20(packet.Windows[i].Id.GetHashCode(), packet.Windows[i].FirstHitPosition.Value); - } - - // lights - LampController[]lights = LocationScene.GetAllObjects(true).ToArray(); - for (int i = 0; i < packet.LightAmount; i++) - { - // TODO: this is totally wrong logic, to fix - lights[i].Switch(packet.Lights[i].LampState); - } - - // TODO: smokes - // serialize - World.method_8 - // deserialize - ClientWorld.method_28 - // GStruct34 for packet + // // TODO: turn into Coroutine for server/client + // // doors/keycard doors/trunks + // WorldInteractiveObject[] interactiveObjects = FindObjectsOfType(); + // for (int i = 0; i < packet.InteractiveObjectAmount; i++) + // { + // WorldInteractiveObject.GStruct385 packetInteractiveObject = packet.InteractiveObjects[i]; + // // find interactive object with id + // WorldInteractiveObject interactiveObject = interactiveObjects.FirstOrDefault(x => x.Id == packetInteractiveObject.Id); + // interactiveObject?.SetFromStatusInfo(packetInteractiveObject); + // } + + // // Windows + // for (int i = 0; i < packet.WindowBreakerAmount; i++) + // { + // gameWorld.method_20(packet.Windows[i].Id.GetHashCode(), packet.Windows[i].FirstHitPosition.Value); + // } + + // // lights + // LampController[] clientLights = LocationScene.GetAllObjects(true).ToArray(); + // for (int i = 0; i < packet.LightAmount; i++) + // { + // LampController lampController = packet.Lights[i]; + // LampController clientLightToChange = clientLights.FirstOrDefault(x => x.NetId == lampController.NetId); + // clientLightToChange?.Switch(lampController.LampState); + // } + + // // TODO: smokes + // // serialize - World.method_8 + // // deserialize - ClientWorld.method_28 + // // GStruct34 for packet } private void OnSendCharacterPacketReceived(SendCharacterPacket packet, NetPeer peer) From f3b7162e12c4456f321b62390f0a560ab1d40740 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 14:35:20 +0100 Subject: [PATCH 11/34] change requestpacket back to profileId, move pose set up to a little later --- Fika.Core/Coop/GameMode/CoopGame.cs | 22 +++++++++---------- .../Packets/Player/ReconnectRequestPacket.cs | 8 +++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 031115c0..e02ccefb 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -657,9 +657,9 @@ public override async Task vmethod_2(int playerId, Vector3 position Quaternion RotToSpawn = spawnPoint.Rotation; if (MatchmakerAcceptPatches.IsReconnect) { - ReconnectRequestPacket reconnectPacket = new(playerId); + ReconnectRequestPacket reconnectPacket = new(ProfileId); Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); - Logger.LogError($"reconnectRequest packet sent"); + Logger.LogError($"reconnectRequest packet sent for netId: {playerId} with profileId: {ProfileId}"); do { @@ -679,14 +679,6 @@ public override async Task vmethod_2(int playerId, Vector3 position GClass549.Config.CharacterController.ClientPlayerMode, () => Singleton.Instance.Control.Settings.MouseSensitivity, () => Singleton.Instance.Control.Settings.MouseAimingSensitivity, new GClass1445(), MatchmakerAcceptPatches.IsServer ? 0 : 1000, questController); - if (MatchmakerAcceptPatches.IsReconnect) - { - // finish off setting client up - // currently only prone - // TODO: get pose from server - myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.IsProne; - } - profile.SetSpawnedInSession(profile.Side == EPlayerSide.Savage); if (!CoopHandler.TryGetCoopHandler(out CoopHandler coopHandler)) @@ -695,7 +687,15 @@ public override async Task vmethod_2(int playerId, Vector3 position await Task.Delay(5000); } - CoopPlayer coopPlayer = (CoopPlayer)myPlayer; + CoopPlayer coopPlayer = (CoopPlayer) myPlayer; + + if (MatchmakerAcceptPatches.IsReconnect) + { + // TODO: get pose from server + myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.IsProne; + coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.NetId; + } + coopHandler.Players.Add(coopPlayer.NetId, coopPlayer); PlayerSpawnRequest body = new PlayerSpawnRequest(myPlayer.ProfileId, MatchmakerAcceptPatches.GetGroupId()); diff --git a/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs index a7f4b1d1..29a215aa 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectRequestPacket.cs @@ -2,18 +2,18 @@ namespace Fika.Core.Networking { - public struct ReconnectRequestPacket(int netId): INetSerializable + public struct ReconnectRequestPacket(string profileId): INetSerializable { - public int NetId = netId; + public string ProfileId = profileId; public void Deserialize(NetDataReader reader) { - NetId = reader.GetInt(); + ProfileId = reader.GetString(); } public void Serialize(NetDataWriter writer) { - writer.Put(NetId); + writer.Put(ProfileId); } } } \ No newline at end of file From a2eb021382ac0136888c0fe88f9c045223df27ef Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 10 May 2024 14:36:04 +0100 Subject: [PATCH 12/34] re-enable syncing of windows/lights/doors, stop reassignment of netid when reconnecting --- Fika.Core/Networking/FikaClient.cs | 72 +++++++++++++++++------------- Fika.Core/Networking/FikaServer.cs | 10 ++--- 2 files changed, 46 insertions(+), 36 deletions(-) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index eae35880..82f7aace 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -137,6 +137,12 @@ private void OnOperationCallbackPacketReceived(OperationCallbackPacket packet, N private void OnSyncNetIdPacketReceived(SyncNetIdPacket packet, NetPeer peer) { + if (MatchmakerAcceptPatches.IsReconnect) + { + FikaPlugin.Instance.FikaLogger.LogInfo($"OnSyncNetIdPacketReceived: Client is reconnecting, ignore Sync."); + return; + } + Dictionary newPlayers = Players; if (Players.TryGetValue(packet.NetId, out CoopPlayer player)) { @@ -166,6 +172,12 @@ private void OnSyncNetIdPacketReceived(SyncNetIdPacket packet, NetPeer peer) private void OnAssignNetIdPacketReceived(AssignNetIdPacket packet, NetPeer peer) { + if (MatchmakerAcceptPatches.IsReconnect) + { + FikaPlugin.Instance.FikaLogger.LogInfo($"OnAssignNetIdPacketReceived: Client is reconnecting, ignore assignment."); + return; + } + FikaPlugin.Instance.FikaLogger.LogInfo($"OnAssignNetIdPacketReceived: Assigned NetId {packet.NetId} to my own client."); MyPlayer.NetId = packet.NetId; int i = -1; @@ -196,36 +208,36 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, N MatchmakerAcceptPatches.IsReconnect = true; MatchmakerAcceptPatches.ReconnectPacket = packet; - // // TODO: turn into Coroutine for server/client - // // doors/keycard doors/trunks - // WorldInteractiveObject[] interactiveObjects = FindObjectsOfType(); - // for (int i = 0; i < packet.InteractiveObjectAmount; i++) - // { - // WorldInteractiveObject.GStruct385 packetInteractiveObject = packet.InteractiveObjects[i]; - // // find interactive object with id - // WorldInteractiveObject interactiveObject = interactiveObjects.FirstOrDefault(x => x.Id == packetInteractiveObject.Id); - // interactiveObject?.SetFromStatusInfo(packetInteractiveObject); - // } - - // // Windows - // for (int i = 0; i < packet.WindowBreakerAmount; i++) - // { - // gameWorld.method_20(packet.Windows[i].Id.GetHashCode(), packet.Windows[i].FirstHitPosition.Value); - // } - - // // lights - // LampController[] clientLights = LocationScene.GetAllObjects(true).ToArray(); - // for (int i = 0; i < packet.LightAmount; i++) - // { - // LampController lampController = packet.Lights[i]; - // LampController clientLightToChange = clientLights.FirstOrDefault(x => x.NetId == lampController.NetId); - // clientLightToChange?.Switch(lampController.LampState); - // } - - // // TODO: smokes - // // serialize - World.method_8 - // // deserialize - ClientWorld.method_28 - // // GStruct34 for packet + // TODO: turn into Coroutine for server/client + // doors/keycard doors/trunks + WorldInteractiveObject[] interactiveObjects = FindObjectsOfType(); + for (int i = 0; i < packet.InteractiveObjectAmount; i++) + { + WorldInteractiveObject.GStruct385 packetInteractiveObject = packet.InteractiveObjects[i]; + // find interactive object with id + WorldInteractiveObject interactiveObject = interactiveObjects.FirstOrDefault(x => x.Id == packetInteractiveObject.Id); + interactiveObject?.SetFromStatusInfo(packetInteractiveObject); + } + + // Windows + for (int i = 0; i < packet.WindowBreakerAmount; i++) + { + gameWorld.method_20(packet.Windows[i].Id.GetHashCode(), packet.Windows[i].FirstHitPosition.Value); + } + + // lights + LampController[] clientLights = LocationScene.GetAllObjects(true).ToArray(); + for (int i = 0; i < packet.LightAmount; i++) + { + LampController lampController = packet.Lights[i]; + LampController clientLightToChange = clientLights.FirstOrDefault(x => x.NetId == lampController.NetId); + clientLightToChange?.Switch(lampController.LampState); + } + + // TODO: smokes + // serialize - World.method_8 + // deserialize - ClientWorld.method_28 + // GStruct34 for packet } private void OnSendCharacterPacketReceived(SendCharacterPacket packet, NetPeer peer) diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index a226cfed..a5f0a3fd 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -173,11 +173,10 @@ public int PopNetId() private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, NetPeer peer) { - serverLogger.LogError($"Player Wanting to reconnect {packet.NetId}"); + serverLogger.LogError($"Player Wanting to reconnect {packet.ProfileId}"); + CoopPlayer playerToUse = Players.FirstOrDefault((v) => v.Value.ProfileId == packet.ProfileId).Value; - var player = Players.TryGetValue(packet.NetId, out CoopPlayer playerToApply); - - if (!player) + if (playerToUse == null) { serverLogger.LogError($"Player was not found"); } @@ -187,8 +186,7 @@ private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, Net WindowBreaker[] windows = Singleton.Instance?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); - ReconnectResponsePacket responsePacket = new(packet.NetId, playerToApply.Transform.position, playerToApply.Transform.rotation, playerToApply.IsInPronePose, interactiveObjects, windows, lights); - _dataWriter.Reset(); + ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.IsInPronePose, interactiveObjects, windows, lights); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } From 4fcd51805bb3c1f7d6e2c702807ab11dcf249919 Mon Sep 17 00:00:00 2001 From: CWX Date: Sat, 11 May 2024 16:11:33 +0100 Subject: [PATCH 13/34] change syncing to coroutine --- Fika.Core/Networking/FikaClient.cs | 32 +++++++++++++++++++++--------- Fika.Core/Networking/FikaServer.cs | 24 +++++++++++++++++++--- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 82f7aace..31a80df8 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -23,6 +23,7 @@ using LiteNetLib; using LiteNetLib.Utils; using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net; @@ -203,13 +204,22 @@ private void OnAssignNetIdPacketReceived(AssignNetIdPacket packet, NetPeer peer) private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, NetPeer peer) { - ClientGameWorld gameWorld = Singleton.Instance as ClientGameWorld; - MatchmakerAcceptPatches.IsReconnect = true; MatchmakerAcceptPatches.ReconnectPacket = packet; - // TODO: turn into Coroutine for server/client - // doors/keycard doors/trunks + StartCoroutine(SyncClientToHost(packet)); + } + + public IEnumerator SyncClientToHost(ReconnectResponsePacket packet) + { + while (!Singleton.Instantiated) + { + yield return null; + } + + ClientGameWorld gameWorld = Singleton.Instance as ClientGameWorld; + + // interactables WorldInteractiveObject[] interactiveObjects = FindObjectsOfType(); for (int i = 0; i < packet.InteractiveObjectAmount; i++) { @@ -234,10 +244,14 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet, N clientLightToChange?.Switch(lampController.LampState); } - // TODO: smokes - // serialize - World.method_8 - // deserialize - ClientWorld.method_28 - // GStruct34 for packet + // smokes + List smokes = new(); + for (int i = 0; i < packet.SmokeAmount; i++) + { + smokes.Add(packet.Smokes[i]); + } + // FIXME: currently ERRORS on bundles not being loaded, maybe delay till after people have spawned + //gameWorld.OnSmokeGrenadesDeserialized(smokes); } private void OnSendCharacterPacketReceived(SendCharacterPacket packet, NetPeer peer) @@ -539,7 +553,7 @@ private void OnAirdropLootPacketReceived(AirdropLootPacket packet, NetPeer peer) else { clientLogger.LogError("OnAirdropLootPacketReceived: Received loot package but manager is not instantiated!"); - } + } } private void OnAirdropPacketReceived(AirdropPacket packet, NetPeer peer) diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index a5f0a3fd..864c954d 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -19,6 +19,7 @@ using LiteNetLib.Utils; using Open.Nat; using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net; @@ -174,6 +175,23 @@ public int PopNetId() private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, NetPeer peer) { serverLogger.LogError($"Player Wanting to reconnect {packet.ProfileId}"); + StartCoroutine(SyncClientToHost(packet, peer)); + } + + public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) + { + while (!Singleton.Instantiated) + { + yield return null; + } + + ClientGameWorld gameWorld = Singleton.Instance as ClientGameWorld; + + while (string.IsNullOrEmpty(gameWorld.MainPlayer.Location)) + { + yield return null; + } + CoopPlayer playerToUse = Players.FirstOrDefault((v) => v.Value.ProfileId == packet.ProfileId).Value; if (playerToUse == null) @@ -181,12 +199,12 @@ private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, Net serverLogger.LogError($"Player was not found"); } - // TODO: double check doors are working WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting).ToArray(); - WindowBreaker[] windows = Singleton.Instance?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); + WindowBreaker[] windows = gameWorld?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); + Throwable[] smokes = gameWorld.Grenades.Where(x => x as SmokeGrenade is SmokeGrenade).ToArray(); // maybe just cast to SmokeGrenade and pass that in - ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.IsInPronePose, interactiveObjects, windows, lights); + ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } From f648b9127dee0becad922ceb0912d6ca94c1b483 Mon Sep 17 00:00:00 2001 From: CWX Date: Sat, 11 May 2024 16:11:46 +0100 Subject: [PATCH 14/34] add spawning as corpse --- 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 b39a573c..6eeb9808 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -363,7 +363,7 @@ await Singleton.Instance.LoadBundlesAndCreatePools(PoolManager.Pool if (!spawnObject.IsAlive) { - // TODO: Spawn them as corpses? + otherPlayer.OnDead(EDamageType.Undefined); } if (MatchmakerAcceptPatches.IsServer) From df71038c7e0eba51c5c1aadd30b30160e3728b12 Mon Sep 17 00:00:00 2001 From: CWX Date: Sat, 11 May 2024 16:12:40 +0100 Subject: [PATCH 15/34] make reconnect nullable, change logic to check for null packet, set packet and isreconnect back to null and false on completed game --- Fika.Core/Coop/GameMode/CoopGame.cs | 21 ++++++++++++------- .../MatchmakerAcceptPatches.cs | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index e02ccefb..d7104a73 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -666,12 +666,12 @@ public override async Task vmethod_2(int playerId, Vector3 position Logger.LogError("Waiting for ReconnectResponse packet from Host..."); await Task.Delay(100); } - while (MatchmakerAcceptPatches.ReconnectPacket.Position == Vector3.zero); + while (MatchmakerAcceptPatches.ReconnectPacket == null); - Logger.LogError($"setting pos to {MatchmakerAcceptPatches.ReconnectPacket.Position}"); - PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Position; - Logger.LogError($"Setting rot to {MatchmakerAcceptPatches.ReconnectPacket.Rotation}"); - RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Rotation; + Logger.LogError($"setting pos to {MatchmakerAcceptPatches.ReconnectPacket.Value.Position}"); + PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; + Logger.LogError($"Setting rot to {MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation}"); + RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; } LocalPlayer myPlayer = await CoopPlayer.Create(playerId, PosToSpawn, RotToSpawn, "Player", "Main_", EPointOfView.FirstPerson, profile, @@ -692,8 +692,8 @@ public override async Task vmethod_2(int playerId, Vector3 position if (MatchmakerAcceptPatches.IsReconnect) { // TODO: get pose from server - myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.IsProne; - coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.NetId; + myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; + coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; } coopHandler.Players.Add(coopPlayer.NetId, coopPlayer); @@ -1378,6 +1378,13 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa { Logger.LogInfo("CoopGame::Stop"); + if (MatchmakerAcceptPatches.IsReconnect) + { + // game ended, reset these values + MatchmakerAcceptPatches.IsReconnect = false; + MatchmakerAcceptPatches.ReconnectPacket = null; + } + CoopPlayer myPlayer = (CoopPlayer)Singleton.Instance.MainPlayer; myPlayer.PacketSender?.DestroyThis(); diff --git a/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs b/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs index 49f75041..62a136fb 100644 --- a/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs +++ b/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs @@ -34,7 +34,7 @@ public static class MatchmakerAcceptPatches private static string groupId; private static long timestamp; public static bool IsReconnect = false; - public static ReconnectResponsePacket ReconnectPacket; + public static ReconnectResponsePacket? ReconnectPacket; #endregion From d3d1598bfcae93ca149094b34c1c378d505ea8cc Mon Sep 17 00:00:00 2001 From: CWX Date: Sat, 11 May 2024 16:13:00 +0100 Subject: [PATCH 16/34] add logic for smoke syncing --- .../Networking/FikaSerializationExtensions.cs | 26 +++++++++++++++++++ .../Packets/Player/ReconnectResponsePacket.cs | 25 +++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index c6e7a72f..3f667ec7 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -289,5 +289,31 @@ public static LampController GetLightState(this NetDataReader reader) LampState = (Turnable.EState) reader.GetByte() }; } + + public static void PutSmokeState(this NetDataWriter writer, Throwable smoke) + { + var test = smoke as SmokeGrenade; + var data = test.NetworkData; + + writer.Put(data.Id); + writer.Put(data.Position); + writer.Put(data.Template); + writer.Put(data.Time); + writer.Put(data.Orientation); + writer.Put(data.PlatformId); + } + + public static GStruct34 GetSmokeState(this NetDataReader reader) + { + return new() + { + Id = reader.GetString(), + Position = reader.GetVector3(), + Template = reader.GetString(), + Time = reader.GetInt(), + Orientation = reader.GetQuaternion(), + PlatformId = reader.GetShort() + }; + } } } diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs index 70a3ecab..b791dfe6 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -5,7 +5,7 @@ namespace Fika.Core.Networking { public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, bool isProne, - WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights): INetSerializable + WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, Throwable[] smokes): INetSerializable { public int NetId = netId; public Vector3 Position = position; @@ -17,6 +17,8 @@ public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion ro public WindowBreaker[] Windows; public int LightAmount; public LampController[] Lights; + public int SmokeAmount; + public GStruct34[] Smokes; public void Deserialize(NetDataReader reader) { @@ -56,6 +58,17 @@ public void Deserialize(NetDataReader reader) Lights[i] = reader.GetLightState(); } } + + SmokeAmount = reader.GetInt(); + + if (SmokeAmount > 0) + { + Smokes = new GStruct34[SmokeAmount]; + for (int i = 0; i < SmokeAmount; i++) + { + Smokes[i] = reader.GetSmokeState(); + } + } } public void Serialize(NetDataWriter writer) @@ -93,6 +106,16 @@ public void Serialize(NetDataWriter writer) writer.PutLightState(lights[i]); } } + + writer.Put(smokes.Length); + + if (smokes.Length > 0) + { + for (int i = 0; i < smokes.Length; i++) + { + writer.PutSmokeState(smokes[i]); + } + } } } } \ No newline at end of file From 20c12f2d136dae3b83dc86585913ea1f69132264 Mon Sep 17 00:00:00 2001 From: CWX Date: Mon, 13 May 2024 15:10:00 +0100 Subject: [PATCH 17/34] add a flag to know when players have finished spawning --- Fika.Core/Coop/GameMode/CoopGame.cs | 5 +++-- .../Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 6cdd9e97..a71c69d1 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -673,9 +673,7 @@ public override async Task vmethod_2(int playerId, Vector3 position } while (MatchmakerAcceptPatches.ReconnectPacket == null); - Logger.LogError($"setting pos to {MatchmakerAcceptPatches.ReconnectPacket.Value.Position}"); PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; - Logger.LogError($"Setting rot to {MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation}"); RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; } @@ -926,6 +924,8 @@ private async Task WaitForPlayers() client.SendData(writer, ref packet, LiteNetLib.DeliveryMethod.ReliableOrdered); await Task.Delay(1000); } while (numbersOfPlayersToWaitFor > 0 && !forceStart); + + MatchmakerAcceptPatches.SpawnedPlayersComplete = true; } } @@ -1397,6 +1397,7 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa // game ended, reset these values MatchmakerAcceptPatches.IsReconnect = false; MatchmakerAcceptPatches.ReconnectPacket = null; + MatchmakerAcceptPatches.SpawnedPlayersComplete = false; } CoopPlayer myPlayer = (CoopPlayer)Singleton.Instance.MainPlayer; diff --git a/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs b/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs index 62a136fb..8d279635 100644 --- a/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs +++ b/Fika.Core/Coop/Matchmaker/MatchmakerAccept/MatchmakerAcceptPatches.cs @@ -35,6 +35,7 @@ public static class MatchmakerAcceptPatches private static long timestamp; public static bool IsReconnect = false; public static ReconnectResponsePacket? ReconnectPacket; + public static bool SpawnedPlayersComplete = false; #endregion From 914a384d5aa9ad92949febdb1ee70a272c6323cc Mon Sep 17 00:00:00 2001 From: CWX Date: Mon, 13 May 2024 15:11:11 +0100 Subject: [PATCH 18/34] change to pass in smokeGrenade to avoid need to cast in extension --- Fika.Core/Networking/FikaSerializationExtensions.cs | 5 ++--- Fika.Core/Networking/FikaServer.cs | 8 +++++--- .../Networking/Packets/Player/ReconnectResponsePacket.cs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index 3f667ec7..4f4ad0d9 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -290,10 +290,9 @@ public static LampController GetLightState(this NetDataReader reader) }; } - public static void PutSmokeState(this NetDataWriter writer, Throwable smoke) + public static void PutSmokeState(this NetDataWriter writer, SmokeGrenade smoke) { - var test = smoke as SmokeGrenade; - var data = test.NetworkData; + GStruct34 data = smoke.NetworkData; writer.Put(data.Id); writer.Put(data.Position); diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 3fbf9a0b..b779145e 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -219,12 +219,14 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) serverLogger.LogError($"Player was not found"); } - WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting).ToArray(); + WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState + && x.DoorState != EDoorState.Interacting && x.DoorState != EDoorState.Interacting).ToArray(); WindowBreaker[] windows = gameWorld?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); - Throwable[] smokes = gameWorld.Grenades.Where(x => x as SmokeGrenade is SmokeGrenade).ToArray(); // maybe just cast to SmokeGrenade and pass that in + SmokeGrenade[] smokes = (SmokeGrenade[]) gameWorld.Grenades.Where(x => x as SmokeGrenade is SmokeGrenade).ToArray(); - ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes); + ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, + playerToUse.Transform.rotation, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs index b791dfe6..1be4447a 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -5,7 +5,7 @@ namespace Fika.Core.Networking { public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, bool isProne, - WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, Throwable[] smokes): INetSerializable + WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, SmokeGrenade[] smokes): INetSerializable { public int NetId = netId; public Vector3 Position = position; From e89086cf59e854ef27dcf67c8f1db9401eb68980 Mon Sep 17 00:00:00 2001 From: CWX Date: Mon, 13 May 2024 15:12:06 +0100 Subject: [PATCH 19/34] wait for players to spawn before doing smoke logic to fix bundles issue, notification for bots dying hidden on reconnect for now --- Fika.Core/Coop/Players/ObservedCoopPlayer.cs | 6 +++++- Fika.Core/Networking/FikaClient.cs | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs index f8274531..950db4dc 100644 --- a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs +++ b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs @@ -11,6 +11,7 @@ using Fika.Core.Coop.Custom; using Fika.Core.Coop.Factories; using Fika.Core.Coop.GameMode; +using Fika.Core.Coop.Matchmaker; using Fika.Core.Coop.ObservedClasses; using Fika.Core.Coop.PacketHandlers; using Fika.Core.Networking; @@ -744,7 +745,10 @@ public override void OnDead(EDamageType damageType) } else { - NotificationManagerClass.DisplayWarningNotification($"Group member '{Profile.Nickname}' has died"); + if (!MatchmakerAcceptPatches.IsReconnect) + { + NotificationManagerClass.DisplayWarningNotification($"Group member '{Profile.Nickname}' has died"); + } } } if (IsBoss(Profile.Info.Settings.Role, out string name) && IsObservedAI && LastAggressor != null) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 67a04f3c..61a0754b 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -28,6 +28,7 @@ using System.Linq; using System.Net; using System.Net.Sockets; +using System.Threading.Tasks; using UnityEngine; namespace Fika.Core.Networking @@ -220,6 +221,7 @@ public IEnumerator SyncClientToHost(ReconnectResponsePacket packet) } ClientGameWorld gameWorld = Singleton.Instance as ClientGameWorld; + CoopGame coopGame = (CoopGame)Singleton.Instance; // interactables WorldInteractiveObject[] interactiveObjects = FindObjectsOfType(); @@ -252,8 +254,16 @@ public IEnumerator SyncClientToHost(ReconnectResponsePacket packet) { smokes.Add(packet.Smokes[i]); } - // FIXME: currently ERRORS on bundles not being loaded, maybe delay till after people have spawned - //gameWorld.OnSmokeGrenadesDeserialized(smokes); + + // ------------------- Anything that needs to come after player spawns ------------------------------- + while (!MatchmakerAcceptPatches.SpawnedPlayersComplete) + { + yield return null; + } + gameWorld.OnSmokeGrenadesDeserialized(smokes); + // TODO: Smokes do spawn on the ground, but no visible smoke effect shows, im using BSG's method of doing this currently, so this might be a BSG thing. + // Decide if to fix or not. + } private void OnSendCharacterPacketReceived(SendCharacterPacket packet, NetPeer peer) From 0c292047b02a421436f8a785dbfa45d350e68852 Mon Sep 17 00:00:00 2001 From: CWX Date: Mon, 13 May 2024 16:50:58 +0100 Subject: [PATCH 20/34] add reconnecting player inv sync, revert change to when smoke logic would be done --- Fika.Core/Coop/GameMode/CoopGame.cs | 4 +++- Fika.Core/Networking/FikaClient.cs | 2 +- Fika.Core/Networking/FikaSerializationExtensions.cs | 5 +++-- Fika.Core/Networking/FikaServer.cs | 8 ++++++-- .../Packets/Player/ReconnectResponsePacket.cs | 13 +++++++++++-- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index a71c69d1..3e5be0d4 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -675,6 +675,7 @@ public override async Task vmethod_2(int playerId, Vector3 position PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; + profile.Inventory.Equipment = MatchmakerAcceptPatches.ReconnectPacket.Value.Equipment; } LocalPlayer myPlayer = await CoopPlayer.Create(playerId, PosToSpawn, RotToSpawn, "Player", "Main_", EPointOfView.FirstPerson, profile, @@ -694,7 +695,8 @@ public override async Task vmethod_2(int playerId, Vector3 position if (MatchmakerAcceptPatches.IsReconnect) { - // TODO: get pose from server + // TODO: get pose and leaning from server + myPlayer.MovementContext.SmoothedPoseLevel = MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel; myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; } diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 61a0754b..2942e102 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -256,7 +256,7 @@ public IEnumerator SyncClientToHost(ReconnectResponsePacket packet) } // ------------------- Anything that needs to come after player spawns ------------------------------- - while (!MatchmakerAcceptPatches.SpawnedPlayersComplete) + while (coopGame.Status != GameStatus.Started) { yield return null; } diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index 4f4ad0d9..da2196c3 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -290,9 +290,10 @@ public static LampController GetLightState(this NetDataReader reader) }; } - public static void PutSmokeState(this NetDataWriter writer, SmokeGrenade smoke) + public static void PutSmokeState(this NetDataWriter writer, Throwable smoke) { - GStruct34 data = smoke.NetworkData; + var smokeToUse = smoke as SmokeGrenade; + GStruct34 data = smokeToUse.NetworkData; writer.Put(data.Id); writer.Put(data.Position); diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index b779145e..60a5a4d4 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -221,12 +221,16 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting && x.DoorState != EDoorState.Interacting).ToArray(); + WindowBreaker[] windows = gameWorld?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); + LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); - SmokeGrenade[] smokes = (SmokeGrenade[]) gameWorld.Grenades.Where(x => x as SmokeGrenade is SmokeGrenade).ToArray(); + + Throwable[] smokes = gameWorld.Grenades.Where(x => x as SmokeGrenade is not null).ToArray(); ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, - playerToUse.Transform.rotation, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes); + playerToUse.Transform.rotation, playerToUse.MovementContext.SmoothedPoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, + playerToUse.Profile.Inventory.Equipment); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs index 1be4447a..2ae45849 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -4,12 +4,14 @@ namespace Fika.Core.Networking { - public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, bool isProne, - WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, SmokeGrenade[] smokes): INetSerializable + public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, float poseLevel, + bool isProne, WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, Throwable[] smokes + , EquipmentClass equipment): INetSerializable { public int NetId = netId; public Vector3 Position = position; public Quaternion Rotation = rotation; + public float PoseLevel; public bool IsProne = isProne; public int InteractiveObjectAmount; public WorldInteractiveObject.GStruct385[] InteractiveObjects; @@ -19,12 +21,14 @@ public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion ro public LampController[] Lights; public int SmokeAmount; public GStruct34[] Smokes; + public EquipmentClass Equipment; public void Deserialize(NetDataReader reader) { NetId = reader.GetInt(); Position = reader.GetVector3(); Rotation = reader.GetQuaternion(); + PoseLevel = reader.GetFloat(); IsProne = reader.GetBool(); InteractiveObjectAmount = reader.GetInt(); @@ -69,6 +73,8 @@ public void Deserialize(NetDataReader reader) Smokes[i] = reader.GetSmokeState(); } } + + Equipment = (EquipmentClass)reader.GetItem(); } public void Serialize(NetDataWriter writer) @@ -76,6 +82,7 @@ public void Serialize(NetDataWriter writer) writer.Put(NetId); writer.Put(Position); writer.Put(Rotation); + writer.Put(poseLevel); writer.Put(IsProne); writer.Put(interactiveObjects.Length); @@ -116,6 +123,8 @@ public void Serialize(NetDataWriter writer) writer.PutSmokeState(smokes[i]); } } + + writer.PutItem(equipment); } } } \ No newline at end of file From 773c75929e6cd3c72ed3bba16739a86813114a48 Mon Sep 17 00:00:00 2001 From: CWX Date: Mon, 13 May 2024 20:41:24 +0100 Subject: [PATCH 21/34] Fix inventory syncing on reconnect, fixes bundles not being loaded --- 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 3e5be0d4..63c23fde 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -699,6 +699,7 @@ public override async Task vmethod_2(int playerId, Vector3 position myPlayer.MovementContext.SmoothedPoseLevel = MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel; myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; + myPlayer.Inventory.Equipment.GetAllBundleTokens(); // force retain bundles to fix bundles not being loaded on reconnect } if (MatchmakerAcceptPatches.IsServer) From d1137440c241ec51ad35300051a3cb75a86f9f30 Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 May 2024 16:46:21 +0100 Subject: [PATCH 22/34] Add static/container loot syncing --- .../BaseLocalGame_method_6_Patch.cs | 26 +++++++++++++++++++ Fika.Core/FikaPlugin.cs | 1 + .../Networking/FikaSerializationExtensions.cs | 16 ++++++++++++ Fika.Core/Networking/FikaServer.cs | 17 +++++++----- .../Packets/Player/ReconnectResponsePacket.cs | 10 ++++++- 5 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs diff --git a/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs b/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs new file mode 100644 index 00000000..38536c29 --- /dev/null +++ b/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using Aki.Reflection.Patching; +using EFT; +using Fika.Core.Coop.Matchmaker; + +namespace Fika.Core.Coop.Patches +{ + internal class BaseLocalGame_method_6_Patch : ModulePatch + { + protected override MethodBase GetTargetMethod() + { + return typeof(BaseLocalGame).GetMethod(nameof(BaseLocalGame.method_11)); + } + + [PatchPrefix] + public static bool PatchPrefix(ref LocationSettingsClass.Location location) + { + if (MatchmakerAcceptPatches.IsReconnect) + { + location.Loot = MatchmakerAcceptPatches.ReconnectPacket.Value.Items; + } + + return true; + } + } +} \ No newline at end of file diff --git a/Fika.Core/FikaPlugin.cs b/Fika.Core/FikaPlugin.cs index f2269f27..dd5d2961 100644 --- a/Fika.Core/FikaPlugin.cs +++ b/Fika.Core/FikaPlugin.cs @@ -195,6 +195,7 @@ protected void Awake() new BotCacher().Enable(); new InventoryScrollPatch().Enable(); new AbstractGame_InRaid_Patch().Enable(); + new BaseLocalGame_method_6_Patch().Enable(); #if GOLDMASTER new TOSPatch().Enable(); #endif diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index da2196c3..70741bdc 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -315,5 +315,21 @@ public static GStruct34 GetSmokeState(this NetDataReader reader) PlatformId = reader.GetShort() }; } + + public static void PutLocationItem(this NetDataWriter writer, LootItemPositionClass[] locationItem) + { + using MemoryStream memoryStream = new(); + using BinaryWriter binaryWriter = new(memoryStream); + binaryWriter.Write(GClass1524.SerializeLootData(locationItem)); + writer.PutByteArray(memoryStream.ToArray()); + } + + public static GClass1202 GetLocationItem(this NetDataReader reader) + { + using MemoryStream memoryStream = new(reader.GetByteArray()); + using BinaryReader binaryReader = new(memoryStream); + + return GClass1524.DeserializeLootData(Singleton.Instance, binaryReader.ReadEFTLootDataDescriptor()); + } } } diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 60a5a4d4..6ecdeb06 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -204,10 +204,10 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) { yield return null; } + GameWorld gameWorld = Singleton.Instance; + ClientGameWorld ClientgameWorld = Singleton.Instance as ClientGameWorld; - ClientGameWorld gameWorld = Singleton.Instance as ClientGameWorld; - - while (string.IsNullOrEmpty(gameWorld.MainPlayer.Location)) + while (string.IsNullOrEmpty(ClientgameWorld.MainPlayer.Location)) { yield return null; } @@ -222,15 +222,18 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting && x.DoorState != EDoorState.Interacting).ToArray(); - WindowBreaker[] windows = gameWorld?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); + WindowBreaker[] windows = ClientgameWorld?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); LampController[] lights = LocationScene.GetAllObjects(false).ToArray(); - Throwable[] smokes = gameWorld.Grenades.Where(x => x as SmokeGrenade is not null).ToArray(); + Throwable[] smokes = ClientgameWorld.Grenades.Where(x => x as SmokeGrenade is not null).ToArray(); + + LootItemPositionClass[] items = gameWorld.GetJsonLootItems().ToArray(); - ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, + ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.MovementContext.SmoothedPoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, - playerToUse.Profile.Inventory.Equipment); + playerToUse.Profile.Inventory.Equipment, items); + SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs index 2ae45849..a8525c7a 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -6,7 +6,7 @@ namespace Fika.Core.Networking { public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, float poseLevel, bool isProne, WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, Throwable[] smokes - , EquipmentClass equipment): INetSerializable + , EquipmentClass equipment, LootItemPositionClass[] items): INetSerializable { public int NetId = netId; public Vector3 Position = position; @@ -22,6 +22,8 @@ public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion ro public int SmokeAmount; public GStruct34[] Smokes; public EquipmentClass Equipment; + public int ItemAmount; + public GClass1202 Items; public void Deserialize(NetDataReader reader) { @@ -75,6 +77,7 @@ public void Deserialize(NetDataReader reader) } Equipment = (EquipmentClass)reader.GetItem(); + Items = reader.GetLocationItem(); } public void Serialize(NetDataWriter writer) @@ -125,6 +128,11 @@ public void Serialize(NetDataWriter writer) } writer.PutItem(equipment); + + if (items.Length > 0) + { + writer.PutLocationItem(items); + } } } } \ No newline at end of file From f16353b1ef0a6ca4ff58ed1479e3133a9924bf34 Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 May 2024 18:19:43 +0100 Subject: [PATCH 23/34] add workaround to collect corpses from Host, and just "kill the players" for the loot, added TODO regarding unused var --- Fika.Core/Coop/Components/CoopHandler.cs | 2 +- Fika.Core/Coop/GameMode/CoopGame.cs | 2 +- Fika.Core/Networking/FikaServer.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index 6b6ee48d..301204b1 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -450,7 +450,7 @@ private LocalPlayer SpawnObservedPlayer(Profile profile, Vector3 position, int p position, Quaternion.identity, "Player", - isAI == true ? "Bot_" : $"Player_{profile.Nickname}_", + isAI == true ? $"Bot_{netId}" : $"Player_{profile.Nickname}_", EPointOfView.ThirdPerson, profile, isAI, diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 9038aac0..f3a0ad21 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -923,7 +923,7 @@ private async Task WaitForPlayers() NetDataWriter writer = new(); writer.Reset(); client.SendData(writer, ref packet, LiteNetLib.DeliveryMethod.ReliableOrdered); - numbersOfPlayersToWaitFor = MatchmakerAcceptPatches.HostExpectedNumberOfPlayers - (client.ConnectedClients + 1); + numbersOfPlayersToWaitFor = MatchmakerAcceptPatches.HostExpectedNumberOfPlayers - (client.ConnectedClients + 1); // TODO: this needed? do { numbersOfPlayersToWaitFor = MatchmakerAcceptPatches.HostExpectedNumberOfPlayers - (client.ConnectedClients + 1); diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 4aa3314b..e7a09f1f 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -228,7 +228,7 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) Throwable[] smokes = ClientgameWorld.Grenades.Where(x => x as SmokeGrenade is not null).ToArray(); - LootItemPositionClass[] items = gameWorld.GetJsonLootItems().ToArray(); + LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.MovementContext.SmoothedPoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, From 53902b0a2e91bfe156b0ed31c0221a681bfadac6 Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 May 2024 18:55:12 +0100 Subject: [PATCH 24/34] Fix name formatting for bots --- 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 301204b1..c5133c93 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -450,7 +450,7 @@ private LocalPlayer SpawnObservedPlayer(Profile profile, Vector3 position, int p position, Quaternion.identity, "Player", - isAI == true ? $"Bot_{netId}" : $"Player_{profile.Nickname}_", + isAI == true ? $"Bot_{netId}_" : $"Player_{profile.Nickname}_", EPointOfView.ThirdPerson, profile, isAI, From 264f368c7977c31052fdc96e6f3ef2a4074e494b Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 May 2024 18:55:30 +0100 Subject: [PATCH 25/34] Fix pose level on spawning --- Fika.Core/Coop/GameMode/CoopGame.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index f3a0ad21..0b0feeac 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -713,10 +713,9 @@ public override async Task vmethod_2(int playerId, Vector3 position if (MatchmakerAcceptPatches.IsReconnect) { - // TODO: get pose and leaning from server - myPlayer.MovementContext.SmoothedPoseLevel = MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel; - myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; + myPlayer.MovementContext.SetPoseLevel(MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel, true); + myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; myPlayer.Inventory.Equipment.GetAllBundleTokens(); // force retain bundles to fix bundles not being loaded on reconnect } From a873a5a0acf666eaf0482575060e94a449acc5b8 Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 May 2024 18:56:04 +0100 Subject: [PATCH 26/34] add poseLevel --- Fika.Core/Networking/FikaServer.cs | 2 +- .../Packets/Player/ReconnectResponsePacket.cs | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index e7a09f1f..2ec94f6e 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -231,7 +231,7 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, - playerToUse.Transform.rotation, playerToUse.MovementContext.SmoothedPoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, + playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, playerToUse.Profile.Inventory.Equipment, items); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs index a8525c7a..4e77ef9a 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -1,16 +1,18 @@ +using EFT; using EFT.Interactive; using LiteNetLib.Utils; using UnityEngine; namespace Fika.Core.Networking { - public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, float poseLevel, + public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, EPlayerPose playerPose, float poseLevel, bool isProne, WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, Throwable[] smokes , EquipmentClass equipment, LootItemPositionClass[] items): INetSerializable { - public int NetId = netId; - public Vector3 Position = position; - public Quaternion Rotation = rotation; + public int NetId; + public Vector3 Position; + public Quaternion Rotation; + public EPlayerPose PlayerPose; public float PoseLevel; public bool IsProne = isProne; public int InteractiveObjectAmount; @@ -30,6 +32,7 @@ public void Deserialize(NetDataReader reader) NetId = reader.GetInt(); Position = reader.GetVector3(); Rotation = reader.GetQuaternion(); + PlayerPose = (EPlayerPose)reader.GetByte(); PoseLevel = reader.GetFloat(); IsProne = reader.GetBool(); InteractiveObjectAmount = reader.GetInt(); @@ -82,9 +85,10 @@ public void Deserialize(NetDataReader reader) public void Serialize(NetDataWriter writer) { - writer.Put(NetId); - writer.Put(Position); - writer.Put(Rotation); + writer.Put(netId); + writer.Put(position); + writer.Put(rotation); + writer.Put((byte)playerPose); writer.Put(poseLevel); writer.Put(IsProne); writer.Put(interactiveObjects.Length); From af7958b532b5c880559fe8314cd3e8178c8a9c1e Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 16 May 2024 20:54:44 +0100 Subject: [PATCH 27/34] add a basic retry mechanism, failing NEEDS to be reworked --- Fika.Core/Coop/GameMode/CoopGame.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 0b0feeac..e053c17b 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -681,15 +681,21 @@ public override async Task vmethod_2(int playerId, Vector3 position if (MatchmakerAcceptPatches.IsReconnect) { ReconnectRequestPacket reconnectPacket = new(ProfileId); - Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); - Logger.LogError($"reconnectRequest packet sent for netId: {playerId} with profileId: {ProfileId}"); + + int retryCount = 0; + while (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount < 5) + { + Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); + Logger.LogError($"reconnectRequest packet sent for netId: {playerId} with profileId: {ProfileId}"); + await Task.Delay(3000); + retryCount++; + } - do + if (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount == 5) { - Logger.LogError("Waiting for ReconnectResponse packet from Host..."); - await Task.Delay(100); + throw new Exception("ReconnectRequestPacket was not received from Host!"); + // TODO: Make this way more elegant and return to mainmenu } - while (MatchmakerAcceptPatches.ReconnectPacket == null); PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; From 027368d8d7518cccff6f9f6376f277f15ca13996 Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 17 May 2024 15:18:41 +0100 Subject: [PATCH 28/34] Add Visual feedback on reconnecting, added Fail message and return to mainmenu, check if reconnecting is client also and fix issue trying to use reconnect when starting host/different lobby after disconnect --- Fika.Core/Coop/Components/CoopHandler.cs | 1 + Fika.Core/Coop/GameMode/CoopGame.cs | 26 +++++++++++++++---- .../BaseLocalGame_method_6_Patch.cs | 2 +- Fika.Core/Networking/FikaClient.cs | 7 +++-- Fika.Core/Networking/FikaServer.cs | 1 + Fika.Core/UI/Custom/MatchMakerUIScript.cs | 12 +++++++-- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index c5133c93..71efb7e8 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -365,6 +365,7 @@ await Singleton.Instance.LoadBundlesAndCreatePools(PoolManager.Pool if (!spawnObject.IsAlive) { + // [CWX] otherPlayer.OnDead(EDamageType.Undefined); } diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index e053c17b..30e1e52b 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -664,6 +664,10 @@ public override async Task vmethod_2(int playerId, Vector3 position { spawnPoint = SpawnSystem.SelectSpawnPoint(ESpawnCategory.Player, Profile_0.Info.Side); await SendOrReceiveSpawnPoint(); + // [CWX] after disconnect, and trying to host, make sure this is set back to defaults + // TODO: move working out if reconnect to earlier on, to mitigate issues hosting your own and joining a different game + MatchmakerAcceptPatches.IsReconnect = false; + MatchmakerAcceptPatches.ReconnectPacket = null; } if (MatchmakerAcceptPatches.IsClient) @@ -676,27 +680,31 @@ public override async Task vmethod_2(int playerId, Vector3 position } } + // [CWX] Vector3 PosToSpawn = spawnPoint.Position; Quaternion RotToSpawn = spawnPoint.Rotation; - if (MatchmakerAcceptPatches.IsReconnect) + if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { ReconnectRequestPacket reconnectPacket = new(ProfileId); + MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Sending Reconnect Request..."); int retryCount = 0; while (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount < 5) { Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); - Logger.LogError($"reconnectRequest packet sent for netId: {playerId} with profileId: {ProfileId}"); + MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Request Sent... {retryCount + 1}"); await Task.Delay(3000); retryCount++; } if (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount == 5) { - throw new Exception("ReconnectRequestPacket was not received from Host!"); - // TODO: Make this way more elegant and return to mainmenu + MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Failed to Reconnect..."); + Singleton.Instance.ShowCriticalErrorScreen("Network Error", "[EXPERIMENTAL] Unable to reconnect to the host. Please try again after returning to main menu.", + ErrorScreen.EButtonType.OkButton, 10f, ReconnectFailed, ReconnectFailed); } + MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Reconnecting to host..."); PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; profile.Inventory.Equipment = MatchmakerAcceptPatches.ReconnectPacket.Value.Equipment; @@ -717,7 +725,8 @@ public override async Task vmethod_2(int playerId, Vector3 position CoopPlayer coopPlayer = (CoopPlayer)myPlayer; - if (MatchmakerAcceptPatches.IsReconnect) + // [CWX] + if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; myPlayer.MovementContext.SetPoseLevel(MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel, true); @@ -839,6 +848,12 @@ public override async Task vmethod_2(int playerId, Vector3 position return myPlayer; } + private void ReconnectFailed() + { + ClientAppUtils.GetMainApp().method_48().HandleExceptions(); + Logger.LogError($"Failed to reconnect to the host. Returning to main menu..."); + } + private void MainPlayerDied(EDamageType obj) { EndByTimerScenario endByTimerScenario = GetComponent(); @@ -1424,6 +1439,7 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa { Logger.LogInfo("CoopGame::Stop"); + // [CWX] if (MatchmakerAcceptPatches.IsReconnect) { // game ended, reset these values diff --git a/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs b/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs index 38536c29..f2af2efd 100644 --- a/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs +++ b/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs @@ -15,7 +15,7 @@ protected override MethodBase GetTargetMethod() [PatchPrefix] public static bool PatchPrefix(ref LocationSettingsClass.Location location) { - if (MatchmakerAcceptPatches.IsReconnect) + if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { location.Loot = MatchmakerAcceptPatches.ReconnectPacket.Value.Items; } diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 2d08a8d7..013c4ae7 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -141,7 +141,8 @@ private void OnOperationCallbackPacketReceived(OperationCallbackPacket packet) private void OnSyncNetIdPacketReceived(SyncNetIdPacket packet) { - if (MatchmakerAcceptPatches.IsReconnect) + // [CWX] + if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { FikaPlugin.Instance.FikaLogger.LogInfo($"OnSyncNetIdPacketReceived: Client is reconnecting, ignore Sync."); return; @@ -176,7 +177,7 @@ private void OnSyncNetIdPacketReceived(SyncNetIdPacket packet) private void OnAssignNetIdPacketReceived(AssignNetIdPacket packet) { - if (MatchmakerAcceptPatches.IsReconnect) + if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { FikaPlugin.Instance.FikaLogger.LogInfo($"OnAssignNetIdPacketReceived: Client is reconnecting, ignore assignment."); return; @@ -207,6 +208,7 @@ private void OnAssignNetIdPacketReceived(AssignNetIdPacket packet) private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet) { + // [CWX] MatchmakerAcceptPatches.IsReconnect = true; MatchmakerAcceptPatches.ReconnectPacket = packet; @@ -215,6 +217,7 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet) public IEnumerator SyncClientToHost(ReconnectResponsePacket packet) { + // [CWX] while (!Singleton.Instantiated) { yield return null; diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 2ec94f6e..3622eb1e 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -194,6 +194,7 @@ public int PopNetId() private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, NetPeer peer) { + // [CWX] serverLogger.LogError($"Player Wanting to reconnect {packet.ProfileId}"); StartCoroutine(SyncClientToHost(packet, peer)); } diff --git a/Fika.Core/UI/Custom/MatchMakerUIScript.cs b/Fika.Core/UI/Custom/MatchMakerUIScript.cs index aa171af5..86f66d44 100644 --- a/Fika.Core/UI/Custom/MatchMakerUIScript.cs +++ b/Fika.Core/UI/Custom/MatchMakerUIScript.cs @@ -300,6 +300,15 @@ private void RefreshUI() } Singleton.Instance.PlayUISound(EUISoundType.ButtonClick); + if (entry.Status == LobbyEntry.ELobbyStatus.REJOIN) + { + // [CWX] + MatchmakerAcceptPatches.IsReconnect = true; + } + else + { + MatchmakerAcceptPatches.IsReconnect = false; + } StartCoroutine(JoinMatch(ProfileId, server.name, button)); }); @@ -395,8 +404,7 @@ private void RefreshUI() tooltipArea.enabled = true; tooltipArea.SetMessageText(new Func(tooltipTextGetter.GetText)); break; - case LobbyEntry.ELobbyStatus.REJOIN: - MatchmakerAcceptPatches.IsReconnect = true; + case LobbyEntry.ELobbyStatus.REJOIN: tooltipTextGetter = new() { TooltipText = "Click to Rejoin raid." From 5ccd9c6e2edf41b764f08665764c27343e8082b3 Mon Sep 17 00:00:00 2001 From: CWX Date: Sun, 19 May 2024 09:51:15 +0100 Subject: [PATCH 29/34] fix spawning of players, fix race condition, leaving temp synthetic delay for now --- Fika.Core/Coop/Components/CoopHandler.cs | 12 +++++++++++- Fika.Core/Coop/GameMode/CoopGame.cs | 11 +++++++++-- Fika.Core/Networking/FikaServer.cs | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index 302d4737..e9cfafaf 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -61,6 +61,7 @@ public class SpawnObject(Profile profile, Vector3 position, bool isAlive, bool i internal static GameObject CoopHandlerParent; private Coroutine PingRoutine; + public bool StartSpawning = false; #endregion @@ -283,6 +284,11 @@ private async Task ReadFromServerCharactersLoop() { while (RunAsyncTasks) { + while (!StartSpawning) + { + await Task.Delay(1000); + } + CoopGame coopGame = (CoopGame)Singleton.Instance; int waitTime = 2500; if (coopGame.Status == GameStatus.Started) @@ -294,7 +300,6 @@ private async Task ReadFromServerCharactersLoop() if (Players == null) { continue; - } ReadFromServerCharacters(); @@ -403,6 +408,11 @@ private IEnumerator ProcessSpawnQueue() { while (true) { + if (!StartSpawning) + { + yield return new WaitUntil(() => StartSpawning); + } + yield return new WaitForSeconds(1f); if (Singleton.Instantiated) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index a8f0d447..1d372455 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -743,11 +743,18 @@ public override async Task vmethod_2(int playerId, Vector3 position while (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount < 5) { Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); - MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Request Sent... {retryCount + 1}"); + MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Requests Sent for reconnect... {retryCount + 1}"); await Task.Delay(3000); retryCount++; } + // TODO: [CWX] Remove before final PR + if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) + { + // add synthetic retrys + await Task.Delay(12000); // 4 extra trys + } + if (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount == 5) { MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Failed to Reconnect..."); @@ -889,6 +896,7 @@ public override async Task vmethod_2(int playerId, Vector3 position } } + coopHandler.StartSpawning = true; await WaitForPlayers(); Destroy(customButton); @@ -934,7 +942,6 @@ private async Task WaitForPlayers() FikaServer server = Singleton.Instance; - numbersOfPlayersToWaitFor = MatchmakerAcceptPatches.HostExpectedNumberOfPlayers - (server.NetServer.ConnectedPeersCount + 1); do { numbersOfPlayersToWaitFor = MatchmakerAcceptPatches.HostExpectedNumberOfPlayers - (server.NetServer.ConnectedPeersCount + 1); diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index f078fbf2..a48459d3 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -229,7 +229,8 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) Throwable[] smokes = ClientgameWorld.Grenades.Where(x => x as SmokeGrenade is not null).ToArray(); - LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); + LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); // will ignore corpses + // LootItemPositionClass[] items = gameWorld.GetJsonLootItems().ToArray(); // will include corpses ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, From e84a5e6b09a63dd348f29c698ac177b8140ca322 Mon Sep 17 00:00:00 2001 From: CWX Date: Tue, 21 May 2024 00:56:15 +0100 Subject: [PATCH 30/34] sync profile instead of just equipment, add some notes --- Fika.Core/Coop/Components/CoopHandler.cs | 3 ++- Fika.Core/Coop/GameMode/CoopGame.cs | 4 ++-- Fika.Core/Networking/FikaServer.cs | 8 ++++++-- .../Networking/Packets/Player/ReconnectResponsePacket.cs | 9 +++++---- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index f22f4300..e5091974 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -374,7 +374,8 @@ await Singleton.Instance.LoadBundlesAndCreatePools(PoolManager.Pool if (!spawnObject.IsAlive) { - // [CWX] + // [CWX] - might be able to be removed if dead AI isnt sent as someone to spawn / dont spawn them + // when sending lootpositions we get corpses. otherPlayer.OnDead(EDamageType.Undefined); } diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 2bbc8bdf..6e6bb68d 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -743,7 +743,7 @@ public override async Task vmethod_2(int playerId, Vector3 position MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Reconnecting to host..."); PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; - profile.Inventory.Equipment = MatchmakerAcceptPatches.ReconnectPacket.Value.Equipment; + profile = MatchmakerAcceptPatches.ReconnectPacket.Value.Profile.Profile; } LocalPlayer myPlayer = await CoopPlayer.Create(playerId, PosToSpawn, RotToSpawn, "Player", "Main_", EPointOfView.FirstPerson, profile, @@ -767,7 +767,7 @@ public override async Task vmethod_2(int playerId, Vector3 position coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; myPlayer.MovementContext.SetPoseLevel(MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel, true); myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; - myPlayer.Inventory.Equipment.GetAllBundleTokens(); // force retain bundles to fix bundles not being loaded on reconnect + // myPlayer.Inventory.Equipment.GetAllBundleTokens(); // force retain bundles to fix bundles not being loaded on reconnect } if (RaidSettings.MetabolismDisabled) diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 150148c7..1b9e19ac 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -214,9 +214,13 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); // will ignore corpses // LootItemPositionClass[] items = gameWorld.GetJsonLootItems().ToArray(); // will include corpses + // activehealthcontroller dictionary_0 each .Health.Value and .IsDestroyed - call method_0 to change + // + ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, - playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, interactiveObjects, windows, lights, smokes, - playerToUse.Profile.Inventory.Equipment, items); + playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, + interactiveObjects, windows, lights, smokes, + new FikaSerialization.PlayerInfoPacket() { Profile = playerToUse.Profile }, items); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); } diff --git a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs index 4e77ef9a..eaa7e254 100644 --- a/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ReconnectResponsePacket.cs @@ -2,12 +2,13 @@ using EFT.Interactive; using LiteNetLib.Utils; using UnityEngine; +using static Fika.Core.Networking.FikaSerialization; namespace Fika.Core.Networking { public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion rotation, EPlayerPose playerPose, float poseLevel, bool isProne, WorldInteractiveObject[] interactiveObjects, WindowBreaker[] windows, LampController[] lights, Throwable[] smokes - , EquipmentClass equipment, LootItemPositionClass[] items): INetSerializable + , PlayerInfoPacket profile, LootItemPositionClass[] items): INetSerializable { public int NetId; public Vector3 Position; @@ -23,7 +24,7 @@ public struct ReconnectResponsePacket(int netId, Vector3 position, Quaternion ro public LampController[] Lights; public int SmokeAmount; public GStruct34[] Smokes; - public EquipmentClass Equipment; + public PlayerInfoPacket Profile; public int ItemAmount; public GClass1202 Items; @@ -79,7 +80,7 @@ public void Deserialize(NetDataReader reader) } } - Equipment = (EquipmentClass)reader.GetItem(); + Profile = PlayerInfoPacket.Deserialize(reader); Items = reader.GetLocationItem(); } @@ -131,7 +132,7 @@ public void Serialize(NetDataWriter writer) } } - writer.PutItem(equipment); + PlayerInfoPacket.Serialize(writer, profile); if (items.Length > 0) { From bed5d8e7b8c5c38d6ea06dbd961495525fe53544 Mon Sep 17 00:00:00 2001 From: CWX Date: Tue, 21 May 2024 23:21:30 +0100 Subject: [PATCH 31/34] attempt to sync quests --- Fika.Core/Coop/GameMode/CoopGame.cs | 10 +++++----- Fika.Core/Coop/Players/CoopPlayer.cs | 1 - Fika.Core/Coop/Players/ObservedCoopPlayer.cs | 11 ++++++++++- Fika.Core/Networking/FikaServer.cs | 5 ++--- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index bf99b6fd..fd09c70b 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -739,11 +739,11 @@ public override async Task vmethod_2(int playerId, Vector3 position } // TODO: [CWX] Remove before final PR - if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) - { - // add synthetic retrys - await Task.Delay(12000); // 4 extra trys - } + // if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) + // { + // // add synthetic retrys + // await Task.Delay(12000); // 4 extra trys + // } if (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount == 5) { diff --git a/Fika.Core/Coop/Players/CoopPlayer.cs b/Fika.Core/Coop/Players/CoopPlayer.cs index 5b1dd094..a7478179 100644 --- a/Fika.Core/Coop/Players/CoopPlayer.cs +++ b/Fika.Core/Coop/Players/CoopPlayer.cs @@ -842,7 +842,6 @@ public override void TryInteractionCallback(LootableContainer container) protected virtual void Start() { Profile.Info.GroupId = "Fika"; - if (Side != EPlayerSide.Savage) { if (Equipment.GetSlot(EquipmentSlot.Dogtag).ContainedItem != null) diff --git a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs index 5bfcb999..90d51e19 100644 --- a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs +++ b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs @@ -138,8 +138,17 @@ public static async Task CreateObservedPlayer(int playerId, CoopObservedStatisticsManager statisticsManager = new(); + //[CWX] Syncing of quests and achievements would help with reconnecting, otherwise we'd have to redo them + GClass3206 questController = new(profile, inventoryController, null, false); + questController.Init(); + questController.Run(); + + AchievementControllerClass achievementsController = new(profile, inventoryController, null, true); + achievementsController.Init(); + achievementsController.Run(); + await player.Init(rotation, layerName, pointOfView, profile, inventoryController, healthController, - statisticsManager, null, null, filter, EVoipState.NotAvailable, aiControl, false); + statisticsManager, questController, achievementsController, filter, EVoipState.NotAvailable, aiControl, false); player._handsController = EmptyHandsController.smethod_5(player); player._handsController.Spawn(1f, delegate { }); diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 14e111f1..4a15b7ad 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -195,7 +195,7 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) yield return null; } - CoopPlayer playerToUse = Players.FirstOrDefault((v) => v.Value.ProfileId == packet.ProfileId).Value; + ObservedCoopPlayer playerToUse = (ObservedCoopPlayer) Players.FirstOrDefault((v) => v.Value.ProfileId == packet.ProfileId).Value; if (playerToUse == null) { @@ -214,8 +214,7 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); // will ignore corpses // LootItemPositionClass[] items = gameWorld.GetJsonLootItems().ToArray(); // will include corpses - // activehealthcontroller dictionary_0 each .Health.Value and .IsDestroyed - call method_0 to change - // + playerToUse.Profile.Health = playerToUse.NetworkHealthController.Store(null); // Hp is synced, Effects are not ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, From 107b63285afcc93f6411ef9828158fd4adfa24f4 Mon Sep 17 00:00:00 2001 From: CWX Date: Wed, 22 May 2024 16:39:20 +0100 Subject: [PATCH 32/34] add quest and achievement syncing --- .../CoopClientAchievementController.cs | 32 +++++++++++++++++++ .../CoopClientQuestController.cs | 32 +++++++++++++++++++ Fika.Core/Coop/Players/CoopPlayer.cs | 12 +++---- Fika.Core/Coop/Players/ObservedCoopPlayer.cs | 10 +----- Fika.Core/Networking/FikaServer.cs | 20 ++++++++---- .../Packets/Player/ConditionChangePacket.cs | 27 ++++++++++++++++ 6 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs create mode 100644 Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs create mode 100644 Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs diff --git a/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs b/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs new file mode 100644 index 00000000..4f9ff25e --- /dev/null +++ b/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs @@ -0,0 +1,32 @@ +using Comfort.Common; +using EFT; +using EFT.Communications; +using EFT.Quests; +using Fika.Core.Coop.Matchmaker; +using Fika.Core.Networking; +using UnityEngine; + +namespace Fika.Core.Coop.ClientClasses +{ + public class CoopClientAchievementController : AchievementControllerClass + { + private readonly FikaClient _fikaClient = Singleton.Instance; + + public CoopClientAchievementController(Profile profile, InventoryControllerClass inventoryController, ISession session, bool fromServer) : base(profile, inventoryController, session, fromServer) + { + } + + public override void OnConditionValueChanged(IConditionCounter conditional, EQuestStatus status, Condition condition, bool notify) + { + if (MatchmakerAcceptPatches.IsClient) + { + // send netId, string for condition, value + ConditionChangePacket packet = new(_fikaClient.MyPlayer.NetId, condition.id, condition.value); + _fikaClient.SendData(_fikaClient.DataWriter, ref packet, LiteNetLib.DeliveryMethod.ReliableUnordered); + NotificationManagerClass.DisplayMessageNotification("Fika Achievement Condition Changed", ENotificationDurationType.Long, ENotificationIconType.Alert, Color.red); + } + + base.OnConditionValueChanged(conditional, status, condition, notify); + } + } +} \ No newline at end of file diff --git a/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs b/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs new file mode 100644 index 00000000..6be41e6d --- /dev/null +++ b/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs @@ -0,0 +1,32 @@ +using Comfort.Common; +using EFT; +using EFT.Communications; +using EFT.Quests; +using Fika.Core.Coop.Matchmaker; +using Fika.Core.Networking; +using UnityEngine; + +namespace Fika.Core.Coop.ClientClasses +{ + public class CoopClientQuestController : GClass3206 + { + private FikaClient fikaClient = Singleton.Instance; + + public CoopClientQuestController(Profile profile, InventoryControllerClass inventoryController, ISession session, bool fromServer) : base(profile, inventoryController, session, fromServer) + { + } + + public override void OnConditionValueChanged(IConditionCounter conditional, EQuestStatus status, Condition condition, bool notify) + { + if (MatchmakerAcceptPatches.IsClient) + { + // send netId, string for condition, value + ConditionChangePacket packet = new(fikaClient.MyPlayer.NetId, condition.id, condition.value); + fikaClient.SendData(fikaClient.DataWriter, ref packet, LiteNetLib.DeliveryMethod.ReliableUnordered); + NotificationManagerClass.DisplayMessageNotification("Fika Quest Condition Changed", ENotificationDurationType.Long, ENotificationIconType.Alert, Color.red); + } + + base.OnConditionValueChanged(conditional, status, condition, notify); + } + } +} \ No newline at end of file diff --git a/Fika.Core/Coop/Players/CoopPlayer.cs b/Fika.Core/Coop/Players/CoopPlayer.cs index 0b7563b0..ec0bac41 100644 --- a/Fika.Core/Coop/Players/CoopPlayer.cs +++ b/Fika.Core/Coop/Players/CoopPlayer.cs @@ -66,11 +66,11 @@ public static async Task Create(int playerId, Vector3 position, Qua ISession session = Singleton>.Instance.GetClientBackEndSession(); - GClass3206 questController = new(profile, inventoryController, session, true); + CoopClientQuestController questController = new(profile, inventoryController, session, true); questController.Init(); questController.Run(); - AchievementControllerClass achievementsController = new(profile, inventoryController, session, true); + CoopClientAchievementController achievementsController = new(profile, inventoryController, session, true); achievementsController.Init(); achievementsController.Run(); @@ -173,7 +173,7 @@ public void ProcessInteractWithBTR(BTRInteractionPacket packet) { if (coopHandler.clientBTR != null) { - coopHandler.clientBTR.ClientInteraction(this, packet.InteractPacket); + coopHandler.clientBTR.ClientInteraction(this, packet.InteractPacket); } } } @@ -399,7 +399,7 @@ public override void SendHeadlightsPacket(bool isSilent) Amount = lightStates.Count(), LightStates = lightStates } - }); + }); } } @@ -551,7 +551,7 @@ private IEnumerator DestroyNetworkedComponents() if (PacketSender != null) { - PacketSender.DestroyThis(); + PacketSender.DestroyThis(); } } @@ -1353,7 +1353,7 @@ public override void Dispose() base.Dispose(); if (PacketSender != null) { - PacketSender.DestroyThis(); + PacketSender.DestroyThis(); } } diff --git a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs index 90d51e19..3a719a43 100644 --- a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs +++ b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs @@ -138,17 +138,9 @@ public static async Task CreateObservedPlayer(int playerId, CoopObservedStatisticsManager statisticsManager = new(); - //[CWX] Syncing of quests and achievements would help with reconnecting, otherwise we'd have to redo them - GClass3206 questController = new(profile, inventoryController, null, false); - questController.Init(); - questController.Run(); - - AchievementControllerClass achievementsController = new(profile, inventoryController, null, true); - achievementsController.Init(); - achievementsController.Run(); await player.Init(rotation, layerName, pointOfView, profile, inventoryController, healthController, - statisticsManager, questController, achievementsController, filter, EVoipState.NotAvailable, aiControl, false); + statisticsManager, null, null, filter, EVoipState.NotAvailable, aiControl, false); player._handsController = EmptyHandsController.smethod_5(player); player._handsController.Spawn(1f, delegate { }); diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index 4a15b7ad..c0048f7a 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -85,6 +85,7 @@ public async void Start() packetProcessor.SubscribeNetSerializable(OnBorderZonePacketReceived); packetProcessor.SubscribeNetSerializable(OnSendCharacterPacketReceived); packetProcessor.SubscribeNetSerializable(OnReconnectRequestPacketReceived); + packetProcessor.SubscribeNetSerializable(OnConditionChangedPacketReceived); _netServer = new NetManager(this) { @@ -166,6 +167,13 @@ await Task.Run(async () => ServerReady = true; } + private void OnConditionChangedPacketReceived(ConditionChangePacket packet, NetPeer peer) + { + // [CWX] + Players.FirstOrDefault(x => x.Key == packet.NetId).Value.Profile.TaskConditionCounters + .FirstOrDefault(c => c.Key == packet.ConditionId).Value.Value = (int)packet.ConditionValue; + } + public int PopNetId() { int netId = _currentNetId; @@ -195,14 +203,14 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) yield return null; } - ObservedCoopPlayer playerToUse = (ObservedCoopPlayer) Players.FirstOrDefault((v) => v.Value.ProfileId == packet.ProfileId).Value; + ObservedCoopPlayer playerToUse = (ObservedCoopPlayer)Players.FirstOrDefault((v) => v.Value.ProfileId == packet.ProfileId).Value; if (playerToUse == null) { serverLogger.LogError($"Player was not found"); } - WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState + WorldInteractiveObject[] interactiveObjects = FindObjectsOfType().Where(x => x.DoorState != x.InitialDoorState && x.DoorState != EDoorState.Interacting && x.DoorState != EDoorState.Interacting).ToArray(); WindowBreaker[] windows = ClientgameWorld?.Windows.Where(x => x.AvailableToSync && x.IsDamaged).ToArray(); @@ -216,9 +224,9 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) playerToUse.Profile.Health = playerToUse.NetworkHealthController.Store(null); // Hp is synced, Effects are not - ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, - playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, - interactiveObjects, windows, lights, smokes, + ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, + playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, + interactiveObjects, windows, lights, smokes, new FikaSerialization.PlayerInfoPacket() { Profile = playerToUse.Profile }, items); SendDataToPeer(peer, _dataWriter, ref responsePacket, DeliveryMethod.ReliableUnordered); @@ -283,7 +291,7 @@ private void OnBTRServicePacketReceived(BTRServicePacket packet, NetPeer peer) { if (CoopHandler.serverBTR != null) { - CoopHandler.serverBTR.NetworkBtrTraderServicePurchased(packet); + CoopHandler.serverBTR.NetworkBtrTraderServicePurchased(packet); } } diff --git a/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs b/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs new file mode 100644 index 00000000..92d888bd --- /dev/null +++ b/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs @@ -0,0 +1,27 @@ +using LiteNetLib.Utils; + +namespace Fika.Core.Networking +{ + // used for both quests and achievements + public struct ConditionChangePacket(int netId, string conditionId, float conditionValue) : INetSerializable + { + public int NetId; + public string ConditionId; + public float ConditionValue; + + public void Deserialize(NetDataReader reader) + { + NetId = reader.GetInt(); + ConditionId = reader.GetString(); + ConditionValue = reader.GetFloat(); + + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(netId); + writer.Put(conditionId); + writer.Put(conditionValue); + } + } +} \ No newline at end of file From 9321aeb4615e8ee4bb3bd52ed80ac47a53d900db Mon Sep 17 00:00:00 2001 From: CWX Date: Wed, 22 May 2024 17:04:05 +0100 Subject: [PATCH 33/34] clean up --- .../BaseLocalGame_method_6_Patch.cs | 6 ++--- .../Networking/FikaSerializationExtensions.cs | 26 +++++++++---------- .../Packets/Player/ConditionChangePacket.cs | 3 +-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs b/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs index f2af2efd..6ecadadf 100644 --- a/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs +++ b/Fika.Core/Coop/Patches/BaseLocalGame/BaseLocalGame_method_6_Patch.cs @@ -17,10 +17,10 @@ public static bool PatchPrefix(ref LocationSettingsClass.Location location) { if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { - location.Loot = MatchmakerAcceptPatches.ReconnectPacket.Value.Items; + location.Loot = MatchmakerAcceptPatches.ReconnectPacket.Value.Items; } - return true; - } + return true; + } } } \ No newline at end of file diff --git a/Fika.Core/Networking/FikaSerializationExtensions.cs b/Fika.Core/Networking/FikaSerializationExtensions.cs index 70741bdc..2c811a42 100644 --- a/Fika.Core/Networking/FikaSerializationExtensions.cs +++ b/Fika.Core/Networking/FikaSerializationExtensions.cs @@ -244,9 +244,9 @@ public static Item GetItem(this NetDataReader reader) public static void PutInteractiveObjectState(this NetDataWriter writer, WorldInteractiveObject worldInteractiveObject) { writer.Put(worldInteractiveObject.Id); - writer.Put((byte) worldInteractiveObject.DoorState); + writer.Put((byte)worldInteractiveObject.DoorState); writer.Put(Mathf.FloorToInt(worldInteractiveObject.CurrentAngle)); - writer.Put(worldInteractiveObject as Door is Door door ? door.IsBroken: false); + writer.Put(worldInteractiveObject as Door is Door door ? door.IsBroken : false); } public static WorldInteractiveObject.GStruct385 GetInteractiveObjectState(this NetDataReader reader) @@ -271,14 +271,14 @@ public static WindowBreaker GetWindowBreakerState(this NetDataReader reader) return new() { Id = reader.GetString(), - FirstHitPosition = reader.GetVector3(), + FirstHitPosition = reader.GetVector3(), }; } public static void PutLightState(this NetDataWriter writer, LampController windowBreaker) { writer.Put(windowBreaker.NetId); - writer.Put((byte) windowBreaker.LampState); + writer.Put((byte)windowBreaker.LampState); } public static LampController GetLightState(this NetDataReader reader) @@ -286,7 +286,7 @@ public static LampController GetLightState(this NetDataReader reader) return new() { NetId = reader.GetInt(), - LampState = (Turnable.EState) reader.GetByte() + LampState = (Turnable.EState)reader.GetByte() }; } @@ -318,18 +318,18 @@ public static GStruct34 GetSmokeState(this NetDataReader reader) public static void PutLocationItem(this NetDataWriter writer, LootItemPositionClass[] locationItem) { - using MemoryStream memoryStream = new(); - using BinaryWriter binaryWriter = new(memoryStream); - binaryWriter.Write(GClass1524.SerializeLootData(locationItem)); - writer.PutByteArray(memoryStream.ToArray()); - } + using MemoryStream memoryStream = new(); + using BinaryWriter binaryWriter = new(memoryStream); + binaryWriter.Write(GClass1524.SerializeLootData(locationItem)); + writer.PutByteArray(memoryStream.ToArray()); + } public static GClass1202 GetLocationItem(this NetDataReader reader) { - using MemoryStream memoryStream = new(reader.GetByteArray()); - using BinaryReader binaryReader = new(memoryStream); + using MemoryStream memoryStream = new(reader.GetByteArray()); + using BinaryReader binaryReader = new(memoryStream); return GClass1524.DeserializeLootData(Singleton.Instance, binaryReader.ReadEFTLootDataDescriptor()); - } + } } } diff --git a/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs b/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs index 92d888bd..2895690d 100644 --- a/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs +++ b/Fika.Core/Networking/Packets/Player/ConditionChangePacket.cs @@ -13,8 +13,7 @@ public void Deserialize(NetDataReader reader) { NetId = reader.GetInt(); ConditionId = reader.GetString(); - ConditionValue = reader.GetFloat(); - + ConditionValue = reader.GetFloat(); } public void Serialize(NetDataWriter writer) From 6c44ec3db8472a59b3dbab95864edd9ff24caaaf Mon Sep 17 00:00:00 2001 From: CWX Date: Fri, 24 May 2024 01:35:48 +0100 Subject: [PATCH 34/34] clean up with fixes --- .../CoopClientAchievementController.cs | 4 -- .../CoopClientQuestController.cs | 4 -- Fika.Core/Coop/Components/CoopHandler.cs | 2 - Fika.Core/Coop/GameMode/CoopGame.cs | 45 ++++++++----------- Fika.Core/Networking/FikaClient.cs | 3 -- Fika.Core/Networking/FikaServer.cs | 27 +++++++++-- Fika.Core/UI/Custom/MatchMakerUIScript.cs | 1 - 7 files changed, 42 insertions(+), 44 deletions(-) diff --git a/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs b/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs index 4f9ff25e..2f62e7ba 100644 --- a/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs +++ b/Fika.Core/Coop/ClientClasses/CoopClientAchievementController.cs @@ -1,10 +1,8 @@ using Comfort.Common; using EFT; -using EFT.Communications; using EFT.Quests; using Fika.Core.Coop.Matchmaker; using Fika.Core.Networking; -using UnityEngine; namespace Fika.Core.Coop.ClientClasses { @@ -20,10 +18,8 @@ public override void OnConditionValueChanged(IConditionCounter conditional, EQue { if (MatchmakerAcceptPatches.IsClient) { - // send netId, string for condition, value ConditionChangePacket packet = new(_fikaClient.MyPlayer.NetId, condition.id, condition.value); _fikaClient.SendData(_fikaClient.DataWriter, ref packet, LiteNetLib.DeliveryMethod.ReliableUnordered); - NotificationManagerClass.DisplayMessageNotification("Fika Achievement Condition Changed", ENotificationDurationType.Long, ENotificationIconType.Alert, Color.red); } base.OnConditionValueChanged(conditional, status, condition, notify); diff --git a/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs b/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs index 6be41e6d..9bc047d2 100644 --- a/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs +++ b/Fika.Core/Coop/ClientClasses/CoopClientQuestController.cs @@ -1,10 +1,8 @@ using Comfort.Common; using EFT; -using EFT.Communications; using EFT.Quests; using Fika.Core.Coop.Matchmaker; using Fika.Core.Networking; -using UnityEngine; namespace Fika.Core.Coop.ClientClasses { @@ -20,10 +18,8 @@ public override void OnConditionValueChanged(IConditionCounter conditional, EQue { if (MatchmakerAcceptPatches.IsClient) { - // send netId, string for condition, value ConditionChangePacket packet = new(fikaClient.MyPlayer.NetId, condition.id, condition.value); fikaClient.SendData(fikaClient.DataWriter, ref packet, LiteNetLib.DeliveryMethod.ReliableUnordered); - NotificationManagerClass.DisplayMessageNotification("Fika Quest Condition Changed", ENotificationDurationType.Long, ENotificationIconType.Alert, Color.red); } base.OnConditionValueChanged(conditional, status, condition, notify); diff --git a/Fika.Core/Coop/Components/CoopHandler.cs b/Fika.Core/Coop/Components/CoopHandler.cs index f528e449..5c47dc5a 100644 --- a/Fika.Core/Coop/Components/CoopHandler.cs +++ b/Fika.Core/Coop/Components/CoopHandler.cs @@ -374,8 +374,6 @@ await Singleton.Instance.LoadBundlesAndCreatePools(PoolManager.Pool if (!spawnObject.IsAlive) { - // [CWX] - might be able to be removed if dead AI isnt sent as someone to spawn / dont spawn them - // when sending lootpositions we get corpses. otherPlayer.OnDead(EDamageType.Undefined); } diff --git a/Fika.Core/Coop/GameMode/CoopGame.cs b/Fika.Core/Coop/GameMode/CoopGame.cs index 44eaa5c3..794271a1 100644 --- a/Fika.Core/Coop/GameMode/CoopGame.cs +++ b/Fika.Core/Coop/GameMode/CoopGame.cs @@ -38,6 +38,7 @@ using Fika.Core.UI.Models; using HarmonyLib; using JsonType; +using LiteNetLib; using LiteNetLib.Utils; using Newtonsoft.Json; using System; @@ -486,7 +487,7 @@ private bool TryDespawnFurthest(Profile profile, Vector3 position, CoopHandler c if (botKey == string.Empty) { #if DEBUG - Logger.LogWarning("TryDespawnFurthest: botKey was empty"); + Logger.LogWarning("TryDespawnFurthest: botKey was empty"); #endif return false; } @@ -677,7 +678,7 @@ private async Task SendOrReceiveSpawnPoint() if (!string.IsNullOrEmpty(name)) { - Logger.LogInfo($"Retrieved Spawn Point '{name}' from server"); + Logger.LogInfo($"Retrieved Spawn Point {name} from server"); Dictionary allSpawnPoints = Traverse.Create(spawnPoints).Field("dictionary_0").GetValue>(); foreach (ISpawnPoint spawnPointObject in allSpawnPoints.Keys) @@ -727,7 +728,6 @@ public override async Task vmethod_2(int playerId, Vector3 position await CreateCoopHandler(); CoopHandler.GetCoopHandler().LocalGameInstance = this; - // [CWX] Vector3 PosToSpawn = spawnPoint.Position; Quaternion RotToSpawn = spawnPoint.Rotation; if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) @@ -738,27 +738,21 @@ public override async Task vmethod_2(int playerId, Vector3 position int retryCount = 0; while (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount < 5) { - Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, LiteNetLib.DeliveryMethod.ReliableUnordered); + Singleton.Instance?.SendData(new NetDataWriter(), ref reconnectPacket, DeliveryMethod.ReliableUnordered); MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Requests Sent for reconnect... {retryCount + 1}"); await Task.Delay(3000); retryCount++; } - // TODO: [CWX] Remove before final PR - // if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) - // { - // // add synthetic retrys - // await Task.Delay(12000); // 4 extra trys - // } - if (MatchmakerAcceptPatches.ReconnectPacket == null && retryCount == 5) { MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Failed to Reconnect..."); - Singleton.Instance.ShowCriticalErrorScreen("Network Error", "[EXPERIMENTAL] Unable to reconnect to the host. Please try again after returning to main menu.", + Singleton.Instance.ShowCriticalErrorScreen("Network Error", "[EXPERIMENTAL] Unable to reconnect to the host. Please try again after returning to main menu.", ErrorScreen.EButtonType.OkButton, 10f, ReconnectFailed, ReconnectFailed); } MatchmakerAcceptPatches.GClass3163?.ChangeStatus($"Reconnecting to host..."); + PosToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Position; RotToSpawn = MatchmakerAcceptPatches.ReconnectPacket.Value.Rotation; profile = MatchmakerAcceptPatches.ReconnectPacket.Value.Profile.Profile; @@ -779,13 +773,11 @@ public override async Task vmethod_2(int playerId, Vector3 position CoopPlayer coopPlayer = (CoopPlayer)myPlayer; - // [CWX] if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { coopPlayer.NetId = MatchmakerAcceptPatches.ReconnectPacket.Value.NetId; myPlayer.MovementContext.SetPoseLevel(MatchmakerAcceptPatches.ReconnectPacket.Value.PoseLevel, true); myPlayer.MovementContext.IsInPronePose = MatchmakerAcceptPatches.ReconnectPacket.Value.IsProne; - // myPlayer.Inventory.Equipment.GetAllBundleTokens(); // force retain bundles to fix bundles not being loaded on reconnect } if (RaidSettings.MetabolismDisabled) @@ -869,15 +861,18 @@ public override async Task vmethod_2(int playerId, Vector3 position } } - SendCharacterPacket packet = new(new FikaSerialization.PlayerInfoPacket() { Profile = myPlayer.Profile }, myPlayer.HealthController.IsAlive, false, myPlayer.Transform.position, (myPlayer as CoopPlayer).NetId); - - if (MatchmakerAcceptPatches.IsServer) + if (!MatchmakerAcceptPatches.IsReconnect) { - await SetStatus(myPlayer, LobbyEntry.ELobbyStatus.COMPLETE); - } - else - { - Singleton.Instance.SendData(new NetDataWriter(), ref packet, LiteNetLib.DeliveryMethod.ReliableUnordered); + SendCharacterPacket packet = new(new FikaSerialization.PlayerInfoPacket() { Profile = myPlayer.Profile }, myPlayer.HealthController.IsAlive, false, myPlayer.Transform.position, (myPlayer as CoopPlayer).NetId); + + if (MatchmakerAcceptPatches.IsServer) + { + await SetStatus(myPlayer, LobbyEntry.ELobbyStatus.COMPLETE); + } + else + { + Singleton.Instance.SendData(new NetDataWriter(), ref packet, LiteNetLib.DeliveryMethod.ReliableUnordered); + } } if (MatchmakerAcceptPatches.IsServer) @@ -1014,8 +1009,6 @@ private async Task CreateLocalPlayer() { spawnPoint = SpawnSystem.SelectSpawnPoint(ESpawnCategory.Player, Profile_0.Info.Side); await SendOrReceiveSpawnPoint(); - // [CWX] after disconnect, and trying to host, make sure this is set back to defaults - // TODO: move working out if reconnect to earlier on, to mitigate issues hosting your own and joining a different game MatchmakerAcceptPatches.IsReconnect = false; MatchmakerAcceptPatches.ReconnectPacket = null; } @@ -1226,7 +1219,7 @@ public override IEnumerator vmethod_4(float startDelay, BotControllerSettings co if (limits > 0) { botsController_0.BotSpawner.SetMaxBots(limits); - } + } } DynamicAI = gameObject.AddComponent(); @@ -1665,10 +1658,8 @@ public override void Stop(string profileId, ExitStatus exitStatus, string exitNa { Logger.LogInfo("CoopGame::Stop"); - // [CWX] if (MatchmakerAcceptPatches.IsReconnect) { - // game ended, reset these values MatchmakerAcceptPatches.IsReconnect = false; MatchmakerAcceptPatches.ReconnectPacket = null; MatchmakerAcceptPatches.SpawnedPlayersComplete = false; diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 9c0a931a..afcb0869 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -128,7 +128,6 @@ private void OnOperationCallbackPacketReceived(OperationCallbackPacket packet) private void OnSyncNetIdPacketReceived(SyncNetIdPacket packet) { - // [CWX] if (MatchmakerAcceptPatches.IsClient && MatchmakerAcceptPatches.IsReconnect) { FikaPlugin.Instance.FikaLogger.LogInfo($"OnSyncNetIdPacketReceived: Client is reconnecting, ignore Sync."); @@ -195,7 +194,6 @@ private void OnAssignNetIdPacketReceived(AssignNetIdPacket packet) private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet) { - // [CWX] MatchmakerAcceptPatches.IsReconnect = true; MatchmakerAcceptPatches.ReconnectPacket = packet; @@ -204,7 +202,6 @@ private void OnReconnectResponsePacketReceived(ReconnectResponsePacket packet) public IEnumerator SyncClientToHost(ReconnectResponsePacket packet) { - // [CWX] while (!Singleton.Instantiated) { yield return null; diff --git a/Fika.Core/Networking/FikaServer.cs b/Fika.Core/Networking/FikaServer.cs index c0048f7a..ecb1ea4a 100644 --- a/Fika.Core/Networking/FikaServer.cs +++ b/Fika.Core/Networking/FikaServer.cs @@ -169,7 +169,6 @@ await Task.Run(async () => private void OnConditionChangedPacketReceived(ConditionChangePacket packet, NetPeer peer) { - // [CWX] Players.FirstOrDefault(x => x.Key == packet.NetId).Value.Profile.TaskConditionCounters .FirstOrDefault(c => c.Key == packet.ConditionId).Value.Value = (int)packet.ConditionValue; } @@ -184,7 +183,6 @@ public int PopNetId() private void OnReconnectRequestPacketReceived(ReconnectRequestPacket packet, NetPeer peer) { - // [CWX] serverLogger.LogError($"Player Wanting to reconnect {packet.ProfileId}"); StartCoroutine(SyncClientToHost(packet, peer)); } @@ -197,6 +195,7 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) } GameWorld gameWorld = Singleton.Instance; ClientGameWorld ClientgameWorld = Singleton.Instance as ClientGameWorld; + CoopGame coopGame = (CoopGame)Singleton.Instance; while (string.IsNullOrEmpty(ClientgameWorld.MainPlayer.Location)) { @@ -222,7 +221,29 @@ public IEnumerator SyncClientToHost(ReconnectRequestPacket packet, NetPeer peer) LootItemPositionClass[] items = gameWorld.GetJsonLootItems().Where(x => x as GClass1200 is null).ToArray(); // will ignore corpses // LootItemPositionClass[] items = gameWorld.GetJsonLootItems().ToArray(); // will include corpses - playerToUse.Profile.Health = playerToUse.NetworkHealthController.Store(null); // Hp is synced, Effects are not + Profile.GClass1756 health = playerToUse.NetworkHealthController.Store(null); + GClass2417.GClass2420[] effects = playerToUse.NetworkHealthController.IReadOnlyList_0.ToArray(); + + foreach (GClass2417.GClass2420 effect in effects) + { + if (!effect.Active) + { + continue; + } + + if (health.BodyParts[effect.BodyPart].Effects == null) + { + health.BodyParts[effect.BodyPart].Effects = new Dictionary(); + } + + if (!health.BodyParts[effect.BodyPart].Effects.ContainsKey(effect.GetType().Name) && effect is GInterface245) + { + health.BodyParts[effect.BodyPart].Effects.Add(effect.GetType().Name, new Profile.GClass1756.GClass1757 { Time = -1f, ExtraData = effect.StoreObj }); + } + } + + playerToUse.Profile.Health = health; + playerToUse.Profile.Info.EntryPoint = coopGame.InfiltrationPoint; ReconnectResponsePacket responsePacket = new(playerToUse.NetId, playerToUse.Transform.position, playerToUse.Transform.rotation, playerToUse.Pose, playerToUse.PoseLevel, playerToUse.IsInPronePose, diff --git a/Fika.Core/UI/Custom/MatchMakerUIScript.cs b/Fika.Core/UI/Custom/MatchMakerUIScript.cs index 63f312f8..4ccddabe 100644 --- a/Fika.Core/UI/Custom/MatchMakerUIScript.cs +++ b/Fika.Core/UI/Custom/MatchMakerUIScript.cs @@ -302,7 +302,6 @@ private void RefreshUI() Singleton.Instance.PlayUISound(EUISoundType.ButtonClick); if (entry.Status == LobbyEntry.ELobbyStatus.REJOIN) { - // [CWX] MatchmakerAcceptPatches.IsReconnect = true; } else