From 171e350e348afadb55967b9c13d5eadc7f7d2cf4 Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Thu, 21 Sep 2023 01:53:59 +0300 Subject: add strings builder, customize ALL outputs (#6) --- pkg/classes/cmdInfo.go | 12 +- pkg/classes/sarData.go | 110 ++++++++++++------ pkg/classes/sendTable.go | 174 ++++++++++++++++++++++------- pkg/classes/serverClassInfo.go | 5 +- pkg/classes/stringTable.go | 15 ++- pkg/classes/userCmdInfo.go | 15 +++ pkg/messages/messages.go | 5 +- pkg/messages/types/netDisconnect.go | 9 +- pkg/messages/types/netFile.go | 7 +- pkg/messages/types/netNop.go | 6 +- pkg/messages/types/netSetConVar.go | 7 +- pkg/messages/types/netSignOnState.go | 6 + pkg/messages/types/netSplitScreenUser.go | 13 ++- pkg/messages/types/netStringCmd.go | 11 +- pkg/messages/types/netTick.go | 11 +- pkg/messages/types/svcBspDecal.go | 6 + pkg/messages/types/svcClassInfo.go | 6 + pkg/messages/types/svcCmdKeyValues.go | 6 +- pkg/messages/types/svcCreateStringTable.go | 8 ++ pkg/messages/types/svcCrosshairAngle.go | 11 +- pkg/messages/types/svcEntityMessage.go | 8 +- pkg/messages/types/svcFixAngle.go | 12 +- pkg/messages/types/svcGameEvent.go | 6 +- pkg/messages/types/svcGameEventList.go | 6 +- pkg/messages/types/svcGetCvarValue.go | 7 +- pkg/messages/types/svcMenu.go | 7 +- pkg/messages/types/svcPacketEntities.go | 8 ++ pkg/messages/types/svcPaintmapData.go | 6 +- pkg/messages/types/svcPrefetch.go | 9 +- pkg/messages/types/svcPrint.go | 12 +- pkg/messages/types/svcSendTable.go | 8 +- pkg/messages/types/svcServerInfo.go | 24 +++- pkg/messages/types/svcSetPause.go | 9 +- pkg/messages/types/svcSetView.go | 9 +- pkg/messages/types/svcSounds.go | 8 +- pkg/messages/types/svcSplitScreen.go | 7 +- pkg/messages/types/svcTempEntities.go | 7 +- pkg/messages/types/svcUpdateStringTable.go | 7 +- pkg/messages/types/svcUserMessage.go | 7 +- pkg/messages/types/svcVoiceData.go | 8 +- pkg/messages/types/svcVoiceInit.go | 8 +- pkg/packets/headers.go | 5 +- pkg/packets/packets.go | 43 ++++--- pkg/packets/types.go | 6 +- pkg/writer/writer.go | 47 ++++++++ 45 files changed, 585 insertions(+), 142 deletions(-) create mode 100644 pkg/writer/writer.go (limited to 'pkg') diff --git a/pkg/classes/cmdInfo.go b/pkg/classes/cmdInfo.go index 545d14b..eccfe99 100644 --- a/pkg/classes/cmdInfo.go +++ b/pkg/classes/cmdInfo.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type CmdInfo struct { @@ -41,7 +42,7 @@ func (cmdInfoFlags CmdInfoFlags) String() string { } func ParseCmdInfo(reader *bitreader.Reader) CmdInfo { - return CmdInfo{ + cmdInfo := CmdInfo{ Flags: CmdInfoFlags(reader.TryReadUInt32()).String(), ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, ViewAngles: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, @@ -50,4 +51,13 @@ func ParseCmdInfo(reader *bitreader.Reader) CmdInfo { ViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, LocalViewAngles2: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, } + writer.AppendLine("\tFlags: %s", cmdInfo.Flags) + writer.AppendLine("\tView Origin: %v", cmdInfo.ViewOrigin) + writer.AppendLine("\tView Angles: %v", cmdInfo.ViewAngles) + writer.AppendLine("\tLocal View Angles: %v", cmdInfo.LocalViewAngles) + writer.AppendLine("\tView Origin 2: %v", cmdInfo.ViewOrigin2) + writer.AppendLine("\tView Angles 2: %v", cmdInfo.ViewAngles2) + writer.AppendLine("\tLocal View Angles 2: %v", cmdInfo.LocalViewAngles2) + writer.AppendLine("") + return cmdInfo } diff --git a/pkg/classes/sarData.go b/pkg/classes/sarData.go index 35163c3..27e8a64 100644 --- a/pkg/classes/sarData.go +++ b/pkg/classes/sarData.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type SarDataType uint8 @@ -137,12 +138,12 @@ type SarDataSpeedrunTimeSplits struct { } type SarDataTimestamp struct { - Year uint16 - Mon uint8 - Day uint8 - Hour uint8 - Min uint8 - Sec uint8 + Year uint16 + Month uint8 + Day uint8 + Hour uint8 + Minute uint8 + Second uint8 } type SarDataFileChecksum struct { @@ -163,6 +164,7 @@ func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) { len = 9 } dataReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(len-1), true) + writer.AppendLine("\tMessage: %s (%d):", sarData.Type.String(), sarData.Type) switch sarData.Type { case ESarDataTimescaleCheat: sarData.Data, err = parseTimescaleCheatData(dataReader, len) @@ -173,6 +175,7 @@ func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) { sarData.Data = parseInitialCVarData(dataReader) case ESarDataEntityInputSlot: sarData.Slot = int(dataReader.TryReadBytes(1)) + writer.AppendLine("\t\tSlot: %d", sarData.Slot) case ESarDataEntityInput: sarData.Data = parseEntityInputData(dataReader) case ESarDataChecksum: @@ -198,6 +201,7 @@ func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) { if err != nil { sarData.Data = nil } + writer.AppendLine("\t\tSlot: %d", sarData.Slot) case ESarDataPause: sarData.Data, err = parsePauseData(dataReader, len) if err != nil { @@ -239,45 +243,60 @@ func parseTimescaleCheatData(reader *bitreader.Reader, length uint64) (SarDataTi if length != 5 { return SarDataTimescaleCheat{}, errors.New("sar data invalid") } - return SarDataTimescaleCheat{ + sarDataTimescaleCheat := SarDataTimescaleCheat{ Timescale: reader.TryReadFloat32(), - }, nil + } + writer.AppendLine("\t\tTimescale: %f", sarDataTimescaleCheat.Timescale) + return sarDataTimescaleCheat, nil } func parseInitialCVarData(reader *bitreader.Reader) SarDataInitialCVar { - return SarDataInitialCVar{ + sarDataInitialCvar := SarDataInitialCVar{ CVar: reader.TryReadString(), Val: reader.TryReadString(), } + writer.AppendLine("\t\tCvar: \"%s\" = \"%s\"", sarDataInitialCvar.CVar, sarDataInitialCvar.Val) + return sarDataInitialCvar } func parseEntityInputData(reader *bitreader.Reader) SarDataEntityInput { - return SarDataEntityInput{ + sarDataEntityInput := SarDataEntityInput{ TargetName: reader.TryReadString(), ClassName: reader.TryReadString(), InputName: reader.TryReadString(), Parameter: reader.TryReadString(), } + writer.AppendLine("\t\tTarget: %s", sarDataEntityInput.TargetName) + writer.AppendLine("\t\tClass: %s", sarDataEntityInput.ClassName) + writer.AppendLine("\t\tInput: %s", sarDataEntityInput.InputName) + writer.AppendLine("\t\tParameter: %s", sarDataEntityInput.Parameter) + return sarDataEntityInput } func parseChecksumData(reader *bitreader.Reader, length uint64) (SarDataChecksum, error) { if length != 9 { return SarDataChecksum{}, errors.New("sar data invalid") } - return SarDataChecksum{ + sarDataChecksum := SarDataChecksum{ DemoSum: reader.TryReadUInt32(), SarSum: reader.TryReadUInt32(), - }, nil + } + writer.AppendLine("\t\tDemo Checksum: %d", sarDataChecksum.DemoSum) + writer.AppendLine("\t\tSAR Checksum: %d", sarDataChecksum.SarSum) + return sarDataChecksum, nil } func parseChecksumV2Data(reader *bitreader.Reader, length uint64) (SarDataChecksumV2, error) { if length != 69 { return SarDataChecksumV2{}, errors.New("sar data invalid") } - return SarDataChecksumV2{ + sarDataChecksumV2 := SarDataChecksumV2{ SarSum: reader.TryReadUInt32(), Signature: [64]byte(reader.TryReadBytesToSlice(60)), - }, nil + } + writer.AppendLine("\t\tSAR Checksum: %d", sarDataChecksumV2.SarSum) + writer.AppendLine("\t\tSignature: %v", sarDataChecksumV2.Signature) + return sarDataChecksumV2, nil } func parsePortalPlacementData(reader *bitreader.Reader, length uint64) (SarDataPortalPlacement, int, error) { @@ -287,12 +306,17 @@ func parsePortalPlacementData(reader *bitreader.Reader, length uint64) (SarDataP slot := int(reader.TryReadBytes(1)) orange := reader.TryReadBool() reader.SkipBits(7) - return SarDataPortalPlacement{ + sarDataPortalPlacement := SarDataPortalPlacement{ Orange: orange, X: reader.TryReadFloat32(), Y: reader.TryReadFloat32(), Z: reader.TryReadFloat32(), - }, slot, nil + } + writer.AppendLine("\t\tOrange: %t", orange) + writer.AppendLine("\t\tX: %f", sarDataPortalPlacement.X) + writer.AppendLine("\t\tY: %f", sarDataPortalPlacement.Y) + writer.AppendLine("\t\tZ: %f", sarDataPortalPlacement.Z) + return sarDataPortalPlacement, slot, nil } func parseChallengeFlagsCrouchFlyData(reader *bitreader.Reader, length uint64) (int, error) { @@ -306,29 +330,37 @@ func parsePauseData(reader *bitreader.Reader, length uint64) (SarDataPause, erro if length != 5 { return SarDataPause{}, errors.New("sar data invalid") } - return SarDataPause{ + sarDataPause := SarDataPause{ PauseTicks: reader.TryReadUInt32(), - }, nil + } + writer.AppendLine("\t\tPause Ticks: %d", sarDataPause.PauseTicks) + return sarDataPause, nil } func parseWaitRunData(reader *bitreader.Reader, length uint64) (SarDataWaitRun, error) { if length < 6 { return SarDataWaitRun{}, errors.New("sar data invalid") } - return SarDataWaitRun{ + sarDataWaitRun := SarDataWaitRun{ Ticks: int(reader.TryReadUInt32()), Cmd: reader.TryReadString(), - }, nil + } + writer.AppendLine("\t\tTicks: %d", sarDataWaitRun.Ticks) + writer.AppendLine("\t\tCmd: \"%s\"", sarDataWaitRun.Cmd) + return sarDataWaitRun, nil } func parseHWaitRunData(reader *bitreader.Reader, length uint64) (SarDataHWaitRun, error) { if length < 6 { return SarDataHWaitRun{}, errors.New("sar data invalid") } - return SarDataHWaitRun{ + sarDataHWaitRun := SarDataHWaitRun{ Ticks: int(reader.TryReadUInt32()), Cmd: reader.TryReadString(), - }, nil + } + writer.AppendLine("\t\tTicks: %d", sarDataHWaitRun.Ticks) + writer.AppendLine("\t\tCmd: \"%s\"", sarDataHWaitRun.Cmd) + return sarDataHWaitRun, nil } func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64) (SarDataSpeedrunTime, error) { @@ -340,10 +372,14 @@ func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64) (SarDataSpee for splitCount := 0; splitCount < int(numberOfSplits); splitCount++ { splits[splitCount].Name = reader.TryReadString() splits[splitCount].NSegs = reader.TryReadUInt32() + writer.AppendLine("\t\t[%d] Split Name: \"%s\"", splitCount, splits[splitCount].Name) + writer.AppendLine("\t\t[%d] Number of Segments: %d", splitCount, splits[splitCount].NSegs) splits[splitCount].Segs = make([]SarDataSpeedrunTimeSegs, splits[splitCount].NSegs) for segCount := 0; segCount < int(splits[splitCount].NSegs); segCount++ { splits[splitCount].Segs[segCount].Name = reader.TryReadString() splits[splitCount].Segs[segCount].Ticks = reader.TryReadUInt32() + writer.AppendLine("\t\t\t[%d] Segment Name: \"%s\"", segCount, splits[splitCount].Segs[segCount].Name) + writer.AppendLine("\t\t\t[%d] Segment Ticks: %d", segCount, splits[splitCount].Segs[segCount].Ticks) } } return SarDataSpeedrunTime{ @@ -357,22 +393,32 @@ func parseTimestampData(reader *bitreader.Reader, length uint64) (SarDataTimesta return SarDataTimestamp{}, errors.New("sar data invalid") } timestamp := reader.TryReadBytesToSlice(7) - return SarDataTimestamp{ - Year: uint16(timestamp[0]) | uint16(timestamp[1])<<8, - Mon: timestamp[2] + 1, - Day: timestamp[3], - Hour: timestamp[4], - Min: timestamp[5], - Sec: timestamp[6], - }, nil + sarDataTimeStamp := SarDataTimestamp{ + Year: uint16(timestamp[0]) | uint16(timestamp[1])<<8, + Month: timestamp[2] + 1, + Day: timestamp[3], + Hour: timestamp[4], + Minute: timestamp[5], + Second: timestamp[6], + } + writer.AppendLine("\t\tYear: %d", sarDataTimeStamp.Year) + writer.AppendLine("\t\tMonth: %d", sarDataTimeStamp.Month) + writer.AppendLine("\t\tDay: %d", sarDataTimeStamp.Day) + writer.AppendLine("\t\tHour: %d", sarDataTimeStamp.Hour) + writer.AppendLine("\t\tMinute: %d", sarDataTimeStamp.Minute) + writer.AppendLine("\t\tSecond: %d", sarDataTimeStamp.Second) + return sarDataTimeStamp, nil } func parseFileChecksumData(reader *bitreader.Reader, length uint64) (SarDataFileChecksum, error) { if length < 6 { return SarDataFileChecksum{}, errors.New("sar data invalid") } - return SarDataFileChecksum{ + sarDataFileChecksum := SarDataFileChecksum{ Sum: reader.TryReadUInt32(), Path: reader.TryReadString(), - }, nil + } + writer.AppendLine("\t\tChecksum: %d", sarDataFileChecksum.Sum) + writer.AppendLine("\t\tPath: \"%s\"", sarDataFileChecksum.Path) + return sarDataFileChecksum, nil } diff --git a/pkg/classes/sendTable.go b/pkg/classes/sendTable.go index bc36d75..927d967 100644 --- a/pkg/classes/sendTable.go +++ b/pkg/classes/sendTable.go @@ -1,7 +1,10 @@ package classes import ( + "fmt" + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type SendTable struct { @@ -12,10 +15,10 @@ type SendTable struct { } type prop struct { - SendPropType int8 + SendPropType sendPropType SendPropName string - SendPropFlags int32 - Priority int8 + SendPropFlags uint32 + Priority uint8 ExcludeDtName string LowValue float32 HighValue float32 @@ -23,84 +26,169 @@ type prop struct { NumElements int32 } -type sendPropFlag int +type sendPropType int const ( - Unsigned sendPropFlag = iota - Coord - NoScale - RoundDown - RoundUp - Normal - Exclude - Xyze - InsideArray - ProxyAlwaysYes - IsVectorElem - Collapsible - CoordMp - CoordMpLp // low precision - CoordMpInt - CellCoord - CellCoordLp - CellCoordInt - ChangesOften + ESendPropTypeInt sendPropType = iota + ESendPropTypeFloat + ESendPropTypeVector3 + ESendPropTypeVector2 + ESendPropTypeString + ESendPropTypeArray + ESendPropTypeDataTable ) -type sendPropType int - const ( - Int sendPropType = iota - Float - Vector3 - Vector2 - String - Array - DataTable + ESendPropFlagUnsigned string = "Unsigned" + ESendPropFlagCoord string = "Coord" + ESendPropFlagNoScale string = "NoScale" + ESendPropFlagRoundDown string = "RoundDown" + ESendPropFlagRoundUp string = "RoundUp" + ESendPropFlagNormal string = "Normal" + ESendPropFlagExclude string = "Exclude" + ESendPropFlagXyze string = "Xyze" + ESendPropFlagInsideArray string = "InsideArray" + ESendPropFlagProxyAlwaysYes string = "ProxyAlwaysYes" + ESendPropFlagIsVectorElem string = "IsVectorElem" + ESendPropFlagCollapsible string = "Collapsible" + ESendPropFlagCoordMp string = "CoordMp" + ESendPropFlagCoordMpLp string = "CoordMpLp" + ESendPropFlagCoordMpInt string = "CoordMpInt" + ESendPropFlagCellCoord string = "CellCoord" + ESendPropFlagCellCoordLp string = "CellCoordLp" + ESendPropFlagCellCoordInt string = "CellCoordInt" + ESendPropFlagChangesOften string = "ChangesOften" ) +func (prop prop) GetFlags() []string { + flags := []string{} + if checkBit(prop.SendPropFlags, 0) { + flags = append(flags, ESendPropFlagUnsigned) + } + if checkBit(prop.SendPropFlags, 1) { + flags = append(flags, ESendPropFlagCoord) + } + if checkBit(prop.SendPropFlags, 2) { + flags = append(flags, ESendPropFlagNoScale) + } + if checkBit(prop.SendPropFlags, 3) { + flags = append(flags, ESendPropFlagRoundDown) + } + if checkBit(prop.SendPropFlags, 4) { + flags = append(flags, ESendPropFlagRoundUp) + } + if checkBit(prop.SendPropFlags, 5) { + flags = append(flags, ESendPropFlagNormal) + } + if checkBit(prop.SendPropFlags, 6) { + flags = append(flags, ESendPropFlagExclude) + } + if checkBit(prop.SendPropFlags, 7) { + flags = append(flags, ESendPropFlagXyze) + } + if checkBit(prop.SendPropFlags, 8) { + flags = append(flags, ESendPropFlagInsideArray) + } + if checkBit(prop.SendPropFlags, 9) { + flags = append(flags, ESendPropFlagProxyAlwaysYes) + } + if checkBit(prop.SendPropFlags, 10) { + flags = append(flags, ESendPropFlagIsVectorElem) + } + if checkBit(prop.SendPropFlags, 11) { + flags = append(flags, ESendPropFlagCollapsible) + } + if checkBit(prop.SendPropFlags, 12) { + flags = append(flags, ESendPropFlagCoordMp) + } + if checkBit(prop.SendPropFlags, 13) { + flags = append(flags, ESendPropFlagCoordMpLp) + } + if checkBit(prop.SendPropFlags, 14) { + flags = append(flags, ESendPropFlagCoordMpInt) + } + if checkBit(prop.SendPropFlags, 15) { + flags = append(flags, ESendPropFlagCellCoord) + } + if checkBit(prop.SendPropFlags, 16) { + flags = append(flags, ESendPropFlagCellCoordLp) + } + if checkBit(prop.SendPropFlags, 17) { + flags = append(flags, ESendPropFlagCellCoordInt) + } + if checkBit(prop.SendPropFlags, 18) { + flags = append(flags, ESendPropFlagChangesOften) + } + return flags +} + +func (sendPropType sendPropType) String() string { + switch sendPropType { + case ESendPropTypeInt: + return "Int" + case ESendPropTypeFloat: + return "Float" + case ESendPropTypeVector3: + return "Vector3" + case ESendPropTypeVector2: + return "Vector2" + case ESendPropTypeString: + return "String" + case ESendPropTypeArray: + return "Array" + case ESendPropTypeDataTable: + return "DataTable" + default: + return fmt.Sprintf("%d", int(sendPropType)) + } +} + func ParseSendTable(reader *bitreader.Reader) SendTable { sendTable := SendTable{ NeedsDecoder: reader.TryReadBool(), NetTableName: reader.TryReadString(), NumOfProps: int16(reader.TryReadBits(10)), - // SendPropType: int8(reader.TryReadBits(5)), - // SendPropName: reader.TryReadString(), - // SendPropFlags: int16(reader.TryReadBits(16)), } if sendTable.NumOfProps < 0 { return sendTable } + writer.TempAppendLine("\t\t%s (%d Props):", sendTable.NetTableName, sendTable.NumOfProps) for count := 0; count < int(sendTable.NumOfProps); count++ { propType := int8(reader.TryReadBits(5)) if propType >= int8(7) { return sendTable } prop := prop{ - SendPropType: propType, + SendPropType: sendPropType(propType), SendPropName: reader.TryReadString(), - SendPropFlags: int32(reader.TryReadBits(19)), - Priority: int8(reader.TryReadBits(8)), + SendPropFlags: uint32(reader.TryReadBits(19)), + Priority: reader.TryReadUInt8(), } - if propType == int8(DataTable) || CheckBit(int64(prop.SendPropFlags), int(Exclude)) { + writer.TempAppend("\t\t\t%s\t", prop.SendPropType) + if propType == int8(ESendPropTypeDataTable) || checkBit(prop.SendPropFlags, 6) { prop.ExcludeDtName = reader.TryReadString() + writer.TempAppend(":\t%s\t", prop.ExcludeDtName) } else { switch propType { - case int8(String), int8(Int), int8(Float), int8(Vector3), int8(Vector2): + case int8(ESendPropTypeString), int8(ESendPropTypeInt), int8(ESendPropTypeFloat), int8(ESendPropTypeVector3), int8(ESendPropTypeVector2): prop.LowValue = reader.TryReadFloat32() prop.HighValue = reader.TryReadFloat32() prop.NumBits = int32(reader.TryReadBits(7)) - case int8(Array): + writer.TempAppend("Low: %f\tHigh: %f\t%d bits\t", prop.LowValue, prop.HighValue, prop.NumBits) + case int8(ESendPropTypeArray): prop.NumElements = int32(reader.TryReadBits(10)) + writer.TempAppend("Elements: %d\t", prop.NumElements) default: + writer.TempAppend("Unknown Prop Type: %v\t", propType) return sendTable } } + writer.TempAppend("Flags: %v\tPriority: %d\n", prop.GetFlags(), prop.Priority) sendTable.Props = append(sendTable.Props, prop) } return sendTable } -func CheckBit(val int64, bit int) bool { - return (val & (int64(1) << bit)) != 0 +func checkBit(val uint32, bit int) bool { + return (val & (uint32(1) << bit)) != 0 } diff --git a/pkg/classes/serverClassInfo.go b/pkg/classes/serverClassInfo.go index 36bd8b8..c0d2a2a 100644 --- a/pkg/classes/serverClassInfo.go +++ b/pkg/classes/serverClassInfo.go @@ -2,6 +2,7 @@ package classes import ( "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type ServerClassInfo struct { @@ -11,11 +12,13 @@ type ServerClassInfo struct { } func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo { - return ServerClassInfo{ + serverClassInfo := ServerClassInfo{ ClassId: reader.TryReadUInt16(), ClassName: reader.TryReadString(), DataTableName: reader.TryReadString(), } + writer.TempAppendLine("\t\t\t[%d] %s (%s)", serverClassInfo.ClassId, serverClassInfo.ClassName, serverClassInfo.DataTableName) + return serverClassInfo } // func serverClassBits(numOfClasses int) int { diff --git a/pkg/classes/stringTable.go b/pkg/classes/stringTable.go index 3983c1f..44d8a73 100644 --- a/pkg/classes/stringTable.go +++ b/pkg/classes/stringTable.go @@ -2,6 +2,7 @@ package classes import ( "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type StringTable struct { @@ -38,6 +39,7 @@ func ParseStringTables(reader *bitreader.Reader) []StringTable { func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) { stringTable.Name = reader.TryReadString() entryCount := reader.TryReadBits(16) + writer.AppendLine("\tTable Name: %s", stringTable.Name) stringTable.TableEntries = make([]StringTableEntry, entryCount) for i := 0; i < int(entryCount); i++ { @@ -45,7 +47,12 @@ func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) { entry.Parse(reader) stringTable.TableEntries[i] = entry } - + if entryCount != 0 { + writer.AppendLine("\t\t%d Table Entries:", entryCount) + writer.AppendOutputFromTemp() + } else { + writer.AppendLine("\t\tNo Table Entries") + } if reader.TryReadBool() { classCount := reader.TryReadBits(16) stringTable.Classes = make([]StringTableClass, classCount) @@ -55,6 +62,10 @@ func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) { class.Parse(reader) stringTable.Classes[i] = class } + writer.AppendLine("\t\t%d Classes:", classCount) + writer.AppendOutputFromTemp() + } else { + writer.AppendLine("\t\tNo Class Entries") } } @@ -73,8 +84,10 @@ func (stringTableEntry *StringTableEntry) Parse(reader *bitreader.Reader) { func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader) { stringTableClass.Name = reader.TryReadString() + writer.TempAppendLine("\t\t\tName: %s", stringTableClass.Name) if reader.TryReadBool() { dataLen := reader.TryReadBits(16) stringTableClass.Data = reader.TryReadStringLength(dataLen) + writer.TempAppendLine("\t\t\tData: %s", stringTableClass.Data) } } diff --git a/pkg/classes/userCmdInfo.go b/pkg/classes/userCmdInfo.go index 04d76b6..f1bb613 100644 --- a/pkg/classes/userCmdInfo.go +++ b/pkg/classes/userCmdInfo.go @@ -4,6 +4,7 @@ import ( "bytes" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type UserCmdInfo struct { @@ -68,5 +69,19 @@ func ParseUserCmdInfo(data []byte) UserCmdInfo { if reader.TryReadBool() { userCmdInfo.MouseDy = int16(reader.TryReadBits(16)) } + writer.AppendLine("\tCommand Number: %v", userCmdInfo.CommandNumber) + writer.AppendLine("\tTick Count: %v", userCmdInfo.TickCount) + writer.AppendLine("\tView Angles X: %v", userCmdInfo.ViewAnglesX) + writer.AppendLine("\tView Angles Y: %v", userCmdInfo.ViewAnglesY) + writer.AppendLine("\tView Angles Z: %v", userCmdInfo.ViewAnglesZ) + writer.AppendLine("\tForward Move: %v", userCmdInfo.ForwardMove) + writer.AppendLine("\tSide Move: %v", userCmdInfo.SideMove) + writer.AppendLine("\tUp Move: %v", userCmdInfo.UpMove) + writer.AppendLine("\tButtons: %v", userCmdInfo.Buttons) + writer.AppendLine("\tImpulse: %v", userCmdInfo.Impulse) + writer.AppendLine("\tWeapon Select: %v", userCmdInfo.WeaponSelect) + writer.AppendLine("\tWeapon Sub Type: %v", userCmdInfo.WeaponSubType) + writer.AppendLine("\tMouse Dx: %v", userCmdInfo.MouseDx) + writer.AppendLine("\tMouse Dy: %v", userCmdInfo.MouseDy) return userCmdInfo } diff --git a/pkg/messages/messages.go b/pkg/messages/messages.go index 9e7dfae..efa9460 100644 --- a/pkg/messages/messages.go +++ b/pkg/messages/messages.go @@ -1,11 +1,11 @@ package messages import ( - "fmt" "reflect" "github.com/pektezol/bitreader" messages "github.com/pektezol/demoparser/pkg/messages/types" + "github.com/pektezol/demoparser/pkg/writer" ) func ParseMessages(messageType int, reader *bitreader.Reader) any { @@ -82,6 +82,7 @@ func ParseMessages(messageType int, reader *bitreader.Reader) any { default: return nil } - fmt.Printf("\t\t(%d) %s:\n\t\t\t%+v\n", messageType, reflect.ValueOf(messageData).Type(), messageData) + writer.AppendLine("\tMessage: %s (%d):", reflect.ValueOf(messageData).Type(), messageType) + writer.AppendOutputFromTemp() return messageData } diff --git a/pkg/messages/types/netDisconnect.go b/pkg/messages/types/netDisconnect.go index 3ecf8e1..c2e22c1 100644 --- a/pkg/messages/types/netDisconnect.go +++ b/pkg/messages/types/netDisconnect.go @@ -1,13 +1,18 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type NetDisconnect struct { Text string } func ParseNetDisconnect(reader *bitreader.Reader) NetDisconnect { - return NetDisconnect{ + netDisconnect := NetDisconnect{ Text: reader.TryReadString(), } + writer.TempAppendLine("\t\tText: %s", netDisconnect.Text) + return netDisconnect } diff --git a/pkg/messages/types/netFile.go b/pkg/messages/types/netFile.go index c9c587d..4ebd770 100644 --- a/pkg/messages/types/netFile.go +++ b/pkg/messages/types/netFile.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type NetFile struct { @@ -34,9 +35,13 @@ func (netFileFlags NetFileFlags) String() string { } func ParseNetFile(reader *bitreader.Reader) NetFile { - return NetFile{ + netFile := NetFile{ TransferId: reader.TryReadUInt32(), FileName: reader.TryReadString(), FileFlags: NetFileFlags(reader.TryReadBits(2)).String(), } + writer.TempAppendLine("\t\tTransfer ID: %d", netFile.TransferId) + writer.TempAppendLine("\t\tFile Name: %s", netFile.FileName) + writer.TempAppendLine("\t\tFile Flags: %s", netFile.FileFlags) + return netFile } diff --git a/pkg/messages/types/netNop.go b/pkg/messages/types/netNop.go index f942786..0ee1d0d 100644 --- a/pkg/messages/types/netNop.go +++ b/pkg/messages/types/netNop.go @@ -1,9 +1,13 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type NetNop struct{} func ParseNetNop(reader *bitreader.Reader) NetNop { + writer.TempAppendLine("\t\t{}") return NetNop{} } diff --git a/pkg/messages/types/netSetConVar.go b/pkg/messages/types/netSetConVar.go index 44b75b9..530cb6b 100644 --- a/pkg/messages/types/netSetConVar.go +++ b/pkg/messages/types/netSetConVar.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type NetSetConVar struct { Length uint8 @@ -15,11 +18,13 @@ type conVar struct { func ParseNetSetConVar(reader *bitreader.Reader) NetSetConVar { length := reader.TryReadUInt8() convars := []conVar{} + writer.TempAppendLine("\t\tLength: %d", length) for count := 0; count < int(length); count++ { convar := conVar{ Name: reader.TryReadString(), Value: reader.TryReadString(), } + writer.TempAppendLine("\t\t[%d] %s: %s", count, convar.Name, convar.Value) convars = append(convars, convar) } return NetSetConVar{ diff --git a/pkg/messages/types/netSignOnState.go b/pkg/messages/types/netSignOnState.go index 78d03aa..f784b0a 100644 --- a/pkg/messages/types/netSignOnState.go +++ b/pkg/messages/types/netSignOnState.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type NetSignOnState struct { @@ -59,12 +60,17 @@ func ParseNetSignOnState(reader *bitreader.Reader) NetSignOnState { NumServerPlayers: reader.TryReadUInt32(), IdsLength: reader.TryReadUInt32(), } + writer.TempAppendLine("\t\tSign On State: %s", netSignOnState.SignOnState) + writer.TempAppendLine("\t\tSpawn Count: %d", netSignOnState.SpawnCount) + writer.TempAppendLine("\t\tNumber Of Server Players: %d", netSignOnState.NumServerPlayers) if netSignOnState.IdsLength > 0 { netSignOnState.PlayersNetworksIds = reader.TryReadBytesToSlice(uint64(netSignOnState.IdsLength)) + writer.TempAppendLine("\t\tPlayer Network IDs: %v", netSignOnState.PlayersNetworksIds) } netSignOnState.MapNameLength = reader.TryReadUInt32() if netSignOnState.MapNameLength > 0 { netSignOnState.MapName = reader.TryReadStringLength(uint64(netSignOnState.MapNameLength)) + writer.TempAppendLine("\t\tMap Name: %s", netSignOnState.MapName) } return netSignOnState } diff --git a/pkg/messages/types/netSplitScreenUser.go b/pkg/messages/types/netSplitScreenUser.go index 9e4caa8..6068a28 100644 --- a/pkg/messages/types/netSplitScreenUser.go +++ b/pkg/messages/types/netSplitScreenUser.go @@ -1,13 +1,18 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type NetSplitScreenUser struct { - Unknown bool + Slot bool } func ParseNetSplitScreenUser(reader *bitreader.Reader) NetSplitScreenUser { - return NetSplitScreenUser{ - Unknown: reader.TryReadBool(), + netSplitScreenUser := NetSplitScreenUser{ + Slot: reader.TryReadBool(), } + writer.TempAppendLine("\t\tSlot: %t", netSplitScreenUser.Slot) + return netSplitScreenUser } diff --git a/pkg/messages/types/netStringCmd.go b/pkg/messages/types/netStringCmd.go index da5a75b..57ae813 100644 --- a/pkg/messages/types/netStringCmd.go +++ b/pkg/messages/types/netStringCmd.go @@ -1,13 +1,20 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "strings" + + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type NetStringCmd struct { Command string } func ParseNetStringCmd(reader *bitreader.Reader) NetStringCmd { - return NetStringCmd{ + netStringCmd := NetStringCmd{ Command: reader.TryReadString(), } + writer.TempAppendLine("\t\tCommand: \"%s\"", strings.TrimSpace(netStringCmd.Command)) + return netStringCmd } diff --git a/pkg/messages/types/netTick.go b/pkg/messages/types/netTick.go index dc941ad..1c01171 100644 --- a/pkg/messages/types/netTick.go +++ b/pkg/messages/types/netTick.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type NetTick struct { Tick uint32 @@ -9,9 +12,13 @@ type NetTick struct { } func ParseNetTick(reader *bitreader.Reader) NetTick { - return NetTick{ + netTick := NetTick{ Tick: reader.TryReadUInt32(), HostFrameTime: float32(reader.TryReadUInt16()) / 1e5, HostFrameTimeStdDeviation: float32(reader.TryReadUInt16()) / 1e5, } + writer.TempAppendLine("\t\tTick: %d", netTick.Tick) + writer.TempAppendLine("\t\tHost Frame Time: %f", netTick.HostFrameTime) + writer.TempAppendLine("\t\tHost Frame Time Std Deviation: %f", netTick.HostFrameTimeStdDeviation) + return netTick } diff --git a/pkg/messages/types/svcBspDecal.go b/pkg/messages/types/svcBspDecal.go index 220f63a..cf94c1d 100644 --- a/pkg/messages/types/svcBspDecal.go +++ b/pkg/messages/types/svcBspDecal.go @@ -2,6 +2,7 @@ package messages import ( "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type SvcBspDecal struct { @@ -27,6 +28,11 @@ func ParseSvcBspDecal(reader *bitreader.Reader) SvcBspDecal { svcBspDecal.ModelIndex = uint16(reader.TryReadBits(11)) } svcBspDecal.LowPriority = reader.TryReadBool() + writer.TempAppendLine("\t\tPosition: %v", svcBspDecal.Pos) + writer.TempAppendLine("\t\tDecal Texture Index: %d", svcBspDecal.DecalTextureIndex) + writer.TempAppendLine("\t\tEntity Index: %d", svcBspDecal.EntityIndex) + writer.TempAppendLine("\t\tModel Index: %d", svcBspDecal.ModelIndex) + writer.TempAppendLine("\t\tLow Priority: %t", svcBspDecal.LowPriority) return svcBspDecal } diff --git a/pkg/messages/types/svcClassInfo.go b/pkg/messages/types/svcClassInfo.go index d2f6a90..384c501 100644 --- a/pkg/messages/types/svcClassInfo.go +++ b/pkg/messages/types/svcClassInfo.go @@ -4,6 +4,7 @@ import ( "math" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type SvcClassInfo struct { @@ -24,14 +25,19 @@ func ParseSvcClassInfo(reader *bitreader.Reader) SvcClassInfo { CreateOnClient: reader.TryReadBool(), } classes := []serverClass{} + writer.TempAppendLine("\t\tCreate On Client: %t", svcClassInfo.CreateOnClient) if !svcClassInfo.CreateOnClient { + writer.TempAppendLine("\t\t%d Server Classes:", svcClassInfo.ClassCount) for count := 0; count < int(svcClassInfo.ClassCount); count++ { classes = append(classes, serverClass{ ClassId: int16(reader.TryReadBits(uint64(math.Log2(float64(svcClassInfo.ClassCount)) + 1))), ClassName: reader.TryReadString(), DataTableName: reader.TryReadString(), }) + writer.TempAppendLine("\t\t\t[%d] %s (%s)", classes[len(classes)-1].ClassId, classes[len(classes)-1].ClassName, classes[len(classes)-1].DataTableName) } + } else { + writer.TempAppendLine("\t\t%d Server Classes", svcClassInfo.ClassCount) } svcClassInfo.ServerClasses = classes return svcClassInfo diff --git a/pkg/messages/types/svcCmdKeyValues.go b/pkg/messages/types/svcCmdKeyValues.go index 8fdd076..5c80d0b 100644 --- a/pkg/messages/types/svcCmdKeyValues.go +++ b/pkg/messages/types/svcCmdKeyValues.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcCmdKeyValues struct { Length uint32 @@ -12,5 +15,6 @@ func ParseSvcCmdKeyValues(reader *bitreader.Reader) SvcCmdKeyValues { Length: reader.TryReadUInt32(), } svcCmdKeyValues.Data = reader.TryReadBytesToSlice(uint64(svcCmdKeyValues.Length)) + writer.TempAppendLine("\t\tData: %v", svcCmdKeyValues.Data) return svcCmdKeyValues } diff --git a/pkg/messages/types/svcCreateStringTable.go b/pkg/messages/types/svcCreateStringTable.go index aea40b0..ff2e27d 100644 --- a/pkg/messages/types/svcCreateStringTable.go +++ b/pkg/messages/types/svcCreateStringTable.go @@ -4,6 +4,7 @@ import ( "math" "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type SvcCreateStringTable struct { @@ -31,6 +32,13 @@ func ParseSvcCreateStringTable(reader *bitreader.Reader) SvcCreateStringTable { svcCreateStringTable.UserDataSizeBits = int8(reader.TryReadBits(4)) } svcCreateStringTable.Flags = int8(reader.TryReadBits(2)) + writer.TempAppendLine("\t\tName: %s", svcCreateStringTable.Name) + writer.TempAppendLine("\t\tMax Enties: %d", svcCreateStringTable.MaxEntries) + writer.TempAppendLine("\t\tNumber Of Entiries: %d", svcCreateStringTable.NumEntries) + writer.TempAppendLine("\t\tUser Data Fixed Size: %t", svcCreateStringTable.UserDataFixedSize) + writer.TempAppendLine("\t\tUser Data Size: %d", svcCreateStringTable.UserDataSize) + writer.TempAppendLine("\t\tUser Data Size In Bits: %d", svcCreateStringTable.UserDataSizeBits) + writer.TempAppendLine("\t\tFlags: %d", svcCreateStringTable.Flags) reader.SkipBits(uint64(svcCreateStringTable.Length)) // TODO: StringTable parsing return svcCreateStringTable } diff --git a/pkg/messages/types/svcCrosshairAngle.go b/pkg/messages/types/svcCrosshairAngle.go index b7d234c..efd6d77 100644 --- a/pkg/messages/types/svcCrosshairAngle.go +++ b/pkg/messages/types/svcCrosshairAngle.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcCrosshairAngle struct { Angle crosshairAngles @@ -13,11 +16,15 @@ type crosshairAngles struct { } func ParseSvcCrosshairAngle(reader *bitreader.Reader) SvcCrosshairAngle { - return SvcCrosshairAngle{ + svcCrosshairAngle := SvcCrosshairAngle{ Angle: crosshairAngles{ X: float32(reader.TryReadBits(16)), Y: float32(reader.TryReadBits(16)), Z: float32(reader.TryReadBits(16)), }, } + writer.TempAppendLine("\t\tX: %f", svcCrosshairAngle.Angle.X) + writer.TempAppendLine("\t\tY: %f", svcCrosshairAngle.Angle.Y) + writer.TempAppendLine("\t\tZ: %f", svcCrosshairAngle.Angle.Z) + return svcCrosshairAngle } diff --git a/pkg/messages/types/svcEntityMessage.go b/pkg/messages/types/svcEntityMessage.go index 58f42ba..a511fea 100644 --- a/pkg/messages/types/svcEntityMessage.go +++ b/pkg/messages/types/svcEntityMessage.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcEntityMessage struct { EntityIndex uint16 @@ -16,5 +19,8 @@ func ParseSvcEntityMessage(reader *bitreader.Reader) SvcEntityMessage { Length: uint16(reader.TryReadBits(11)), } svcEntityMessage.Data = reader.TryReadBitsToSlice(uint64(svcEntityMessage.Length)) + writer.TempAppendLine("\t\tEntity Index: %d", svcEntityMessage.EntityIndex) + writer.TempAppendLine("\t\tClass ID: %d", svcEntityMessage.ClassId) + writer.TempAppendLine("\t\tData: %v", svcEntityMessage.Data) return svcEntityMessage } diff --git a/pkg/messages/types/svcFixAngle.go b/pkg/messages/types/svcFixAngle.go index 95f67ec..b79c02d 100644 --- a/pkg/messages/types/svcFixAngle.go +++ b/pkg/messages/types/svcFixAngle.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcFixAngle struct { Relative bool @@ -14,7 +17,7 @@ type fixAngles struct { } func ParseSvcFixAngle(reader *bitreader.Reader) SvcFixAngle { - return SvcFixAngle{ + svcFixAngle := SvcFixAngle{ Relative: reader.TryReadBool(), Angle: fixAngles{ X: float32(reader.TryReadBits(16)), @@ -22,4 +25,9 @@ func ParseSvcFixAngle(reader *bitreader.Reader) SvcFixAngle { Z: float32(reader.TryReadBits(16)), }, } + writer.TempAppendLine("\t\tRelative: %t", svcFixAngle.Relative) + writer.TempAppendLine("\t\tX: %f", svcFixAngle.Angle.X) + writer.TempAppendLine("\t\tY: %f", svcFixAngle.Angle.Y) + writer.TempAppendLine("\t\tZ: %f", svcFixAngle.Angle.Z) + return svcFixAngle } diff --git a/pkg/messages/types/svcGameEvent.go b/pkg/messages/types/svcGameEvent.go index 9e4564a..e12d75a 100644 --- a/pkg/messages/types/svcGameEvent.go +++ b/pkg/messages/types/svcGameEvent.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcGameEvent struct { Length uint16 @@ -12,5 +15,6 @@ func ParseSvcGameEvent(reader *bitreader.Reader) SvcGameEvent { Length: uint16(reader.TryReadBits(11)), } svcGameEvent.Data = reader.TryReadBitsToSlice(uint64(svcGameEvent.Length)) + writer.TempAppendLine("\t\tData: %v", svcGameEvent.Data) return svcGameEvent } diff --git a/pkg/messages/types/svcGameEventList.go b/pkg/messages/types/svcGameEventList.go index c6eb896..1fa7589 100644 --- a/pkg/messages/types/svcGameEventList.go +++ b/pkg/messages/types/svcGameEventList.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcGameEventList struct { Events int16 @@ -17,5 +20,6 @@ func ParseSvcGameEventList(reader *bitreader.Reader) SvcGameEventList { Length: int32(reader.TryReadBits(20)), } reader.TryReadBitsToSlice(uint64(svcGameEventList.Length)) + writer.TempAppendLine("\t\tEvents: %d", svcGameEventList.Events) return svcGameEventList } diff --git a/pkg/messages/types/svcGetCvarValue.go b/pkg/messages/types/svcGetCvarValue.go index 19fc362..939e6b6 100644 --- a/pkg/messages/types/svcGetCvarValue.go +++ b/pkg/messages/types/svcGetCvarValue.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcGetCvarValue struct { Cookie int32 @@ -12,5 +15,7 @@ func ParseSvcGetCvarValue(reader *bitreader.Reader) SvcGetCvarValue { Cookie: reader.TryReadSInt32(), CvarName: reader.TryReadString(), } + writer.TempAppendLine("\t\tCookie: %d", svcGetCvarValue.Cookie) + writer.TempAppendLine("\t\tCvar: \"%s\"", svcGetCvarValue.CvarName) return svcGetCvarValue } diff --git a/pkg/messages/types/svcMenu.go b/pkg/messages/types/svcMenu.go index 9e8e2eb..33ccb70 100644 --- a/pkg/messages/types/svcMenu.go +++ b/pkg/messages/types/svcMenu.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcMenu struct { Type uint16 @@ -14,5 +17,7 @@ func ParseSvcMenu(reader *bitreader.Reader) SvcMenu { Length: reader.TryReadUInt32(), } svcMenu.Data = reader.TryReadBitsToSlice(uint64(svcMenu.Length)) + writer.TempAppendLine("\t\tType: %d", svcMenu.Type) + writer.TempAppendLine("\t\tData: %v", svcMenu.Data) return svcMenu } diff --git a/pkg/messages/types/svcPacketEntities.go b/pkg/messages/types/svcPacketEntities.go index 2d86bf2..05b6794 100644 --- a/pkg/messages/types/svcPacketEntities.go +++ b/pkg/messages/types/svcPacketEntities.go @@ -2,6 +2,7 @@ package messages import ( "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type SvcPacketEntities struct { @@ -30,5 +31,12 @@ func ParseSvcPacketEntities(reader *bitreader.Reader) SvcPacketEntities { svcPacketEntities.Length = uint32(reader.TryReadBits(20)) svcPacketEntities.UpdatedBaseline = reader.TryReadBool() svcPacketEntities.Data = reader.TryReadBitsToSlice(uint64(svcPacketEntities.Length)) + writer.TempAppendLine("\t\tMax Entries: %d", svcPacketEntities.MaxEntries) + writer.TempAppendLine("\t\tIs Delta: %t", svcPacketEntities.IsDelta) + writer.TempAppendLine("\t\tDelta From: %d", svcPacketEntities.DeltaFrom) + writer.TempAppendLine("\t\tBaseline: %t", svcPacketEntities.BaseLine) + writer.TempAppendLine("\t\tUpdated Baseline: %t", svcPacketEntities.UpdatedBaseline) + writer.TempAppendLine("\t\t%d Updated Entries:", svcPacketEntities.UpdatedEntries) + writer.TempAppendLine("\t\tData: %v", svcPacketEntities.Data) return svcPacketEntities } diff --git a/pkg/messages/types/svcPaintmapData.go b/pkg/messages/types/svcPaintmapData.go index 380016a..40f6ad0 100644 --- a/pkg/messages/types/svcPaintmapData.go +++ b/pkg/messages/types/svcPaintmapData.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcPaintmapData struct { Length uint32 @@ -12,5 +15,6 @@ func ParseSvcPaintmapData(reader *bitreader.Reader) SvcPaintmapData { Length: reader.TryReadUInt32(), } svcPaintmapData.Data = reader.TryReadBitsToSlice(uint64(svcPaintmapData.Length)) + writer.TempAppendLine("\t\tData: %v", svcPaintmapData.Data) return svcPaintmapData } diff --git a/pkg/messages/types/svcPrefetch.go b/pkg/messages/types/svcPrefetch.go index 50d01e9..b71e61f 100644 --- a/pkg/messages/types/svcPrefetch.go +++ b/pkg/messages/types/svcPrefetch.go @@ -1,13 +1,18 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcPrefetch struct { SoundIndex int16 } func ParseSvcPrefetch(reader *bitreader.Reader) SvcPrefetch { - return SvcPrefetch{ + svcPrefetch := SvcPrefetch{ SoundIndex: int16(reader.TryReadBits(13)), } + writer.TempAppendLine("\t\tSound Index: %d", svcPrefetch.SoundIndex) + return svcPrefetch } diff --git a/pkg/messages/types/svcPrint.go b/pkg/messages/types/svcPrint.go index f31d046..760a3c5 100644 --- a/pkg/messages/types/svcPrint.go +++ b/pkg/messages/types/svcPrint.go @@ -1,13 +1,21 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "strings" + + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcPrint struct { Message string } func ParseSvcPrint(reader *bitreader.Reader) SvcPrint { - return SvcPrint{ + svcPrint := SvcPrint{ Message: reader.TryReadString(), } + // common psycopath behaviour + writer.TempAppendLine("\t\t%s", strings.Replace(strings.ReplaceAll(strings.ReplaceAll(svcPrint.Message, "\n", "\n\t\t"), "\n\t\t\n\t\t", ""), "\n\t\t", "", 1)) + return svcPrint } diff --git a/pkg/messages/types/svcSendTable.go b/pkg/messages/types/svcSendTable.go index 2395e9f..78df195 100644 --- a/pkg/messages/types/svcSendTable.go +++ b/pkg/messages/types/svcSendTable.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcSendTable struct { NeedsDecoder bool @@ -14,5 +17,8 @@ func ParseSvcSendTable(reader *bitreader.Reader) SvcSendTable { Length: reader.TryReadUInt8(), } svcSendTable.Props = uint32(reader.TryReadBits(uint64(svcSendTable.Length))) + writer.TempAppendLine("\t\tNeeds Decoder: %t", svcSendTable.NeedsDecoder) + writer.TempAppendLine("\t\tLength: %d", svcSendTable.Length) + writer.TempAppendLine("\t\tProps: %d", svcSendTable.Props) return svcSendTable } diff --git a/pkg/messages/types/svcServerInfo.go b/pkg/messages/types/svcServerInfo.go index 7d44569..a6acd53 100644 --- a/pkg/messages/types/svcServerInfo.go +++ b/pkg/messages/types/svcServerInfo.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcServerInfo struct { Protocol uint16 @@ -22,7 +25,7 @@ type SvcServerInfo struct { } func ParseSvcServerInfo(reader *bitreader.Reader) SvcServerInfo { - return SvcServerInfo{ + svcServerInfo := SvcServerInfo{ Protocol: reader.TryReadUInt16(), ServerCount: reader.TryReadUInt32(), IsHltv: reader.TryReadBool(), @@ -40,4 +43,21 @@ func ParseSvcServerInfo(reader *bitreader.Reader) SvcServerInfo { SkyName: reader.TryReadString(), HostName: reader.TryReadString(), } + writer.TempAppendLine("\t\tNetwork Protocol: %d", svcServerInfo.Protocol) + writer.TempAppendLine("\t\tServer Count: %d", svcServerInfo.ServerCount) + writer.TempAppendLine("\t\tIs Hltv: %t", svcServerInfo.IsHltv) + writer.TempAppendLine("\t\tIs Dedicated: %t", svcServerInfo.IsDedicated) + writer.TempAppendLine("\t\tServer Client CRC: %d", svcServerInfo.ClientCrc) + writer.TempAppendLine("\t\tString Table CRC: %d", svcServerInfo.StringTableCrc) + writer.TempAppendLine("\t\tMax Server Classes: %d", svcServerInfo.MaxServerClasses) + writer.TempAppendLine("\t\tServer Map CRC: %d", svcServerInfo.MapCrc) + writer.TempAppendLine("\t\tCurrent Player Count: %d", svcServerInfo.PlayerCount) + writer.TempAppendLine("\t\tMax Player Count: %d", svcServerInfo.MaxClients) + writer.TempAppendLine("\t\tInterval Per Tick: %f", svcServerInfo.TickInterval) + writer.TempAppendLine("\t\tPlatform: %s", svcServerInfo.Platform) + writer.TempAppendLine("\t\tGame Directory: %s", svcServerInfo.GameDir) + writer.TempAppendLine("\t\tMap Name: %s", svcServerInfo.MapName) + writer.TempAppendLine("\t\tSky Name: %s", svcServerInfo.SkyName) + writer.TempAppendLine("\t\tHost Name: %s", svcServerInfo.HostName) + return svcServerInfo } diff --git a/pkg/messages/types/svcSetPause.go b/pkg/messages/types/svcSetPause.go index 551a4d3..d979ac5 100644 --- a/pkg/messages/types/svcSetPause.go +++ b/pkg/messages/types/svcSetPause.go @@ -1,13 +1,18 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcSetPause struct { Paused bool } func ParseSvcSetPause(reader *bitreader.Reader) SvcSetPause { - return SvcSetPause{ + svcSetPause := SvcSetPause{ Paused: reader.TryReadBool(), } + writer.TempAppendLine("\t\tPaused: %t", svcSetPause.Paused) + return svcSetPause } diff --git a/pkg/messages/types/svcSetView.go b/pkg/messages/types/svcSetView.go index 4ba5e3c..bdb6203 100644 --- a/pkg/messages/types/svcSetView.go +++ b/pkg/messages/types/svcSetView.go @@ -1,13 +1,18 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcSetView struct { EntityIndex uint16 } func ParseSvcSetView(reader *bitreader.Reader) SvcSetView { - return SvcSetView{ + svcSetView := SvcSetView{ EntityIndex: uint16(reader.TryReadBits(11)), } + writer.TempAppendLine("\t\tEntity Index: %d", svcSetView.EntityIndex) + return svcSetView } diff --git a/pkg/messages/types/svcSounds.go b/pkg/messages/types/svcSounds.go index 1553450..1affeb4 100644 --- a/pkg/messages/types/svcSounds.go +++ b/pkg/messages/types/svcSounds.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcSounds struct { ReliableSound bool @@ -21,5 +24,8 @@ func ParseSvcSounds(reader *bitreader.Reader) SvcSounds { svcSounds.Length = reader.TryReadUInt16() } svcSounds.Data = reader.TryReadBitsToSlice(uint64(svcSounds.Length)) + writer.TempAppendLine("\t\tReliable Sound: %t", svcSounds.ReliableSound) + writer.TempAppendLine("\t\tSound Count: %d", svcSounds.SoundCount) + writer.TempAppendLine("\t\tData: %v", svcSounds.Data) return svcSounds } diff --git a/pkg/messages/types/svcSplitScreen.go b/pkg/messages/types/svcSplitScreen.go index 5ddc131..653438a 100644 --- a/pkg/messages/types/svcSplitScreen.go +++ b/pkg/messages/types/svcSplitScreen.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcSplitScreen struct { RemoveUser bool @@ -14,5 +17,7 @@ func ParseSvcSplitScreen(reader *bitreader.Reader) SvcSplitScreen { Length: uint16(reader.TryReadBits(11)), } svcSplitScreen.Data = reader.TryReadBitsToSlice(uint64(svcSplitScreen.Length)) + writer.TempAppendLine("\t\tRemove User: %t", svcSplitScreen.RemoveUser) + writer.TempAppendLine("\t\tData: %v", svcSplitScreen.Data) return svcSplitScreen } diff --git a/pkg/messages/types/svcTempEntities.go b/pkg/messages/types/svcTempEntities.go index 9c20a65..407bfd6 100644 --- a/pkg/messages/types/svcTempEntities.go +++ b/pkg/messages/types/svcTempEntities.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcTempEntities struct { NumEntries uint8 @@ -14,5 +17,7 @@ func ParseSvcTempEntities(reader *bitreader.Reader) SvcTempEntities { Length: uint32(reader.TryReadBits(17)), } svcTempEntities.Data = reader.TryReadBitsToSlice(uint64(svcTempEntities.Length)) + writer.TempAppendLine("\t\tNumber Of Entries: %d", svcTempEntities.NumEntries) + writer.TempAppendLine("\t\tData: %v", svcTempEntities.Data) return svcTempEntities } diff --git a/pkg/messages/types/svcUpdateStringTable.go b/pkg/messages/types/svcUpdateStringTable.go index 0ff076c..68c8fb5 100644 --- a/pkg/messages/types/svcUpdateStringTable.go +++ b/pkg/messages/types/svcUpdateStringTable.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcUpdateStringTable struct { TableId uint8 @@ -18,5 +21,7 @@ func ParseSvcUpdateStringTable(reader *bitreader.Reader) SvcUpdateStringTable { } svcUpdateStringTable.Length = int32(reader.TryReadBits(20)) svcUpdateStringTable.Data = reader.TryReadBitsToSlice(uint64(svcUpdateStringTable.Length)) + writer.TempAppendLine("\t\tTable ID: %d", svcUpdateStringTable.TableId) + writer.TempAppendLine("\t\tNumber Of Changed Entries: %d", svcUpdateStringTable.NumChangedEntries) return svcUpdateStringTable } diff --git a/pkg/messages/types/svcUserMessage.go b/pkg/messages/types/svcUserMessage.go index 3cc6de2..e5b1943 100644 --- a/pkg/messages/types/svcUserMessage.go +++ b/pkg/messages/types/svcUserMessage.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcUserMessage struct { Type int8 @@ -86,6 +89,8 @@ func ParseSvcUserMessage(reader *bitreader.Reader) SvcUserMessage { Length: int16(reader.TryReadBits(12)), } svcUserMessage.Data = reader.TryReadBitsToSlice(uint64(svcUserMessage.Length)) + writer.TempAppendLine("\t\tType: %d", svcUserMessage.Type) + writer.TempAppendLine("\t\tData: %v", svcUserMessage.Data) return svcUserMessage } diff --git a/pkg/messages/types/svcVoiceData.go b/pkg/messages/types/svcVoiceData.go index efcae85..c3e08ee 100644 --- a/pkg/messages/types/svcVoiceData.go +++ b/pkg/messages/types/svcVoiceData.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcVoiceData struct { FromClient uint8 @@ -18,5 +21,8 @@ func ParseSvcVoiceData(reader *bitreader.Reader) SvcVoiceData { svcVoiceData.Proximity = true } svcVoiceData.Data = reader.TryReadBitsToSlice(uint64(svcVoiceData.Length)) + writer.TempAppendLine("\t\tFrom Client: %d", svcVoiceData.FromClient) + writer.TempAppendLine("\t\tProximity: %t", svcVoiceData.Proximity) + writer.TempAppendLine("\t\tData: %v", svcVoiceData.Data) return svcVoiceData } diff --git a/pkg/messages/types/svcVoiceInit.go b/pkg/messages/types/svcVoiceInit.go index a6d711a..03e0e25 100644 --- a/pkg/messages/types/svcVoiceInit.go +++ b/pkg/messages/types/svcVoiceInit.go @@ -1,6 +1,9 @@ package messages -import "github.com/pektezol/bitreader" +import ( + "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" +) type SvcVoiceInit struct { Codec string @@ -22,5 +25,8 @@ func ParseSvcVoiceInit(reader *bitreader.Reader) SvcVoiceInit { svcVoiceInit.SampleRate = 11025 } } + writer.TempAppendLine("\t\tCodec: %s", svcVoiceInit.Codec) + writer.TempAppendLine("\t\tQuality: %d", svcVoiceInit.Quality) + writer.TempAppendLine("\t\tSample Rate: %d", svcVoiceInit.SampleRate) return svcVoiceInit } diff --git a/pkg/packets/headers.go b/pkg/packets/headers.go index dbeab87..d92b22d 100644 --- a/pkg/packets/headers.go +++ b/pkg/packets/headers.go @@ -1,9 +1,8 @@ package packets import ( - "fmt" - "github.com/pektezol/bitreader" + "github.com/pektezol/demoparser/pkg/writer" ) type Headers struct { @@ -43,6 +42,6 @@ func ParseHeaders(reader *bitreader.Reader) Headers { if headers.NetworkProtocol != 2001 { panic("this parser only supports demos from portal 2") } - fmt.Printf("Headers: %+v\n", headers) + writer.AppendLine("Headers: %+v", headers) return headers } diff --git a/pkg/packets/packets.go b/pkg/packets/packets.go index 3a01370..33350d5 100644 --- a/pkg/packets/packets.go +++ b/pkg/packets/packets.go @@ -4,6 +4,7 @@ import ( "github.com/pektezol/bitreader" "github.com/pektezol/demoparser/pkg/classes" "github.com/pektezol/demoparser/pkg/messages" + "github.com/pektezol/demoparser/pkg/writer" ) type PacketMessageInfo struct { @@ -23,6 +24,7 @@ func ParsePackets(reader *bitreader.Reader) PacketMessageInfo { switch packetType { case 1: // SignOn signOn := SignOn{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "SIGNON", packetType) for count := 0; count < MSSC; count++ { signOn.PacketInfo = append(signOn.PacketInfo, classes.ParseCmdInfo(reader)) } @@ -41,6 +43,7 @@ func ParsePackets(reader *bitreader.Reader) PacketMessageInfo { packetData = signOn case 2: // Packet packet := Packet{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "PACKET", packetType) for count := 0; count < MSSC; count++ { packet.PacketInfo = append(packet.PacketInfo, classes.ParseCmdInfo(reader)) } @@ -59,16 +62,18 @@ func ParsePackets(reader *bitreader.Reader) PacketMessageInfo { packetData = packet case 3: // SyncTick syncTick := SyncTick{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "SYNCTICK", packetType) packetData = syncTick case 4: // ConsoleCmd - size := reader.TryReadSInt32() - consoleCmd := ConsoleCmd{ - Size: int32(size), - Data: reader.TryReadStringLength(uint64(size)), - } + consoleCmd := ConsoleCmd{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "CONSOLECMD", packetType) + consoleCmd.Size = reader.TryReadSInt32() + consoleCmd.Data = reader.TryReadStringLength(uint64(consoleCmd.Size)) + writer.AppendLine("\t%s", consoleCmd.Data) packetData = consoleCmd case 5: // UserCmd TODO: usercmdinfo refactor userCmd := UserCmd{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "USERCMD", packetType) userCmd.Cmd = int32(reader.TryReadSInt32()) userCmd.Size = int32(reader.TryReadSInt32()) data := reader.TryReadBytesToSlice(uint64(userCmd.Size)) @@ -76,6 +81,7 @@ func ParsePackets(reader *bitreader.Reader) PacketMessageInfo { packetData = userCmd case 6: // DataTables TODO: prop stuff dataTables := DataTables{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "DATATABLES", packetType) dataTables.Size = int32(reader.TryReadSInt32()) data := reader.TryReadBytesToSlice(uint64(dataTables.Size)) dataTableReader := bitreader.NewReaderFromBytes(data, true) @@ -84,43 +90,52 @@ func ParsePackets(reader *bitreader.Reader) PacketMessageInfo { count++ dataTables.SendTable = append(dataTables.SendTable, classes.ParseSendTable(dataTableReader)) } + writer.AppendLine("\t%d Send Tables:", count) + writer.AppendOutputFromTemp() numOfClasses := dataTableReader.TryReadBits(16) for count = 0; count < int(numOfClasses); count++ { dataTables.ServerClassInfo = append(dataTables.ServerClassInfo, classes.ParseServerClassInfo(dataTableReader, count, int(numOfClasses))) } + writer.AppendLine("\t%d Classes:", count) + writer.AppendOutputFromTemp() packetData = dataTables case 7: // Stop stop := Stop{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "STOP", packetType) if reader.TryReadBool() { stop.RemainingData = reader.TryReadBitsToSlice(uint64(reader.TryReadRemainingBits())) + writer.AppendLine("\tRemaining Data: %v", stop.RemainingData) } packetData = stop - case 8: // CustomData - customData := CustomData{ - Unknown: int32(reader.TryReadBits(32)), - Size: int32(reader.TryReadBits(32)), - } - if customData.Unknown != 0 || customData.Size == 8 { + case 8: // CustomData TODO: not sar data + customData := CustomData{} + customData.Type = reader.TryReadSInt32() + customData.Size = reader.TryReadSInt32() + if customData.Type != 0 || customData.Size == 8 { // Not SAR data + writer.AppendLine("[%d] %s (%d):", tickNumber, "CUSTOMDATA", packetType) customData.Data = string(reader.TryReadBytesToSlice(uint64(customData.Size))) + writer.AppendLine("\t%s", customData.Data) packetData = customData break } // SAR data sarData := classes.SarData{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "SARDATA", packetType) data := reader.TryReadBytesToSlice(uint64(customData.Size)) sarReader := bitreader.NewReaderFromBytes(data, true) sarData.ParseSarData(sarReader) packetData = sarData case 9: // StringTables TODO: parsing string table data - stringTables := StringTables{ - Size: int32(reader.TryReadSInt32()), - } + stringTables := StringTables{} + writer.AppendLine("[%d] %s (%d):", tickNumber, "STRINGTABLES", packetType) + stringTables.Size = reader.TryReadSInt32() data := reader.TryReadBytesToSlice(uint64(stringTables.Size)) stringTableReader := bitreader.NewReaderFromBytes(data, true) stringTables.Data = classes.ParseStringTables(stringTableReader) packetData = stringTables default: // invalid + writer.AppendLine("[%d] %s (%d):", tickNumber, "INVALID", packetType) panic("invalid packet type") } return PacketMessageInfo{ diff --git a/pkg/packets/types.go b/pkg/packets/types.go index 6297b01..a2fb78f 100644 --- a/pkg/packets/types.go +++ b/pkg/packets/types.go @@ -42,9 +42,9 @@ type Stop struct { } type CustomData struct { - Unknown int32 - Size int32 - Data string + Type int32 + Size int32 + Data string } type StringTables struct { diff --git a/pkg/writer/writer.go b/pkg/writer/writer.go new file mode 100644 index 0000000..6b66e75 --- /dev/null +++ b/pkg/writer/writer.go @@ -0,0 +1,47 @@ +package writer + +import ( + "fmt" + "strings" +) + +var output strings.Builder + +var temp strings.Builder + +func Append(str string, a ...any) { + _, err := output.WriteString(fmt.Sprintf(str, a...)) + if err != nil { + output.WriteString(err.Error()) + } +} + +func AppendLine(str string, a ...any) { + Append(str, a...) + output.WriteString("\n") +} + +func GetString() string { + return output.String() +} + +func TempAppend(str string, a ...any) { + _, err := temp.WriteString(fmt.Sprintf(str, a...)) + if err != nil { + temp.WriteString(err.Error()) + } +} + +func TempAppendLine(str string, a ...any) { + TempAppend(str, a...) + temp.WriteString("\n") +} + +func TempGetString() string { + return temp.String() +} + +func AppendOutputFromTemp() { + output.WriteString(temp.String()) + temp.Reset() +} -- cgit v1.2.3