diff --git a/Fika.Core/Coop/Components/CorpsePositionSyncer.cs b/Fika.Core/Coop/Components/CorpsePositionSyncer.cs new file mode 100644 index 00000000..cc0a60a7 --- /dev/null +++ b/Fika.Core/Coop/Components/CorpsePositionSyncer.cs @@ -0,0 +1,71 @@ +using Comfort.Common; +using EFT.Interactive; +using Fika.Core.Networking; +using Fika.Core.Networking.Packets; +using HarmonyLib; +using LiteNetLib; +using System.Reflection; +using UnityEngine; + +namespace Fika.Core.Coop.Components +{ + internal class CorpsePositionSyncer : MonoBehaviour + { + private FieldInfo ragdollDoneField = AccessTools.Field(typeof(RagdollClass), "bool_2"); + + private FikaServer server; + private Corpse corpse; + private GStruct129 data; + + public static void Create(GameObject gameObject, Corpse corpse) + { + CorpsePositionSyncer corpsePositionSyncer = gameObject.AddComponent(); + corpsePositionSyncer.corpse = corpse; + corpsePositionSyncer.server = Singleton.Instance; + corpsePositionSyncer.data = new() + { + Id = corpse.GetNetId() + }; + } + + public void Start() + { + if (corpse == null) + { + FikaPlugin.Instance.FikaLogger.LogError("CorpsePositionSyncer::Start: Corpse was null!"); + Destroy(this); + } + + if (!corpse.HasRagdoll) + { + FikaPlugin.Instance.FikaLogger.LogError("CorpsePositionSyncer::Start: Ragdoll was null!"); + Destroy(this); + } + } + + public void FixedUpdate() + { + if ((bool)ragdollDoneField.GetValue(corpse.Ragdoll)) + { + data.Position = corpse.TrackableTransform.position; + data.TransformSyncs = corpse.TransformSyncs; + data.Done = true; + CorpsePositionPacket endPacket = new() + { + Data = data + }; + server.SendDataToAll(ref endPacket, DeliveryMethod.ReliableOrdered); + Destroy(this); + return; + } + + data.Position = corpse.TrackableTransform.position; + CorpsePositionPacket packet = new() + { + Data = data + }; + + server.SendDataToAll(ref packet, DeliveryMethod.Unreliable); + } + } +} diff --git a/Fika.Core/Coop/Players/CoopPlayer.cs b/Fika.Core/Coop/Players/CoopPlayer.cs index ba366b95..f7af8c31 100644 --- a/Fika.Core/Coop/Players/CoopPlayer.cs +++ b/Fika.Core/Coop/Players/CoopPlayer.cs @@ -12,6 +12,7 @@ using EFT.Vehicle; using Fika.Core.Coop.ClientClasses; using Fika.Core.Coop.ClientClasses.HandsControllers; +using Fika.Core.Coop.Components; using Fika.Core.Coop.HostClasses; using Fika.Core.Coop.ObservedClasses.Snapshotting; using Fika.Core.Coop.PacketHandlers; @@ -626,6 +627,13 @@ public override void OnPhraseTold(EPhraseTrigger @event, TaggedClip clip, TagBan } } + public override Corpse CreateCorpse() + { + Corpse corpse = base.CreateCorpse(); + CorpsePositionSyncer.Create(corpse.gameObject, corpse); + return corpse; + } + public override void OperateStationaryWeapon(StationaryWeapon stationaryWeapon, GStruct177.EStationaryCommand command) { base.OperateStationaryWeapon(stationaryWeapon, command); diff --git a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs index b4a84753..b9a8b934 100644 --- a/Fika.Core/Coop/Players/ObservedCoopPlayer.cs +++ b/Fika.Core/Coop/Players/ObservedCoopPlayer.cs @@ -7,6 +7,7 @@ using EFT.Interactive; using EFT.InventoryLogic; using EFT.Vaulting; +using Fika.Core.Coop.Components; using Fika.Core.Coop.Custom; using Fika.Core.Coop.Factories; using Fika.Core.Coop.GameMode; @@ -794,7 +795,16 @@ public override Corpse CreateCorpse() { SetInventory(CorpseSyncPacket.InventoryDescriptor); } - return CreateCorpse(CorpseSyncPacket.OverallVelocity); + if (FikaBackendUtils.IsClient) + { + ObservedCorpse observedCorpse = CreateCorpse(CorpseSyncPacket.OverallVelocity); + Singleton.Instance.ObservedPlayersCorpses.Add(observedCorpse.GetNetId(), observedCorpse); + return observedCorpse; + } + + Corpse corpse = CreateCorpse(CorpseSyncPacket.OverallVelocity); + CorpsePositionSyncer.Create(corpse.gameObject, corpse); + return corpse; } public override void OnDead(EDamageType damageType) diff --git a/Fika.Core/Networking/FikaClient.cs b/Fika.Core/Networking/FikaClient.cs index 9b585076..60cfd044 100644 --- a/Fika.Core/Networking/FikaClient.cs +++ b/Fika.Core/Networking/FikaClient.cs @@ -22,7 +22,9 @@ using Fika.Core.Coop.Utils; using Fika.Core.Modding; using Fika.Core.Modding.Events; +using Fika.Core.Networking.Packets; using Fika.Core.Utils; +using FlyingWormConsole3; using HarmonyLib; using LiteNetLib; using LiteNetLib.Utils; @@ -158,6 +160,7 @@ public async void Init() packetProcessor.SubscribeNetSerializable(OnPingPacketReceived); packetProcessor.SubscribeNetSerializable(OnLootSyncPacketReceived); packetProcessor.SubscribeNetSerializable(OnLoadingProfilePacketReceived); + packetProcessor.SubscribeNetSerializable(OnCorpsePositionPacketReceived); #if DEBUG AddDebugPackets(); @@ -209,6 +212,19 @@ public async void Init() FikaEventDispatcher.DispatchEvent(new FikaNetworkManagerCreatedEvent(this)); } + private void OnCorpsePositionPacketReceived(CorpsePositionPacket packet) + { + GameWorld gameWorld = Singleton.Instance; + if (gameWorld != null) + { + if (gameWorld.ObservedPlayersCorpses.TryGetValue(packet.Data.Id, out ObservedCorpse corpse)) + { + corpse.ApplyNetPacket(packet.Data); + return; + } + } + } + private void OnLoadingProfilePacketReceived(LoadingProfilePacket packet) { if (packet.Profiles != null) diff --git a/Fika.Core/Networking/Packets/GameWorld/CorpsePositionPacket.cs b/Fika.Core/Networking/Packets/GameWorld/CorpsePositionPacket.cs new file mode 100644 index 00000000..6fa6843f --- /dev/null +++ b/Fika.Core/Networking/Packets/GameWorld/CorpsePositionPacket.cs @@ -0,0 +1,49 @@ +using LiteNetLib.Utils; + +namespace Fika.Core.Networking +{ + public struct CorpsePositionPacket : INetSerializable + { + public GStruct129 Data; + + public void Deserialize(NetDataReader reader) + { + Data = new() + { + Id = reader.GetInt(), + Position = reader.GetVector3(), + Done = reader.GetBool() + }; + + if (Data.Done) + { + Data.TransformSyncs = new GStruct107[12]; + for (int i = 0; i < 12; i++) + { + Data.TransformSyncs[i] = new() + { + Position = reader.GetVector3(), + Rotation = reader.GetQuaternion() + }; + } + } + } + + public void Serialize(NetDataWriter writer) + { + writer.Put(Data.Id); + writer.Put(Data.Position); + writer.Put(Data.Done); + + if (Data.Done && Data.TransformSyncs != null) + { + GStruct107[] transforms = Data.TransformSyncs; + for (int i = 0; i < 12; i++) + { + writer.Put(transforms[i].Position); + writer.Put(transforms[i].Rotation); + } + } + } + } +}