From 57466417f5a3038fea939e3708b68d1d8d4e0efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Fekete?= <49228974+donCalculator@users.noreply.github.com> Date: Mon, 12 Jun 2023 13:18:41 +0200 Subject: [PATCH 1/4] rename ReplayVersionHistory.HISTORY_2500 --- src/Unreal.Core/Models/Enums/ReplayVersionHistory.cs | 4 ++-- src/Unreal.Core/ReplayReader.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Unreal.Core/Models/Enums/ReplayVersionHistory.cs b/src/Unreal.Core/Models/Enums/ReplayVersionHistory.cs index eb3c2ba..3107a92 100644 --- a/src/Unreal.Core/Models/Enums/ReplayVersionHistory.cs +++ b/src/Unreal.Core/Models/Enums/ReplayVersionHistory.cs @@ -1,7 +1,7 @@ namespace Unreal.Core.Models { /// - /// see https://github.com/EpicGames/UnrealEngine/blob/70bc980c6361d9a7d23f6d23ffe322a2d6ef16fb/Engine/Source/Runtime/NetworkReplayStreaming/LocalFileNetworkReplayStreaming/Private/LocalFileNetworkReplayStreaming.cpp#L45 + /// see https://github.com/EpicGames/UnrealEngine/blob/996ef9a9f4ad5a899abf70fb292d2914a46d0876/Engine/Source/Runtime/NetworkReplayStreaming/LocalFileNetworkReplayStreaming/Public/LocalFileNetworkReplayStreaming.h#L34 /// [System.Flags] public enum ReplayVersionHistory : uint @@ -13,7 +13,7 @@ public enum ReplayVersionHistory : uint HISTORY_STREAM_CHUNK_TIMES = 4, HISTORY_FRIENDLY_NAME_ENCODING = 5, HISTORY_ENCRYPTION = 6, - HISTORY_2500 = 7, // TODO, FIND THE NAME OF THIS + HISTORY_CUSTOM_VERSIONS = 7, HISTORY_PLUS_ONE, LATEST = HISTORY_PLUS_ONE - 1 diff --git a/src/Unreal.Core/ReplayReader.cs b/src/Unreal.Core/ReplayReader.cs index ae3664f..8483fdc 100644 --- a/src/Unreal.Core/ReplayReader.cs +++ b/src/Unreal.Core/ReplayReader.cs @@ -531,7 +531,7 @@ public virtual void ReadReplayInfo(FArchive archive) { _logger?.LogWarning("Found unexpected ReplayVersionHistory: {}", fileVersion); } - if (archive.ReplayVersion >= ReplayVersionHistory.HISTORY_2500) + if (archive.ReplayVersion >= ReplayVersionHistory.HISTORY_CUSTOM_VERSIONS) { var customVersionCount = archive.ReadInt32(); From 93015a61ef06e1daea89de5de21044ef88792228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Fekete?= <49228974+donCalculator@users.noreply.github.com> Date: Mon, 12 Jun 2023 13:51:23 +0200 Subject: [PATCH 2/4] adding parsing of ReplicatedWorldTimeSecondsDouble --- .../FortniteReplayBuilderTest.cs | 1 + .../FortniteReplayBuilder.cs | 16 +++++++++++++++- src/FortniteReplayReader/Models/KillFeedEntry.cs | 1 + src/FortniteReplayReader/Models/Llama.cs | 1 + .../Models/NetFieldExports/GameState.cs | 3 +++ src/FortniteReplayReader/Models/PlayerData.cs | 5 ++++- src/FortniteReplayReader/Models/SupplyDrop.cs | 2 ++ src/Unreal.Core/Contracts/ITelemetryEvent.cs | 2 ++ src/Unreal.Core/Models/Enums/RepLayoutCmdType.cs | 1 + src/Unreal.Core/NetBitReader.cs | 5 +++++ src/Unreal.Core/NetFieldParser.cs | 3 +++ 11 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/FortniteReplayReader.Test/FortniteReplayBuilderTest.cs b/src/FortniteReplayReader.Test/FortniteReplayBuilderTest.cs index 9cde900..aca9777 100644 --- a/src/FortniteReplayReader.Test/FortniteReplayBuilderTest.cs +++ b/src/FortniteReplayReader.Test/FortniteReplayBuilderTest.cs @@ -25,6 +25,7 @@ public void GameStateTest() GameSessionId = "123", WinningTeam = 99, ReplicatedWorldTimeSeconds = 1, + ReplicatedWorldTimeSecondsDouble = 1, }; builder.UpdateGameState(state); diff --git a/src/FortniteReplayReader/FortniteReplayBuilder.cs b/src/FortniteReplayReader/FortniteReplayBuilder.cs index 90314d6..5560933 100644 --- a/src/FortniteReplayReader/FortniteReplayBuilder.cs +++ b/src/FortniteReplayReader/FortniteReplayBuilder.cs @@ -37,6 +37,7 @@ public class FortniteReplayBuilder private readonly Dictionary _unknownWeapons = new(); private float? ReplicatedWorldTimeSeconds = 0; + private float? ReplicatedWorldTimeSecondsDouble = 0; public void AddActorChannel(uint channelIndex, uint guid) { @@ -132,6 +133,11 @@ public void UpdateGameState(GameState state) ReplicatedWorldTimeSeconds = state.ReplicatedWorldTimeSeconds; } + if (state.ReplicatedWorldTimeSecondsDouble != null) + { + ReplicatedWorldTimeSecondsDouble = state.ReplicatedWorldTimeSecondsDouble; + } + GameData.WinningPlayerIds ??= state.WinningPlayerList; GameData.WinningTeam ??= state.WinningTeam; GameData.RecorderId ??= state.RecorderPlayerState?.Value; @@ -246,6 +252,8 @@ public void UpdatePlayerState(uint channelIndex, FortPlayerState state) if (state.DeathTags != null) { playerData.DeathTime = ReplicatedWorldTimeSeconds; + playerData.DeathTimeDouble = ReplicatedWorldTimeSecondsDouble; + } playerData.Cosmetics.Parts ??= state.Parts?.Name; @@ -262,7 +270,8 @@ public void UpdateKillFeed(uint channelIndex, PlayerData data, FortPlayerState s { KillFeedEntry? entry = new KillFeedEntry() { - ReplicatedWorldTimeSeconds = ReplicatedWorldTimeSeconds + ReplicatedWorldTimeSeconds = ReplicatedWorldTimeSeconds, + ReplicatedWorldTimeSecondsDouble = ReplicatedWorldTimeSecondsDouble, }; if (state.RebootCounter != null) @@ -363,6 +372,7 @@ public void UpdatePlayerPawn(uint channelIndex, PlayerPawn pawn) { ReplicatedMovement = pawn.ReplicatedMovement, ReplicatedWorldTimeSeconds = ReplicatedWorldTimeSeconds, + ReplicatedWorldTimeSecondsDouble = ReplicatedWorldTimeSecondsDouble, LastUpdateTime = pawn.ReplayLastTransformUpdateTimeStamp, bIsCrouched = pawn.bIsCrouched, bIsInAnyStorm = pawn.bIsInAnyStorm, @@ -495,6 +505,7 @@ public void UpdateLlama(uint channelIndex, SupplyDropLlama supplyDropLlama) { llama.Looted = true; llama.LootedTime = ReplicatedWorldTimeSeconds; + llama.LootedTimeDouble = ReplicatedWorldTimeSecondsDouble; } if (supplyDropLlama.bHasSpawnedPickups) @@ -517,12 +528,15 @@ public void UpdateSupplyDrop(uint channelIndex, Models.NetFieldExports.SupplyDro { drop.Looted = true; drop.LootedTime = ReplicatedWorldTimeSeconds; + drop.LootedTimeDouble = ReplicatedWorldTimeSecondsDouble; } if (supplyDrop.BalloonPopped) { drop.BalloonPopped = true; drop.BalloonPoppedTime = ReplicatedWorldTimeSeconds; + drop.BalloonPoppedTimeDouble = ReplicatedWorldTimeSecondsDouble; + } if (supplyDrop.bHasSpawnedPickups) diff --git a/src/FortniteReplayReader/Models/KillFeedEntry.cs b/src/FortniteReplayReader/Models/KillFeedEntry.cs index 854dbb2..43fbc11 100644 --- a/src/FortniteReplayReader/Models/KillFeedEntry.cs +++ b/src/FortniteReplayReader/Models/KillFeedEntry.cs @@ -14,6 +14,7 @@ public class KillFeedEntry public bool FinisherOrDownerIsBot { get; set; } public float? ReplicatedWorldTimeSeconds { get; set; } + public float? ReplicatedWorldTimeSecondsDouble { get; set; } public float? Distance { get; set; } public int? DeathCause { get; set; } public FVector DeathLocation { get; set; } diff --git a/src/FortniteReplayReader/Models/Llama.cs b/src/FortniteReplayReader/Models/Llama.cs index ddd1a92..08e37ba 100644 --- a/src/FortniteReplayReader/Models/Llama.cs +++ b/src/FortniteReplayReader/Models/Llama.cs @@ -24,6 +24,7 @@ public Llama(uint channelIndex, SupplyDropLlama drop) public bool HasSpawnedPickups { get; set; } public bool Looted { get; set; } public float? LootedTime { get; set; } + public double? LootedTimeDouble { get; set; } public FVector? LandingLocation { get; set; } } } diff --git a/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs b/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs index 594d6a8..bd4dc46 100644 --- a/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs +++ b/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs @@ -108,6 +108,9 @@ public class GameState : INetFieldExportGroup [NetFieldExport("ReplicatedWorldTimeSeconds", RepLayoutCmdType.PropertyFloat)] public float? ReplicatedWorldTimeSeconds { get; set; } + [NetFieldExport("ReplicatedWorldTimeSecondsDouble", RepLayoutCmdType.PropertyDouble)] + public float? ReplicatedWorldTimeSecondsDouble { get; set; } + [NetFieldExport("MatchState", RepLayoutCmdType.Property)] public FName MatchState { get; set; } diff --git a/src/FortniteReplayReader/Models/PlayerData.cs b/src/FortniteReplayReader/Models/PlayerData.cs index 97fd8f4..48e7227 100644 --- a/src/FortniteReplayReader/Models/PlayerData.cs +++ b/src/FortniteReplayReader/Models/PlayerData.cs @@ -71,7 +71,7 @@ public PlayerData(FortPlayerState playerState) public IEnumerable DeathTags { get; set; } public FVector DeathLocation { get; set; } public float? DeathTime { get; set; } - + public double? DeathTimeDouble { get; set; } public Cosmetics Cosmetics { get; set; } public uint? CurrentWeapon { get; internal set; } @@ -104,6 +104,9 @@ public class PlayerMovement { public FRepMovement? ReplicatedMovement { get; set; } public float? ReplicatedWorldTimeSeconds { get; set; } + + public float? ReplicatedWorldTimeSecondsDouble { get; set; } + public float? LastUpdateTime { get; set; } public bool? bIsCrouched { get; set; } diff --git a/src/FortniteReplayReader/Models/SupplyDrop.cs b/src/FortniteReplayReader/Models/SupplyDrop.cs index ad52764..9819fad 100644 --- a/src/FortniteReplayReader/Models/SupplyDrop.cs +++ b/src/FortniteReplayReader/Models/SupplyDrop.cs @@ -21,8 +21,10 @@ public SupplyDrop(uint channelIndex, NetFieldExports.SupplyDrop drop) public bool HasSpawnedPickups { get; set; } public bool Looted { get; set; } public float? LootedTime { get; set; } + public double? LootedTimeDouble { get; set; } public bool BalloonPopped { get; set; } public float? BalloonPoppedTime { get; set; } + public double? BalloonPoppedTimeDouble { get; set; } public float FallSpeed { get; set; } public FVector LandingLocation { get; set; } public float FallHeight { get; set; } diff --git a/src/Unreal.Core/Contracts/ITelemetryEvent.cs b/src/Unreal.Core/Contracts/ITelemetryEvent.cs index d4ac4a2..8927bb6 100644 --- a/src/Unreal.Core/Contracts/ITelemetryEvent.cs +++ b/src/Unreal.Core/Contracts/ITelemetryEvent.cs @@ -6,5 +6,7 @@ public interface ITelemetryEvent { public float? ReplicatedWorldTimeSeconds { get; set; } + + public float? ReplicatedWorldTimeSecondsDouble { get; set; } } } diff --git a/src/Unreal.Core/Models/Enums/RepLayoutCmdType.cs b/src/Unreal.Core/Models/Enums/RepLayoutCmdType.cs index a818965..08eb72b 100644 --- a/src/Unreal.Core/Models/Enums/RepLayoutCmdType.cs +++ b/src/Unreal.Core/Models/Enums/RepLayoutCmdType.cs @@ -32,6 +32,7 @@ public enum RepLayoutCmdType PropertySoftObject = 22, PropertyWeakObject = 23, + PropertyDouble = 94, PropertyVector2D = 95, PropertyInt16 = 96, PropertyUInt16 = 97, diff --git a/src/Unreal.Core/NetBitReader.cs b/src/Unreal.Core/NetBitReader.cs index 6ec7ff8..ac80c94 100644 --- a/src/Unreal.Core/NetBitReader.cs +++ b/src/Unreal.Core/NetBitReader.cs @@ -41,6 +41,11 @@ public float SerializePropertyFloat() return ReadSingle(); } + public double SerializePropertyDouble() + { + return ReadDouble(); + } + public string SerializePropertyName() { return ReadFName(); diff --git a/src/Unreal.Core/NetFieldParser.cs b/src/Unreal.Core/NetFieldParser.cs index a140aa3..7cfad59 100644 --- a/src/Unreal.Core/NetFieldParser.cs +++ b/src/Unreal.Core/NetFieldParser.cs @@ -379,6 +379,9 @@ private void SetType(INetFieldExportGroup obj, NetFieldInfo netFieldInfo, NetFie case RepLayoutCmdType.PropertyFloat: data = netBitReader.SerializePropertyFloat(); break; + case RepLayoutCmdType.PropertyDouble: + data = netBitReader.SerializePropertyDouble(); + break; case RepLayoutCmdType.PropertyNativeBool: data = netBitReader.SerializePropertyNativeBool(); break; From edc5b950e7b2cc74cdcb7e741adaf005b5be42c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Fekete?= <49228974+donCalculator@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:19:18 +0200 Subject: [PATCH 3/4] fix types --- src/FortniteReplayReader/FortniteReplayBuilder.cs | 2 +- src/FortniteReplayReader/Models/KillFeedEntry.cs | 2 +- src/FortniteReplayReader/Models/NetFieldExports/GameState.cs | 2 +- src/FortniteReplayReader/Models/PlayerData.cs | 2 +- src/Unreal.Core/Contracts/ITelemetryEvent.cs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/FortniteReplayReader/FortniteReplayBuilder.cs b/src/FortniteReplayReader/FortniteReplayBuilder.cs index 5560933..05854ac 100644 --- a/src/FortniteReplayReader/FortniteReplayBuilder.cs +++ b/src/FortniteReplayReader/FortniteReplayBuilder.cs @@ -37,7 +37,7 @@ public class FortniteReplayBuilder private readonly Dictionary _unknownWeapons = new(); private float? ReplicatedWorldTimeSeconds = 0; - private float? ReplicatedWorldTimeSecondsDouble = 0; + private double? ReplicatedWorldTimeSecondsDouble = 0; public void AddActorChannel(uint channelIndex, uint guid) { diff --git a/src/FortniteReplayReader/Models/KillFeedEntry.cs b/src/FortniteReplayReader/Models/KillFeedEntry.cs index 43fbc11..1c72a7f 100644 --- a/src/FortniteReplayReader/Models/KillFeedEntry.cs +++ b/src/FortniteReplayReader/Models/KillFeedEntry.cs @@ -14,7 +14,7 @@ public class KillFeedEntry public bool FinisherOrDownerIsBot { get; set; } public float? ReplicatedWorldTimeSeconds { get; set; } - public float? ReplicatedWorldTimeSecondsDouble { get; set; } + public double? ReplicatedWorldTimeSecondsDouble { get; set; } public float? Distance { get; set; } public int? DeathCause { get; set; } public FVector DeathLocation { get; set; } diff --git a/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs b/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs index bd4dc46..b22e0e1 100644 --- a/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs +++ b/src/FortniteReplayReader/Models/NetFieldExports/GameState.cs @@ -109,7 +109,7 @@ public class GameState : INetFieldExportGroup public float? ReplicatedWorldTimeSeconds { get; set; } [NetFieldExport("ReplicatedWorldTimeSecondsDouble", RepLayoutCmdType.PropertyDouble)] - public float? ReplicatedWorldTimeSecondsDouble { get; set; } + public double? ReplicatedWorldTimeSecondsDouble { get; set; } [NetFieldExport("MatchState", RepLayoutCmdType.Property)] public FName MatchState { get; set; } diff --git a/src/FortniteReplayReader/Models/PlayerData.cs b/src/FortniteReplayReader/Models/PlayerData.cs index 48e7227..6bd01e1 100644 --- a/src/FortniteReplayReader/Models/PlayerData.cs +++ b/src/FortniteReplayReader/Models/PlayerData.cs @@ -105,7 +105,7 @@ public class PlayerMovement public FRepMovement? ReplicatedMovement { get; set; } public float? ReplicatedWorldTimeSeconds { get; set; } - public float? ReplicatedWorldTimeSecondsDouble { get; set; } + public double? ReplicatedWorldTimeSecondsDouble { get; set; } public float? LastUpdateTime { get; set; } diff --git a/src/Unreal.Core/Contracts/ITelemetryEvent.cs b/src/Unreal.Core/Contracts/ITelemetryEvent.cs index 8927bb6..bdc4be5 100644 --- a/src/Unreal.Core/Contracts/ITelemetryEvent.cs +++ b/src/Unreal.Core/Contracts/ITelemetryEvent.cs @@ -7,6 +7,6 @@ public interface ITelemetryEvent { public float? ReplicatedWorldTimeSeconds { get; set; } - public float? ReplicatedWorldTimeSecondsDouble { get; set; } + public double? ReplicatedWorldTimeSecondsDouble { get; set; } } } From 4fed5c1f8f1b355a9d2438a0c161a4683de99b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Fekete?= <49228974+donCalculator@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:41:06 +0200 Subject: [PATCH 4/4] adding 31 to EngineNetworkCustomVersion.h --- src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs b/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs index b4cd62e..2d16a71 100644 --- a/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs +++ b/src/Unreal.Core/Models/Enums/EngineNetworkVersionHistory.cs @@ -35,6 +35,7 @@ public enum EngineNetworkVersionHistory HISTORY_RUNTIME_FEATURES_COMPATIBILITY = 28, // Bump version to add network runtime feature compatibility test to handshake (hello/upgrade) control messages HISTORY_SOFTOBJECTPTR_NETGUIDS = 29, // Bump version to support replicating SoftObjectPtrs by NetGuid instead of raw strings. HISTORY_SUBOBJECT_DESTROY_FLAG = 30, // Bump version to support subobject destruction message flags + HISTORY_GAMESTATE_REPLCIATED_TIME_AS_DOUBLE = 31, // Bump version to support AGameStateBase::ReplicatedWorldTimeSeconds as double instead of float. HISTORY_ENGINENETVERSION_PLUS_ONE, LATEST = HISTORY_ENGINENETVERSION_PLUS_ONE - 1,