예제 #1
0
        /// <summary>
        /// see https://github.com/EpicGames/UnrealEngine/blob/70bc980c6361d9a7d23f6d23ffe322a2d6ef16fb/Engine/Source/Runtime/NetworkReplayStreaming/LocalFileNetworkReplayStreaming/Private/LocalFileNetworkReplayStreaming.cpp#L363
        /// </summary>
        /// <param name="archive"></param>
        /// <returns></returns>
        protected override void ReadEvent(FArchive archive)
        {
            var info = new EventInfo
            {
                Id          = archive.ReadFString(),
                Group       = archive.ReadFString(),
                Metadata    = archive.ReadFString(),
                StartTime   = archive.ReadUInt32(),
                EndTime     = archive.ReadUInt32(),
                SizeInBytes = archive.ReadInt32()
            };

            _logger?.LogDebug($"Encountered event {info.Group} ({info.Metadata}) at {info.StartTime} of size {info.SizeInBytes}");

            // Every event seems to start with some unknown int
            if (info.Group == ReplayEventTypes.PLAYER_ELIMINATION)
            {
                var elimination = ParseElimination(archive, info);
                Replay.Eliminations.Add(elimination);
                return;
            }
            else if (info.Metadata == ReplayEventTypes.MATCH_STATS)
            {
                Replay.Stats = ParseMatchStats(archive, info);
                return;
            }
            else if (info.Metadata == ReplayEventTypes.TEAM_STATS)
            {
                Replay.TeamStats = ParseTeamStats(archive, info);
                return;
            }
            else if (info.Metadata == ReplayEventTypes.ENCRYPTION_KEY)
            {
                Replay.GameInformation.PlayerStateEncryptionKey = ParseEncryptionKeyEvent(archive, info);
                return;
            }
            else if (info.Metadata == ReplayEventTypes.CHARACTER_SAMPLE)
            {
                ParseCharacterSample(archive, info);
                return;
            }
            else if (info.Group == ReplayEventTypes.ZONE_UPDATE)
            {
                ParseZoneUpdateEvent(archive, info);
                return;
            }
            else if (info.Group == ReplayEventTypes.BATTLE_BUS)
            {
                ParseBattleBusFlightEvent(archive, info);
                return;
            }
            else if (info.Group == "fortBenchEvent")
            {
                return;
            }

            _logger?.LogWarning($"Unknown event {info.Group} ({info.Metadata}) of size {info.SizeInBytes}");
            // optionally throw?
            throw new UnknownEventException($"Unknown event {info.Group} ({info.Metadata}) of size {info.SizeInBytes}");
        }
예제 #2
0
        public override void ReadEvent(FArchive archive)
        {
            int startPosition = archive.Position;

            var info = new EventInfo
            {
                Id          = archive.ReadFString(),
                Group       = archive.ReadFString(),
                Metadata    = archive.ReadFString(),
                StartTime   = archive.ReadUInt32(),
                EndTime     = archive.ReadUInt32(),
                SizeInBytes = archive.ReadInt32()
            };

            int infoSize = archive.Position - startPosition;

            using var decryptedReader = (Unreal.Core.BinaryReader)base.DecryptBuffer(archive, info.SizeInBytes);

            _writer.Write(infoSize + decryptedReader.Bytes.Length); //Chunk Size
            _writer.Write(info.Id);
            _writer.Write(info.Group);
            _writer.Write(info.Metadata);
            _writer.Write(info.StartTime);
            _writer.Write(info.EndTime);
            _writer.Write(decryptedReader.Bytes.Length);    //Decrypted size
            _writer.Write(decryptedReader.Bytes.ToArray()); //Decrypted bytes
        }
예제 #3
0
        public override void ReadCheckpoint(FArchive archive)
        {
            int startPosition = archive.Position;

            var info = new CheckpointInfo
            {
                Id          = archive.ReadFString(),
                Group       = archive.ReadFString(),
                Metadata    = archive.ReadFString(),
                StartTime   = archive.ReadUInt32(),
                EndTime     = archive.ReadUInt32(),
                SizeInBytes = archive.ReadInt32()
            };

            int infoSize = archive.Position - startPosition;

            using var decrypted     = (Unreal.Core.BinaryReader)DecryptBuffer(archive, info.SizeInBytes);
            using var binaryArchive = (Unreal.Core.BinaryReader)Decompress(decrypted, decrypted.Bytes.Length);

            _writer.Write(infoSize + binaryArchive.Bytes.Length); //Chunk Size
            _writer.Write(info.Id);
            _writer.Write(info.Group);
            _writer.Write(info.Metadata);
            _writer.Write(info.StartTime);
            _writer.Write(info.EndTime);
            _writer.Write(binaryArchive.Bytes.Length);    //Decompressed checkpoint length
            _writer.Write(binaryArchive.Bytes.ToArray()); //Decompressed checkpoint
        }
예제 #4
0
        public override void ReadReplayData(FArchive archive)
        {
            int startPosition = archive.Position;

            var info = new ReplayDataInfo();

            if (archive.ReplayVersion >= ReplayVersionHistory.HISTORY_STREAM_CHUNK_TIMES)
            {
                info.Start  = archive.ReadUInt32();
                info.End    = archive.ReadUInt32();
                info.Length = archive.ReadUInt32();
            }
            else
            {
                info.Length = archive.ReadUInt32();
            }

            int memorySizeInBytes = (int)info.Length;

            if (archive.ReplayVersion >= ReplayVersionHistory.HISTORY_ENCRYPTION)
            {
                memorySizeInBytes = archive.ReadInt32();
            }

            int infoSize = archive.Position - startPosition;

            using var decryptedReader = DecryptBuffer(archive, (int)info.Length);
            using var binaryArchive   = (Unreal.Core.BinaryReader)Decompress(decryptedReader, memorySizeInBytes);

            //Chunk size
            _writer.Write(infoSize + binaryArchive.Bytes.Length);

            if (archive.ReplayVersion >= ReplayVersionHistory.HISTORY_STREAM_CHUNK_TIMES)
            {
                _writer.Write(info.Start);
                _writer.Write(info.End);
                _writer.Write(binaryArchive.Bytes.Length);
            }
            else
            {
                _writer.Write(binaryArchive.Bytes.Length);
            }

            if (archive.ReplayVersion >= ReplayVersionHistory.HISTORY_ENCRYPTION)
            {
                _writer.Write(binaryArchive.Bytes.Length);
            }

            _writer.Write(binaryArchive.Bytes.ToArray());
        }
예제 #5
0
        public override void ReadReplayChunks(FArchive archive)
        {
            while (!archive.AtEnd())
            {
                var chunkType = archive.ReadUInt32AsEnum <ReplayChunkType>();
                _writer.Write((uint)chunkType);

                var chunkSize = archive.ReadInt32();
                var offset    = archive.Position;

                //Console.WriteLine($"Chunk {chunkType}. Size: {chunkSize}. Offset: {offset}");

                if (chunkType == ReplayChunkType.Checkpoint)
                {
                    ReadCheckpoint(archive);
                }
                else if (chunkType == ReplayChunkType.Event)
                {
                    ReadEvent(archive);
                }
                else if (chunkType == ReplayChunkType.ReplayData)
                {
                    ReadReplayData(archive);
                }
                else if (chunkType == ReplayChunkType.Header)
                {
                    //Copy over bytes
                    _writer.Write(chunkSize);
                    _writer.Write(archive.ReadBytes(chunkSize));

                    _writer.Flush();
                }

                if (archive.Position != offset + chunkSize)
                {
                    //_logger?.LogWarning($"Chunk ({chunkType}) at offset {offset} not correctly read...");
                    archive.Seek(offset + chunkSize, SeekOrigin.Begin);
                }
            }
        }