Esempio n. 1
0
        public virtual async ValueTask <bool> ParseReplayHeader(CustomBinaryReaderAsync binaryReader)
        {
            if (!await ParseMagicNumber(binaryReader))
            {
                return(false);
            }
            ReplayHeader.ReplayVersionHistory fileVersion = (ReplayHeader.ReplayVersionHistory) await binaryReader.ReadUInt32Async();

            int lengthInMs = await binaryReader.ReadInt32Async();

            uint networkVersion = await binaryReader.ReadUInt32Async();

            uint changelist = await binaryReader.ReadUInt32Async();

            string friendlyName = await binaryReader.ReadStringAsync();

            bool isLive = await binaryReader.ReadUInt32Async() != 0;

            DateTime timestamp = DateTime.MinValue;

            if (fileVersion >= ReplayHeader.ReplayVersionHistory.recordedTimestamp)
            {
                timestamp = DateTime.FromBinary(await binaryReader.ReadInt64Async());
            }
            bool compressed = false;

            if (fileVersion >= ReplayHeader.ReplayVersionHistory.compression)
            {
                compressed = await binaryReader.ReadUInt32Async() != 0;
            }
            ReplayHeader = new ReplayHeader(lengthInMs, networkVersion, changelist, friendlyName, timestamp, 0,
                                            isLive, compressed, fileVersion);
            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Simply return true and does nothing else. It depends on the implementation of the game.
        /// </summary>
        /// <param name="chunk"></param>
        /// <returns></returns>
        public virtual async ValueTask <bool> ParseGameSpecificHeaderChunk(CustomBinaryReaderAsync binaryReader)
        {
            if (await binaryReader.ReadUInt32Async() != DemoHeaderMagic)
            {
                return(false);
            }
            NetworkVersionHistory version = (NetworkVersionHistory)await binaryReader.ReadUInt32Async();

            if (version < NetworkVersionHistory.saveFullEngineVersion)
            {
                return(false);
            }
            uint networkChecksum = await binaryReader.ReadUInt32Async();

            EngineNetworkVersionHistory engineNetworkProtocolVersion = (EngineNetworkVersionHistory)await binaryReader.ReadUInt32Async();

            uint gameNetworkProtocolVersion = await binaryReader.ReadUInt32Async();

            Guid guid = Guid.Empty;

            if (version >= NetworkVersionHistory.guidDemoHeader)
            {
                guid = new Guid((await binaryReader.ReadBytesAsync(16)).Span);
            }
            ushort major = await binaryReader.ReadUInt16Async();

            ushort minor = await binaryReader.ReadUInt16Async();

            ushort patch = await binaryReader.ReadUInt16Async();

            uint changeList = await binaryReader.ReadUInt32Async();

            string branch = await binaryReader.ReadStringAsync();

            (string, uint)[] levelNamesAndTimes = await binaryReader.ReadArrayAsync(async() => (await binaryReader.ReadStringAsync(), await binaryReader.ReadUInt32Async()));
Esempio n. 3
0
 /// <summary>
 /// Only does routing to the right method
 /// No operation should be done here.
 /// </summary>
 /// <param name="replayInfo"></param>
 /// <param name="chunk"></param>
 /// <returns></returns>
 public virtual async ValueTask <bool> ChooseChunkType(CustomBinaryReaderAsync binaryReader, ChunkType chunkType)
 {
     return((chunkType switch
     {
         ChunkType.Header => throw new InvalidOperationException("Replay Header was already read."),
         ChunkType.Checkpoint => await ParseCheckpointHeader(binaryReader),
         ChunkType.Event => await ParseEventHeader(binaryReader),
         ChunkType.ReplayData => await ParseReplayDataChunkHeader(binaryReader),
         _ => throw new InvalidOperationException("Invalid ChunkType")
     }) ? true : await ErrorOnChunkContentParsingAsync());
Esempio n. 4
0
        public virtual async ValueTask <bool> ParseEventHeader(CustomBinaryReaderAsync binaryReader)
        {
            string id = await binaryReader.ReadStringAsync();

            string group = await binaryReader.ReadStringAsync();

            string metadata = await binaryReader.ReadStringAsync();

            uint time1 = await binaryReader.ReadUInt32Async();

            uint time2 = await binaryReader.ReadUInt32Async();

            int eventSizeInBytes = await binaryReader.ReadInt32Async();

            return(await ChooseEventChunkType(binaryReader, new EventOrCheckpointInfo( id, group, metadata, time1, time2 )));
        }
Esempio n. 5
0
        public virtual async ValueTask <bool> ParseCheckpointHeader(CustomBinaryReaderAsync binaryReader)
        {
            string id = await binaryReader.ReadStringAsync();

            string group = await binaryReader.ReadStringAsync();

            string metadata = await binaryReader.ReadStringAsync();

            uint time1 = await binaryReader.ReadUInt32Async();

            uint time2 = await binaryReader.ReadUInt32Async();

            int eventSizeInBytes = await binaryReader.ReadInt32Async();

            using (IMemoryOwner <byte> uncompressed = await binaryReader.UncompressData())
            {
                return(ParseCheckpointContent(new MemoryReader(uncompressed.Memory, Endianness.Native), id, group, metadata, time1, time2));
            }
        }
Esempio n. 6
0
        public virtual async ValueTask <bool> ParseReplayDataChunkHeader(CustomBinaryReaderAsync chunkReader)
        {
            uint time1 = uint.MaxValue;
            uint time2 = uint.MaxValue;

            if (ReplayHeader !.FileVersion >= ReplayVersionHistory.streamChunkTimes)
            {
                time1 = await chunkReader.ReadUInt32Async();

                time2 = await chunkReader.ReadUInt32Async();

                int replaySizeInBytes = await chunkReader.ReadInt32Async();
            }
            using (IMemoryOwner <byte> uncompressedData = await chunkReader.UncompressData())//TODO: check compress
            {
                //return ParseReplayData( new MemoryReader( uncompressedData.Memory, Endianness.Native ));
            }
            return(true);
        }
Esempio n. 7
0
        public virtual async ValueTask <bool> ParseReplayInfo()
        {
            using (CustomBinaryReaderAsync binaryReader = new CustomBinaryReaderAsync(SubStreamFactory.BaseStream, true))
            {
                if (!await ParseReplayHeader(binaryReader))
                {
                    return(false);
                }
                ChunkHeader chunkHeader = await ParseChunkHeader();

                if (chunkHeader.ChunkType != ChunkType.Header)
                {
                    return(false);
                }
                await using (SubStream stream = SubStreamFactory.CreateSubstream(chunkHeader.ChunkSize))
                    using (CustomBinaryReaderAsync chunkReader = new CustomBinaryReaderAsync(stream, true))
                    {
                        return(await ParseGameSpecificHeaderChunk(chunkReader));
                    }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Parse the header of a chunk, with that we know the <see cref="ChunkType"/> and the length of the chunk
        /// Took extra caution because there is no <see cref="SubStream"/> to protect the reading.
        /// When I discover the length of the replay, I immediatly create a SubStream so i can protect the rest of the replay.
        /// </summary>
        /// <param name="replayInfo"></param>
        /// <returns></returns>
        public virtual async ValueTask <ChunkHeader> ParseChunkHeader()
        {
            if (SubStreamFactory.CanReadLength && SubStreamFactory.CanReadPosition &&
                SubStreamFactory.BaseStream.Position == SubStreamFactory.BaseStream.Length)
            {
                return(new ChunkHeader {
                    ChunkType = ChunkType.EndOfStream, ChunkSize = 0
                });
            }

            int       chunkSize;
            ChunkType chunkType;

            await using (SubStream chunkHeader = SubStreamFactory.CreateSubstream(8))
                await using (CustomBinaryReaderAsync customReader = new CustomBinaryReaderAsync(chunkHeader, true))
                {
                    try //TODO add case when you can seek.
                    {
                        chunkType = (ChunkType)await customReader.ReadUInt32Async();
                    }
                    catch (EndOfStreamException)
                    {
                        chunkHeader.CancelSelfRepositioning();
                        return(new ChunkHeader {
                            ChunkType = ChunkType.EndOfStream, ChunkSize = 0
                        });
                    }
                    chunkSize = await customReader.ReadInt32Async();

                    if ((uint)chunkType > 3)
                    {
                        return(new ChunkHeader {
                            ChunkType = ChunkType.Unknown, ChunkSize = 0
                        });
                    }
                }
            return(new ChunkHeader {
                ChunkType = chunkType, ChunkSize = chunkSize
            });
        }
Esempio n. 9
0
        public virtual async ValueTask <bool> VisitChunks()
        {
            while (true)
            {
                ChunkHeader chunkHeader = await ParseChunkHeader();

                await using (SubStream stream = SubStreamFactory.CreateSubstream(chunkHeader.ChunkSize))
                    using (CustomBinaryReaderAsync binaryReader = new CustomBinaryReaderAsync(stream, true))
                    {
                        if (chunkHeader.ChunkType == ChunkType.EndOfStream)
                        {
                            if (await VisitEndOfStream())
                            {
                                continue;
                            }
                            return(true);
                        }
                        if (!await ChooseChunkType(binaryReader, chunkHeader.ChunkType))
                        {
                            return(false);
                        }
                    }
            }
        }
Esempio n. 10
0
 /// <summary>
 /// We do nothing there
 /// </summary>
 /// <param name="eventInfo"></param>
 /// <returns>always <see langword="true"/></returns>
 public virtual ValueTask <bool> ChooseEventChunkType(CustomBinaryReaderAsync binaryReader, EventOrCheckpointInfo eventInfo)
 {
     return(new ValueTask <bool>(true));
 }
Esempio n. 11
0
 public override ValueTask <bool> ChooseEventChunkType(CustomBinaryReaderAsync chunkReader, EventOrCheckpointInfo eventInfo) => eventInfo.Group.Trim('\0') switch
 {
     "playerElim" => VisitPlayerElimChunk(chunkReader, eventInfo),
Esempio n. 12
0
 /// <summary>
 /// I don't know maybe you want to change that ? Why i did this ? I don't know me too.
 /// </summary>
 /// <param name="binaryReader"></param>
 /// <returns></returns>
 public virtual async ValueTask <bool> ParseMagicNumber(CustomBinaryReaderAsync binaryReader)
 {
     return(await VisitMagicNumber(await binaryReader.ReadUInt32Async()));
 }