forked from dotabuff/manta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sendtable.go
109 lines (90 loc) · 2.76 KB
/
sendtable.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package manta
import (
"github.com/dotabuff/manta/dota"
"github.com/golang/protobuf/proto"
)
var pointerTypes = map[string]bool{
"CBodyComponent": true,
"CEntityIdentity": true,
"CPhysicsComponent": true,
"CRenderComponent": true,
"CDOTAGamerules": true,
"CDOTAGameManager": true,
"CDOTASpectatorGraphManager": true,
"CPlayerLocalData": true,
}
var itemCounts = map[string]int{
"MAX_ITEM_STOCKS": 8,
"MAX_ABILITY_DRAFT_ABILITIES": 48,
}
// Internal callback for OnCDemoSendTables.
func (p *Parser) onCDemoSendTables(m *dota.CDemoSendTables) error {
r := newReader(m.GetData())
buf := r.readBytes(r.readVarUint32())
msg := &dota.CSVCMsg_FlattenedSerializer{}
if err := proto.Unmarshal(buf, msg); err != nil {
return err
}
patches := []fieldPatch{}
for _, h := range fieldPatches {
if h.shouldApply(p.GameBuild) {
patches = append(patches, h)
}
}
fields := map[int32]*field{}
fieldTypes := map[string]*fieldType{}
for _, s := range msg.GetSerializers() {
serializer := &serializer{
name: msg.GetSymbols()[s.GetSerializerNameSym()],
version: s.GetSerializerVersion(),
fields: []*field{},
}
for _, i := range s.GetFieldsIndex() {
if _, ok := fields[i]; !ok {
// create a new field
field := newField(msg, msg.GetFields()[i])
// patch parent name in builds <= 990
if p.GameBuild <= 990 {
field.parentName = serializer.name
}
// find or create a field type
if _, ok := fieldTypes[field.varType]; !ok {
fieldTypes[field.varType] = newFieldType(field.varType)
}
field.fieldType = fieldTypes[field.varType]
// find associated serializer
if field.serializerName != "" {
field.serializer = p.serializers[field.serializerName]
}
// apply any build-specific patches to the field
for _, h := range patches {
h.patch(field)
}
// determine field model
if field.serializer != nil {
if pointerTypes[field.fieldType.baseType] {
field.setModel(fieldModelFixedTable)
} else {
field.setModel(fieldModelVariableTable)
}
} else if field.fieldType.count > 0 && field.fieldType.baseType != "char" {
field.setModel(fieldModelFixedArray)
} else if field.fieldType.baseType == "CUtlVector" {
field.setModel(fieldModelVariableArray)
} else {
field.setModel(fieldModelSimple)
}
// store the field
fields[i] = field
}
// add the field to the serializer
serializer.fields = append(serializer.fields, fields[i])
}
// store the serializer for field reference
p.serializers[serializer.name] = serializer
if _, ok := p.classesByName[serializer.name]; ok {
p.classesByName[serializer.name].serializer = serializer
}
}
return nil
}