aboutsummaryrefslogtreecommitdiff
path: root/pkg/classes
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/classes')
-rw-r--r--pkg/classes/cmdInfo.go2
-rw-r--r--pkg/classes/sarData.go378
-rw-r--r--pkg/classes/sendTable.go2
-rw-r--r--pkg/classes/serverClassInfo.go2
-rw-r--r--pkg/classes/stringTable.go16
-rw-r--r--pkg/classes/userCmdInfo.go2
6 files changed, 389 insertions, 13 deletions
diff --git a/pkg/classes/cmdInfo.go b/pkg/classes/cmdInfo.go
index 6e56c41..b56afed 100644
--- a/pkg/classes/cmdInfo.go
+++ b/pkg/classes/cmdInfo.go
@@ -14,7 +14,7 @@ type CmdInfo struct {
14 LocalViewAngles2 []float32 14 LocalViewAngles2 []float32
15} 15}
16 16
17func ParseCmdInfo(reader *bitreader.ReaderType) CmdInfo { 17func ParseCmdInfo(reader *bitreader.Reader) CmdInfo {
18 return CmdInfo{ 18 return CmdInfo{
19 Flags: int32(reader.TryReadBits(32)), 19 Flags: int32(reader.TryReadBits(32)),
20 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()}, 20 ViewOrigin: []float32{reader.TryReadFloat32(), reader.TryReadFloat32(), reader.TryReadFloat32()},
diff --git a/pkg/classes/sarData.go b/pkg/classes/sarData.go
new file mode 100644
index 0000000..133b67a
--- /dev/null
+++ b/pkg/classes/sarData.go
@@ -0,0 +1,378 @@
1package classes
2
3import (
4 "errors"
5 "fmt"
6
7 "github.com/pektezol/bitreader"
8)
9
10type SarDataType uint8
11
12const (
13 ESarDataTimescaleCheat SarDataType = 0x01
14 ESarDataInitialCVar SarDataType = 0x02
15 ESarDataEntityInput SarDataType = 0x03
16 ESarDataEntityInputSlot SarDataType = 0x04
17 ESarDataPortalPlacement SarDataType = 0x05
18 ESarDataChallengeFlags SarDataType = 0x06
19 ESarDataCrouchFly SarDataType = 0x07
20 ESarDataPause SarDataType = 0x08
21 ESarDataWaitRun SarDataType = 0x09
22 ESarDataSpeedrunTime SarDataType = 0x0A
23 ESarDataTimestamp SarDataType = 0x0B
24 ESarDataFileChecksum SarDataType = 0x0C
25 ESarDataHWaitRun SarDataType = 0x0D
26 ESarDataChecksum SarDataType = 0xFF
27 ESarDataChecksumV2 SarDataType = 0xFE
28 ESarDataInvalid SarDataType = iota
29)
30
31func (t SarDataType) String() string {
32 switch t {
33 case ESarDataTimescaleCheat:
34 return "SarDataTimescaleCheat"
35 case ESarDataInitialCVar:
36 return "SarDataInitialCVar"
37 case ESarDataEntityInput:
38 return "SarDataEntityInput"
39 case ESarDataEntityInputSlot:
40 return "SarDataEntityInputSlot"
41 case ESarDataPortalPlacement:
42 return "SarDataPortalPlacement"
43 case ESarDataChallengeFlags:
44 return "SarDataChallengeFlags"
45 case ESarDataCrouchFly:
46 return "SarDataCrouchFly"
47 case ESarDataPause:
48 return "SarDataPause"
49 case ESarDataWaitRun:
50 return "SarDataWaitRun"
51 case ESarDataSpeedrunTime:
52 return "SarDataSpeedrunTime"
53 case ESarDataTimestamp:
54 return "SarDataTimestamp"
55 case ESarDataFileChecksum:
56 return "SarDataFileChecksum"
57 case ESarDataHWaitRun:
58 return "SarDataHWaitRun"
59 case ESarDataChecksum:
60 return "SarDataChecksum"
61 case ESarDataChecksumV2:
62 return "SarDataChecksumV2"
63 case ESarDataInvalid:
64 return "SarDataInvalid"
65 default:
66 return fmt.Sprintf("%d", int(t))
67 }
68}
69
70type SarData struct {
71 Type SarDataType
72 Slot int
73 Data any
74}
75
76type SarDataTimescaleCheat struct {
77 Timescale float32
78}
79
80type SarDataInitialCVar struct {
81 CVar string
82 Val string
83}
84
85type SarDataChecksum struct {
86 DemoSum uint32
87 SarSum uint32
88}
89
90type SarDataChecksumV2 struct {
91 SarSum uint32
92 Signature [64]byte
93}
94
95type SarDataEntityInput struct {
96 TargetName string
97 ClassName string
98 InputName string
99 Parameter string
100}
101
102type SarDataPortalPlacement struct {
103 Orange bool
104 X float32
105 Y float32
106 Z float32
107}
108
109type SarDataPause struct {
110 PauseTicks uint32
111}
112
113type SarDataWaitRun struct {
114 Ticks int
115 Cmd string
116}
117
118type SarDataHWaitRun struct {
119 Ticks int
120 Cmd string
121}
122
123type SarDataSpeedrunTime struct {
124 NSplits uint32
125 Splits []SarDataSpeedrunTimeSplits
126}
127
128type SarDataSpeedrunTimeSegs struct {
129 Name string
130 Ticks uint32
131}
132
133type SarDataSpeedrunTimeSplits struct {
134 Name string
135 NSegs uint32
136 Segs []SarDataSpeedrunTimeSegs
137}
138
139type SarDataTimestamp struct {
140 Year uint16
141 Mon uint8
142 Day uint8
143 Hour uint8
144 Min uint8
145 Sec uint8
146}
147
148type SarDataFileChecksum struct {
149 Sum uint32
150 Path string
151}
152
153func (sarData *SarData) ParseSarData(reader *bitreader.Reader) (err error) {
154 reader.SkipBytes(8)
155 len := reader.TryReadRemainingBits() / 8
156 if len == 0 {
157 sarData.Type = ESarDataInvalid
158 err = errors.New("sar data invalid")
159 return err
160 }
161 sarData.Type = SarDataType(reader.TryReadBytes(1))
162 if sarData.Type == ESarDataChecksum && len == 5 {
163 len = 9
164 }
165 dataReader := bitreader.NewReaderFromBytes(reader.TryReadBytesToSlice(len-1), true)
166 switch sarData.Type {
167 case ESarDataTimescaleCheat:
168 sarData.Data, err = parseTimescaleCheatData(dataReader, len)
169 if err != nil {
170 sarData.Data = nil
171 }
172 case ESarDataInitialCVar:
173 sarData.Data = parseInitialCVarData(dataReader)
174 case ESarDataEntityInputSlot:
175 sarData.Slot = int(dataReader.TryReadBytes(1))
176 case ESarDataEntityInput:
177 sarData.Data = parseEntityInputData(dataReader)
178 case ESarDataChecksum:
179 sarData.Data, err = parseChecksumData(dataReader, len)
180 if err != nil {
181 sarData.Data = nil
182 }
183 case ESarDataChecksumV2:
184 sarData.Data, err = parseChecksumV2Data(dataReader, len)
185 if err != nil {
186 sarData.Data = nil
187 }
188 case ESarDataPortalPlacement:
189 data, slot, err := parsePortalPlacementData(dataReader, len)
190 if err != nil {
191 sarData.Data = nil
192 } else {
193 sarData.Data = data
194 sarData.Slot = slot
195 }
196 case ESarDataChallengeFlags, ESarDataCrouchFly:
197 sarData.Slot, err = parseChallengeFlagsCrouchFlyData(dataReader, len)
198 if err != nil {
199 sarData.Data = nil
200 }
201 case ESarDataPause:
202 sarData.Data, err = parsePauseData(dataReader, len)
203 if err != nil {
204 sarData.Data = nil
205 }
206 case ESarDataWaitRun:
207 sarData.Data, err = parseWaitRunData(dataReader, len)
208 if err != nil {
209 sarData.Data = nil
210 }
211 case ESarDataHWaitRun:
212 sarData.Data, err = parseHWaitRunData(dataReader, len)
213 if err != nil {
214 sarData.Data = nil
215 }
216 case ESarDataSpeedrunTime:
217 sarData.Data, err = parseSpeedrunTimeData(dataReader, len)
218 if err != nil {
219 sarData.Data = nil
220 }
221 case ESarDataTimestamp:
222 sarData.Data, err = parseTimestampData(dataReader, len)
223 if err != nil {
224 sarData.Data = nil
225 }
226 case ESarDataFileChecksum:
227 sarData.Data, err = parseFileChecksumData(dataReader, len)
228 if err != nil {
229 sarData.Data = nil
230 }
231 default:
232 err = errors.New("unsupported SAR data type")
233 return err
234 }
235 return nil
236}
237
238func parseTimescaleCheatData(reader *bitreader.Reader, length uint64) (SarDataTimescaleCheat, error) {
239 if length != 5 {
240 return SarDataTimescaleCheat{}, errors.New("sar data invalid")
241 }
242 return SarDataTimescaleCheat{
243 Timescale: reader.TryReadFloat32(),
244 }, nil
245}
246
247func parseInitialCVarData(reader *bitreader.Reader) SarDataInitialCVar {
248 return SarDataInitialCVar{
249 CVar: reader.TryReadString(),
250 Val: reader.TryReadString(),
251 }
252}
253
254func parseEntityInputData(reader *bitreader.Reader) SarDataEntityInput {
255 return SarDataEntityInput{
256 TargetName: reader.TryReadString(),
257 ClassName: reader.TryReadString(),
258 InputName: reader.TryReadString(),
259 Parameter: reader.TryReadString(),
260 }
261}
262
263func parseChecksumData(reader *bitreader.Reader, length uint64) (SarDataChecksum, error) {
264 if length != 9 {
265 return SarDataChecksum{}, errors.New("sar data invalid")
266 }
267 return SarDataChecksum{
268 DemoSum: reader.TryReadUInt32(),
269 SarSum: reader.TryReadUInt32(),
270 }, nil
271}
272
273func parseChecksumV2Data(reader *bitreader.Reader, length uint64) (SarDataChecksumV2, error) {
274 if length != 69 {
275 return SarDataChecksumV2{}, errors.New("sar data invalid")
276 }
277 return SarDataChecksumV2{
278 SarSum: reader.TryReadUInt32(),
279 Signature: [64]byte(reader.TryReadBytesToSlice(60)),
280 }, nil
281}
282
283func parsePortalPlacementData(reader *bitreader.Reader, length uint64) (SarDataPortalPlacement, int, error) {
284 if length != 15 {
285 return SarDataPortalPlacement{}, 0, errors.New("sar data invalid")
286 }
287 slot := int(reader.TryReadBytes(1))
288 orange := reader.TryReadBool()
289 reader.SkipBits(7)
290 return SarDataPortalPlacement{
291 Orange: orange,
292 X: reader.TryReadFloat32(),
293 Y: reader.TryReadFloat32(),
294 Z: reader.TryReadFloat32(),
295 }, slot, nil
296}
297
298func parseChallengeFlagsCrouchFlyData(reader *bitreader.Reader, length uint64) (int, error) {
299 if length != 2 {
300 return 0, errors.New("sar data invalid")
301 }
302 return int(reader.TryReadBytes(1)), nil
303}
304
305func parsePauseData(reader *bitreader.Reader, length uint64) (SarDataPause, error) {
306 if length != 5 {
307 return SarDataPause{}, errors.New("sar data invalid")
308 }
309 return SarDataPause{
310 PauseTicks: reader.TryReadUInt32(),
311 }, nil
312}
313
314func parseWaitRunData(reader *bitreader.Reader, length uint64) (SarDataWaitRun, error) {
315 if length < 6 {
316 return SarDataWaitRun{}, errors.New("sar data invalid")
317 }
318 return SarDataWaitRun{
319 Ticks: int(reader.TryReadUInt32()),
320 Cmd: reader.TryReadString(),
321 }, nil
322}
323
324func parseHWaitRunData(reader *bitreader.Reader, length uint64) (SarDataHWaitRun, error) {
325 if length < 6 {
326 return SarDataHWaitRun{}, errors.New("sar data invalid")
327 }
328 return SarDataHWaitRun{
329 Ticks: int(reader.TryReadUInt32()),
330 Cmd: reader.TryReadString(),
331 }, nil
332}
333
334func parseSpeedrunTimeData(reader *bitreader.Reader, length uint64) (SarDataSpeedrunTime, error) {
335 if length < 5 {
336 return SarDataSpeedrunTime{}, errors.New("sar data invalid")
337 }
338 numberOfSplits := reader.TryReadUInt32()
339 splits := make([]SarDataSpeedrunTimeSplits, numberOfSplits)
340 for splitCount := 0; splitCount < int(numberOfSplits); splitCount++ {
341 splits[splitCount].Name = reader.TryReadString()
342 splits[splitCount].NSegs = reader.TryReadUInt32()
343 splits[splitCount].Segs = make([]SarDataSpeedrunTimeSegs, splits[splitCount].NSegs)
344 for segCount := 0; segCount < int(splits[splitCount].NSegs); segCount++ {
345 splits[splitCount].Segs[segCount].Name = reader.TryReadString()
346 splits[splitCount].Segs[segCount].Ticks = reader.TryReadUInt32()
347 }
348 }
349 return SarDataSpeedrunTime{
350 NSplits: numberOfSplits,
351 Splits: splits,
352 }, nil
353}
354
355func parseTimestampData(reader *bitreader.Reader, length uint64) (SarDataTimestamp, error) {
356 if length != 8 {
357 return SarDataTimestamp{}, errors.New("sar data invalid")
358 }
359 timestamp := reader.TryReadBytesToSlice(7)
360 return SarDataTimestamp{
361 Year: uint16(timestamp[0]) | uint16(timestamp[1])<<8,
362 Mon: timestamp[2] + 1,
363 Day: timestamp[3],
364 Hour: timestamp[4],
365 Min: timestamp[5],
366 Sec: timestamp[6],
367 }, nil
368}
369
370func parseFileChecksumData(reader *bitreader.Reader, length uint64) (SarDataFileChecksum, error) {
371 if length < 6 {
372 return SarDataFileChecksum{}, errors.New("sar data invalid")
373 }
374 return SarDataFileChecksum{
375 Sum: reader.TryReadUInt32(),
376 Path: reader.TryReadString(),
377 }, nil
378}
diff --git a/pkg/classes/sendTable.go b/pkg/classes/sendTable.go
index 4521464..bc36d75 100644
--- a/pkg/classes/sendTable.go
+++ b/pkg/classes/sendTable.go
@@ -59,7 +59,7 @@ const (
59 DataTable 59 DataTable
60) 60)
61 61
62func ParseSendTable(reader *bitreader.ReaderType) SendTable { 62func ParseSendTable(reader *bitreader.Reader) SendTable {
63 sendTable := SendTable{ 63 sendTable := SendTable{
64 NeedsDecoder: reader.TryReadBool(), 64 NeedsDecoder: reader.TryReadBool(),
65 NetTableName: reader.TryReadString(), 65 NetTableName: reader.TryReadString(),
diff --git a/pkg/classes/serverClassInfo.go b/pkg/classes/serverClassInfo.go
index c60dad1..fbccffb 100644
--- a/pkg/classes/serverClassInfo.go
+++ b/pkg/classes/serverClassInfo.go
@@ -10,7 +10,7 @@ type ServerClassInfo struct {
10 DataTableName string 10 DataTableName string
11} 11}
12 12
13func ParseServerClassInfo(reader *bitreader.ReaderType, count int, numOfClasses int) ServerClassInfo { 13func ParseServerClassInfo(reader *bitreader.Reader, count int, numOfClasses int) ServerClassInfo {
14 return ServerClassInfo{ 14 return ServerClassInfo{
15 ClassId: int16(reader.TryReadBits(16)), 15 ClassId: int16(reader.TryReadBits(16)),
16 ClassName: reader.TryReadString(), 16 ClassName: reader.TryReadString(),
diff --git a/pkg/classes/stringTable.go b/pkg/classes/stringTable.go
index c6709f5..3983c1f 100644
--- a/pkg/classes/stringTable.go
+++ b/pkg/classes/stringTable.go
@@ -1,8 +1,6 @@
1package classes 1package classes
2 2
3import ( 3import (
4 "bytes"
5
6 "github.com/pektezol/bitreader" 4 "github.com/pektezol/bitreader"
7) 5)
8 6
@@ -26,7 +24,7 @@ type StringTableClass struct {
26 Data string 24 Data string
27} 25}
28 26
29func ParseStringTables(reader *bitreader.ReaderType) []StringTable { 27func ParseStringTables(reader *bitreader.Reader) []StringTable {
30 tableCount := reader.TryReadBits(8) 28 tableCount := reader.TryReadBits(8)
31 stringTables := make([]StringTable, tableCount) 29 stringTables := make([]StringTable, tableCount)
32 for i := 0; i < int(tableCount); i++ { 30 for i := 0; i < int(tableCount); i++ {
@@ -37,7 +35,7 @@ func ParseStringTables(reader *bitreader.ReaderType) []StringTable {
37 return stringTables 35 return stringTables
38} 36}
39 37
40func (stringTable *StringTable) ParseStream(reader *bitreader.ReaderType) { 38func (stringTable *StringTable) ParseStream(reader *bitreader.Reader) {
41 stringTable.Name = reader.TryReadString() 39 stringTable.Name = reader.TryReadString()
42 entryCount := reader.TryReadBits(16) 40 entryCount := reader.TryReadBits(16)
43 stringTable.TableEntries = make([]StringTableEntry, entryCount) 41 stringTable.TableEntries = make([]StringTableEntry, entryCount)
@@ -60,23 +58,23 @@ func (stringTable *StringTable) ParseStream(reader *bitreader.ReaderType) {
60 } 58 }
61} 59}
62 60
63func (stringTableEntry *StringTableEntry) Parse(reader *bitreader.ReaderType) { 61func (stringTableEntry *StringTableEntry) Parse(reader *bitreader.Reader) {
64 stringTableEntry.Name = reader.TryReadString() 62 stringTableEntry.Name = reader.TryReadString()
65 if reader.TryReadBool() { 63 if reader.TryReadBool() {
66 byteLen, err := reader.ReadBits(16) 64 byteLen, err := reader.ReadBits(16)
67 if err != nil { 65 if err != nil {
68 return 66 return
69 } 67 }
70 dataBsr := reader.TryReadBytesToSlice(int(byteLen)) 68 dataBsr := reader.TryReadBytesToSlice(byteLen)
71 _ = bitreader.Reader(bytes.NewReader(dataBsr), true) // TODO: Parse StringTableEntry 69 _ = bitreader.NewReaderFromBytes(dataBsr, true) // TODO: Parse StringTableEntry
72 // stringTableEntry.EntryData.ParseStream(entryReader) 70 // stringTableEntry.EntryData.ParseStream(entryReader)
73 } 71 }
74} 72}
75 73
76func (stringTableClass *StringTableClass) Parse(reader *bitreader.ReaderType) { 74func (stringTableClass *StringTableClass) Parse(reader *bitreader.Reader) {
77 stringTableClass.Name = reader.TryReadString() 75 stringTableClass.Name = reader.TryReadString()
78 if reader.TryReadBool() { 76 if reader.TryReadBool() {
79 dataLen := reader.TryReadBits(16) 77 dataLen := reader.TryReadBits(16)
80 stringTableClass.Data = reader.TryReadStringLen(int(dataLen)) 78 stringTableClass.Data = reader.TryReadStringLength(dataLen)
81 } 79 }
82} 80}
diff --git a/pkg/classes/userCmdInfo.go b/pkg/classes/userCmdInfo.go
index a6d9091..04d76b6 100644
--- a/pkg/classes/userCmdInfo.go
+++ b/pkg/classes/userCmdInfo.go
@@ -24,7 +24,7 @@ type UserCmdInfo struct {
24} 24}
25 25
26func ParseUserCmdInfo(data []byte) UserCmdInfo { 26func ParseUserCmdInfo(data []byte) UserCmdInfo {
27 reader := bitreader.Reader(bytes.NewReader(data), true) 27 reader := bitreader.NewReader(bytes.NewReader(data), true)
28 userCmdInfo := UserCmdInfo{} 28 userCmdInfo := UserCmdInfo{}
29 if reader.TryReadBool() { 29 if reader.TryReadBool() {
30 userCmdInfo.CommandNumber = int32(reader.TryReadBits(32)) 30 userCmdInfo.CommandNumber = int32(reader.TryReadBits(32))