Example #1
0
class Map(Resource):
    url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma'

    def __init__(self, map_file, filename=None, gateway=None, map_hash=None, **options):
        super(Map, self).__init__(map_file, filename, **options)
        self.hash = map_hash
        self.gateway = gateway
        self.url = Map.get_url(gateway, map_hash)
        self.archive = MPQArchive(StringIO(self.file))
        self.minimap = self.archive.read_file('Minimap.tga')

    @classmethod
    def get_url(gateway, map_hash):
        if gateway and map_hash:
            return Map.url_template.format(gateway, map_hash)
        else:
            return None

    def load(self):
        self.read_game_strings()

    def read_game_strings(self):
        self.game_strings = self.archive.read_file('enUS.SC2Data\LocalizedData\GameStrings.txt')
        for line in self.game_strings.split('\r\n'):
            parts = line.split('=')
            if parts[0] == 'DocInfo/Name':
                self.name = parts[1]
            elif parts[0] == 'DocInfo/Author':
                self.author = parts[1]
            elif parts[0] == 'DocInfo/DescLong':
                self.description = parts[1]
Example #2
0
class Map(Resource):
    url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma'

    #: The unique hash used to identify this map on bnet's depots.
    hash = str()

    #: The gateway this map was posted to.
    #: Maps must be posted individually to each gateway.
    gateway = str()

    #: A URL reference to the location of this map on bnet's depots.
    url = str()

    #: The localized (only enUS supported right now) map name
    name = str()

    #: The map's author
    author = str()

    #: The map description as written by author
    description = str()

    #: A byte string representing the minimap in tga format.
    minimap = str()

    def __init__(self, map_file, filename=None, gateway=None, map_hash=None, **options):
        super(Map, self).__init__(map_file, filename, **options)
        self.hash = map_hash
        self.gateway = gateway
        self.url = Map.get_url(gateway, map_hash)
        self.archive = MPQArchive(map_file)
        self.minimap = self.archive.read_file('Minimap.tga')

        # This will only populate the fields for maps with enUS localizations.
        # Clearly this isn't a great solution but we can't be throwing exceptions
        # just because US English wasn't a concern of the map author.
        # TODO: Make this work regardless of the localizations available.
        game_strings = self.archive.read_file('enUS.SC2Data\LocalizedData\GameStrings.txt')
        if game_strings:
            for line in game_strings.split('\r\n'):
                parts = line.split('=')
                if parts[0] == 'DocInfo/Name':
                    self.name = parts[1]
                elif parts[0] == 'DocInfo/Author':
                    self.author = parts[1]
                elif parts[0] == 'DocInfo/DescLong':
                    self.description = parts[1]

    @classmethod
    def get_url(cls, gateway, map_hash):
        """Builds a download URL for the map from its components."""
        if gateway and map_hash:
            # it seems like sea maps are stored on us depots.
            gateway = 'us' if gateway=='sea' else gateway
            return cls.url_template.format(gateway, map_hash)
        else:
            return None
Example #3
0
class Map(Resource):
    url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma'

    #: The unique hash used to identify this map on bnet's depots.
    hash = str()

    #: The gateway this map was posted to.
    #: Maps must be posted individually to each gateway.
    gateway = str()

    #: A URL reference to the location of this map on bnet's depots.
    url = str()

    #: The localized (only enUS supported right now) map name
    name = str()

    #: The map's author
    author = str()

    #: The map description as written by author
    description = str()

    #: A byte string representing the minimap in tga format.
    minimap = str()

    def __init__(self, map_file, filename=None, gateway=None, map_hash=None, **options):
        super(Map, self).__init__(map_file, filename, **options)
        self.hash = map_hash
        self.gateway = gateway
        self.url = Map.get_url(gateway, map_hash)
        self.archive = MPQArchive(map_file)
        self.minimap = self.archive.read_file('Minimap.tga')

        # This will only populate the fields for maps with enUS localizations.
        # Clearly this isn't a great solution but we can't be throwing exceptions
        # just because US English wasn't a concern of the map author.
        # TODO: Make this work regardless of the localizations available.
        game_strings = self.archive.read_file('enUS.SC2Data\LocalizedData\GameStrings.txt')
        if game_strings:
            for line in game_strings.split('\r\n'):
                parts = line.split('=')
                if parts[0] == 'DocInfo/Name':
                    self.name = parts[1]
                elif parts[0] == 'DocInfo/Author':
                    self.author = parts[1]
                elif parts[0] == 'DocInfo/DescLong':
                    self.description = parts[1]

    @classmethod
    def get_url(cls, gateway, map_hash):
        """Builds a download URL for the map from its components."""
        if gateway and map_hash:
            # it seems like sea maps are stored on us depots.
            gateway = 'us' if gateway=='sea' else gateway
            return cls.url_template.format(gateway, map_hash)
        else:
            return None
Example #4
0
def get_commands(filename):
    archive = MPQArchive(filename, listfile=False)
    script = archive.read_file('war3map.j')
    if not script:
        script = archive.read_file(r'Scripts\war3map.j')
    script = script.decode('utf-8', errors='replace')

    re_str = r'call TriggerRegisterPlayerChatEvent\([^,]*,([^,]*),[ ]*"([^"]*)"[ ]*,[^,]*\)'

    cmds = dict()
    for player, cmd in re.findall(re_str, script):
        if cmd not in cmds:
            cmds[cmd] = []
        cmds[cmd].append(player.strip())

    return cmds
Example #5
0
def read_file(filename, config=DefaultConfig()):
    if (os.path.splitext(filename)[1].lower() != '.sc2replay'):
        raise TypeError("Target file must of the SC2Replay file extension")

    with open(filename) as replay_file:
        release, frames = read_header(replay_file)
        replay = config.ReplayClass(filename, release, frames)
        archive = MPQArchive(filename, listfile=False)

        #Extract and Parse the relevant files
        for file, readers in config.readers.iteritems():
            for reader in readers:
                if reader.reads(replay.build):
                    reader.read(archive.read_file(file), replay)
                    break
            else:
                raise NotYetImplementedError(
                    "No parser was found that accepted the replay file;check configuration"
                )

        #Do cleanup and post processing
        for processor in config.processors:
            replay = processor.process(replay)

        return replay
Example #6
0
class Map(object):
    url_template = 'http://{0}.depot.battle.net:1119/{1}.s2ma'

    def __init__(self, gateway, map_hash, map_name=''):
        self.hash = map_hash.encode('hex')
        self.gateway = gateway
        self.url = Map.url_template.format(self.gateway, self.hash)
        self.name = map_name

    def load(self):
        print "Fetching map: {0}".format(self.url);
        self.file = urllib2.urlopen(self.url).read()
        print "Map Received"
        self.archive = MPQArchive(StringIO(self.file))
        self.minimap = self.archive.read_file('Minimap.tga')
        self.game_strings = self.archive.read_file('enUS.SC2Data\LocalizedData\GameStrings.txt')
        for line in self.game_strings.split('\r\n'):
            parts = line.split('=')
            if parts[0] == 'DocInfo/Name':
                self.name = parts[1]
            elif parts[0] == 'DocInfo/Author':
                self.author = parts[1]
            elif parts[0] == 'DocInfo/DescLong':
                self.description = parts[1]
Example #7
0
def read_file(filename,config=DefaultConfig()):
    if(os.path.splitext(filename)[1].lower() != '.sc2replay'):
        raise TypeError("Target file must of the SC2Replay file extension")
    
    with open(filename) as replay_file:
        release,frames = read_header(replay_file)
        replay = config.ReplayClass(filename,release,frames)
        archive = MPQArchive(filename,listfile=False)
        
        #Extract and Parse the relevant files
        for file,readers in config.readers.iteritems():
            for reader in readers:
                if reader.reads(replay.build):
                    reader.read(archive.read_file(file),replay)
                    break
            else:
                raise NotYetImplementedError("No parser was found that accepted the replay file;check configuration")

        #Do cleanup and post processing
        for processor in config.processors:
            replay = processor.process(replay)
            
        return replay
Example #8
0
 def read_game_events(protocol, archive: MPQArchive) -> dict:
     game_event_file = archive.read_file('replay.game.events')
     return protocol.decode_replay_game_events(game_event_file)
Example #9
0
 def read_details(protocol, archive: MPQArchive) -> dict:
     detail_file = archive.read_file('replay.details')
     return protocol.decode_replay_details(detail_file)
Example #10
0
 def read_initdata(protocol, archive: MPQArchive) -> dict:
     init_file = archive.read_file('replay.initData')
     return protocol.decode_replay_initdata(init_file)
Example #11
0
 def read_metadata(protocol, archive: MPQArchive) -> dict:
     return archive.read_file('replay.gamemetadata.json')
Example #12
0
 def read_tracker_events(protocol, archive: MPQArchive) -> dict:
     tracker_event_file = archive.read_file('replay.tracker.events')
     return protocol.decode_replay_tracker_events(tracker_event_file)
Example #13
0
 def read_attribute_events(protocol, archive: MPQArchive) -> dict:
     attrib_event_file = archive.read_file('replay.attributes.events')
     return protocol.decode_replay_attributes_events(attrib_event_file)
Example #14
0
    def __init__(self, replay, partial_parse=True, full_parse=True):
        self.filename = replay
        self.speed = ""
        self.release_string = ""
        self.build = ""
        self.type = ""
        self.category = ""
        self.is_ladder = False
        self.is_private = False
        self.map = ""
        self.realm = ""
        self.events = list()
        self.results = dict()
        self.teams = defaultdict(list)
        self.players = list() #Unordered list of Player
        self.player = PlayerDict() #Maps pid to Player
        self.events_by_type = dict()
        self.attributes = list()
        self.length = None # (minutes, seconds) tuple
        self.messages = list()
        self.seconds = None # Length of the game in seconds
        self.versions = None # (number,number,number,number) tuple
        self.recorder = None # Player object
        self.frames = None # Integer representing FPS
        self.winner_known = False

        # Set in parsers.DetailParser.load, should we hide this?
        self.file_time = None # Probably number milliseconds since EPOCH
        # Marked as private in case people want raw file access
        self._files = dict() # Files extracted from mpyq

         #Used internally to ensure parse ordering
        self.__parsed = dict(details=False, attributes=False, messages=False, events=False, initdata=False)
        
        # TODO: Change to something better
        # http://en.wikipedia.org/wiki/Epoch_(reference_date)
        # Notice that Windows and Mac have different EPOCHs, I wonder whether
        # this is different depending on the OS on which the replay was played.
        self.date = "" # Date when the game was played
        
        #Make sure the file exists and is readable, first and foremost
        if not os.access(self.filename, os.F_OK):
            raise ValueError("File at '%s' cannot be found" % self.filename)
        elif not os.access(self.filename, os.R_OK):
            raise ValueError("File at '%s' cannot be read" % self.filename)
            
        #Always parse the header first, the extract the files
        self._parse_header()

        #Manually extract the contents of SC2Replay file (bypass the listfile)
        archive = MPQArchive(replay, listfile=False)
        self._files['replay.initData'] = archive.read_file('replay.initData')
        self._files['replay.details'] = archive.read_file('replay.details')
        self._files['replay.attributes.events'] = archive.read_file('replay.attributes.events')
        self._files['replay.message.events'] = archive.read_file('replay.message.events')
        self._files['replay.game.events'] = archive.read_file('replay.game.events')
                
        #These are quickly parsed files that contain most of the game information
        #The order is important, I need some way to reinforce it in the future
        if partial_parse or full_parse:
            self._parse_initdata()
            self._parse_details()
            self._parse_attributes()
            self._parse_messages()
        
        #Parsing events takes forever, so only do this on request
        if full_parse:
            self._parse_events()