|
11 | 11 |
|
12 | 12 | from sc2reader import utils |
13 | 13 | from sc2reader import log_utils |
14 | | -from sc2reader.objects import Player, Observer, Team |
15 | | -from sc2reader.constants import REGIONS, LOCALIZED_RACES, GAME_SPEED_FACTOR |
| 14 | +from sc2reader.objects import Player, Observer, Team, PlayerSummary, Graph |
| 15 | +from sc2reader.constants import REGIONS, LOCALIZED_RACES, GAME_SPEED_FACTOR, GAME_SPEED_CODES, RACE_CODES |
16 | 16 |
|
17 | 17 |
|
18 | 18 | class Resource(object): |
@@ -397,40 +397,105 @@ def read_game_strings(self): |
397 | 397 | elif parts[0] == 'DocInfo/DescLong': |
398 | 398 | self.description = parts[1] |
399 | 399 |
|
400 | | -s2gsmap = [[4, "Average Unspent Resources"], |
401 | | - [5, "Resource Collection Rate"], |
402 | | - [6, "Workers Created"], |
403 | | - [7, "Units Trained"], |
404 | | - [8, "Killed Unit Count"], |
405 | | - [9, "Structure Built"], |
406 | | - ] |
407 | 400 |
|
408 | 401 | class GameSummary(Resource): |
409 | 402 | url_template = 'http://{0}.depot.battle.net:1119/{1}.s2gs' |
| 403 | + |
| 404 | + stats_keys = [ |
| 405 | + 'R', |
| 406 | + 'U', |
| 407 | + 'S', |
| 408 | + 'O', |
| 409 | + 'AUR', |
| 410 | + 'RCR', |
| 411 | + 'WC', |
| 412 | + 'UT', |
| 413 | + 'KUC', |
| 414 | + 'SB', |
| 415 | + 'SRC', |
| 416 | + ] |
| 417 | + |
| 418 | + #: Game speed |
| 419 | + game_speed = str() |
| 420 | + |
| 421 | + #: Players, a list of :class`PlayerSummary` from the game |
| 422 | + players = list() |
| 423 | + |
410 | 424 | def __init__(self, summary_file, filename=None, **options): |
411 | 425 | super(GameSummary, self).__init__(summary_file, filename,**options) |
412 | 426 | self.data = zlib.decompress(summary_file.read()[16:]) |
413 | 427 | self.parts = list() |
414 | 428 | buffer = utils.ReplayBuffer(self.data) |
415 | 429 | while buffer.left: |
416 | 430 | part = buffer.read_data_struct() |
417 | | -# print str(part)+"\n\n\n" |
418 | 431 | self.parts.append(part) |
419 | | -# print len(self.parts) |
420 | | -# pprint.PrettyPrinter(indent=2).pprint(self.parts) |
421 | | - for index, name in s2gsmap: |
422 | | - for player in [0, 1]: |
423 | | - print "Player", player, name, self.parts[3][0][index][1][player][0][0] |
424 | 432 |
|
425 | | -class MatchInfo(Resource): |
426 | | - url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma' |
427 | | - def __init__(self, info_file, filename=None, **options): |
428 | | - super(MatchInfo, self).__init__(info_file, filename,**options) |
429 | | - self.data = utils.ReplayBuffer(info_file).read_data_struct() |
| 433 | + # Parse basic info |
| 434 | + self.game_speed = GAME_SPEED_CODES[''.join(reversed(self.parts[0][0][1]))] |
| 435 | + |
| 436 | + # Parse player structs, 16 is the maximum amount of players |
| 437 | + for i in range(16): |
| 438 | + player = None |
| 439 | + # Check if player, break if not |
| 440 | + if self.parts[0][3][i][2] == '\x00\x00\x00\x00': |
| 441 | + break |
| 442 | + player_struct = self.parts[0][3][i] |
| 443 | + |
| 444 | + player = PlayerSummary(player_struct[0][0]) |
| 445 | + player.race = RACE_CODES[''.join(reversed(player_struct[2]))] |
| 446 | + player.bnetid = player_struct[0][1][0][3] |
| 447 | + player.subregion = player_struct[0][1][0][2] |
| 448 | + |
| 449 | + # int |
| 450 | + player.unknown1 = player_struct[0][1][0] |
| 451 | + # {0:long1, 1:long2} |
| 452 | + # Example: |
| 453 | + # { 0: 3405691582L, 1: 11402158793782460416L} |
| 454 | + player.unknown2 = player_struct[0][1][1] |
430 | 455 |
|
| 456 | + self.players.append(player) |
| 457 | + |
| 458 | + # Parse graph and stats stucts, for each player |
| 459 | + for p in self.players: |
| 460 | + |
| 461 | + # Graph stuff |
| 462 | + xy = [(o[2], o[0]) for o in self.parts[4][0][2][1][p.pid]] |
| 463 | + p.army_graph = Graph([], [], xy_list=xy) |
| 464 | + |
| 465 | + xy = [(o[2], o[0]) for o in self.parts[4][0][1][1][p.pid]] |
| 466 | + p.income_graph = Graph([], [], xy_list=xy) |
| 467 | + |
| 468 | + # Stats stuff |
| 469 | + stats_struct = self.parts[3][0] |
| 470 | + # The first group of stats is located in parts[3][0] |
| 471 | + for i in range(len(stats_struct)): |
| 472 | + p.stats[self.stats_keys[i]] = stats_struct[i][1][p.pid][0][0] |
| 473 | + # The last piece of stats is in parts[4][0][0][1] |
| 474 | + p.stats[self.stats_keys[len(stats_struct)]] = self.parts[4][0][0][1][p.pid][0][0] |
| 475 | + |
| 476 | + |
| 477 | +class MapInfo(Resource): |
| 478 | + url_template = 'http://{0}.depot.battle.net:1119/{1}.s2mi' |
| 479 | + |
| 480 | + #: Name of the Map |
| 481 | + map_name = str() |
| 482 | + |
| 483 | + #: Hash of referenced s2mh file |
| 484 | + s2mh_hash = str() |
| 485 | + |
| 486 | + #: URL of referenced s2mh file |
| 487 | + s2mh_url = str() |
431 | 488 |
|
432 | | -class MatchHistory(Resource): |
433 | | - url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma' |
434 | | - def __init__(self, history_file, filename=None, **options): |
435 | | - super(MatchHistory, self).__init__(history_file, filename,**options) |
436 | | - self.data = utils.ReplayBuffer(history_file).read_data_struct() |
| 489 | + def __init__(self, info_file, filename=None, **options): |
| 490 | + super(MapInfo, self).__init__(info_file, filename,**options) |
| 491 | + self.data = utils.ReplayBuffer(info_file).read_data_struct() |
| 492 | + self.map_name = self.data[0][7] |
| 493 | + self.language = self.data[0][13] |
| 494 | + self.s2mh_hash = ''.join([hex(ord(x))[2:] for x in self.data[0][1][8:]]) |
| 495 | + self.s2mh_url = MapHeader.url_template.format(self.data[0][1][6:8], self.s2mh_hash) |
| 496 | + |
| 497 | +class MapHeader(Resource): |
| 498 | + url_template = 'http://{0}.depot.battle.net:1119/{1}.s2mh' |
| 499 | + def __init__(self, header_file, filename=None, **options): |
| 500 | + super(MapHeader, self).__init__(header_file, filename,**options) |
| 501 | + self.data = utils.ReplayBuffer(header_file).read_data_struct() |
0 commit comments