Skip to content

Commit 9780cbc

Browse files
committed
Add the tracker events at the new location.
1 parent 14fb33c commit 9780cbc

File tree

2 files changed

+326
-0
lines changed

2 files changed

+326
-0
lines changed

sc2reader/events/tracker.py

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
# -*- coding: utf-8 -*-
2+
import json
3+
4+
class TrackerEvent(object):
5+
def __init__(self, frames):
6+
self.frame = frames
7+
8+
def __str__(self):
9+
return json.dumps(self.__dict__)
10+
11+
class PlayerStatsEvent(TrackerEvent):
12+
name = 'PlayerStatsEvent'
13+
14+
def __init__(self, frames, data):
15+
super(PlayerStatsEvent, self).__init__(frames)
16+
17+
#: Id of the player the stats are for
18+
self.pid = data[0]
19+
20+
#: An ordered list of all the available stats
21+
self.stats = data[1]
22+
23+
#: Minerals currently available to the player
24+
self.minerals_current = self.stats[0]
25+
26+
#: Vespene currently available to the player
27+
self.vespene_current = self.stats[1]
28+
29+
#: The rate the player is collecting minerals
30+
self.minerals_collection_rate = self.stats[2]
31+
32+
#: The rate the player is collecting vespene
33+
self.vespene_collection_rate = self.stats[3]
34+
35+
#: The number of active workers the player has
36+
self.workers_active_count = self.stats[4]
37+
38+
#: The total mineral cost of army units (buildings?) currently being built/queued
39+
self.minerals_used_in_progress_army = self.stats[5]
40+
41+
#: The total mineral cost of economy units (buildings?) currently being built/queued
42+
self.minerals_used_in_progress_economy = self.stats[6]
43+
44+
#: The total mineral cost of technology research (buildings?) currently being built/queued
45+
self.minerals_used_in_process_technology = self.stats[7]
46+
47+
#: The total vespene cost of army units (buildings?) currently being built/queued
48+
self.vespene_used_in_progress_army = self.stats[8]
49+
50+
#: The total vespene cost of economy units (buildings?) currently being built/queued.
51+
self.vespene_used_in_progress_economy = self.stats[9]
52+
53+
#: The total vespene cost of technology research (buildings?) currently being built/queued.
54+
self.vespene_used_in_progress_technology = self.stats[10]
55+
56+
#: The total mineral cost of current army units (buildings?)
57+
self.minerals_used_current_army = self.stats[11]
58+
59+
#: The total mineral cost of current economy units (buildings?)
60+
self.minerals_used_current_economy = self.stats[12]
61+
62+
#: The total mineral cost of current technology research (buildings?)
63+
self.minerals_used_current_technology = self.stats[13]
64+
65+
#: The total vespene cost of current army units (buildings?)
66+
self.vespene_used_current_army = self.stats[14]
67+
68+
#: The total vespene cost of current economy units (buildings?)
69+
self.vespene_used_current_economy = self.stats[15]
70+
71+
#: The total vespene cost of current technology research (buildings?)
72+
self.vespene_used_current_technology = self.stats[16]
73+
74+
#: The total mineral cost of all army units (buildings?) lost
75+
self.minerals_lost_army = self.stats[17]
76+
77+
#: The total minerals cost of all economy units (buildings?) lost
78+
self.minerals_lost_economy = self.stats[18]
79+
80+
#: The total minerals cost of all technology research (buildings?) lost
81+
self.minerals_lost_technology = self.stats[19]
82+
83+
#: The total vespene cost of all army units (buildings?) lost
84+
self.vespene_lost_army = self.stats[20]
85+
86+
#: The total vespene cost of all economy units (buildings?) lost
87+
self.vespene_lost_economy = self.stats[21]
88+
89+
#: The total vespene cost of all technology research (buildings?) lost
90+
self.vespene_lost_technology = self.stats[22]
91+
92+
#: The total mineral value of enemy army units (buildings?) killed
93+
self.minerals_killed_army = self.stats[23]
94+
95+
#: The total mineral value of enemy economy units (buildings?) killed
96+
self.minerals_killed_economy = self.stats[24]
97+
98+
#: The total mineral value of enemy technology research (buildings?) killed
99+
self.minerals_killed_technology = self.stats[25]
100+
101+
#: The total vespene value of enemy army units (buildings?) killed
102+
self.vespene_killed_army = self.stats[26]
103+
104+
#: The total vespene value of enemy economy units (buildings?) killed
105+
self.vespene_killed_economy = self.stats[27]
106+
107+
#: The total vespene value of enemy technology research (buildings?) killed
108+
self.vespene_killed_technology = self.stats[28]
109+
110+
#: The food supply currently used
111+
self.food_used = self.stats[29]
112+
113+
#: The food supply currently available
114+
self.food_made = self.stats[30]
115+
116+
#: The total mineral value of all active forces
117+
self.minerals_used_active_forces = self.stats[31]
118+
119+
#: The total vespene value of all active forces
120+
self.vespene_used_active_forces = self.stats[32]
121+
122+
class UnitBornEvent(TrackerEvent):
123+
name = 'UnitBornEvent'
124+
125+
def __init__(self, frames, data):
126+
super(UnitBornEvent, self).__init__(frames)
127+
128+
#: The index portion of the unit id
129+
self.unit_id_index = data[0]
130+
131+
#: The recycle portion of the unit id
132+
self.unit_id_recycle = data[1]
133+
134+
#: The unique id of the unit being born
135+
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
136+
137+
#: The unit type name of the unit being born
138+
self.unit_type_name = data[2]
139+
140+
#: The id of the player that controls this unit.
141+
self.control_pid = data[3]
142+
143+
#: The id of the player that pays upkeep for this unit.
144+
self.upkeep_pid = data[4]
145+
146+
#: The x coordinate of the location
147+
self.x = data[5]
148+
149+
#: The y coordinate of the location
150+
self.y = data[6]
151+
152+
#: The map location of the unit birth
153+
self.location = (self.x, self.y)
154+
155+
156+
class UnitDiedEvent(TrackerEvent):
157+
name = 'UnitDiedEvent'
158+
159+
def __init__(self, frames, data):
160+
super(UnitDiedEvent, self).__init__(frames)
161+
162+
#: The index portion of the unit id
163+
self.unit_id_index = data[0]
164+
165+
#: The recycle portion of the unit id
166+
self.unit_id_recycle = data[1]
167+
168+
#: The unique id of the unit being killed
169+
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
170+
171+
#: The id of the player that killed this unit. None when not available.
172+
self.killer_pid = data[2]
173+
174+
#: The x coordinate of the location
175+
self.x = data[3]
176+
177+
#: The y coordinate of the location
178+
self.y = data[4]
179+
180+
#: The map location the unit was killed at.
181+
self.location = (self.x, self.y)
182+
183+
184+
class UnitOwnerChangeEvent(TrackerEvent):
185+
name = 'UnitOwnerChangeEvent'
186+
187+
def __init__(self, frames, data):
188+
super(UnitOwnerChangeEvent, self).__init__(frames)
189+
190+
#: The index portion of the unit id
191+
self.unit_id_index = data[0]
192+
193+
#: The recycle portion of the unit id
194+
self.unit_id_recycle = data[1]
195+
196+
#: The unique id of the unit changing ownership
197+
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
198+
199+
#: The new id of the player that controls this unit.
200+
self.control_pid = data[2]
201+
202+
#: The new id of the player that pays upkeep for this unit.
203+
self.upkeep_pid = data[3]
204+
205+
fields = ['unit_tag_index','unit_tag_recycle','control_player_id','upkeep_player_id']
206+
207+
class UnitTypeChangeEvent(TrackerEvent):
208+
name = 'UnitTypeChangeEvent'
209+
210+
def __init__(self, frames, data):
211+
super(UnitTypeChangeEvent, self).__init__(frames)
212+
213+
#: The index portion of the unit id
214+
self.unit_id_index = data[0]
215+
216+
#: The recycle portion of the unit id
217+
self.unit_id_recycle = data[1]
218+
219+
#: The unique id of the unit changing type
220+
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
221+
222+
#: The the new unit type name
223+
self.unit_type_name = data[2]
224+
225+
class UpgradeCompleteEvent(TrackerEvent):
226+
name = 'UpgradeCompleteEvent'
227+
228+
def __init__(self, frames, data):
229+
super(UpgradeCompleteEvent, self).__init__(frames)
230+
231+
#: The player that completed the upgrade
232+
self.pid = data[0]
233+
234+
#: The name of the upgrade
235+
self.upgrade_type_name = data[1]
236+
237+
#: The number of times this upgrade as been researched
238+
self.count = data[2]
239+
240+
class UnitInitEvent(TrackerEvent):
241+
name = 'UnitInitEvent'
242+
243+
def __init__(self, frames, data):
244+
super(UnitInitEvent, self).__init__(frames)
245+
246+
#: The index portion of the unit id
247+
self.unit_id_index = data[0]
248+
249+
#: The recycle portion of the unit id
250+
self.unit_id_recycle = data[1]
251+
252+
#: The unique id of the stated unit
253+
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
254+
255+
#: The id of the player that controls this unit.
256+
self.control_pid = data[2]
257+
258+
#: The id of the player that pays upkeep for this unit.
259+
self.upkeep_pid = data[3]
260+
261+
#: The x coordinate of the location
262+
self.x = data[4]
263+
264+
#: The y coordinate of the location
265+
self.y = data[5]
266+
267+
#: The map location the unit was started at
268+
self.location = (self.x, self.y)
269+
270+
class UnitDoneEvent(TrackerEvent):
271+
name = 'UnitDoneEvent'
272+
273+
def __init__(self, frames, data):
274+
super(UnitDoneEvent, self).__init__(frames)
275+
276+
#: The index portion of the unit id
277+
self.unit_id_index = data[0]
278+
279+
#: The recycle portion of the unit id
280+
self.unit_id_recycle = data[1]
281+
282+
#: The unique id of the finished unit
283+
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
284+
285+
class UnitPositionsEvent(TrackerEvent):
286+
name = 'UnitPositionsEvent'
287+
288+
def __init__(self, frames, data):
289+
super(UnitPositionsEvent, self).__init__(frames)
290+
291+
#: ???
292+
self.first_unit_index = data[0]
293+
294+
#: ???
295+
self.items = data[1]

sc2reader/readers.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from sc2reader.objects import *
1111
from sc2reader.events.game import *
1212
from sc2reader.events.message import *
13+
from sc2reader.events.tracker import *
1314
from sc2reader.utils import AttributeDict
1415
from sc2reader.decoders import BitPackedDecoder, ByteDecoder
1516

@@ -839,3 +840,33 @@ def player_selection_event(self, data, fstamp, pid, event_type):
839840
class GameEventsReader_Beta_23925(GameEventsReader_Beta):
840841
PLAYER_JOIN_FLAGS = 32
841842

843+
844+
class TrackerEventsReader_Base(Reader):
845+
846+
def __init__(self):
847+
self.EVENT_DISPATCH = {
848+
0: PlayerStatsEvent,
849+
1: UnitBornEvent,
850+
2: UnitDiedEvent,
851+
3: UnitOwnerChangeEvent,
852+
4: UnitTypeChangeEvent,
853+
5: UpgradeCompleteEvent,
854+
6: UnitInitEvent,
855+
7: UnitDoneEvent,
856+
8: UnitPositionsEvent,
857+
}
858+
859+
def __call__(self, data, replay):
860+
decoder = BitPackedDecoder(data)
861+
862+
frames = 0
863+
events = list()
864+
while not decoder.done():
865+
frames += decoder.read_struct()
866+
etype = decoder.read_struct()
867+
event_data = decoder.read_struct()
868+
event = self.EVENT_DISPATCH[etype](frames, event_data)
869+
events.append(event)
870+
871+
return events
872+

0 commit comments

Comments
 (0)