@@ -21,71 +21,205 @@ def __call__(self, data, replay):
2121
2222class InitDataReader_Base (Reader ):
2323
24- def get_player_names (self , data , replay ):
25- # The first block of the replay.initData file represents a list of
26- # human player names; computers are no recorded. This list appears to
27- # always be 16 long, with "" names filling in the balance. Each name
28- # is followed by a 5 byte string that appears to be always all zeros.
29- player_names = list ()
30- for player in range (data .read_uint8 ()):
31- name = data .read_aligned_bytes (data .read_uint8 ())
32- data .read_bytes (5 )
33- if name :
34- player_names .append (name )
35- return player_names
36-
3724 def __call__ (self , data , replay ):
3825 data = BitPackedDecoder (data )
3926
40- player_names = self .get_player_names (data , replay )
41-
42- # The next block contains information about the structure of the MPQ
43- # archive. We don't read this information because we've got mpyq for
44- # that. Its split into 3 sections because of the variable length segment
45- # in the middle that prevents bulk skipping. The last section also
46- # appears to be variable length, hack it to do a find for the section
47- # we are looking for.
48- data .read_bytes (24 )
49- #sc_account_id = data.read_string()
50- distance = data .read_range (data .tell (), data .length ).find ('s2ma' )
51- data .read_bytes (distance )
52-
53- # The final block of this file that we concern ourselves with is a list
54- # of what appears to be map data with the s2ma header on each element.
55- # Each element consists of two unknown bytes, a realm id (e.g EU or US)
56- # and a map hash which probably ties back to the sc2map files.
57- #
58- # Some replays don't seem to have a maps section at all, now we can't
59- # know what gateway its from? Very strange...
60- #
61- # TODO: Figure out how we could be missing a maps section.
62- map_data = list ()
63- while data .peek (4 ) == 's2ma' :
64- map_data .append (DepotFile (data .read_bytes (40 )))
27+ init_data = dict ( #58
28+ player_init_data = [dict ( #38
29+ name = data .read_aligned_bytes (data .read_uint8 ()),
30+ random_seed = data .read_uint32 (),
31+ race_preference = data .read_uint8 () if data .read_bool () else None , #38
32+ team_preference = data .read_uint8 () if data .read_bool () else None , #39
33+ test_map = data .read_bool (),
34+ test_auto = data .read_bool (),
35+ examine = data .read_bool (),
36+ observe = data .read_bits (2 ),
37+ ) for i in range (data .read_bits (5 ))
38+ ],
39+
40+ game_description = dict ( # 48
41+ random_value = data .read_uint32 (), # 4
42+ game_cache_name = data .read_aligned_bytes (data .read_bits (10 )), # 24
43+ game_options = dict ( #40
44+ lock_teams = data .read_bool (), #27
45+ teams_together = data .read_bool (),
46+ advanced_shared_control = data .read_bool (),
47+ random_races = data .read_bool (),
48+ battle_net = data .read_bool (),
49+ amm = data .read_bool (),
50+ competitive = data .read_bool (),
51+ no_victory_or_defeat = data .read_bool (),
52+ fog = data .read_bits (2 ), #19
53+ observers = data .read_bits (2 ), #19
54+ user_difficulty = data .read_bits (2 ), #19
55+ client_debug_flags = data .read_uint64 (), #15
56+ ),
57+ game_speed = data .read_bits (3 ),
58+ game_type = data .read_bits (3 ),
59+ max_users = data .read_bits (5 ),
60+ max_observers = data .read_bits (5 ),
61+ max_players = data .read_bits (5 ),
62+ max_teams = data .read_bits (4 )+ 1 ,
63+ max_colors = data .read_bits (6 ),
64+ max_races = data .read_uint8 ()+ 1 ,
65+ max_controls = data .read_uint8 ()+ 1 ,
66+ map_size_x = data .read_uint8 (),
67+ map_size_y = data .read_uint8 (),
68+ map_file_sync_checksum = data .read_uint32 (),
69+ map_file_name = data .read_aligned_bytes (data .read_bits (11 )),
70+ map_author_name = data .read_aligned_bytes (data .read_uint8 ()),
71+ mod_file_sync_checksum = data .read_uint32 (),
72+ slot_descriptions = [dict ( #47
73+ allowed_colors = data .read_bits (data .read_bits (6 )),
74+ allowed_races = data .read_bits (data .read_uint8 ()),
75+ allowedDifficulty = data .read_bits (data .read_bits (6 )),
76+ allowedControls = data .read_bits (data .read_uint8 ()),
77+ allowed_observe_types = data .read_bits (data .read_bits (2 )),
78+ ) for i in range (data .read_bits (5 ))],
79+ default_difficulty = data .read_bits (6 ),
80+ cache_handles = [
81+ DepotFile (data .read_aligned_bytes (40 )) for i in range (data .read_bits (6 ))
82+ ],
83+ is_blizzardMap = data .read_bool (),
84+ is_premade_ffa = data .read_bool (),
85+ ),
86+ )
87+ """ # For builds <= 1.5.4 this won't work.
88+ lobby_state = dict( #56
89+ phase = data.read_bits(3),
90+ max_users = data.read_bits(5),
91+ max_observers = data.read_bits(5),
92+ slots = [dict( #54
93+ control = data.read_uint8(),
94+ user_id = data.read_bits(4) if data.read_bool() else None,
95+ team_id = data.read_bits(4),
96+ colorPref = data.read_bits(5) if data.read_bool() else None,
97+ race_pref = data.read_uint8() if data.read_bool() else None,
98+ difficulty = data.read_bits(6),
99+ handicap = data.read_bits(7),
100+ observe = data.read_bits(2),
101+ rewards = [data.read_uint32() for i in range(data.read_bits(6))],
102+ toon_handle = data.read_aligned_bytes(data.read_bits(7)), # 14
103+ licenses = [data.read_uint32() for i in range(data.read_bits(9))], # 56
104+ ) for i in range(data.read_bits(5))], # 58
105+ random_seed = data.read_uint32(),
106+ host_user_id = data.read_bits(4) if data.read_bool() else None, # 52
107+ is_single_player = data.read_bool(), # 27
108+ game_duration = data.read_uint32(), # 4
109+ default_difficulty = data.read_bits(6), # 1
110+ ),
111+ )"""
65112
66- # Return the extracted information inside an AttributeDict.
67113 return AttributeDict (
68- map_data = map_data ,
69- player_names = player_names ,
114+ map_data = init_data [ 'game_description' ][ 'cache_handles' ] ,
115+ player_names = [ d [ 'name' ] for d in init_data [ 'player_init_data' ] if d [ 'name' ]] ,
70116 sc_account_id = None ,#sc_account_id,
71117 )
72118
73119class InitDataReader_24764 (InitDataReader_Base ):
74- def get_player_names (self , data , replay ):
75- player_names = list ()
76- for player in range (data .read_uint8 ()):
77- name = data .read_aligned_bytes (data .read_uint8 ())
78-
79- # Flag is 1 for multiplayer, 0 for single player
80- if data .read_bits (1 ):
81- clan_name = data .read_aligned_bytes (data .read_uint8 ())
82- unknown = data .read_bits (42 )
83120
84- data .read_bytes (5 )
85- if name :
86- player_names .append (name )
87- return player_names
121+ def __call__ (self , data , replay ):
122+ data = BitPackedDecoder (data )
88123
124+ init_data = dict (
125+ player_init_data = [dict (
126+ name = data .read_aligned_bytes (data .read_uint8 ()),
127+ clan_tag = data .read_aligned_bytes (data .read_uint8 ()) if data .read_bool () else "" , # 36
128+ highest_league = data .read_uint8 () if data .read_bool () else None , #20
129+ combined_race_levels = data .read_uint32 () if data .read_bool () else None , #37
130+ random_seed = data .read_uint32 (),
131+ race_preference = data .read_uint8 () if data .read_bool () else None , #38
132+ team_preference = data .read_uint8 () if data .read_bool () else None , #39
133+ test_map = data .read_bool (),
134+ test_auto = data .read_bool (),
135+ examine = data .read_bool (),
136+ custom_interface = data .read_bool (),
137+ observe = data .read_bits (2 ),
138+ ) for i in range (data .read_bits (5 ))
139+ ],
140+
141+ game_description = dict (
142+ random_value = data .read_uint32 (), # 4
143+ game_cache_name = data .read_aligned_bytes (data .read_bits (10 )), # 24
144+ game_options = dict (
145+ lock_teams = data .read_bool (), #27
146+ teams_together = data .read_bool (),
147+ advanced_shared_control = data .read_bool (),
148+ random_races = data .read_bool (),
149+ battle_net = data .read_bool (),
150+ amm = data .read_bool (),
151+ competitive = data .read_bool (),
152+ no_victory_or_defeat = data .read_bool (),
153+ fog = data .read_bits (2 ), #19
154+ observers = data .read_bits (2 ), #19
155+ user_difficulty = data .read_bits (2 ), #19
156+ client_debug_flags = data .read_uint64 (), #15
157+ ),
158+ game_speed = data .read_bits (3 ),
159+ game_type = data .read_bits (3 ),
160+ max_users = data .read_bits (5 ),
161+ max_observers = data .read_bits (5 ),
162+ max_players = data .read_bits (5 ),
163+ max_teams = data .read_bits (4 )+ 1 ,
164+ max_colors = data .read_bits (6 ),
165+ max_races = data .read_uint8 ()+ 1 ,
166+ max_controls = data .read_uint8 ()+ 1 ,
167+ map_size_x = data .read_uint8 (),
168+ map_size_y = data .read_uint8 (),
169+ map_file_sync_checksum = data .read_uint32 (),
170+ map_file_name = data .read_aligned_bytes (data .read_bits (11 )),
171+ map_author_name = data .read_aligned_bytes (data .read_uint8 ()),
172+ mod_file_sync_checksum = data .read_uint32 (),
173+ slot_descriptions = [dict ( #50
174+ allowed_colors = data .read_bits (data .read_bits (6 )),
175+ allowed_races = data .read_bits (data .read_uint8 ()),
176+ allowedDifficulty = data .read_bits (data .read_bits (6 )),
177+ allowedControls = data .read_bits (data .read_uint8 ()),
178+ allowed_observe_types = data .read_bits (data .read_bits (2 )),
179+ allowed_ai_builds = data .read_bits (data .read_bits (7 )),
180+ ) for i in range (data .read_bits (5 ))],
181+ default_difficulty = data .read_bits (6 ),
182+ default_AI_build = data .read_bits (7 ),
183+ cache_handles = [
184+ DepotFile (data .read_aligned_bytes (40 )) for i in range (data .read_bits (6 ))
185+ ],
186+ is_blizzardMap = data .read_bool (),
187+ is_premade_ffa = data .read_bool (),
188+ is_coop_mode = data .read_bool (),
189+ ),
190+
191+ lobby_state = dict (
192+ phase = data .read_bits (3 ),
193+ max_users = data .read_bits (5 ),
194+ max_observers = data .read_bits (5 ),
195+ slots = [dict (
196+ control = data .read_uint8 (),
197+ user_id = data .read_bits (4 ) if data .read_bool () else None ,
198+ team_id = data .read_bits (4 ),
199+ colorPref = data .read_bits (5 ) if data .read_bool () else None ,
200+ race_pref = data .read_uint8 () if data .read_bool () else None ,
201+ difficulty = data .read_bits (6 ),
202+ ai_build = data .read_bits (7 ),
203+ handicap = data .read_bits (7 ),
204+ observe = data .read_bits (2 ),
205+ working_set_slot_id = data .read_uint8 () if data .read_bool () else None ,
206+ rewards = [data .read_uint32 () for i in range (data .read_bits (6 ))],
207+ toon_handle = data .read_aligned_bytes (data .read_bits (7 )), # 14
208+ licenses = [data .read_uint32 () for i in range (data .read_bits (9 ))], # 56
209+ ) for i in range (data .read_bits (5 ))], # 58
210+ random_seed = data .read_uint32 (),
211+ host_user_id = data .read_bits (4 ) if data .read_bool () else None , # 52
212+ is_single_player = data .read_bool (), # 27
213+ game_duration = data .read_uint32 (), # 4
214+ default_difficulty = data .read_bits (6 ), # 1
215+ default_ai_build = data .read_bits (7 ), # 0
216+ ),
217+ )
218+ return AttributeDict (
219+ map_data = init_data ['game_description' ]['cache_handles' ],
220+ player_names = [d ['name' ] for d in init_data ['player_init_data' ] if d ['name' ]],
221+ sc_account_id = None ,#sc_account_id,
222+ )
89223
90224
91225class AttributesEventsReader_Base (Reader ):
0 commit comments