Skip to content

Commit 3bdf6df

Browse files
committed
Improved the tracker events processing.
Tracker Events now provide: unit.owner player.units unit.started_at unit.finished_at unit.died_at
1 parent a28df92 commit 3bdf6df

File tree

6 files changed

+74
-20
lines changed

6 files changed

+74
-20
lines changed

sc2reader/data/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@
2626
class Unit(object):
2727

2828
def __init__(self, unit_id, flags):
29+
#: A reference to the player that owns this unit
30+
self.owner = None
31+
32+
#: The frame the unit was started at
33+
self.started_at = None
34+
35+
#: The frame the unit was finished at
36+
self.finished_at = None
37+
38+
#: The frame the unit died at
39+
self.died_at = None
40+
2941
self.id = unit_id
3042
self.flags = flags
3143
self._type_class = None

sc2reader/events/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def load_context(self, replay):
1919
if replay.versions[1]==1 or (replay.versions[1]==2 and replay.build < 24247):
2020
if self.pid <= len(replay.people):
2121
self.player = replay.person[self.pid]
22+
self.player.events.append(self)
2223
elif self.pid != 16:
2324
self.logger.error("Bad pid ({0}) for event {1} at {2}.".format(self.pid, self.__class__, Length(seconds=self.second)))
2425
else:
@@ -27,6 +28,7 @@ def load_context(self, replay):
2728
else:
2829
if self.pid < len(replay.clients):
2930
self.player = replay.client[self.pid]
31+
self.player.events.append(self)
3032
elif self.pid != 16:
3133
self.logger.error("Bad pid ({0}) for event {1} at {2}.".format(self.pid, self.__class__, Length(seconds=self.second)))
3234
else:

sc2reader/events/tracker.py

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
# -*- coding: utf-8 -*-
22
import json
3+
from sc2reader.utils import Length
34

45
class TrackerEvent(object):
56
def __init__(self, frames):
67
#: The frame of the game this event was applied
78
self.frame = frames
89

9-
def __str__(self):
10-
""" Dumps the event data to a json string. """
11-
return json.dumps(self.__dict__)
12-
1310
def load_context(self, replay):
1411
pass
1512

13+
def _str_prefix(self):
14+
return "{0}\t ".format(Length(seconds=int(self.frame/16)))
15+
16+
def __str__(self):
17+
return self._str_prefix() + self.name
1618

1719
class PlayerStatsEvent(TrackerEvent):
1820
name = 'PlayerStatsEvent'
@@ -131,6 +133,8 @@ def __init__(self, frames, data):
131133
def load_context(self, replay):
132134
self.player = replay.player[self.pid]
133135

136+
def __str__(self):
137+
return self._str_prefix()+"{0: >15} - Stats Update".format(self.player)
134138

135139
class UnitBornEvent(TrackerEvent):
136140
name = 'UnitBornEvent'
@@ -195,9 +199,15 @@ def load_context(self, replay):
195199

196200
replay.active_units[self.unit_id_index] = self.unit
197201
self.unit.location = self.location
198-
self.unit.birth = self.frame
199-
self.unit.owner = self.unit_upkeeper
202+
self.unit.started_at = self.frame
203+
self.unit.finished_at = self.frame
204+
205+
if self.unit_upkeeper:
206+
self.unit.owner = self.unit_upkeeper
207+
self.unit.owner.units.append(self.unit)
200208

209+
def __str__(self):
210+
return self._str_prefix()+"{0: >15} - Unit born {1}".format(self.unit_upkeeper,self.unit)
201211

202212
class UnitDiedEvent(TrackerEvent):
203213
name = 'UnitDiedEvent'
@@ -235,7 +245,7 @@ def __init__(self, frames, data):
235245
def load_context(self, replay):
236246
if self.unit_id in replay.objects:
237247
self.unit = replay.objects[self.unit_id]
238-
self.unit.death = self.frame
248+
self.unit.died_at = self.frame
239249
self.unit.location = self.location
240250
if self.unit_id_index in replay.active_units:
241251
del replay.active_units[self.unit_id_index]
@@ -249,6 +259,9 @@ def load_context(self, replay):
249259
elif self.killer_pid:
250260
pass#print "Unknown killer pid", self.killer_pid
251261

262+
def __str__(self):
263+
return self._str_prefix()+"{0: >15} - Unit died {1}.".format(self.unit.owner, self.unit)
264+
252265

253266
class UnitOwnerChangeEvent(TrackerEvent):
254267
name = 'UnitOwnerChangeEvent'
@@ -293,10 +306,19 @@ def load_context(self, replay):
293306

294307
if self.unit_id in replay.objects:
295308
self.unit = replay.objects[self.unit_id]
296-
self.unit.owner = self.unit_upkeeper
297309
else:
298310
print "Unit owner changed before it was born!"
299311

312+
if self.unit_upkeeper:
313+
if unit.owner:
314+
print "stduff"
315+
unit.owner.units.remove(unit)
316+
unit.owner = self.unit_upkeeper
317+
self.unit_upkeeper.units.append(unit)
318+
319+
def __str__(self):
320+
return self._str_prefix()+"{0: >15} took {1}".format(self.unit_upkeeper, self.unit)
321+
300322

301323
class UnitTypeChangeEvent(TrackerEvent):
302324
name = 'UnitTypeChangeEvent'
@@ -326,6 +348,9 @@ def load_context(self, replay):
326348
else:
327349
print "Unit type changed before it was born!"
328350

351+
def __str__(self):
352+
return self._str_prefix()+"{0: >15} - Unit {0} type changed to {1}".format(self.unit.owner, self.unit, self.unit_type_name)
353+
329354

330355
class UpgradeCompleteEvent(TrackerEvent):
331356
name = 'UpgradeCompleteEvent'
@@ -354,6 +379,8 @@ def load_context(self, replay):
354379
# TODO: We don't have upgrade -> ability maps
355380
# TODO: we can probably do the same thing we did for units
356381

382+
def __str__(self):
383+
return self._str_prefix()+"{0: >15} - {1}upgrade completed".format(self.player, self.upgrade_type_name)
357384

358385
class UnitInitEvent(TrackerEvent):
359386
name = 'UnitInitEvent'
@@ -419,9 +446,16 @@ def load_context(self, replay):
419446
replay.objects[self.unit_id] = self.unit
420447

421448
replay.active_units[self.unit_id_index] = self.unit
422-
self.unit.owner = self.unit_upkeeper
423449
self.unit.location = self.location
424-
self.unit.birth = self.frame
450+
self.unit.started_at = self.frame
451+
# self.unit.finished_at = self.frame
452+
453+
if self.unit_upkeeper:
454+
self.unit.owner = self.unit_upkeeper
455+
self.unit.owner.units.append(self.unit)
456+
457+
def __str__(self):
458+
return self._str_prefix()+"{0: >15} - Unit inititated {1}".format(self.unit_upkeeper, self.unit)
425459

426460

427461
class UnitDoneEvent(TrackerEvent):
@@ -445,9 +479,12 @@ def __init__(self, frames, data):
445479
def load_context(self, replay):
446480
if self.unit_id in replay.objects:
447481
self.unit = replay.objects[self.unit_id]
482+
self.unit.finished_at = self.frame
448483
else:
449484
print "Unit done before it was started!"
450485

486+
def __str__(self):
487+
return self._str_prefix()+"{0: >15} - Unit {1} done".format(self.unit.owner, self.unit)
451488

452489
class UnitPositionsEvent(TrackerEvent):
453490
name = 'UnitPositionsEvent'
@@ -482,3 +519,6 @@ def load_context(self, replay):
482519
self.units.append(unit)
483520
else:
484521
print "Unit moved that doesn't exist!"
522+
523+
def __str__(self):
524+
return self._str_prefix()+"Unit positions update"

sc2reader/objects.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ def __init__(self, pid, name):
201201
super(Player,self).__init__(pid, name)
202202
self.is_observer = False
203203

204+
#: A list of references to the units the player had this game
205+
self.units = list()
206+
207+
204208
@property
205209
def url(self):
206210
"""The player's battle.net profile url"""

sc2reader/plugins/replay.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ def SelectionTracker(replay):
115115
player_selections = GameState(PlayerSelection())
116116
for event in person.events:
117117
error = False
118-
119118
if event.name == 'SelectionEvent':
120119
selections = player_selections[event.frame]
121120
control_group = selections[event.control_group].copy()

sc2reader/resources.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ def __init__(self, replay_file, filename=None, load_level=4, **options):
281281
for event in self.events:
282282
event.load_context(self)
283283

284+
284285
def load_details(self):
285286
if 'replay.attributes.events' in self.raw_data:
286287
# Organize the attribute data to be useful
@@ -475,21 +476,17 @@ def load_messages(self):
475476
def load_events(self):
476477
# Copy the events over
477478
# TODO: the events need to be fixed both on the reader and processor side
478-
if 'replay.game.events' in self.raw_data:
479-
self.game_events = self.raw_data['replay.game.events']
480-
self.events = sorted(self.game_events+self.events, key=lambda e: e.frame)
479+
if 'replay.game.events' not in self.raw_data:
480+
return
481+
482+
self.game_events = self.raw_data['replay.game.events']
483+
self.events = sorted(self.game_events+self.events, key=lambda e: e.frame)
481484

482485
# hideous hack for HotS 2.0.0.23925, see https://github.com/GraylinKim/sc2reader/issues/87
483486
if self.events and self.events[-1].frame > self.frames:
484487
self.frames = self.events[-1].frame
485488
self.length = utils.Length(seconds=int(self.frames/self.game_fps))
486489

487-
self.camera_events = list()
488-
self.selection_events = list()
489-
self.ability_events = list()
490-
for event in self.events:
491-
if event.pid != 16 and hasattr(event,'player'):
492-
event.player.events.append(event)
493490

494491
def load_tracker_events(self):
495492
if 'replay.tracker.events' not in self.raw_data:

0 commit comments

Comments
 (0)