示例#1
0
        public void AddMessageHandlers(HalfLifeDemoParser parser)
        {
            this.parser = parser;

            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_event, MessageEvent);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_sound, MessageSound);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_serverinfo, MessageServerInfo);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_updateuserinfo, MessageUpdateUserInfo);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_deltadescription, MessageDeltaDescription);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_clientdata, MessageClientData);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_pings, MessagePings);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_spawnbaseline, MessageSpawnBaseline);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_newusermsg, MessageNewUserMsg);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_packetentities, MessagePacketEntities);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_deltapacketentities, MessageDeltaPacketEntities);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_resourcelist, MessageResourceList);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_hltv, MessageHltv);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_director, MessageDirector);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_voiceinit, MessageVoiceInit);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_timescale, MessageTimeScale);
            parser.AddUserMessageHandler("ClCorpse", MessageClCorpse);
            parser.AddUserMessageHandler("ScreenFade", MessageScreenFade);
            parser.AddUserMessageHandler("SendAudio", MessageSendAudio);
            parser.AddUserMessageHandler("TextMsg", MessageTextMsg);

            Procedure <String> removeMessage = (s) =>
            {
                Int32 startOffset   = parser.BitBuffer.CurrentByte;
                Int32 messageLength = parser.FindUserMessageLength(s);
                Int32 endOffset     = parser.BitBuffer.CurrentByte + messageLength;
                parser.Seek(startOffset - 1, SeekOrigin.Begin);
                parser.BitBuffer.RemoveBytes(endOffset - startOffset + 1);
            };

            parser.AddUserMessageHandler("CDChallenge", () =>
            {
                removeMessage("CDChallenge");
            });

            parser.AddUserMessageHandler("CDSalt", () =>
            {
                removeMessage("CDSalt");
            });
        }
示例#2
0
        private void ReadMessageServerInfo()
        {
            parser.Seek(4); // network protocol
            parser.Seek(4); // process count
            mungedMapChecksum = parser.BitBuffer.ReadUInt32();

            // read client.dll checksum
            Byte[] checksum = parser.BitBuffer.ReadBytes(16);

            // convert client.dll checksum to string
            StringBuilder sb = new StringBuilder();

            for (Int32 i = 0; i < checksum.Length; i++)
            {
                sb.Append(checksum[i].ToString("X2"));
            }

            clientDllChecksum = sb.ToString();

            // determine engine and game versions
            CalculateGameAndGameVersion();
            CalculateEngineVersionAndType();

            maxClients   = parser.BitBuffer.ReadByte();
            recorderSlot = parser.BitBuffer.ReadByte();

            // skip unknown byte, game folder
            parser.Seek(1);
            parser.BitBuffer.ReadString();

            // see base handler
            if (networkProtocol > 43)
            {
                serverName = parser.BitBuffer.ReadString();
            }
            else
            {
                serverName = "Unknown";
            }

            // skip map
            parser.BitBuffer.ReadString();

            if (NetworkProtocol == 45)
            {
                Byte extraInfo = parser.BitBuffer.ReadByte();
                parser.Seek(-1);

                if (extraInfo != (Byte)HalfLifeDemoParser.MessageId.svc_sendextrainfo)
                {
                    parser.BitBuffer.ReadString(); // skip mapcycle

                    if (parser.BitBuffer.ReadByte() > 0)
                    {
                        parser.Seek(36);
                    }
                }
            }
            else
            {
                parser.BitBuffer.ReadString(); // skip mapcycle

                if (NetworkProtocol > 43)
                {
                    if (parser.BitBuffer.ReadByte() > 0)
                    {
                        parser.Seek(21);
                    }
                }
            }

            // "no loading segment" bug
            serverInfoParsed = true;
        }
示例#3
0
        /// <summary>
        /// Writes the demo to the destination folder while performing modifications such as removing the scoreboard or fade to black, possibly converting messages to the current network protocol, as well as re-writing directory entries.
        /// </summary>
        /// <param name="_destinationPath">The destination folder.</param>
        protected override void WritingThread(object _destinationFileName)
        {
            firstFrameToWriteIndex = 0;

            try
            {
                /*
                 * Converted demos: pre-process the loading segment and get the frame index of the last
                 * svc_serverinfo message in the loading segment.
                 *
                 * This fixes several bugs:
                 *      1. long (for Half-Life) loading times, since the resources of several maps may be
                 *      loaded.
                 *
                 *      2. wrong map in resource list
                 *
                 *      3. random SendAudio CTD (indirectly)
                 */
                if (ConvertNetworkProtocol() && !IsBetaSteam())
                {
                    currentFrameIndex = 0;

                    // initialise parser
                    parser = new HalfLifeDemoParser(this);
                    parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_serverinfo, PreWriteMessageServerInfo);
                    parser.Open();

                    try
                    {
                        parser.Seek(HeaderSizeInBytes);

                        while (true)
                        {
                            HalfLifeDemoParser.FrameHeader frameHeader = parser.ReadFrameHeader();

                            if (frameHeader.Type == 1)
                            {
                                break;
                            }

                            if (frameHeader.Type == 0)
                            {
                                HalfLifeDemoParser.GameDataFrameHeader gameDataFrameHeader = parser.ReadGameDataFrameHeader();
                                Byte[] frameData = parser.Reader.ReadBytes((Int32)gameDataFrameHeader.Length);
                                parser.ParseGameDataMessages(frameData);
                            }
                            else if (frameHeader.Type != 5)
                            {
                                parser.SkipFrame(frameHeader.Type);
                            }

                            currentFrameIndex++;
                        }
                    }
                    finally
                    {
                        parser.Close();
                    }
                }

                // demo writer
                HalfLifeDemoConverter demoConverter = new HalfLifeDemoConverter(this);
                HalfLifeDemoWriter    demoWriter    = new HalfLifeDemoWriter(this, (IHalfLifeDemoWriter)demoConverter, writeProgressWindowInterface, firstFrameToWriteIndex);

                demoWriter.ThreadWorker((String)_destinationFileName);
            }
            catch (ThreadAbortException)
            {
                throw;
            }
            catch (HalfLifeDemoWriter.AbortWritingException)
            {
                writeProgressWindowInterface.CloseWithResult(false);
                return;
            }
            catch (Exception ex)
            {
                writeProgressWindowInterface.Error("Error writing demo file \"" + fileFullPath + "\".", ex, false, null);
                writeProgressWindowInterface.CloseWithResult(false);
                return;
            }

            writeProgressWindowInterface.CloseWithResult(true);
        }
示例#4
0
        private void ReadingThreadWorker()
        {
            FileStream   fs = null;
            BinaryReader br = null;

            // read header
            try
            {
                fs = File.OpenRead(FileFullPath);
                br = new BinaryReader(fs);

                fileLengthInBytes = fs.Length;

                if (fileLengthInBytes < HeaderSizeInBytes)
                {
                    throw new ApplicationException("File length is too short to parse the header.");
                }

                ReadHeader(br);
            }
            finally
            {
                if (br != null)
                {
                    br.Close();
                }

                if (fs != null)
                {
                    fs.Close();
                }
            }

            // create parser
            parser = new HalfLifeDemoParser(this);

            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_setview, ReadMessageSetView);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_print, ReadMessagePrint);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_serverinfo, ReadMessageServerInfo);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_updateuserinfo, ReadMessageUpdateUserInfo);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_hltv, ReadMessageHltv);

            parser.Open();
            parser.Seek(HeaderSizeInBytes); // seek past header

            try
            {
                // read and parse frames until the end of the loading segment
                while (true)
                {
                    HalfLifeDemoParser.FrameHeader frameHeader = parser.ReadFrameHeader();

                    // "no loading segment" bug
                    if (frameHeader.Type == 1)
                    {
                        if (serverInfoParsed)
                        {
                            break;
                        }
                    }

                    if (frameHeader.Type == 0 || frameHeader.Type == 1)
                    {
                        HalfLifeDemoParser.GameDataFrameHeader gameDataFrameHeader = parser.ReadGameDataFrameHeader();

                        if (gameDataFrameHeader.Length > 0)
                        {
                            Byte[] frameData = parser.Reader.ReadBytes((Int32)gameDataFrameHeader.Length);

                            try
                            {
                                parser.ParseGameDataMessages(frameData);
                            }
                            catch (ThreadAbortException)
                            {
                                throw;
                            }
                            catch (Exception ex)
                            {
                                throw new ApplicationException("Error parsing gamedata frame.\n\n" + parser.ComputeMessageLog(), ex);
                            }
                        }
                    }
                    else
                    {
                        parser.SkipFrame(frameHeader.Type);
                    }
                }
            }
            finally
            {
                parser.Close();
            }

            // get demo recorder's name
            if (perspective == Perspectives.Pov)
            {
                foreach (Player p in playerList)
                {
                    if (p.Slot == recorderSlot)
                    {
                        recorderName = p.InfoKeys["name"];
                    }
                }
            }
        }
示例#5
0
        public void Parse()
        {
            parser = new HalfLifeDemoParser(demo);

            // add svc message handlers
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_print, MessagePrint);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_stufftext, MessageStuffText);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_serverinfo, MessageServerInfo);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_updateuserinfo, MessageUpdateUserInfo);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_pings, MessagePings);
            parser.AddMessageHandler((Byte)HalfLifeDemoParser.MessageId.svc_event_reliable, MessageEventReliable);

            // add user message handlers
            parser.AddUserMessageHandler("SayText", MessageSayText);
            parser.AddUserMessageHandler("TextMsg", MessageTextMsg);
            parser.AddUserMessageHandler("ResetHUD", MessageResetHUD);
            parser.AddUserMessageHandler("DeathMsg", MessageDeathMsg);
            parser.AddUserMessageHandler("ScoreInfo", MessageScoreInfo);
            parser.AddUserMessageHandler("TeamInfo", MessageTeamInfo);
            parser.AddUserMessageHandler("TeamScore", MessageTeamScore);

            parser.Open();
            parser.Seek(HalfLifeDemo.HeaderSizeInBytes); // seek past header

            Int32   percentRead          = 0;
            Boolean foundPlaybackSegment = false;

            try
            {
                while (true)
                {
                    HalfLifeDemoParser.FrameHeader frameHeader = parser.ReadFrameHeader();

                    if (frameHeader.Type == 0 || frameHeader.Type == 1)
                    {
                        if (!foundPlaybackSegment && frameHeader.Type == 1)
                        {
                            foundPlaybackSegment = true;
                        }

                        HalfLifeDemoParser.GameDataFrameHeader gameDataFrameHeader = parser.ReadGameDataFrameHeader();
                        currentTimestamp = frameHeader.Timestamp;

                        // length can be 0
                        // e.g. GotFrag Demo 15111 (volcano vs 4k).zip
                        if (gameDataFrameHeader.Length > 0)
                        {
                            Byte[] frameData = parser.Reader.ReadBytes((Int32)gameDataFrameHeader.Length);

                            if (frameData.Length != gameDataFrameHeader.Length)
                            {
                                throw new ApplicationException("Gamedata frame length doesn't match header.");
                            }

                            try
                            {
                                parser.ParseGameDataMessages(frameData);
                            }
                            catch (ThreadAbortException)
                            {
                                throw;
                            }
                            catch (Exception ex)
                            {
                                throw new ApplicationException("Message parsing error.\n\n" + parser.ComputeMessageLog(), ex);
                            }
                        }
                    }
                    else if (frameHeader.Type == 5) // end of segment
                    {
                        if (foundPlaybackSegment)
                        {
                            progressWindowInterface.UpdateProgress(100);
                            break;
                        }
                    }
                    else
                    {
                        parser.SkipFrame(frameHeader.Type);
                    }

                    // calculate what percent of the file has been read
                    Int32 oldPercentRead = percentRead;

                    percentRead = (Int32)(parser.Position / (Single)parser.FileLength * 100.0f);

                    if (percentRead != oldPercentRead)
                    {
                        progressWindowInterface.UpdateProgress(percentRead);
                    }
                }
            }
            finally
            {
                parser.Close();
            }
        }
        private Byte[] ReadFrameData(HalfLifeDemoParser.FrameHeader frameHeader, out Boolean writeFrame)
        {
            Byte[] result = null;
            writeFrame = true;

            if (frameHeader.Type == 0 || frameHeader.Type == 1)
            {
                // frame header
                Byte[] frameHeaderDemoInfo     = parser.Reader.ReadBytes(parser.GameDataDemoInfoLength);
                Byte[] frameHeaderSequenceInfo = parser.Reader.ReadBytes(parser.GameDataSequenceInfoLength);
                UInt32 gameDataLength          = parser.Reader.ReadUInt32();

                // frame data
                Byte[] frameData = null;

                if (gameDataLength != 0)
                {
                    // read frame data
                    frameData = parser.Reader.ReadBytes((Int32)gameDataLength);

                    if (frameData.Length != gameDataLength)
                    {
                        throw new ApplicationException("Gamedata frame length doesn't match header.");
                    }

                    // Give the writer interface a chance to insert any new messages into the first gamedata frame.
                    if (frameHeader.Type == 1 && !foundPlaybackOffset)
                    {
                        demoWriterInterface.ProcessFirstGameDataFrame(ref frameData);
                    }

                    // parse frame messages
                    try
                    {
                        if (demoWriterInterface.ShouldParseGameDataMessages(frameHeader.Type))
                        {
                            parser.ParseGameDataMessages(frameData, demoWriterInterface.GetNewUserMessageId);

                            // set frame data to version modified by parsing
                            frameData = parser.BitBuffer.Data;
                        }
                    }
                    catch (ThreadAbortException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        Error("Error parsing gamedata frame.\n\n" + parser.ComputeMessageLog(), ex, true);

                        if (lastErrorResult != MessageWindow.Result.Continue)
                        {
                            throw new AbortWritingException();
                        }
                        else
                        {
                            writeFrame = false;
                            return(null);
                        }
                    }
                }

                // check for end of loading segment
                if (frameHeader.Type == 1)
                {
                    if (!foundPlaybackOffset)
                    {
                        // last 5 frame (end of segment) will have stored the correct offset
                        foundPlaybackOffset = true;
                    }

                    // count playback segment gamedata frames
                    nPlaybackFrames++;
                }

                // copy contents of frame into memorystream, return result
                MemoryStream ms = new MemoryStream();
                demoWriterInterface.WriteDemoInfo(frameHeaderDemoInfo, ms);
                ms.Write(frameHeaderSequenceInfo, 0, frameHeaderSequenceInfo.Length);

                if (gameDataLength == 0)
                {
                    ms.Write(BitConverter.GetBytes(gameDataLength), 0, 4);
                }
                else
                {
                    ms.Write(BitConverter.GetBytes(frameData.Length), 0, 4);
                    ms.Write(frameData, 0, frameData.Length);
                }

                return(ms.ToArray());
            }
            else if (frameHeader.Type == 3) // client command
            {
                String command = Common.ReadNullTerminatedString(parser.Reader, 64);

                if (!demoWriterInterface.ShouldWriteClientCommand(command))
                {
                    // don't write frame
                    writeFrame = false;
                    return(null);
                }

                parser.Seek(-64);
                result = parser.Reader.ReadBytes(64);

                if (result.Length != 64)
                {
                    throw new ApplicationException("Unexpected client command frame data length.");
                }
            }
            else if (Config.Settings.PlaybackRemoveWeaponAnimations && frameHeader.Type == 7)
            {
                parser.Seek(8);
                writeFrame = false;
                return(null);
            }
            else if (frameHeader.Type != 5)
            {
                Int32 frameLength = parser.GetFrameLength(frameHeader.Type);

                if (frameLength != 0)
                {
                    result = parser.Reader.ReadBytes(frameLength);

                    if (result.Length != frameLength)
                    {
                        throw new ApplicationException("Unexpected frame data length.");
                    }
                }
            }

            return(result);
        }
示例#7
0
        private void ReWriteMessage(Int32 messageStartOffset, Byte[] data)
        {
            // remove old message
            Int32 messageEndOffset = parser.BitBuffer.CurrentByte;

            parser.Seek(messageStartOffset, SeekOrigin.Begin);
            parser.BitBuffer.RemoveBytes(messageEndOffset - messageStartOffset);

            // insert new message
            parser.BitBuffer.InsertBytes(data);
        }