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 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"]; } } } }
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); }