/// <summary> Parses the Replay.Messages.Events file. </summary>
        /// <param name="buffer"> Buffer containing the contents of the replay.messages.events file. </param>
        /// <returns> A list of chat messages parsed from the buffer. </returns>
        public static void Parse(Replay replay, byte[] buffer)
        {
            using (var stream = new MemoryStream(buffer))
            {
                using (var reader = new BinaryReader(stream))
                {
                    int totalTime = 0;
                    while (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        // While not EOF
                        var message = new ChatMessage();

                        var time = ParseTimestamp(reader);

                        // sometimes we only have a header for the message
                        if (reader.BaseStream.Position >= reader.BaseStream.Length) 
                            break;

                        message.PlayerId = reader.ReadByte();

                        // I believe this 'PlayerId' is an index for this client list, which can include observers
                        // var player = replay.ClientList[message.PlayerId];

                        totalTime += time;
                        var opCode = reader.ReadByte();

                        if (opCode == 0x80)
                            reader.ReadBytes(4);
                        else if (opCode == 0x83)
                            reader.ReadBytes(8);
                        else if (opCode == 2 && message.PlayerId <= 10)
                        {
                            if (message.PlayerId == 80)
                                continue;

                            message.MessageTarget = (ChatMessageTarget)(opCode & 7);
                            var length = reader.ReadByte();

                            if ((opCode & 8) == 8)
                                length += 64;

                            if ((opCode & 16) == 16)
                                length += 128;

                            message.Message = Encoding.UTF8.GetString(reader.ReadBytes(length));
                        }
                        else
                        {
                            
                        }

                        if (message.Message != null)
                        {
                            message.Timestamp = new TimeSpan(0, 0, (int)Math.Round(totalTime / 16.0));
                            replay.ChatMessages.Add(message);
                        }
                    }
                }
            }
        }
        /// <summary> Parses the Replay.Messages.Events file. </summary>
        /// <param name="buffer"> Buffer containing the contents of the replay.messages.events file. </param>
        /// <returns> A list of chat messages parsed from the buffer. </returns>
        public static void Parse(Replay replay, byte[] buffer)
        {
            var messages = new List<ChatMessage>();
            using (var stream = new MemoryStream(buffer))
            {
                using (var reader = new BinaryReader(stream))
                {
                    int totalTime = 0;
                    while (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        // While not EOF
                        var message = new ChatMessage();

                        var time = ParseTimestamp(reader);
                        message.PlayerId = reader.ReadByte();

                        totalTime += time;
                        var opCode = reader.ReadByte();

                        if (opCode == 0x80)
                            reader.ReadBytes(4);
                        else if (opCode == 0x83)
                            reader.ReadBytes(8);
                        else if (opCode == 2 && message.PlayerId <= 10)
                        {
                            if (message.PlayerId == 80)
                                continue;

                            message.MessageTarget = (ChatMessageTarget)(opCode & 7);
                            var length = reader.ReadByte();

                            if ((opCode & 8) == 8)
                                length += 64;

                            if ((opCode & 16) == 16)
                                length += 128;

                            message.Message = Encoding.UTF8.GetString(reader.ReadBytes(length));
                        }
                        else
                        {
                            
                        }

                        if (message.Message != null)
                        {
                            message.Timestamp = new TimeSpan(0, 0, (int)Math.Round(totalTime / 16.0));
                            messages.Add(message);
                        }
                    }
                }
            }

            replay.ChatMessages = messages;
        }
예제 #3
0
        /// <summary> Parses the Replay.Messages.Events file. </summary>
        /// <param name="buffer"> Buffer containing the contents of the replay.messages.events file. </param>
        /// <returns> A list of messages parsed from the buffer. </returns>
        public static void Parse(Replay replay, byte[] buffer)
        {
            if (buffer.Length <= 1)
            {
                // Chat has been removed from this replay
                return;
            }

            var ticksElapsed = 0;

            using (var stream = new MemoryStream(buffer))
            {
                var bitReader = new Streams.BitReader(stream);

                while (!bitReader.EndOfStream)
                {
                    var message = new Message();

                    ticksElapsed     += (int)bitReader.Read(6 + (bitReader.Read(2) << 3));
                    message.Timestamp = new TimeSpan(0, 0, (int)Math.Round(ticksElapsed / 16.0));

                    var playerIndex = (int)bitReader.Read(5);
                    if (playerIndex != 16)
                    {
                        message.MessageSender = replay.ClientListByUserID[playerIndex];
                        message.PlayerIndex   = playerIndex;
                    }

                    message.MessageEventType = (MessageEventType)bitReader.Read(4);
                    switch (message.MessageEventType)
                    {
                    case MessageEventType.SChatMessage:
                    {
                        ChatMessage chatMessage = new ChatMessage();

                        chatMessage.MessageTarget = (MessageTarget)bitReader.Read(3);                                  // m_recipient (the target)
                        chatMessage.Message       = Encoding.UTF8.GetString(bitReader.ReadBlobPrecededWithLength(11)); // m_string

                        message.ChatMessage = chatMessage;
                        replay.Messages.Add(message);
                        break;
                    }

                    case MessageEventType.SPingMessage:
                    {
                        PingMessage pingMessage = new PingMessage();

                        pingMessage.MessageTarget = (MessageTarget)bitReader.Read(3);         // m_recipient (the target)

                        pingMessage.XCoordinate = bitReader.ReadInt32() - (-2147483648);      // m_point x
                        pingMessage.YCoordinate = bitReader.ReadInt32() - (-2147483648);      // m_point y

                        message.PingMessage = pingMessage;
                        replay.Messages.Add(message);
                        break;
                    }

                    case MessageEventType.SLoadingProgressMessage:
                    {
                        // can be used to keep track of how fast/slow players are loading
                        // also includes players who are reloading the game
                        var progress = bitReader.ReadInt32() - (-2147483648);         // m_progress
                        break;
                    }

                    case MessageEventType.SServerPingMessage:
                    {
                        break;
                    }

                    case MessageEventType.SReconnectNotifyMessage:
                    {
                        bitReader.Read(2);         // m_status; is either a 1 or a 2
                        break;
                    }

                    case MessageEventType.SPlayerAnnounceMessage:
                    {
                        PlayerAnnounceMessage announceMessage = new PlayerAnnounceMessage();

                        announceMessage.AnnouncementType = (AnnouncementType)bitReader.Read(2);

                        switch (announceMessage.AnnouncementType)
                        {
                        case AnnouncementType.None:
                        {
                            break;
                        }

                        case AnnouncementType.Ability:
                        {
                            AbilityAnnouncment ability = new AbilityAnnouncment();
                            ability.AbilityLink  = bitReader.ReadInt16();               // m_abilLink
                            ability.AbilityIndex = (int)bitReader.Read(5);              // m_abilCmdIndex
                            ability.ButtonLink   = bitReader.ReadInt16();               // m_buttonLink

                            announceMessage.AbilityAnnouncement = ability;
                            break;
                        }

                        case AnnouncementType.Behavior:            // no idea what triggers this
                        {
                            bitReader.ReadInt16();                 // m_behaviorLink
                            bitReader.ReadInt16();                 // m_buttonLink
                            break;
                        }

                        case AnnouncementType.Vitals:
                        {
                            VitalAnnouncment vital = new VitalAnnouncment();
                            vital.VitalType = (VitalType)(bitReader.ReadInt16() - (-32768));

                            announceMessage.VitalAnnouncement = vital;
                            break;
                        }

                        default:
                            throw new NotImplementedException();
                        }

                        if (replay.ReplayBuild > 45635)
                        {
                            // m_announceLink
                            bitReader.ReadInt16();
                        }

                        bitReader.ReadInt32();         // m_otherUnitTag
                        bitReader.ReadInt32();         // m_unitTag

                        message.PlayerAnnounceMessage = announceMessage;
                        replay.Messages.Add(message);
                        break;
                    }

                    default:
                        throw new NotImplementedException();
                    }

                    bitReader.AlignToByte();
                }
            }
        }