Skip to content

Commit a15e713

Browse files
committed
Add 1.4.0 support.
1 parent ceb6d42 commit a15e713

File tree

3 files changed

+134
-150
lines changed

3 files changed

+134
-150
lines changed

sc2reader/config.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,39 @@ def __init__(self):
8383
'replay.game.events': GameEventsReader_18574(),
8484
}
8585

86+
self.set5 = {
87+
'replay.initData': InitDataReader(),
88+
'replay.details': DetailsReader(),
89+
'replay.attributes.events': AttributeEventsReader_17326(),
90+
'replay.message.events': MessageEventsReader(),
91+
'replay.game.events': GameEventsReader_19595(),
92+
}
93+
94+
# 1.0.0-3
8695
for key in (16117,16195,16223,16291):
8796
self[key] = self.set1
8897

98+
# 1.1.0-3
8999
for key in (16561,16605,16755,16939):
90100
self[key] = self.set2
91101

102+
# 1.2.0-1.3.2
92103
for key in (17326,17682,17811,18092,18221,18317):
93104
self[key] = self.set3
94105

95-
for key in (18574,):
106+
# 1.3.3-1.3.6
107+
for key in (18574,18701,19132,19269):
96108
self[key] = self.set4
97109

110+
# 1.4beta, 1.4.0
111+
for key in (19595,19679):
112+
self[key] = self.set5
113+
98114
def __getitem__(self,key):
99115
try:
100116
return super(ReaderMap,self).__getitem__(key)
117+
# Keep using the latest dict for all newer replay versions
101118
except KeyError:
102-
return self.set4
119+
return self.set5
103120

104121
readers = ReaderMap()

sc2reader/parsers.py

Lines changed: 111 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -72,92 +72,6 @@ def read_resource(buffer):
7272
return ResourceTransferEvent(frames, pid, type, code, target, minerals, vespene)
7373

7474
class ActionParser_16561(ActionParser):
75-
def parse_ability_event(self, buffer, frames, type, code, pid):
76-
flag = buffer.read_byte()
77-
atype = buffer.read_byte()
78-
79-
if atype & 0x20: # command card
80-
end = buffer.peek(35)
81-
ability = buffer.read_short()
82-
83-
if flag in (0x29, 0x19, 0x14): # cancels
84-
# creation autoid number / object id
85-
ability = ability << 8 | buffer.read_byte()
86-
created_id = buffer.read_object_id()
87-
# TODO : expose the id
88-
return AbilityEvent(frames, pid, type, code, ability)
89-
90-
else:
91-
ability_flags = buffer.shift(6)
92-
ability = ability << 8 | ability_flags
93-
94-
if ability_flags & 0x10:
95-
# ability(3), coordinates (4), ?? (4)
96-
location = buffer.read_coordinate()
97-
buffer.skip(4)
98-
return LocationAbilityEvent(frames, pid, type, code, ability, location)
99-
100-
elif ability_flags & 0x20:
101-
# ability(3), object id (4), object type (2), ?? (10)
102-
code = buffer.read_short() # code??
103-
obj_id = buffer.read_object_id()
104-
obj_type = buffer.read_object_type()
105-
target = (obj_id, obj_type,)
106-
switch = buffer.read_byte()
107-
buffer.read_hex(9)
108-
return TargetAbilityEvent(frames, pid, type, code, ability, target)
109-
110-
else:
111-
return AbilityEvent(frames,pid,type,code,ability)
112-
113-
elif atype & 0x40: # location/move
114-
if flag == 0x08:
115-
# coordinates (4), ?? (6)
116-
location = buffer.read_coordinate()
117-
buffer.skip(5)
118-
return LocationAbilityEvent(frames, pid, type, code, None, location)
119-
120-
elif flag in (0x04,0x05,0x07):
121-
# print "Made it!"
122-
h = buffer.read_hex(2)
123-
hinge = buffer.read_byte()
124-
if hinge & 0x20:
125-
"\t%s - %s" % (hex(hinge),buffer.read_hex(9))
126-
elif hinge & 0x40:
127-
"\t%s - %s" % (hex(hinge),buffer.read_hex(18))
128-
elif hinge < 0x10:
129-
pass
130-
131-
return UnknownLocationAbilityEvent(frames, pid, type, code, None)
132-
133-
else:
134-
raise ParseError("Unknown atype & 0x40: flag %X at frame %X" % (flag,frames))
135-
136-
elif atype & 0x80: # right-click on target?
137-
# ability (2), object id (4), object type (2), ?? (10)
138-
ability = buffer.read_byte() << 8 | buffer.read_byte()
139-
obj_id = buffer.read_object_id()
140-
obj_type = buffer.read_object_type()
141-
target = (obj_id, obj_type,)
142-
buffer.skip(10)
143-
return TargetAbilityEvent(frames, pid, type, code, ability, target)
144-
145-
elif atype in (0x08,0x0a): #new to patch 1.3.3
146-
#10 bytes total, coordinates have a different format?
147-
#X coordinate definitely is the first byte, with (hopefully) y next
148-
# print hex(flag)
149-
event = UnknownAbilityEvent(frames, pid, type, code, None)
150-
event.location1 = buffer.read_coordinate()
151-
buffer.skip(5)
152-
return event
153-
154-
else:
155-
# print hex(atype)
156-
# print hex(buffer.cursor)
157-
raise ParseError()
158-
159-
# print "%s - %s" % (hex(atype),hex(flag))
160-
raise ParseError("Shouldn't be here EVER!")
16175

16276
def parse_selection_event(self, buffer, frames, type, code, pid):
16377
bank = code >> 4
@@ -212,80 +126,129 @@ def parse_hotkey_event(self, buffer, frames, type, code, pid):
212126
else:
213127
raise ParseError("Hotkey Action '{0}' unknown")
214128

215-
class ActionParser_18574(ActionParser_16561):
129+
def command_card(self, buffer, frames, type, code, pid, flag, atype):
130+
ability = buffer.read_short()
131+
132+
if flag in (0x29, 0x19, 0x14, 0x0c): # cancels
133+
# creation autoid number / object id
134+
ability = ability << 8 | buffer.read_byte()
135+
created_id = buffer.read_object_id()
136+
# TODO : expose the id
137+
return AbilityEvent(frames, pid, type, code, ability)
138+
139+
else:
140+
ability_flags = buffer.shift(6)
141+
ability = ability << 8 | ability_flags
142+
143+
if ability_flags & 0x10:
144+
# ability(3), coordinates (4), ?? (4)
145+
location = buffer.read_coordinate()
146+
buffer.skip(4)
147+
return LocationAbilityEvent(frames, pid, type, code, ability, location)
148+
149+
elif ability_flags & 0x20:
150+
# ability(3), object id (4), object type (2), ?? (10)
151+
code = buffer.read_short() # code??
152+
obj_id = buffer.read_object_id()
153+
obj_type = buffer.read_object_type()
154+
target = (obj_id, obj_type,)
155+
switch = buffer.read_byte()
156+
buffer.read_hex(9)
157+
return TargetAbilityEvent(frames, pid, type, code, ability, target)
158+
159+
else:
160+
return AbilityEvent(frames,pid,type,code,ability)
161+
162+
def location_move(self, buffer, frames, type, code, pid, flag, atype):
163+
h = buffer.read_hex(2)
164+
hinge = buffer.read_byte()
165+
if hinge & 0x20:
166+
"\t%s - %s" % (hex(hinge),buffer.read_hex(9))
167+
elif hinge & 0x40:
168+
"\t%s - %s" % (hex(hinge),buffer.read_hex(18))
169+
elif hinge < 0x10:
170+
pass
171+
else:
172+
pass
173+
174+
return UnknownLocationAbilityEvent(frames, pid, type, code, None)
175+
176+
def right_click_target(self, buffer, frames, type, code, pid, flag, atype):
177+
# ability (2), object id (4), object type (2), ?? (10)
178+
ability = buffer.read_short()
179+
obj_id = buffer.read_object_id()
180+
obj_type = buffer.read_object_type()
181+
target = (obj_id, obj_type,)
182+
buffer.skip(10)
183+
return TargetAbilityEvent(frames, pid, type, code, ability, target)
184+
185+
def right_click_move(self, buffer, frames, type, code, pid, flag, atype):
186+
#10 bytes total, coordinates have a different format?
187+
#X coordinate definitely is the first byte, with (hopefully) y next
188+
location = buffer.read_coordinate()
189+
buffer.skip(5)
190+
return LocationAbilityEvent(frames, pid, type, code, None, location)
191+
216192
def parse_ability_event(self, buffer, frames, type, code, pid):
217193
flag = buffer.read_byte()
218194
atype = buffer.read_byte()
219-
195+
220196
if atype & 0x20: # command card
221-
end = buffer.peek(35)
222-
ability = buffer.read_short()
197+
return self.command_card(buffer, frames, type, code, pid, flag, atype)
198+
elif atype & 0x40: # location/move
199+
if flag == 0x08:
200+
return self.right_click_move(buffer, frames, type, code, pid, flag, atype)
201+
elif flag in (0x04,0x05,0x07):
202+
return self.location_move(buffer, frames, type, code, pid, flag, atype)
203+
elif atype & 0x80: # right-click on target?
204+
return self.right_click_target(buffer, frames, type, code, pid, flag, atype)
223205

224-
if flag in (0x29, 0x19, 0x14, 0x0c): # cancels
225-
# creation autoid number / object id
226-
ability = ability << 8 | buffer.read_byte()
227-
created_id = buffer.read_object_id()
228-
# TODO : expose the id
229-
return AbilityEvent(frames, pid, type, code, ability)
206+
raise ParseError()
230207

231-
else:
232-
ability_flags = buffer.shift(6)
233-
ability = ability << 8 | ability_flags
234-
235-
if ability_flags & 0x10:
236-
# ability(3), coordinates (4), ?? (4)
237-
location = buffer.read_coordinate()
238-
buffer.skip(4)
239-
return LocationAbilityEvent(frames, pid, type, code, ability, location)
240-
241-
elif ability_flags & 0x20:
242-
# ability(3), object id (4), object type (2), ?? (10)
243-
code = buffer.read_short() # code??
244-
obj_id = buffer.read_object_id()
245-
obj_type = buffer.read_object_type()
246-
target = (obj_id, obj_type,)
247-
switch = buffer.read_byte()
248-
buffer.read_hex(9)
249-
return TargetAbilityEvent(frames, pid, type, code, ability, target)
250-
251-
else:
252-
return AbilityEvent(frames,pid,type,code,ability)
253208

254-
elif atype & 0x40: # location/move ??
255-
h = buffer.read_hex(2)
256-
hinge = buffer.read_byte()
257-
if hinge & 0x20:
258-
"\t%s - %s" % (hex(hinge),buffer.read_hex(9))
259-
elif hinge & 0x40:
260-
"\t%s - %s" % (hex(hinge),buffer.read_hex(18))
261-
elif hinge < 0x10:
262-
pass
209+
class ActionParser_18574(ActionParser_16561):
263210

264-
return UnknownLocationAbilityEvent(frames, pid, type, code, None)
211+
def parse_ability_event(self, buffer, frames, type, code, pid):
212+
"""Moves the right click move to the top level"""
213+
flag = buffer.read_byte()
214+
atype = buffer.read_byte()
265215

216+
if atype & 0x20: # command card
217+
return self.command_card(buffer, frames, type, code, pid, flag, atype)
218+
elif atype & 0x40: # location/move ??
219+
return self.location_move(buffer, frames, type, code, pid, flag, atype)
266220
elif atype & 0x80: # right-click on target?
267-
# ability (2), object id (4), object type (2), ?? (10)
268-
ability = buffer.read_byte() << 8 | buffer.read_byte()
269-
obj_id = buffer.read_object_id()
270-
obj_type = buffer.read_object_type()
271-
target = (obj_id, obj_type,)
272-
buffer.skip(10)
273-
return TargetAbilityEvent(frames, pid, type, code, ability, target)
274-
221+
return self.right_click_target(buffer, frames, type, code, pid, flag, atype)
275222
elif atype < 0x10: #new to patch 1.3.3, location now??
276-
#10 bytes total, coordinates have a different format?
277-
#X coordinate definitely is the first byte, with (hopefully) y next
278-
location = buffer.read_coordinate()
279-
buffer.skip(5)
280-
return LocationAbilityEvent(frames, pid, type, code, None, location)
281-
223+
return self.right_click_move(buffer, frames, type, code, pid, flag, atype)
224+
225+
raise ParseError()
226+
227+
class ActionParser_19595(ActionParser_18574):
228+
def location_move(self, buffer, frames, type, code, pid, flag, atype):
229+
h = buffer.read_hex(2)
230+
hinge = buffer.read_byte()
231+
if hinge & 0x20:
232+
"\t%s - %s" % (hex(hinge),buffer.read_hex(9))
233+
elif hinge & 0x40:
234+
# extra byte
235+
"\t%s - %s" % (hex(hinge),buffer.read_hex(19))
236+
elif hinge < 0x10:
237+
pass
282238
else:
283-
# print hex(atype)
284-
# print hex(buffer.cursor)
285-
raise ParseError()
286-
287-
# print "%s - %s" % (hex(atype),hex(flag))
288-
raise ParseError("Shouldn't be here EVER!")
239+
pass
240+
241+
return UnknownLocationAbilityEvent(frames, pid, type, code, None)
242+
243+
def right_click_target(self, buffer, frames, type, code, pid, flag, atype):
244+
# ability (2), object id (4), object type (2), ?? (10)
245+
ability = buffer.read_byte() << 8 | buffer.read_byte()
246+
obj_id = buffer.read_object_id()
247+
obj_type = buffer.read_object_type()
248+
target = (obj_id, obj_type,)
249+
# extra byte
250+
buffer.skip(11)
251+
return TargetAbilityEvent(frames, pid, type, code, ability, target)
289252

290253
class Unknown2Parser(object):
291254
def parse_0206_event(self, buffer, frames, type, code, pid):

sc2reader/readers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,7 @@ class GameEventsReader_16561( GameEventsBase, Unknown2Parser, Unknown4Parser,
329329
class GameEventsReader_18574( GameEventsBase, Unknown2Parser, Unknown4Parser,
330330
ActionParser_18574, SetupParser, CameraParser ):
331331
pass
332+
333+
class GameEventsReader_19595( GameEventsBase, Unknown2Parser, Unknown4Parser,
334+
ActionParser_19595, SetupParser, CameraParser ):
335+
pass

0 commit comments

Comments
 (0)