Skip to content

Commit 1787f56

Browse files
committed
Clean up of sendtables package (#16)
1 parent 450a40c commit 1787f56

File tree

8 files changed

+351
-305
lines changed

8 files changed

+351
-305
lines changed

datatables.go

Lines changed: 81 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -17,38 +17,37 @@ const (
1717
maxWeapons = 64
1818
)
1919

20-
// Everything here feels kinda fucked
21-
2220
func (p *Parser) mapEquipment() {
2321
for _, sc := range p.stParser.ServerClasses() {
24-
for _, bc := range sc.BaseClasses {
25-
if bc.Name == "CBaseGrenade" { // Grenades projectiles, i.e. thrown by player
26-
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.DTName[3:]))
22+
baseClasses := sc.BaseClasses()
23+
for _, bc := range baseClasses {
24+
if bc.Name() == "CBaseGrenade" { // Grenades projectiles, i.e. thrown by player
25+
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.DataTableName()[3:]))
2726
}
2827
}
2928

30-
if len(sc.BaseClasses) > 6 && sc.BaseClasses[6].Name == "CWeaponCSBase" {
31-
if len(sc.BaseClasses) > 7 {
32-
switch sc.BaseClasses[7].Name {
29+
if len(baseClasses) > 6 && baseClasses[6].Name() == "CWeaponCSBase" {
30+
if len(baseClasses) > 7 {
31+
switch baseClasses[7].Name() {
3332
case "CWeaponCSBaseGun":
3433
// Most guns
35-
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.DTName[9:]))
34+
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.DataTableName()[9:]))
3635
case "CBaseCSGrenade":
3736
// Nades
38-
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.DTName[3:]))
37+
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.DataTableName()[3:]))
3938
}
40-
} else if sc.Name == "CKnife" || (len(sc.BaseClasses) > 6 && sc.BaseClasses[6].Name == "CKnife") {
39+
} else if sc.Name() == "CKnife" || (len(baseClasses) > 6 && baseClasses[6].Name() == "CKnife") {
4140
p.equipmentMapping[sc] = common.EqKnife
4241
} else {
43-
switch sc.Name {
42+
switch sc.Name() {
4443
case "CC4":
4544
p.equipmentMapping[sc] = common.EqBomb
4645
case "CWeaponNOVA":
4746
fallthrough
4847
case "CWeaponSawedoff":
4948
fallthrough
5049
case "CWeaponXM1014":
51-
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.Name[7:]))
50+
p.equipmentMapping[sc] = common.MapEquipment(strings.ToLower(sc.Name()[7:]))
5251
}
5352
}
5453
}
@@ -64,18 +63,18 @@ func (p *Parser) bindEntities() {
6463
}
6564

6665
func (p *Parser) bindTeamScores() {
67-
p.stParser.FindServerClassByName("CCSTeam").RegisterEntityCreatedHandler(func(event st.EntityCreatedEvent) {
66+
p.stParser.ServerClasses().FindByName("CCSTeam").OnEntityCreated(func(entity *st.Entity) {
6867
teamID := -1
6968
var clanName string
7069
var flagImage string
7170
score := 0
7271

73-
event.Entity.BindProperty("m_iTeamNum", &teamID, st.ValTypeInt)
74-
event.Entity.BindProperty("m_szClanTeamname", &clanName, st.ValTypeString)
75-
event.Entity.BindProperty("m_szTeamFlagImage", &flagImage, st.ValTypeString)
76-
event.Entity.BindProperty("m_scoreTotal", &score, st.ValTypeInt)
72+
entity.BindProperty("m_iTeamNum", &teamID, st.ValTypeInt)
73+
entity.BindProperty("m_szClanTeamname", &clanName, st.ValTypeString)
74+
entity.BindProperty("m_szTeamFlagImage", &flagImage, st.ValTypeString)
75+
entity.BindProperty("m_scoreTotal", &score, st.ValTypeInt)
7776

78-
event.Entity.FindProperty("m_szTeamname").OnUpdate(func(val st.PropValue) {
77+
entity.FindProperty("m_szTeamname").OnUpdate(func(val st.PropertyValue) {
7978
team := val.StringVal
8079

8180
var s *TeamState
@@ -103,54 +102,54 @@ func (p *Parser) bindTeamScores() {
103102

104103
// Register direct updates for the future
105104
// Except for teamId, it doesn't change; players swap teams instead
106-
event.Entity.BindProperty("m_szClanTeamname", &s.clanName, st.ValTypeString)
107-
event.Entity.BindProperty("m_szTeamFlagImage", &s.flag, st.ValTypeString)
108-
event.Entity.BindProperty("m_scoreTotal", &s.score, st.ValTypeInt)
105+
entity.BindProperty("m_szClanTeamname", &s.clanName, st.ValTypeString)
106+
entity.BindProperty("m_szTeamFlagImage", &s.flag, st.ValTypeString)
107+
entity.BindProperty("m_scoreTotal", &s.score, st.ValTypeInt)
109108
}
110109
})
111110
})
112111
}
113112

114113
func (p *Parser) bindBombSites() {
115-
p.stParser.FindServerClassByName("CCSPlayerResource").RegisterEntityCreatedHandler(func(playerResource st.EntityCreatedEvent) {
116-
playerResource.Entity.BindProperty("m_bombsiteCenterA", &p.bombsiteA.center, st.ValTypeVector)
117-
playerResource.Entity.BindProperty("m_bombsiteCenterB", &p.bombsiteB.center, st.ValTypeVector)
114+
p.stParser.ServerClasses().FindByName("CCSPlayerResource").OnEntityCreated(func(playerResource *st.Entity) {
115+
playerResource.BindProperty("m_bombsiteCenterA", &p.bombsiteA.center, st.ValTypeVector)
116+
playerResource.BindProperty("m_bombsiteCenterB", &p.bombsiteB.center, st.ValTypeVector)
118117
})
119118

120-
p.stParser.FindServerClassByName("CBaseTrigger").RegisterEntityCreatedHandler(func(baseTrigger st.EntityCreatedEvent) {
119+
p.stParser.ServerClasses().FindByName("CBaseTrigger").OnEntityCreated(func(baseTrigger *st.Entity) {
121120
t := new(boundingBoxInformation)
122-
p.triggers[baseTrigger.Entity.ID] = t
121+
p.triggers[baseTrigger.ID()] = t
123122

124-
baseTrigger.Entity.BindProperty("m_Collision.m_vecMins", &t.min, st.ValTypeVector)
125-
baseTrigger.Entity.BindProperty("m_Collision.m_vecMaxs", &t.max, st.ValTypeVector)
123+
baseTrigger.BindProperty("m_Collision.m_vecMins", &t.min, st.ValTypeVector)
124+
baseTrigger.BindProperty("m_Collision.m_vecMaxs", &t.max, st.ValTypeVector)
126125
})
127126
}
128127

129128
func (p *Parser) bindPlayers() {
130-
p.stParser.FindServerClassByName("CCSPlayer").RegisterEntityCreatedHandler(func(e st.EntityCreatedEvent) {
131-
p.bindNewPlayer(e.Entity)
129+
p.stParser.ServerClasses().FindByName("CCSPlayer").OnEntityCreated(func(player *st.Entity) {
130+
p.bindNewPlayer(player)
132131
})
133132

134-
p.stParser.FindServerClassByName("CCSPlayerResource").RegisterEntityCreatedHandler(func(pr st.EntityCreatedEvent) {
133+
p.stParser.ServerClasses().FindByName("CCSPlayerResource").OnEntityCreated(func(plInfo *st.Entity) {
135134
for i := 0; i < maxPlayers; i++ {
136135
i2 := i // Copy so it stays the same (for passing to handlers)
137136
iStr := fmt.Sprintf("%03d", i)
138137

139-
pr.Entity.BindProperty("m_szClan."+iStr, &p.additionalPlayerInfo[i2].ClanTag, st.ValTypeString)
140-
pr.Entity.BindProperty("m_iPing."+iStr, &p.additionalPlayerInfo[i2].Ping, st.ValTypeInt)
141-
pr.Entity.BindProperty("m_iScore."+iStr, &p.additionalPlayerInfo[i2].Score, st.ValTypeInt)
142-
pr.Entity.BindProperty("m_iKills."+iStr, &p.additionalPlayerInfo[i2].Kills, st.ValTypeInt)
143-
pr.Entity.BindProperty("m_iDeaths."+iStr, &p.additionalPlayerInfo[i2].Deaths, st.ValTypeInt)
144-
pr.Entity.BindProperty("m_iAssists."+iStr, &p.additionalPlayerInfo[i2].Assists, st.ValTypeInt)
145-
pr.Entity.BindProperty("m_iMVPs."+iStr, &p.additionalPlayerInfo[i2].MVPs, st.ValTypeInt)
146-
pr.Entity.BindProperty("m_iTotalCashSpent."+iStr, &p.additionalPlayerInfo[i2].TotalCashSpent, st.ValTypeInt)
138+
plInfo.BindProperty("m_szClan."+iStr, &p.additionalPlayerInfo[i2].ClanTag, st.ValTypeString)
139+
plInfo.BindProperty("m_iPing."+iStr, &p.additionalPlayerInfo[i2].Ping, st.ValTypeInt)
140+
plInfo.BindProperty("m_iScore."+iStr, &p.additionalPlayerInfo[i2].Score, st.ValTypeInt)
141+
plInfo.BindProperty("m_iKills."+iStr, &p.additionalPlayerInfo[i2].Kills, st.ValTypeInt)
142+
plInfo.BindProperty("m_iDeaths."+iStr, &p.additionalPlayerInfo[i2].Deaths, st.ValTypeInt)
143+
plInfo.BindProperty("m_iAssists."+iStr, &p.additionalPlayerInfo[i2].Assists, st.ValTypeInt)
144+
plInfo.BindProperty("m_iMVPs."+iStr, &p.additionalPlayerInfo[i2].MVPs, st.ValTypeInt)
145+
plInfo.BindProperty("m_iTotalCashSpent."+iStr, &p.additionalPlayerInfo[i2].TotalCashSpent, st.ValTypeInt)
147146
}
148147
})
149148
}
150149

151150
func (p *Parser) bindNewPlayer(playerEntity *st.Entity) {
152151
var pl *common.Player
153-
playerIndex := playerEntity.ID - 1
152+
playerIndex := playerEntity.ID() - 1
154153
if p.entityIDToPlayers[playerIndex] != nil {
155154
pl = p.entityIDToPlayers[playerIndex]
156155
} else {
@@ -160,18 +159,18 @@ func (p *Parser) bindNewPlayer(playerEntity *st.Entity) {
160159
pl.Name = "unconnected"
161160
}
162161

163-
pl.EntityID = playerEntity.ID
162+
pl.EntityID = playerEntity.ID()
164163
pl.Entity = playerEntity
165164

166165
// Position
167-
playerEntity.FindProperty("cslocaldata.m_vecOrigin").OnUpdate(func(val st.PropValue) {
166+
playerEntity.FindProperty("cslocaldata.m_vecOrigin").OnUpdate(func(val st.PropertyValue) {
168167
pl.Position.X = val.VectorVal.X
169168
pl.Position.Y = val.VectorVal.Y
170169
})
171170
playerEntity.BindProperty("cslocaldata.m_vecOrigin[2]", &pl.Position.Z, st.ValTypeFloat64)
172171

173172
// General info
174-
playerEntity.FindProperty("m_iTeamNum").OnUpdate(func(val st.PropValue) {
173+
playerEntity.FindProperty("m_iTeamNum").OnUpdate(func(val st.PropertyValue) {
175174
pl.Team = common.Team(val.IntVal) // Need to cast to team so we can't use BindProperty
176175
})
177176
playerEntity.BindProperty("m_iHealth", &pl.Hp, st.ValTypeInt)
@@ -195,19 +194,19 @@ func (p *Parser) bindNewPlayer(playerEntity *st.Entity) {
195194
playerEntity.BindProperty("m_unRoundStartEquipmentValue", &pl.RoundStartEquipmentValue, st.ValTypeInt)
196195
playerEntity.BindProperty("m_unFreezetimeEndEquipmentValue", &pl.FreezetimeEndEquipmentValue, st.ValTypeInt)
197196

198-
// Weapons
199-
wepPrefix := playerWeaponPrePrefix + playerWeaponPrefix
200-
for _, prop := range playerEntity.Props() {
201-
if prop.Entry().Name() == playerWeaponPrefix+"000" {
202-
wepPrefix = playerWeaponPrefix
203-
break
204-
}
197+
// Some demos have an additional prefix for player weapons weapon
198+
var wepPrefix string
199+
if playerEntity.FindProperty(playerWeaponPrefix+"000") != nil {
200+
wepPrefix = playerWeaponPrefix
201+
} else {
202+
wepPrefix = playerWeaponPrePrefix + playerWeaponPrefix
205203
}
206204

205+
// Weapons
207206
var cache [maxWeapons]int
208207
for i := range cache {
209208
i2 := i // Copy for passing to handler
210-
playerEntity.FindProperty(wepPrefix + fmt.Sprintf("%03d", i)).OnUpdate(func(val st.PropValue) {
209+
playerEntity.FindProperty(wepPrefix + fmt.Sprintf("%03d", i)).OnUpdate(func(val st.PropertyValue) {
211210
entityID := val.IntVal & indexMask
212211
if entityID != indexMask {
213212
if cache[i2] != 0 {
@@ -232,7 +231,7 @@ func (p *Parser) bindNewPlayer(playerEntity *st.Entity) {
232231
}
233232

234233
// Active weapon
235-
playerEntity.FindProperty("m_hActiveWeapon").OnUpdate(func(val st.PropValue) {
234+
playerEntity.FindProperty("m_hActiveWeapon").OnUpdate(func(val st.PropertyValue) {
236235
pl.ActiveWeaponID = val.IntVal & indexMask
237236
})
238237

@@ -244,12 +243,13 @@ func (p *Parser) bindNewPlayer(playerEntity *st.Entity) {
244243

245244
func (p *Parser) bindWeapons() {
246245
for _, sc := range p.stParser.ServerClasses() {
247-
for _, bc := range sc.BaseClasses {
248-
switch bc.Name {
246+
for _, bc := range sc.BaseClasses() {
247+
switch bc.Name() {
249248
case "CWeaponCSBase":
250-
sc.RegisterEntityCreatedHandler(p.bindWeapon)
249+
sc2 := sc // Local copy for loop
250+
sc.OnEntityCreated(func(e *st.Entity) { p.bindWeapon(e, p.equipmentMapping[sc2]) })
251251
case "CBaseGrenade": // Grenade that has been thrown by player.
252-
sc.RegisterEntityCreatedHandler(p.bindGrenadeProjectiles)
252+
sc.OnEntityCreated(p.bindGrenadeProjectiles)
253253
case "CBaseCSGrenade":
254254
// @micvbang TODO: handle grenades dropped by dead player.
255255
// Grenades that were dropped by a dead player (and can be picked up by other players).
@@ -261,45 +261,46 @@ func (p *Parser) bindWeapons() {
261261

262262
// bindGrenadeProjectiles keeps track of the location of live grenades (Parser.gameState.grenadeProjectiles), actively thrown by players.
263263
// It does NOT track the location of grenades lying on the ground, i.e. that were dropped by dead players.
264-
func (p *Parser) bindGrenadeProjectiles(event st.EntityCreatedEvent) {
265-
p.gameState.grenadeProjectiles[event.Entity.ID] = common.NewGrenadeProjectile()
264+
func (p *Parser) bindGrenadeProjectiles(entity *st.Entity) {
265+
entityID := entity.ID()
266+
p.gameState.grenadeProjectiles[entityID] = common.NewGrenadeProjectile()
266267

267-
event.Entity.OnDestroy(func() {
268-
delete(p.gameState.grenadeProjectiles, event.Entity.ID)
268+
entity.OnDestroy(func() {
269+
delete(p.gameState.grenadeProjectiles, entityID)
269270
})
270271

271-
proj := p.gameState.grenadeProjectiles[event.Entity.ID]
272-
proj.EntityID = event.Entity.ID
272+
proj := p.gameState.grenadeProjectiles[entityID]
273+
proj.EntityID = entityID
273274

274-
event.Entity.FindProperty("m_nModelIndex").OnUpdate(func(val st.PropValue) {
275+
entity.FindProperty("m_nModelIndex").OnUpdate(func(val st.PropertyValue) {
275276
proj.Weapon = p.grenadeModelIndices[val.IntVal]
276277
})
277278

278279
// @micvbang: not quite sure what the difference between Thrower and Owner is.
279-
event.Entity.FindProperty("m_hThrower").OnUpdate(func(val st.PropValue) {
280+
entity.FindProperty("m_hThrower").OnUpdate(func(val st.PropertyValue) {
280281
throwerID := val.IntVal & indexMask
281282
throwerIndex := throwerID - 1
282283

283284
thrower := p.entityIDToPlayers[throwerIndex]
284285
proj.Thrower = thrower
285286
})
286287

287-
event.Entity.FindProperty("m_hOwnerEntity").OnUpdate(func(val st.PropValue) {
288+
entity.FindProperty("m_hOwnerEntity").OnUpdate(func(val st.PropertyValue) {
288289
ownerID := val.IntVal & indexMask
289290
ownerIndex := ownerID - 1
290291
player := p.entityIDToPlayers[ownerIndex]
291292
proj.Owner = player
292293
})
293294

294-
event.Entity.FindProperty("m_vecOrigin").OnUpdate(func(st.PropValue) {
295-
proj.Position = event.Entity.Position()
295+
entity.FindProperty("m_vecOrigin").OnUpdate(func(st.PropertyValue) {
296+
proj.Position = entity.Position()
296297
})
297298

298299
// Some demos don't have this property as it seems
299300
// So we need to check for nil and can't send out bounce events if it's missing
300-
bounceProp := event.Entity.FindProperty("m_nBounces")
301+
bounceProp := entity.FindProperty("m_nBounces")
301302
if bounceProp != nil {
302-
bounceProp.OnUpdate(func(val st.PropValue) {
303+
bounceProp.OnUpdate(func(val st.PropertyValue) {
303304
if val.IntVal != 0 {
304305
p.eventDispatcher.Dispatch(events.NadeProjectileBouncedEvent{
305306
Projectile: proj,
@@ -309,29 +310,30 @@ func (p *Parser) bindGrenadeProjectiles(event st.EntityCreatedEvent) {
309310
})
310311
}
311312

312-
event.Entity.OnCreateFinished(func() {
313+
entity.OnCreateFinished(func() {
313314
p.eventDispatcher.Dispatch(events.NadeProjectileThrownEvent{
314315
Projectile: proj,
315316
})
316317
})
317318
}
318319

319-
func (p *Parser) bindWeapon(event st.EntityCreatedEvent) {
320-
p.weapons[event.Entity.ID] = common.NewEquipment("")
321-
eq := &p.weapons[event.Entity.ID]
322-
eq.EntityID = event.Entity.ID
323-
eq.Weapon = p.equipmentMapping[event.ServerClass]
320+
func (p *Parser) bindWeapon(entity *st.Entity, wepType common.EquipmentElement) {
321+
entityID := entity.ID()
322+
p.weapons[entityID] = common.NewEquipment("")
323+
eq := &p.weapons[entityID]
324+
eq.EntityID = entityID
325+
eq.Weapon = wepType
324326
eq.AmmoInMagazine = -1
325327

326-
event.Entity.FindProperty("m_iClip1").OnUpdate(func(val st.PropValue) {
328+
entity.FindProperty("m_iClip1").OnUpdate(func(val st.PropertyValue) {
327329
eq.AmmoInMagazine = val.IntVal - 1
328330
})
329331

330-
event.Entity.BindProperty("LocalWeaponData.m_iPrimaryAmmoType", &eq.AmmoType, st.ValTypeInt)
332+
entity.BindProperty("LocalWeaponData.m_iPrimaryAmmoType", &eq.AmmoType, st.ValTypeInt)
331333

332334
// Detect alternative weapons (P2k -> USP, M4A4 -> M4A1-S etc.)
333335
wepFix := func(defaultName, altName string, alt common.EquipmentElement) {
334-
event.Entity.FindProperty("m_nModelIndex").OnUpdate(func(val st.PropValue) {
336+
entity.FindProperty("m_nModelIndex").OnUpdate(func(val st.PropertyValue) {
335337
eq.OriginalString = p.modelPreCache[val.IntVal]
336338
// Check 'altName' first because otherwise the m4a1_s is recognized as m4a4
337339
if strings.Contains(eq.OriginalString, altName) {

entities.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
bit "github.com/markus-wa/demoinfocs-golang/bitread"
77
msg "github.com/markus-wa/demoinfocs-golang/msg"
8-
st "github.com/markus-wa/demoinfocs-golang/sendtables"
98
)
109

1110
const entitySentinel = 9999
@@ -35,10 +34,7 @@ func (p *Parser) handlePacketEntities(pe *msg.CSVCMsg_PacketEntities) {
3534
} else {
3635
if r.ReadBit() {
3736
// Enter PVS
38-
e := p.readEnterPVS(r, currentEntity)
39-
p.entities[currentEntity] = e
40-
e.ApplyUpdate(r)
41-
e.ServerClass.FireEntityCreatedEvent(e)
37+
p.entities[currentEntity] = p.stParser.ReadEnterPVS(r, currentEntity)
4238
} else {
4339
// Delta Update
4440
p.entities[currentEntity].ApplyUpdate(r)
@@ -47,24 +43,3 @@ func (p *Parser) handlePacketEntities(pe *msg.CSVCMsg_PacketEntities) {
4743
}
4844
r.Pool()
4945
}
50-
51-
func (p *Parser) readEnterPVS(reader *bit.BitReader, entityID int) *st.Entity {
52-
scID := int(reader.ReadInt(p.stParser.ClassBits()))
53-
reader.Skip(10) // Serial Number
54-
55-
newEntity := st.NewEntity(entityID, p.stParser.ServerClasses()[scID])
56-
57-
if p.preprocessedBaselines[scID] != nil {
58-
newEntity.ApplyBaseline(p.preprocessedBaselines[scID])
59-
} else {
60-
if p.instanceBaselines[scID] != nil {
61-
r := bit.NewSmallBitReader(bytes.NewReader(p.instanceBaselines[scID]))
62-
p.preprocessedBaselines[scID] = newEntity.InitializeBaseline(r)
63-
r.Pool()
64-
} else {
65-
p.preprocessedBaselines[scID] = make(map[int]st.PropValue)
66-
}
67-
}
68-
69-
return newEntity
70-
}

0 commit comments

Comments
 (0)