Skip to content

Commit bbb6a79

Browse files
committed
Added lobby properties to parsing
1 parent cf288a6 commit bbb6a79

File tree

2 files changed

+73
-11
lines changed

2 files changed

+73
-11
lines changed

sc2reader/resources.py

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from sc2reader import utils
1414
from sc2reader import log_utils
1515
from sc2reader.objects import Player, Observer, Team, PlayerSummary, Graph
16-
from sc2reader.constants import REGIONS, LOCALIZED_RACES, GAME_SPEED_FACTOR, GAME_SPEED_CODES, RACE_CODES
16+
from sc2reader.constants import REGIONS, LOCALIZED_RACES, GAME_SPEED_FACTOR, GAME_SPEED_CODES, RACE_CODES, PLAYER_TYPE_CODES, TEAM_COLOR_CODES, GAME_FORMAT_CODES, GAME_TYPE_CODES, DIFFICULTY_CODES
1717

1818

1919
class Resource(object):
@@ -416,6 +416,24 @@ class GameSummary(Resource):
416416
'SB',
417417
'SRC',
418418
]
419+
lobby_keys = {
420+
3000 : ('game_speed', GAME_SPEED_CODES),
421+
2001 : ('game_type', GAME_FORMAT_CODES), #1v1/2v2/3v3/4v4/5v5/6v6/FFA
422+
3010 : ('unknown1', {'sey':'yes', 'on':'no'} ), #yes/no
423+
3006 : ('unknown2', {'3':'3','5':'5','7':'7','01':'10','51':'15','02':'20','52':'25','03':'30'}), #3',5/7/10/15/20/25/30
424+
1001 : ('unknown3', {'sey':'yes', 'on':'no'}), #yes/no
425+
1000 : ('unknown4', {'tlfD':'Default'}), #Dflt
426+
2000 : ('unknown5', {'2t':'t2', '3t':'t3', 'AFF':'FFA', 'tsuC':'Custom'}), #t2/t3/FFA/Cust
427+
3009 : ('lobby_type', GAME_TYPE_CODES) #Priv/Pub/Amm (Auto MatchMaking)
428+
}
429+
lobby_player_keys = {
430+
500 : ('slot_state', PLAYER_TYPE_CODES), #Clsd/Open/Humn/Comp
431+
3001 : ('race', RACE_CODES),
432+
3003 : ('energy', {'05':'50','06':'60','07':'70','08':'80','09':'90','001':'100'}),
433+
3002 : ('color', TEAM_COLOR_CODES),
434+
3004 : ('difficulty', DIFFICULTY_CODES),
435+
3008 : ('nonplayer_mode', {'sbO':'Observer','feR':'Ref'}) #Obs/Ref
436+
}
419437

420438
#: Game speed
421439
game_speed = str()
@@ -426,11 +444,17 @@ class GameSummary(Resource):
426444
#: Game length (in-game)
427445
game_length_ingame = int()
428446

447+
#: Lobby properties
448+
lobby_properties = dict()
449+
429450
#: Game completion time
430451
time = int()
431452

432-
#: Players, a list of :class`PlayerSummary` from the game
433-
players = list()
453+
#: Players, a dict of :class`PlayerSummary` from the game
454+
players = dict()
455+
456+
#: Teams, a dict of pids
457+
teams = dict()
434458

435459
#: Build orders, a dict of build orders indexed by player id
436460
build_orders = dict()
@@ -444,10 +468,12 @@ class GameSummary(Resource):
444468
def __init__(self, summary_file, filename=None, **options):
445469
super(GameSummary, self).__init__(summary_file, filename,**options)
446470

447-
self.players = list()
471+
self.players = dict()
448472
self.build_orders = dict()
449473
self.image_urls = list()
450474
self.localization_urls = dict()
475+
self.lobby_properties = dict()
476+
self.teams = dict()
451477

452478
self.data = zlib.decompress(summary_file.read()[16:])
453479
self.parts = list()
@@ -470,12 +496,32 @@ def __init__(self, summary_file, filename=None, **options):
470496
self.game_length_ingame = self.parts[0][7]
471497
self.game_length = self.game_length_ingame / GAME_SPEED_FACTOR[self.game_speed]
472498

499+
# parse lobby properties
500+
lobby_template = dict()
501+
for prop in self.parts[0][5]:
502+
if not prop[0][1] in self.lobby_keys:
503+
continue
504+
lobby_template[prop[0][1]] = [o[0].strip('\x00') for o in prop[1]]
505+
for prop in self.parts[0][6][6]:
506+
if not prop[0][1] in lobby_template:
507+
continue
508+
key = self.lobby_keys[prop[0][1]][0]
509+
val = lobby_template[prop[0][1]][prop[1][0]]
510+
self.lobby_properties[key] = self.lobby_keys[prop[0][1]][1][utils.reverse_str(val)]
511+
512+
# Prepare player lobby properties
513+
lobby_player_template = dict()
514+
for prop in self.parts[0][5]:
515+
if not prop[0][1] in self.lobby_player_keys:
516+
continue
517+
lobby_player_template[prop[0][1]] = [o[0].strip().strip('\x00') for o in prop[1]]
518+
473519
# Parse player structs, 16 is the maximum amount of players
474520
for i in range(16):
475521
player = None
476-
# Check if player, break if not
522+
# Check if player, skip if not
477523
if self.parts[0][3][i][2] == '\x00\x00\x00\x00':
478-
break
524+
continue
479525
player_struct = self.parts[0][3][i]
480526

481527
player = PlayerSummary(player_struct[0][0])
@@ -498,11 +544,24 @@ def __init__(self, summary_file, filename=None, **options):
498544
# { 0: 3405691582L, 1: 11402158793782460416L}
499545
player.unknown2 = player_struct[0][1][1]
500546

501-
self.players.append(player)
547+
# Parse lobby properties
548+
player.lobby_properties = dict()
549+
for prop in self.parts[0][6][6]:
550+
if not prop[0][1] in lobby_player_template:
551+
continue
552+
key = self.lobby_player_keys[prop[0][1]][0]
553+
val = lobby_player_template[prop[0][1]][prop[1][player.pid][0]]
554+
player.lobby_properties[key] = self.lobby_player_keys[prop[0][1]][1][utils.reverse_str(val)]
555+
556+
self.players[player.pid] = player
557+
if not player.teamid in self.teams:
558+
self.teams[player.teamid] = list()
559+
self.teams[player.teamid].append(player.pid)
560+
502561

503562
# Parse graph and stats stucts, for each player
504-
for p in self.players:
505-
563+
for pid in self.players:
564+
p = self.players[pid]
506565
# Graph stuff
507566
xy = [(o[2], o[0]) for o in self.parts[4][0][2][1][p.pid]]
508567
p.army_graph = Graph([], [], xy_list=xy)
@@ -542,7 +601,8 @@ def __init__(self, summary_file, filename=None, **options):
542601
bo_structs.append(self.parts[4][0][3:])
543602

544603
# This might not be the most effective way, but it works
545-
for p in self.players:
604+
for pid in self.players:
605+
p = self.players[pid]
546606
bo = list()
547607
for bo_struct in bo_structs:
548608
for order in bo_struct:
@@ -571,7 +631,7 @@ def __str__(self):
571631
int(self.game_length)/3600,
572632
(int(self.game_length)%3600)/60,
573633
(int(self.game_length)%3600)%60,
574-
''.join(p.race[0] for p in self.players))
634+
''.join(self.players[p].race[0] for p in self.players))
575635

576636
class MapInfo(Resource):
577637
url_template = 'http://{0}.depot.battle.net:1119/{1}.s2mi'

sc2reader/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,8 @@ def parse_hash(hash_string):
769769
'hash' : ''.join([('%02x' % ord(x)) for x in hash]),
770770
'type' : hash_string[0:4]
771771
}
772+
def reverse_str(s):
773+
return ''.join(reversed(s))
772774
def flip_int(num, b):
773775
"""
774776
Flips the b first bytes in num

0 commit comments

Comments
 (0)