forked from dotabuff/manta
/
packet_entity.go
114 lines (95 loc) · 2.93 KB
/
packet_entity.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
110
111
112
113
114
package manta
import (
"github.com/dotabuff/manta/dota"
)
// Represents the state of an entity
type packetEntity struct {
index int32
classId int32
className string
sendTable *sendTable
properties map[string]interface{}
}
// Internal callback for CSVCMsg_PacketEntities.
func (p *Parser) onCSVCMsg_PacketEntities(m *dota.CSVCMsg_PacketEntities) error {
// XXX: Remove once we've gotten readProperties working.
return nil
defer func() {
if err := recover(); err != nil {
_debugf("recovered: %s", err)
}
}()
_debugf("pTick=%d isDelta=%v deltaFrom=%d updatedEntries=%d maxEntries=%d baseline=%d updateBaseline=%v", p.Tick, m.GetIsDelta(), m.GetDeltaFrom(), m.GetUpdatedEntries(), m.GetMaxEntries(), m.GetBaseline(), m.GetUpdateBaseline())
r := newReader(m.GetEntityData())
index := int32(-1)
ok := false
// Iterate over all entries
for i := 0; i < int(m.GetUpdatedEntries()); i++ {
// Read the index delta from the buffer. This is an implementation
// from Alice. An alternate implementation from Yasha has the same result.
delta := r.readUBitVar()
index += int32(delta) + 1
_debugf("index delta is %d to %d", delta, index)
// Read the type of update based on two booleans.
// This appears to be backwards from source 1:
// true+true used to be "create", now appears to be false+true?
// This seems suspcious.
updateType := " "
if r.readBoolean() {
if r.readBoolean() {
updateType = "D"
} else {
updateType = "?"
}
} else {
if r.readBoolean() {
updateType = "C"
} else {
updateType = "U"
}
}
_debugf("update type is %s", updateType)
// Proceed based on the update type
switch updateType {
case "C":
// Create a new packetEntity.
pe := &packetEntity{
index: index,
classId: int32(r.readBits(p.classIdSize)),
properties: make(map[string]interface{}),
}
// Skip the 10 serial bits for now.
r.seekBits(10)
// Get the associated class.
if pe.className, ok = p.classInfo[pe.classId]; !ok {
_panicf("unable to find class %d", pe.classId)
}
// Get the associated send table.
if pe.sendTable, ok = p.sendTables.getTableByName(pe.className); !ok {
_panicf("unable to find sendtable for class %s", pe.className)
}
// Register the packetEntity with the parser.
p.packetEntities[index] = pe
_debugf("created a pe: %+v", pe)
// Read properties and set them in the packetEntity
pe.properties = readProperties(r, pe.sendTable)
case "U":
// Find the existing packetEntity
pe, ok := p.packetEntities[index]
if !ok {
_panicf("unable to find packet entity %d for update", index)
}
// Read properties and update the packetEntity
for k, v := range readProperties(r, pe.sendTable) {
pe.properties[k] = v
}
case "D":
if _, ok := p.packetEntities[index]; !ok {
_panicf("unable to find packet entity %d for delete", index)
} else {
delete(p.packetEntities, index)
}
}
}
return nil
}