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 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