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
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
def kill(): logger.warn("Process forcefully terminated.") instance.kill()
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