Example #1
0
def check(mod, mapname = None, version = None, modVersions = None, sim_mods = None, silent=False):
    '''
    This checks whether the game is properly updated and has the correct map.
    '''
    logger.info("Checking FA for: " + str(mod) + " and map " + str(mapname))
    
    if not mod:
        QtGui.QMessageBox.warning(None, "No Mod Specified", "The application didn't specify which mod to update.")
        return False
        
    if not fa.gamepath:
        savePath(fa.updater.autoDetectPath())
               
    while (not fa.updater.validatePath(fa.gamepath)):
        logger.warn("Invalid path: " + str(fa.gamepath))
        wizard = fa.updater.Wizard(None)
        result = wizard.exec_()
        if not result:  # The wizard only returns successfully if the path is okay.
            return False
    
    # Perform the actual comparisons and updating                    
    logger.info("Updating FA for mod: " + str(mod) + ", version " + str(version))

    # Spawn an update for the required mod
    updater = fa.updater.Updater(mod, version, modVersions, silent=silent)
            
    result = updater.run()

    updater = None #Our work here is done

    if (result != fa.updater.Updater.RESULT_SUCCESS):
        return False 

    logger.info("Writing fa_path.lua config file.")
    try:
        writeFAPathLua()
    except:
        logger.error("fa_path.lua can't be written: ", exc_info=sys.exc_info())
        QtGui.QMessageBox.critical(None, "Cannot write fa_path.lua", "This is a  rare error and you should report it!<br/>(open Menu BETA, choose 'Report a Bug')")             
        return False
        

    # Now it's down to having the right map
    if mapname:
        if not checkMap(mapname, silent=silent):
            return False

    if sim_mods:
        return checkMods(sim_mods)
        
    return True #FA is checked and ready
Example #2
0
def checkMods(mods): #mods is a dictionary of uid-name pairs
    '''
    Assures that the specified mods are available in FA, or returns False.
    Also sets the correct active mods in the ingame mod manager.
    '''
    logger.info("Updating FA for mods %s" % ", ".join(mods))
    to_download = []
    inst = modvault.getInstalledMods()
    uids = [mod.uid for mod in inst]
    for uid in mods:
        if uid not in uids:
            to_download.append(uid)

    for uid in to_download:
        result = QtGui.QMessageBox.question(None, "Download Mod", "Seems that you don't have this mod. Do you want to download it?<br/><b>" + mods[uid] + "</b>", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        if result == QtGui.QMessageBox.Yes:
            # Spawn an update for the required mod
            updater = fa.updater.Updater(uid, sim=True)
            result = updater.run()
            updater = None #Our work here is done
            if (result != fa.updater.Updater.RESULT_SUCCESS):
                return False
        else:
            return False

    actual_mods = []
    inst = modvault.getInstalledMods()
    uids = {}
    for mod in inst:
        uids[mod.uid] = mod
    for uid in mods:
        if uid not in uids:
            QtGui.QMessageBox.warning(None, "Mod not Found", "%s was apparently not installed correctly. Please check this." % mods[uid])
            return
        actual_mods.append(uids[uid])
    if not modvault.setActiveMods(actual_mods):
        logger.warn("Couldn't set the active mods in the game.prefs file")
        return False

    return True
Example #3
0
def kill():
    logger.warn("Process forcefully terminated.")
    instance.kill()
Example #4
0
def replay(source, detach = False):
    '''
    Launches FA streaming the replay from the given location. Source can be a QUrl or a string
    '''
    logger.info("fa.exe.replay(" + str(source) + ", detach = " + str(detach))
    
    if (available()):
        version = None
        featured_mod_versions = None
        arg_string = None
        replay_id = None
        # Convert strings to URLs
        if isinstance(source, basestring):
            if os.path.isfile(source):
                if source.endswith(".fafreplay"):   # the new way of doing things
                    replay = open(source, "rt")
                    info = json.loads(replay.readline())
                    
                    binary = QtCore.qUncompress(QtCore.QByteArray.fromBase64(replay.read()))
                    logger.info("Extracted " + str(binary.size()) + " bytes of binary data from .fafreplay.")
                    replay.close()
                    
                    if binary.size() == 0:
                        logger.info("Invalid replay")
                        QtGui.QMessageBox.critical(None, "FA Forever Replay", "Sorry, this replay is corrupted.")
                        return False
                        
                    scfa_replay = QtCore.QFile(os.path.join(util.CACHE_DIR, "temp.scfareplay"))
                    scfa_replay.open(QtCore.QIODevice.WriteOnly | QtCore.QIODevice.Truncate)                
                    scfa_replay.write(binary)
                    scfa_replay.flush()
                    scfa_replay.close()                    
                                
                    mapname = info.get('mapname', None)
                    mod = info['featured_mod']        
                    replay_id = info['uid']
                    featured_mod_versions = info.get('featured_mod_versions', None)
                    arg_string = scfa_replay.fileName()
                    
                    parser = replayParser(arg_string)
                    version = parser.getVersion() 
                    
                    if mod == "gw":
                        infoReplayGW = fa.gwreplayinfo.GWReplayInfo(info['uid'])
                        result = infoReplayGW.run()
                        if (result != fa.gwreplayinfo.GWReplayInfo.RESULT_SUCCESS):
                            logger.info("We don't have the info necessary for GW")
                            return False                  

                        logger.info("Writing GW game table file.")

                elif source.endswith(".scfareplay"):   # compatibility mode
                    filename = os.path.basename(source)
                    if len(filename.split(".")) > 2:                        
                        mod = filename.rsplit(".", 2)[1]
                        logger.info("mod guessed from " + source + " is " + mod)
                    else:
                        mod = "faf" #TODO: maybe offer a list of mods for the user.
                        logger.warn("no mod could be guessed, using fallback ('faf') ")
                                    
                    mapname = None
                    arg_string = source
                    parser = replayParser(arg_string)
                    version = parser.getVersion()
                else:
                    QtGui.QMessageBox.critical(None, "FA Forever Replay", "Sorry, FAF has no idea how to replay this file:<br/><b>" + source + "</b>")        
                
                logger.info("Replaying " + str(arg_string) + " with mod " + str(mod) + " on map " + str(mapname))
            else:
                source = QtCore.QUrl(source)    #Try to interpret the string as an actual url, it may come from the command line
        
        if isinstance(source, QtCore.QUrl):
            url = source
            #Determine if it's a faflive url
            if url.scheme() == "faflive":
                mod = url.queryItemValue("mod")
                mapname = url.queryItemValue("map")                
                replay_id = url.path().split("/")[0]
                # whip the URL into shape so ForgedAlliance.exe understands it
                arg_url = QtCore.QUrl(url)
                arg_url.setScheme("gpgnet")
                arg_url.setEncodedQuery(QtCore.QByteArray())
                arg_string = arg_url.toString()
            else:
                QtGui.QMessageBox.critical(None, "FA Forever Replay", "App doesn't know how to play replays from that scheme:<br/><b>" + url.scheme() + "</b>")        
                return False                        

        # We couldn't construct a decent argument format to tell ForgedAlliance for this replay
        if not arg_string:
            QtGui.QMessageBox.critical(None, "FA Forever Replay", "App doesn't know how to play replays from that source:<br/><b>" + str(source) + "</b>")
            return False
            
        # Launch preparation: Start with an empty arguments list
        arguments = []    
        arguments.append('/replay')         
        arguments.append(arg_string)  
        #arguments.append('/sse2')
        #arguments.append('/networksafe')                        
                        
        #Proper mod loading code
        if not '/init' in arguments:
            arguments.append('/init')
            arguments.append("init_" + mod + ".lua")
                                        
        #disable bug reporter and movies
        arguments.append('/nobugreport')

        #log file
        arguments.append("/log")
        arguments.append('"' + util.LOG_FILE_REPLAY + '"')

        if replay_id:
            arguments.append("/replayid")
            arguments.append(str(replay_id))

        # Update the game appropriately
        if not check(mod, mapname, version, featured_mod_versions):
            logger.error("Can't watch replays without an updated Forged Alliance game!")
            return False        

        if mod == "gw":
        # in case of GW, we need to alter the scenario for support AIs
            if not fa.maps.gwmap(info['mapname']):
                logger.error("You don't have the required map.")
                return    

        # Finally, run executable        
        if __run(None, arguments, detach):
            logger.info("Viewing Replay.")
            return True
        else:
            logger.error("Replaying failed.")
            return False