@@ -30,6 +30,11 @@ def __init__(self, file_object, filename=None, **options):
3030
3131class Replay (Resource ):
3232
33+ #: A nested dictionary of player => { attr_name : attr_value } for
34+ #: known attributes. Player 16 represents the global context and
35+ #: contains attributes like game speed.
36+ attributes = defaultdict (dict )
37+
3338 #: Fully qualified filename of the replay file represented.
3439 filename = str ()
3540
@@ -42,10 +47,10 @@ class Replay(Resource):
4247 #: The full version release string as seen on Battle.net
4348 release_string = str ()
4449
45- #: The :class:`Length` of the replay as an alternative to :attr:`frames`
46- length = utils . Length ()
50+ #: A tuple of the individual pieces of the release string
51+ versions = tuple ()
4752
48- #: The effective game speed when the game was played.
53+ #: The game speed: Slower, Slow, Normal, Fast, Faster
4954 speed = str ()
5055
5156 #: The game type: 1v1, 2v2, 3v3, 4v4, FFA
@@ -60,9 +65,42 @@ class Replay(Resource):
6065 #: A flag for private non-ladder games
6166 is_private = bool ()
6267
68+ #: The raw hash name of the s2ma resource as hosted on bnet depots
69+ map_hash = str ()
70+
6371 #: The name of the map the game was played on
72+ map_name = str ()
73+
74+ #: A reference to the loaded :class:`Map` resource.
6475 map = None
6576
77+ #: The UTC time the game was ended as represented by the Windows OS
78+ windows_timestamp = int ()
79+
80+ #: The UTC time the game was ended as represented by the Unix OS
81+ unix_timestamp = int ()
82+
83+ #: The time zone adjustment for the location the replay was recorded at
84+ time_zone = int ()
85+
86+ #: Deprecated: See `end_time` below.
87+ date = None
88+
89+ #: A datetime object representing the local time at the end of the game.
90+ end_time = None
91+
92+ #: A datetime object representing the local time at the start of the game
93+ start_time = None
94+
95+ #: Deprecated: See `game_length` below.
96+ length = None
97+
98+ #: The :class:`Length` of the replay as an alternative to :attr:`frames`
99+ game_length = None
100+
101+ #: The :class:`Length` of the replay in real time adjusted for the game speed
102+ self .real_length = None
103+
66104 #: The gateway the game was played on: us, eu, sea, etc
67105 gateway = str ()
68106
@@ -103,12 +141,27 @@ class Replay(Resource):
103141 #: A list of all the chat message events from the game
104142 messages = list ()
105143
144+ #: A list of pings sent by all the different people in the game
145+ pings = list ()
146+
147+ #: A list of packets sent between the various game clients
148+ packets = list ()
149+
106150 #: A reference to the :class:`Person` that recorded the game
107151 recorder = None
108152
109153 #: If there is a valid winning team this will contain a :class:`Team` otherwise it will be :class:`None`
110154 winner = None
111155
156+ #: A dictionary mapping unit unique ids to their corresponding classes
157+ objects = dict ()
158+
159+ #: A sha256 hash uniquely representing the combination of people in the game.
160+ #: Can be used in conjunction with date times to match different replays
161+ #: of the game game.
162+ people_hash = str ()
163+
164+
112165 def __init__ (self , replay_file , filename = None , load_level = 4 , ** options ):
113166 super (Replay , self ).__init__ (replay_file , filename , ** options )
114167 self .datapack = None
@@ -123,23 +176,20 @@ def __init__(self, replay_file, filename=None, load_level=4, **options):
123176 self .is_ladder = False
124177 self .is_private = False
125178 self .map = ""
179+ self .map_hash = ""
126180 self .gateway = ""
127181 self .events = list ()
128182 self .events_by_type = defaultdict (list )
129183 self .results = dict ()
130-
131184 self .teams , self .team = list (), dict ()
132185 self .players , self .player = list (), utils .PersonDict ()
133186 self .observers = list () #Unordered list of Observer
134-
135187 self .people , self .humans = list (), list () #Unordered list of Players+Observers
136-
137188 self .person = utils .PersonDict () #Maps pid to Player/Observer
138- self .attributes = list ( )
189+ self .attributes = defaultdict ( dict )
139190 self .messages = list ()
140191 self .recorder = None # Player object
141192 self .packets = list ()
142-
143193 self .objects = {}
144194
145195 # Bootstrap the readers.
@@ -152,6 +202,7 @@ def __init__(self, replay_file, filename=None, load_level=4, **options):
152202
153203 # Unpack the MPQ and read header data if requested
154204 if load_level >= 0 :
205+ # Set ('versions', 'frames', 'build', 'release_string', 'length')
155206 self .__dict__ .update (utils .read_header (replay_file ))
156207 self .archive = utils .open_archive (replay_file )
157208
@@ -331,7 +382,7 @@ def load_players(self):
331382 if obs_name in all_players : continue
332383
333384 observer = Observer (obs_index ,obs_name )
334- observer .gateway = self . gateway
385+ observer .region = default_region
335386 self .observers .append (observer )
336387 self .people .append (observer )
337388 self .person [obs_index ] = observer
@@ -372,6 +423,7 @@ def load_events(self):
372423
373424 for event in self .events :
374425 event .load_context (self )
426+ # TODO: Should this be documented or removed? I don't like it.
375427 self .events_by_type [event .name ].append (event )
376428 if event .pid != 16 :
377429 self .person [event .pid ].events .append (event )
@@ -462,6 +514,28 @@ def _read_data(self, data_file, reader):
462514class Map (Resource ):
463515 url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma'
464516
517+ #: The unique hash used to identify this map on bnet's depots.
518+ hash = str ()
519+
520+ #: The gateway this map was posted to.
521+ #: Maps must be posted individually to each gateway.
522+ gateway = str ()
523+
524+ #: A URL reference to the location of this map on bnet's depots.
525+ url = str ()
526+
527+ #: The localized (only enUS supported right now) map name
528+ name = str ()
529+
530+ #: The map's author
531+ author = str ()
532+
533+ #: The map description as written by author
534+ description = str ()
535+
536+ #: A byte string representing the minimap in tga format.
537+ minimap = str ()
538+
465539 def __init__ (self , map_file , filename = None , gateway = None , map_hash = None , ** options ):
466540 super (Map , self ).__init__ (map_file , filename , ** options )
467541 self .hash = map_hash
0 commit comments