def ripAppearance(srcName, destName, srcForm='player', destForm='player', flags=unicode(0x2 | 0x4 | 0x8 | 0x10)): """Rips a face from one save game and pastes it into another.""" flags = intArg(flags) srcName = GPath(srcName) destName = GPath(destName) #--Get source face srcFile = data.getSaveFile(srcName) if srcForm == 'player': face = PCFaces.save_getPlayerFace(srcFile) else: srcForm = intArg(srcForm) face = PCFaces.save_getCreatedFace(srcFile, srcForm) #printFace(face) #--Set destination face if srcName == destName: destFile = srcFile else: destFile = data.getSaveFile(destName) if destForm == 'player': PCFaces.save_setPlayerFace(destFile, face, flags) #--Race, gender, hair, eyes else: destForm = intArg(destForm) PCFaces.save_setCreatedFace(destFile, destForm, face) if not face.gender: data.shapeIsMale.touch() if destName not in data.saves: destFile.safeSave() #--Done print face.pcName, u'...',
def renameArchives(root=r"C:\Program Files\Bethesda Softworks\Fallout 3\Downloads"): """Renames TesSource archive files to sort a little better. E.g., change 12345-2.23-My Wicked Mod-TESSource.zip to My Wicked Mod 2.23.zip.""" reTesSource = re.compile(r"^\d{4}-(\d[^-]*)-(.+)-TESSource.(zip|rar|7z|ace|exe)$", re.I) reTesSourceNV = re.compile(r"^\d{4}-(.+)-TESSource.(zip|rar|7z|ace|exe)$", re.I) reTesSource3 = re.compile(r"^(.+)-\d+-TESSource.(zip|rar|7z|ace|exe|esp)$", re.I) reBracketNum = re.compile(r"\[1\]") for (dirPath, dirNames, fileNames) in os.walk(root): dirPath = GPath(dirPath) for name in fileNames: path = dirPath.join(name) maTesSource = reTesSource.match(name.s) maTesSource3 = reTesSource3.match(name.s) maTesSourceNV = reTesSourceNV.match(name.s) if maTesSource: newName = "%s %s.%s" % maTesSource.group(2, 1, 3) elif maTesSourceNV: newName = "%s.%s" % maTesSourceNV.group(1, 2) elif maTesSource3: newName = "%s.%s" % maTesSource3.group(1, 2) else: newName = name newName = reBracketNum.sub("", newName) if newName != name: newPath = os.path.join(dirPath, newName) print newName.s path.moveTo(newPath)
def bookImport(fileName=None): """Import data from text file into book.""" fileName = GPath(fileName) init(3) data = {} # --Import from book textPath = GPath(fileName.root() + ".csv") ins = textPath.open() ins.readline() # --Skip first line for line in ins: line = line.strip() if not line or "\t" not in line: return (eid, full, value) = line.split("\t")[:3] eid = eid[1:-1] full = full[1:-1] value = int(value) # print eid,full,value data[eid] = value ins.close() # --Export to book modInfo = bosh.modInfos[fileName] loadFactory = bosh.LoadFactory(True, bosh.MreBook) modFile = bosh.ModFile(modInfo, loadFactory) modFile.load(True) for book in modFile.BOOK.records: if book.eid in data: print "%-35s %3d %3d" % (book.eid, book.value, data[book.eid]) book.value = data[book.eid] book.setChanged() else: print book.eid, "NOT----------" modFile.safeSave()
def __init__(self, settings_file): self._settings_file = GPath(settings_file) self._saved_settings_version = self._settings_saved_with = None # bash.ini handling self._timestamped_old = self.__unset self._bash_ini_path = self.__unset # extract folder self._extract_dir = self.__unset
def getOblivionModsPath(bash_ini_, game_info): ob_mods_path = get_path_from_ini(bash_ini_, u'sOblivionMods') if ob_mods_path: src = [u'[General]', u'sOblivionMods'] else: ob_mods_path = GPath(GPath(u'..').join(u'%s Mods' % game_info.fsName)) src = u'Relative Path' if not ob_mods_path.isabs(): ob_mods_path = dirs['app'].join(ob_mods_path) return ob_mods_path, src
def getJava(): """Locate javaw.exe to launch jars from Bash.""" if _os.name == 'posix': import subprocess java_bin_path = '' try: java_bin_path = subprocess.check_output('command -v java', shell=True).rstrip('\n') except subprocess.CalledProcessError: pass # what happens when java doesn't exist? return GPath(java_bin_path) try: java_home = GPath(_os.environ['JAVA_HOME']) java = java_home.join('bin', u'javaw.exe') if java.exists(): return java except KeyError: # no JAVA_HOME pass win = GPath(_os.environ['SYSTEMROOT']) # Default location: Windows\System32\javaw.exe java = win.join(u'system32', u'javaw.exe') if not java.exists(): # 1st possibility: # - Bash is running as 32-bit # - The only Java installed is 64-bit # Because Bash is 32-bit, Windows\System32 redirects to # Windows\SysWOW64. So look in the ACTUAL System32 folder # by using Windows\SysNative java = win.join(u'sysnative', u'javaw.exe') if not java.exists(): # 2nd possibility # - Bash is running as 64-bit # - The only Java installed is 32-bit # So javaw.exe would actually be in Windows\SysWOW64 java = win.join(u'syswow64', u'javaw.exe') return java
def moveSave(oldSave,newSave): """Temporarilty moves quicksave.ess to quicktemp.ess.""" #--Use path.tail to prevent access outside of saves directory oldPath = data.savesDir.join(GPath(oldSave).tail) newPath = data.savesDir.join(GPath(newSave).tail) if newPath.exists() and not newPath.isfile(): raise bolt.BoltError(newPath+_(' exists and is not a save file.')) if oldPath.exists(): if not oldPath.isfile(): raise bolt.BoltError(oldPath+_(' is not a save file.')) oldPath.moveTo(newPath) bosh.CoSaves(oldPath).move(newPath)
def temp(fileName=None): import psyco psyco.full() init(3) testClasses = (bosh.MreWrld, bosh.MreCell, bosh.MreAcre, bosh.MreAchr, bosh.MreRefr) loadFactory = bosh.LoadFactory(False, *testClasses) modInfo = bosh.modInfos[GPath(fileName)] modFile = bosh.ModFile(modInfo, loadFactory) modFile.load(True) strf = bosh.strFid for cb in modFile.CELL.cellBlocks: print cb.cell.full, strf(cb.cell.fid) cb.cell.setChanged() for attr in ("persistent", "temp", "distant"): # print ' ',attr for record in getattr(cb, attr): # print ' ',strf(record.fid) record.setChanged() for wb in modFile.WRLD.worldBlocks: print wb.world.full, strf(wb.world.fid) for cb in wb.cellBlocks: print ".", cb.cell.full, strf(cb.cell.fid) cb.cell.setChanged() for attr in ("persistent", "temp", "distant"): # print ' ',attr for record in getattr(cb, attr): # print ' ',strf(record.fid) record.setChanged() modFile.tes4.masters.append(modInfo.name) modFile.tes4.setChanged() outInfo = bosh.ModInfo(modInfo.dir, GPath("Wrye Dump.esp")) modFile.fileInfo = outInfo loadFactory.keepAll = True modFile.askSave() return for record in modFile.SCPT.getActiveRecords(): print record.eid out = GPath(record.eid + ".mws").open("w") out.write(record.scriptText) out.close() return # --Save to test file for testClass in testClasses: print testClass.classType for record in getattr(modFile, testClass.classType).records: # print record.eid if reBarExt.match(record.model.modPath): record.model.modPath = reBarExt.sub(r"Architecture\\BarabusCrypt", record.model.modPath) print record.eid, record.model.modPath record.setChanged() modFile.askSave(True)
def compressionSettings(archive_path, blockSize, isSolid): archiveType = writeExts.get(archive_path.cext) if not archiveType: #--Always fall back to using the defaultExt archive_path = GPath(archive_path.sbody + defaultExt).tail archiveType = writeExts.get(archive_path.cext) if archive_path.cext in noSolidExts: # zip solid = u'' else: if isSolid: if blockSize: solid = u'-ms=on -ms=%dm' % blockSize else: solid = u'-ms=on' else: solid = u'-ms=off' userArgs = bass.inisettings['7zExtraCompressionArguments'] if userArgs: if reSolid.search(userArgs): if not solid: # zip, will blow if ms=XXX is passed in old = userArgs userArgs = reSolid.sub(u'', userArgs).strip() if old != userArgs: deprint(archive_path.s + u': 7zExtraCompressionArguments ini option "' + old + u'" -> "' + userArgs + u'"') solid = userArgs else: solid += userArgs return archive_path, archiveType, solid
def swapPlayer(saveName, oldForm, newForm, flags=0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40): """Swaps the player between old and new forms. Archives player's current form/stats to oldForm, then changes player into new form.""" oldForm = intArg(oldForm) newForm = intArg(newForm) flags = intArg(flags) #--Open Save file saveName = GPath(saveName) saveFile = data.getSaveFile(saveName) #--player >> oldForm oldFace = PCFaces.save_getPlayerFace(saveFile) PCFaces.save_setCreatedFace(saveFile, oldForm, oldFace) if not oldFace.gender: data.shapeIsMale.touch() #--newForm >> player newFace = PCFaces.save_getCreatedFace(saveFile, newForm) PCFaces.save_setPlayerFace(saveFile, newFace, flags) #--Checking #printFace(oldFace) #printFace(PCFaces.save_getCreatedFace(saveFile,oldForm)) #printFace(newFace) #printFace(PCFaces.save_getPlayerFace(saveFile)) #--Save and done if saveName not in data.saves: saveFile.safeSave() print u' %s >> %s...' % (oldFace.pcName, newFace.pcName)
def extract7z(src_archive, extract_dir, progress=None, readExtensions=None, recursive=False, filelist_to_extract=None): command = _extract_command(src_archive, extract_dir, recursive, filelist_to_extract) proc = subprocess.Popen(command, stdout=subprocess.PIPE, bufsize=1, stdin=subprocess.PIPE, startupinfo=startupinfo) # Error checking, progress feedback and subArchives for recursive unpacking index, errorLine, subArchives = 0, u'', [] source_archive = src_archive.tail.s with proc.stdout as out: for line in iter(out.readline, b''): line = unicode(line, 'utf8') if regErrMatch(line): errorLine = line + u''.join(out) break maExtracting = regExtractMatch(line) if maExtracting: extracted = GPath(maExtracting.group(1).strip()) if readExtensions and extracted.cext in readExtensions: subArchives.append(extracted) if not progress: continue progress(index, source_archive + u'\n' + _( u'Extracting files...') + u'\n' + extracted.s) index += 1 returncode = proc.wait() if returncode or errorLine: raise StateError(u'%s: Extraction failed:\n7z.exe return value: %s\n%s' % (source_archive, str(returncode), errorLine)) return subArchives
def BrowseToMWDir(): """Dialog to select Morrowind installation directory. Called by OnInit().""" # --Ask user through dialog. while True: mwDirDialog = wx.DirDialog( None, _(u"Select your Morrowind installation directory.")) result = mwDirDialog.ShowModal() mwDir = mwDirDialog.GetPath() mwDirDialog.Destroy() # --User canceled? if result != wx.ID_OK: return False # --Valid Morrowind install directory? elif os.path.exists(os.path.join(mwDir, u'Morrowind.ini')): conf.settings['mwDir'] = mwDir conf.dirs['app'] = GPath(mwDir) return True # --Retry? retryDialog = wx.MessageDialog( None, _(u"Can't find Morrowind.ini in {!s}! Try again?".format(mwDir)), _(u'Morrowind Install Directory'), wx.YES_NO | wx.ICON_EXCLAMATION) result = retryDialog.ShowModal() retryDialog.Destroy() if result != wx.ID_YES: return False
def get_personal_path(): if shell and shellcon: path = _getShellPath(shellcon.CSIDL_PERSONAL) sErrorInfo = _(u"Folder path extracted from win32com.shell.") else: path = _getShellPath('Personal') sErrorInfo = __get_error_info() return GPath(path), sErrorInfo
def _supportedGames(useCache=True): """Set games supported by Bash and return their paths from the registry.""" if useCache and _allGames: return _registryGames.copy() # rebuilt cache _allGames.clear() _registryGames.clear() import pkgutil import game as _game # Detect the known games for importer,modname,ispkg in pkgutil.iter_modules(_game.__path__): if not ispkg: continue # game support modules are packages # Equivalent of "from game import <modname>" try: module = __import__('game',globals(),locals(),[modname],-1) except ImportError: deprint(u'Error in game support module:', modname, traceback=True) continue submod = getattr(module,modname) if not hasattr(submod,'fsName') or not hasattr(submod,'exe'): continue _allGames[submod.fsName.lower()] = submod #--Get this game's install path if not winreg: del module continue for hkey in (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE): for wow6432 in (u'',u'Wow6432Node\\'): for (subkey,entry) in submod.regInstallKeys: try: key = winreg.OpenKey(hkey, u'Software\\%s%s' % (wow6432,subkey)) value = winreg.QueryValueEx(key,entry) except: continue if value[1] != winreg.REG_SZ: continue installPath = GPath(value[0]) if not installPath.exists(): continue exePath = installPath.join(submod.exe) if not exePath.exists(): continue _registryGames[submod.fsName.lower()] = installPath del module # unload some modules, _supportedGames is meant to run once del pkgutil del _game deprint(u'Detected the following supported games via Windows Registry:') for foundName in _registryGames: deprint(u' %s:' % foundName, _registryGames[foundName]) return _registryGames.copy()
def get_local_app_data_path(): if shell and shellcon: path = _getShellPath(shellcon.CSIDL_LOCAL_APPDATA) sErrorInfo = _(u"Folder path extracted from win32com.shell.") else: path = _getShellPath('Local AppData') sErrorInfo = __get_error_info() return GPath(path), sErrorInfo
def __init__(self, settings_file, fsName): self._backup_dest_file = settings_file # absolute path to dest 7z file self.files = {} for (bash_dir, tmpdir), setting_files in \ _init_settings_files(fsName).iteritems(): if not setting_files: # we have to backup everything in there setting_files = bash_dir.list() tmp_dir = GPath(tmpdir) for name in setting_files: fpath = bash_dir.join(name) if fpath.exists(): self.files[tmp_dir.join(name)] = fpath # backup save profile settings savedir = GPath(u'My Games').join(fsName) profiles = [u''] + initialization.getLocalSaveDirs() for profile in profiles: pluginsTxt = (u'Saves', profile, u'plugins.txt') loadorderTxt = (u'Saves', profile, u'loadorder.txt') for txt in (pluginsTxt, loadorderTxt): tpath = savedir.join(*txt) fpath = dirs['saveBase'].join(*txt) if fpath.exists(): self.files[tpath] = fpath table = (u'Saves', profile, u'Bash', u'Table.dat') tpath = savedir.join(*table) fpath = dirs['saveBase'].join(*table) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def restore_ini(self): if self._timestamped_old is self.__unset: return # we did not move bash.ini if self._timestamped_old is not None: bolt.deprint(u'Restoring bash.ini') GPath(self._timestamped_old).copyTo(u'bash.ini') elif self._bash_ini_path: # remove bash.ini as it is the one from the backup bolt.GPath(u'bash.ini').remove()
def get_registry_path(subkey, entry, exe): """Check registry for a path to a program.""" if not winreg: return None for hkey in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER): for wow6432 in (u'', u'Wow6432Node\\'): try: key = winreg.OpenKey(hkey, u'Software\\%s%s' % (wow6432, subkey)) value = winreg.QueryValueEx(key, entry) except OSError: continue if value[1] != winreg.REG_SZ: continue installPath = GPath(value[0]) if not installPath.exists(): continue exePath = installPath.join(exe) if not exePath.exists(): continue return installPath return None
def keepRecords(self, keepIds): """Keeps records with fid in set keepIds. Discards the rest.""" self.records = [ record for record in self.records if (record.fid == (record.isKeyedByEid and GPath(bosh.modInfos.masterName), 0) and record.eid in keepIds) or record.fid in keepIds ] self.id_records.clear() self.setChanged()
def unpack7z(srcFile, dstDir, progress=None): # extract srcFile to dstDir progress = progress or Progress() # count the files in the archive length = 0 reList = re.compile(u'Path = (.*?)(?:\r\n|\n)', re.U) command = ur'"%s" l -slt "%s"' % (dirs['compiled'].join(u'7z.exe').s, srcFile.s) ins, err = Popen(command, stdout=PIPE, stdin=PIPE, startupinfo=startupinfo).communicate() ins = StringIO.StringIO(ins) for line in ins: length += 1 ins.close() if progress: progress(0, srcFile.s + u'\n' + _(u'Extracting files...')) progress.setFull(1 + length) #end if app7z = dirs['compiled'].join(u'7z.exe').s command = u'"%s" x "%s" -y -o"%s"' % (app7z, srcFile.s, dstDir.s) #--Extract files ins = Popen(command, stdout=PIPE, stdin=PIPE, startupinfo=startupinfo).stdout #--Error Checking, and progress feedback #--Note subArchives for recursive unpacking reExtracting = re.compile(u'Extracting\s+(.+)', re.U) regMatch = reExtracting.match reError = re.compile(u'Error: (.*)', re.U) regErrMatch = reError.match errorLine = [] index = 0 for line in ins: line = unicode(line, 'utf8') maExtracting = regMatch(line) if len(errorLine) or regErrMatch(line): errorLine.append(line) if maExtracting: extracted = GPath(maExtracting.group(1).strip()) if progress: progress( index, srcFile.s + u'\n' + _(u'Extracting files...') + u'\n' + extracted.s) #end if index += 1 #end if #end for result = ins.close() if result: raise StateError(srcFile.s + u': Extraction failed:\n' + u'\n'.join(errorLine))
def GetActivePlugins(self): plugins = c_uint8_p_p() num = c_size_t() try: _CGetActivePlugins(self._DB, byref(plugins), byref(num)) except BossError as e: if e.code == BOSS_API_ERROR_FILE_NOT_FOUND: self.SetActivePlugins([]) _CGetActivePlugins(self._DB, byref(plugins), byref(num)) else: raise return [GPath(_uni(plugins[i])) for i in xrange(num.value)]
def csType(newType, fileName="CS Functions.txt"): """Generates various function tables for CS Wiki from a raw CSFunctions.csv file.""" # --Get list path = GPath("CS Types.txt") funcs = set([x.strip() for x in path.open()]) changed = set() # --Edit records = [] functions = set() path = GPath(fileName) ins = path.open() out = path.temp.open("w") for line in ins: line = re.sub("#.*", "", line.strip()) fields = line.split(";") fields = map(string.strip, fields) if fields and fields[0] and fields[0] != "Function": while len(fields) < 4: fields.append("") func, source, type, text = fields if func and func in funcs and newType not in type: if type: type += ", " + newType else: type = newType changed.add(func) out.write(";".join((func, source, type, text)) + "\n") ins.close() out.close() path.untemp(True) print "\n".join(sorted(changed))
def getPersonalPath(bash_ini_, my_docs_path): #--Determine User folders from Personal and Local Application Data directories # Attempt to pull from, in order: Command Line, Ini, win32com, Registry if my_docs_path: my_docs_path = GPath(my_docs_path) sErrorInfo = _(u"Folder path specified on command line (-p)") else: my_docs_path = get_path_from_ini(bash_ini_, 'sPersonalPath') if my_docs_path: sErrorInfo = _( u"Folder path specified in bash.ini (%s)") % u'sPersonalPath' else: my_docs_path, sErrorInfo = get_personal_path() # If path is relative, make absolute if not my_docs_path.isabs(): my_docs_path = dirs['app'].join(my_docs_path) # Error check if not my_docs_path.exists(): raise BoltError(u"Personal folder does not exist.\n" u"Personal folder: %s\nAdditional info:\n%s" % (my_docs_path.s, sErrorInfo)) return my_docs_path
def _restore_settings(self, fsName): deprint(u'') deprint(_(u'RESTORE BASH SETTINGS: ') + self._settings_file.s) # backup previous Bash ini if it exists old_bash_ini = dirs['mopy'].join(u'bash.ini') self._timestamped_old = u''.join( [old_bash_ini.root.s, u'(', bolt.timestamp(), u').ini']) try: old_bash_ini.moveTo(self._timestamped_old) deprint(u'Existing bash.ini moved to %s' % self._timestamped_old) except StateError: # does not exist self._timestamped_old = None # restore all the settings files restore_paths = _init_settings_files(fsName).keys() for dest_dir, back_path in restore_paths: full_back_path = self._extract_dir.join(back_path) for name in full_back_path.list(): if full_back_path.join(name).isfile(): deprint( GPath(back_path).join(name).s + u' --> ' + dest_dir.join(name).s) full_back_path.join(name).copyTo(dest_dir.join(name)) # restore savegame profile settings back_path = GPath(u'My Games').join(fsName, u'Saves') saves_dir = dirs['saveBase'].join(u'Saves') full_back_path = self._extract_dir.join(back_path) if full_back_path.exists(): for root_dir, folders, files_ in full_back_path.walk( True, None, True): root_dir = GPath(u'.' + root_dir.s) for name in files_: deprint( back_path.join(root_dir, name).s + u' --> ' + saves_dir.join(root_dir, name).s) full_back_path.join(root_dir, name).copyTo( saves_dir.join(root_dir, name))
def setRecord(self, record): """Adds record to record list and indexed.""" if self.records and not self.id_records: self.indexRecords() record_id = record.fid if record.isKeyedByEid: if record_id == (GPath(bosh.modInfos.masterName), 0): record_id = record.eid if record_id in self.id_records: oldRecord = self.id_records[record_id] index = self.records.index(oldRecord) self.records[index] = record else: self.records.append(record) self.id_records[record_id] = record
def cmdRestore(): # restore settings on user request if not basherImported: import basher, barb backup = None path = None quit = opts.restore and opts.quietquit if opts.restore: path = GPath(opts.filename) if opts.restore: try: backup = barb.RestoreSettings(basher.bashFrame, path, quit, opts.backup_images) backup.Apply() except barb.BackupCancelled: pass del backup return quit
def cmdBackup(): # backup settings if app version has changed or on user request global basher, balt, barb if not basher: import basher, balt, barb path = None quit = opts.backup and opts.quietquit if opts.backup: path = GPath(opts.filename) if barb.BackupSettings.PromptMismatch() or opts.backup: backup = barb.BackupSettings(balt.Link.Frame, path, quit, opts.backup_images) try: backup.Apply() except bolt.StateError: if backup.SameAppVersion(): backup.WarnFailed() elif backup.PromptQuit(): return False except barb.BackupCancelled: if not backup.SameAppVersion() and not backup.PromptContinue(): return False del backup return quit
def init_app_links(apps_dir, badIcons, iconList): init_params = [] for path, (target, icon, description) in _get_app_links(apps_dir).iteritems(): if target.lower().find( ur'installer\{') != -1: # msi shortcuts: dc0c8de target = path else: target = GPath(target) if not target.exists(): continue # Target exists - extract path, icon and description # First try a custom icon #TODO(ut) docs - also comments methods here! fileName = u'%s%%i.png' % path.sbody customIcons = [apps_dir.join(fileName % x) for x in (16, 24, 32)] if customIcons[0].exists(): icon = customIcons # Next try the shortcut specified icon else: icon, idex = icon.split(u',') if icon == u'': if target.cext == u'.exe': if win32gui and win32gui.ExtractIconEx(target.s, -1): # -1 queries num of icons embedded in the exe icon = target else: # generic exe icon, hardcoded and good to go icon, idex = _os.path.expandvars( u'%SystemRoot%\\System32\\shell32.dll'), u'2' else: icon, idex = _get_default_app_icon(idex, target) icon = GPath(icon) if icon.exists(): fileName = u';'.join((icon.s, idex)) icon = iconList(fileName) # Last, use the 'x' icon else: icon = badIcons init_params.append((path, icon, description))
def SortMods(self, trialOnly=False): plugins = c_uint8_p_p() num = c_size_t() lastRec = c_size_t() _CSortMods(self._DB, byref(plugins), byref(num), byref(lastRec)) return [GPath(_uni(plugins[i])) for i in xrange(num.value)]
def dumpPage(fileName, records, source=None, header=None): doLinks = source != "TSFC" # --Filter? if source: records = [x for x in records if re.match(source, x[1])] out = GPath(fileName).open("w") # --Header if header: out.write(header + "\n\n") out.write("'''Editors:''' Do not edit entries on this page. See [[Raw Function List]] for more info.\n\n") if doLinks: out.write("{{CompactTOC4}}\n") # --Sort records.sort(key=lambda x: x[0].lower()) current = "" links = ( "", " - [[#A|A]][[#B|B]][[#C|C]][[#D|D]][[#E|E]][[#F|F]][[#G|G]][[#H|H]][[#I|I]][[#J|J]][[#K|K]][[#L|L]][[#M|M]][[#N|N]][[#O|O]][[#P|P]][[#Q|Q]][[#R|R]][[#S|S]][[#T|T]][[#U|U]][[#V|V]][[#W|W]][[#X|X]][[#Y|Y]][[#Z|Z]]", )[doLinks] if source == "TSFC": links = "" for func, src, type, text in records: # --Alpha header if func[0].upper() != current: if current: out.write("|}\n\n") current = func[0].upper() if doLinks: out.write("===%s===\n" % current) out.write("{| width=100% class=functionTable\n|-\n") out.write("!align=left width=10%|Source\n") # out.write('!align=left width=10%|Type\n') out.write("!align=left width=35%|Function\n") # out.write('!align=left|Description ([[#top|Top]])\n') out.write("!align=left|Description" + links + "\n") # --Entry fields = (groupLink(src), "[[" + func + "]]", text) out.write("|-\n|" + (" || ".join(fields)) + "\n") if current: out.write("|}\n") out.write("\n[[Category:Scripting]]\n") out.close() print "Wrote", fileName
def csFunctions(fileName="CS Functions.txt"): """Generates various function tables for CS Wiki from a raw CSFunctions.csv file.""" records = [] functions = set() source_icol = {"Function": 0, "Source": 1, "Type": 2, "Description": 3} ins = GPath(fileName).open() for line in ins: line = re.sub("#.*", "", line.strip()) fields = line.split(";") fields = map(string.strip, fields) if fields and fields[0] and fields[0] != "Function": while len(fields) < 4: fields.append("") if not fields[1]: print " No source for", fields[0] if fields[0] in functions: print " Repeated function", fields[0] functions.add(fields[0]) records.append(fields) ins.close() print "Read", fileName # --Page writer def groupLink(group): group = re.sub("OBSE", "[[:Category:Fallout3_Script_Extender|OBSE]]", group) group = re.sub("Pluggy", "[[:Category:Pluggy|]]", group) group = re.sub("TSFC", "[[:Category:TSFC|]]", group) return group def dumpPage(fileName, records, source=None, header=None): doLinks = source != "TSFC" # --Filter? if source: records = [x for x in records if re.match(source, x[1])] out = GPath(fileName).open("w") # --Header if header: out.write(header + "\n\n") out.write("'''Editors:''' Do not edit entries on this page. See [[Raw Function List]] for more info.\n\n") if doLinks: out.write("{{CompactTOC4}}\n") # --Sort records.sort(key=lambda x: x[0].lower()) current = "" links = ( "", " - [[#A|A]][[#B|B]][[#C|C]][[#D|D]][[#E|E]][[#F|F]][[#G|G]][[#H|H]][[#I|I]][[#J|J]][[#K|K]][[#L|L]][[#M|M]][[#N|N]][[#O|O]][[#P|P]][[#Q|Q]][[#R|R]][[#S|S]][[#T|T]][[#U|U]][[#V|V]][[#W|W]][[#X|X]][[#Y|Y]][[#Z|Z]]", )[doLinks] if source == "TSFC": links = "" for func, src, type, text in records: # --Alpha header if func[0].upper() != current: if current: out.write("|}\n\n") current = func[0].upper() if doLinks: out.write("===%s===\n" % current) out.write("{| width=100% class=functionTable\n|-\n") out.write("!align=left width=10%|Source\n") # out.write('!align=left width=10%|Type\n') out.write("!align=left width=35%|Function\n") # out.write('!align=left|Description ([[#top|Top]])\n') out.write("!align=left|Description" + links + "\n") # --Entry fields = (groupLink(src), "[[" + func + "]]", text) out.write("|-\n|" + (" || ".join(fields)) + "\n") if current: out.write("|}\n") out.write("\n[[Category:Scripting]]\n") out.close() print "Wrote", fileName # --Dump pages dumpPage( "CS All.txt", records, None, "[[Category:Scripting]]\nThis page lists all scripting functions including OBSE and OBSE plugin functions.", ) dumpPage( "CS CS.txt", records, "CS", "[[Category:Scripting]]\nThis page lists all native CS scripting functions. For a more comprehensive list (including OBSE and OBSE plugin functions), see [[List of Functions]].", ) dumpPage( "CS OBSE.txt", records, "OBSE", "[[Category:Scripting]][[Category:Fallout3 Script Extender]]\nThis page lists all functions for [[:Category:Fallout3_Script_Extender|]]. For a more comprehensive list (including native CS and OBSE plugin functions), see [[List of Functions]].", ) dumpPage( "CS Pluggy.txt", records, "Pluggy", "[[Category:Scripting]][[Category:Pluggy]]\nThis page lists all functions for [[:Category:Pluggy|]]. For a more comprehesive list of functions (including native CS and other OBSE related functions), see [[List of Functions]].", ) dumpPage( "CS TSFC.txt", records, "TSFC", "[[Category:Scripting]][[Category:TSFC]]\nThis page lists all functions for [[:Category:TSFC|]]. For a more comprehesive list of functions (including native CS and other OBSE related functions), see [[List of Functions]].", )
def ExtractAssets(self, contentPath, destPath): assets = c_char_p_p() num = c_size_t() _Cbsa_extract_assets(self._handle, _enc(contentPath), _enc(destPath), byref(assets), byref(num), True) return [GPath(_uni(assets[i])) for i in xrange(num.value)]
def detectGames(workingDir=u''): """Detect which supported games are intalled. - First, read the windows registry, checking for the install keys for the games. - Next, check for a valid game at "workingDir" - Finally, also look one directory up from the cwd.""" #--First: Find all supported games via the registry import pkgutil import game as _game foundGames = {} allGames = {} # Detect the known games for importer,modname,ispkg in pkgutil.iter_modules(_game.__path__): # Equivalent of "from game import <modname>" try: module = __import__('game',globals(),locals(),[modname],-1) except: deprint(u'Error in game support file:', modname, traceback=True) continue submod = getattr(module,modname) if not hasattr(submod,'name') or not hasattr(submod,'exe'): continue allGames[submod.name.lower()] = submod #--Get this game's install path for hkey in (_winreg.HKEY_CURRENT_USER, _winreg.HKEY_LOCAL_MACHINE): for wow6432 in (u'',u'Wow6432Node\\'): for (subkey,entry) in submod.regInstallKeys: try: key = _winreg.OpenKey(hkey, u'Software\\%s%s' % (wow6432,subkey)) value = _winreg.QueryValueEx(key,entry) except: continue if value[1] != _winreg.REG_SZ: continue installPath = GPath(value[0]) if not installPath.exists(): continue exePath = installPath.join(submod.exe) if not exePath.exists(): continue foundGames[submod.name.lower()] = installPath del module # unload some modules del pkgutil del _game deprint(u'Detected the following supported games via Windows Registry:') for foundName in foundGames: deprint(u' %s:' % foundName, foundGames[foundName]) #--Second: Detect what game is installed on directory up from Mopy path = Path.getcwd() if path.cs[-4:] == u'mopy': path = GPath(path.s[:-5]) installPaths = [path] #--Third: Detect what game is installed at the specified "workingDir" if workingDir != u'': path = GPath(workingDir) if not path.isabs(): path = Path.getcwd().join(path) installPaths.insert(0,path) deprint(u'Detecting games via relative path and the -o argument:') name = None for path in installPaths: _name = path.tail.cs if _name in allGames: # We have a config for that game deprint(u' %s:' % _name, path) foundGames[_name] = path name = _name break else: # Folder name wasn't found, try looking by exe name for file in path.list(): for _name in allGames: if allGames[_name].exe == file: # Must be this game deprint(u' %s:' % _name, path) name = _name foundGames[name] = path break else: continue break else: continue break return foundGames,allGames,name
def Apply(self): if self.ErrorConflict(): self.WarnFailed() return elif not self.PromptMismatch(): raise BackupCancelled() deprint(u'') deprint(_(u'RESTORE BASH SETTINGS: ') + self.dir.join(self.archive).s) # reinitialize bosh.dirs using the backup copy of bash.ini if it exists game = bush.game.name tmpBash = self.tmp.join(game+u'\\Mopy\\bash.ini') opts, args = bash.opts, bash.extra bash.SetUserPath(tmpBash.s,opts.userPath) bashIni = bash.GetBashIni(tmpBash.s) bosh.initBosh(opts.personalPath,opts.localAppDataPath,opts.oblivionPath) # restore all the settings files restore_paths = ( (dirs['mopy'], game+u'\\Mopy'), (dirs['mods'].join(u'Bash'), game+u'\\Data\\Bash'), (dirs['mods'].join(u'Bash Patches'),game+u'\\Data\\Bash Patches'), (dirs['mods'].join(u'Docs'), game+u'\\Data\\Docs'), (dirs['mods'].join(u'INI Tweaks'), game+u'\\Data\\INI Tweaks'), (dirs['modsBash'], game+u' Mods\\Bash Mod Data'), (dirs['modsBash'].join(u'INI Data'),game+u' Mods\\Bash Mod Data\\INI Data'), (dirs['bainData'], game+u' Mods\\Bash Installers\\Bash'), (dirs['userApp'], u'LocalAppData\\'+game), (dirs['saveBase'], u'My Games\\'+game), ) if 293 >= self.verApp: # restore from old data paths restore_paths += ( (dirs['l10n'], game+u'\\Data'),) if self.restore_images: restore_paths += ( (dirs['images'], game+u'\\Mopy\\images'),) else: restore_paths += ( (dirs['l10n'], game+u'\\bash\\l10n'),) if self.restore_images: restore_paths += ( (dirs['images'], game+u'\\Mopy\\bash\\images'),) for fpath, tpath in restore_paths: path = self.tmp.join(tpath) if path.exists(): for name in path.list(): if path.join(name).isfile(): deprint(GPath(tpath).join(name).s + u' --> ' + fpath.join(name).s) path.join(name).copyTo(fpath.join(name)) #restore savegame profile settings tpath = GPath(u'My Games\\'+game+u'\\Saves') fpath = dirs['saveBase'].join(u'Saves') path = self.tmp.join(tpath) if path.exists(): for root, folders, files in path.walk(True,None,True): root = GPath(u'.'+root.s) for name in files: deprint(tpath.join(root,name).s + u' --> ' + fpath.join(root,name).s) path.join(root,name).copyTo(fpath.join(root,name)) # tell the user the restore is compete and warn about restart self.WarnRestart() if basher.bashFrame: # should always exist basher.bashFrame.Destroy()
def GetAssets(self, contentPath): assets = c_char_p_p() num = c_size_t() _Cbsa_get_assets(self._handle, _enc(contentPath), byref(assets), byref(num)) return [GPath(_uni(assets[i])) for i in xrange(num.value)]
def __init__(self, parent=None, path=None, quit=False, backup_images=None): BaseBackupSettings.__init__(self,parent,path,quit) game = bush.game.name for path, name, tmpdir in ( (dirs['mopy'], u'bash.ini', game+u'\\Mopy'), (dirs['mods'].join(u'Bash'), u'Table', game+u'\\Data\\Bash'), (dirs['mods'].join(u'Docs'), u'Bash Readme Template', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'Bashed Lists', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_sand_small.css', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_teal.css', game+u'\\Data\\Docs'), (dirs['modsBash'], u'Table', game+u' Mods\\Bash Mod Data'), (dirs['modsBash'].join(u'INI Data'),u'Table', game+u' Mods\\Bash Mod Data\\INI Data'), (dirs['bainData'], u'Converters', game+u' Mods\\Bash Installers\\Bash'), (dirs['bainData'], u'Installers', game+u' Mods\\Bash Installers\\Bash'), (dirs['userApp'], u'Profiles', u'LocalAppData\\'+game), (dirs['userApp'], u'bash config', u'LocalAppData\\'+game), (dirs['saveBase'], u'BashProfiles', u'My Games\\'+game), (dirs['saveBase'], u'BashSettings', u'My Games\\'+game), (dirs['saveBase'], u'Messages', u'My Games\\'+game), (dirs['saveBase'], u'ModeBase', u'My Games\\'+game), (dirs['saveBase'], u'People', u'My Games\\'+game), ): tmpdir = GPath(tmpdir) for ext in (u'',u'.dat',u'.pkl',u'.html',u'.txt'): # hack so the above file list can be shorter, could include rogue files but not very likely tpath = tmpdir.join(name+ext) fpath = path.join(name+ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup #end for #end for #backup all files in Mopy\Data, Data\Bash Patches\ and Data\INI Tweaks for path, tmpdir in ( (dirs['l10n'], game+u'\\Mopy\\bash\\l10n'), (dirs['mods'].join(u'Bash Patches'),game+u'\\Data\\Bash Patches'), (dirs['mods'].join(u'INI Tweaks'), game+u'\\Data\\INI Tweaks'), ): tmpdir = GPath(tmpdir) for name in path.list(): if path.join(name).isfile(): self.files[tmpdir.join(name)] = path.join(name) #backup image files if told to if backup_images == 1: #changed images only tmpdir = GPath(game+u'\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): fullname = path.join(name) if fullname.isfile(): changed = True for ver_list in bolt.images_list: if name.s in bolt.images_list[ver_list] and bolt.images_list[ver_list][name.s] == fullname.size: changed = False if changed and not name.s.lower() == u'thumbs.db': self.files[tmpdir.join(name)] = fullname elif backup_images == 2: #all images tmpdir = GPath(game+u'\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): if path.join(name).isfile() and not name.s.lower() == u'thumbs.db': self.files[tmpdir.join(name)] = path.join(name) #backup save profile settings savedir = GPath(u'My Games\\'+game) profiles = [u''] + [x for x in dirs['saveBase'].join(u'Saves').list() if dirs['saveBase'].join(u'Saves',x).isdir() and x != u'bash'] for profile in profiles: tpath = savedir.join(u'Saves',profile,u'plugins.txt') fpath = dirs['saveBase'].join(u'Saves',profile,u'plugins.txt') if fpath.exists(): self.files[tpath] = fpath for ext in (u'.dat',u'.pkl'): tpath = savedir.join(u'Saves',profile,u'Bash',u'Table'+ext) fpath = dirs['saveBase'].join(u'Saves',profile,u'Bash',u'Table'+ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def Apply(self): if self.ErrorConflict(): self.WarnFailed() return elif not self.PromptMismatch(): raise BackupCancelled() return deprint('') deprint('RESTORE BASH SETTINGS: ' + self.dir.join(self.archive).s) # reinitialize bosh.dirs using the backup copy of bash.ini if it exists tmpBash = self.tmp.join('Fallout New Vegas\\Mopy\\bash.ini') opts, args = bash.opts, bash.extra bash.SetUserPath(tmpBash.s, opts.userPath) bashIni = bash.GetBashIni(tmpBash.s) bosh.initBosh(opts.personalPath, opts.localAppDataPath, opts.falloutPath) # restore all the settings files restore_paths = ( (dirs['mopy'], 'Fallout New Vegas\\Mopy'), (dirs['mods'].join('Bash'), 'Fallout New Vegas\\Data\\Bash'), (dirs['mods'].join('Bash Patches'), 'Fallout New Vegas\\Data\\Bash Patches'), (dirs['mods'].join('Docs'), 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('INI Tweaks'), 'Fallout New Vegas\\Data\\INI Tweaks'), (dirs['modsBash'], 'Fallout New Vegas Mods\\Bash Mod Data'), (dirs['modsBash'].join('INI Data'), 'Fallout New Vegas Mods\\Bash Mod Data\\INI Data'), (dirs['installers'].join('Bash'), 'Fallout New Vegas Mods\\Bash Installers\\Bash'), (dirs['userApp'], 'LocalAppData\\FalloutNV'), (dirs['saveBase'], 'My Games\\FalloutNV'), ) if 14 >= self.verApp: # restore from old data paths restore_paths += ((dirs['l10n'], 'Fallout New Vegas\\Data'), ) if self.restore_images: restore_paths += ((dirs['images'], 'Fallout New Vegas\\Mopy\\images'), ) else: restore_paths += ((dirs['l10n'], 'Fallout New Vegas\\bash\\l10n'), ) if self.restore_images: restore_paths += ((dirs['images'], 'Fallout New Vegas\\Mopy\\bash\\images'), ) for fpath, tpath in restore_paths: path = self.tmp.join(tpath) if path.exists(): for name in path.list(): if path.join(name).isfile(): deprint( GPath(tpath).join(name).s + ' --> ' + fpath.join(name).s) path.join(name).copyTo(fpath.join(name)) #restore savegame profile settings tpath = GPath('My Games\\FalloutNV\\Saves') fpath = dirs['saveBase'].join('Saves') path = self.tmp.join(tpath) if path.exists(): for root, folders, files in path.walk(True, None, True): root = GPath('.' + root.s) for name in files: deprint( tpath.join(root, name).s + ' --> ' + fpath.join(root, name).s) path.join(root, name).copyTo(fpath.join(root, name)) # tell the user the restore is compete and warn about restart self.WarnRestart() if basher.bashFrame: # should always exist basher.bashFrame.Destroy()
def __init__(self, parent=None, path=None, quit=False, backup_images=None): BaseBackupSettings.__init__(self,parent,path,quit) game, dirs = bush.game.fsName, bosh.dirs for path, name, tmpdir in ( (dirs['mopy'], u'bash.ini', game+u'\\Mopy'), (dirs['mods'].join(u'Bash'), u'Table', game+u'\\Data\\Bash'), (dirs['mods'].join(u'Docs'), u'Bash Readme Template', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'Bashed Lists', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_sand_small.css', game+u'\\Data\\Docs'), (dirs['mods'].join(u'Docs'), u'wtxt_teal.css', game+u'\\Data\\Docs'), (dirs['modsBash'], u'Table', game+u' Mods\\Bash Mod Data'), (dirs['modsBash'].join(u'INI Data'),u'Table', game+u' Mods\\Bash Mod Data\\INI Data'), (dirs['bainData'], u'Converters', game+u' Mods\\Bash Installers\\Bash'), (dirs['bainData'], u'Installers', game+u' Mods\\Bash Installers\\Bash'), (dirs['userApp'], u'Profiles', u'LocalAppData\\'+game), (dirs['userApp'], u'bash config', u'LocalAppData\\'+game), (dirs['saveBase'], u'BashProfiles', u'My Games\\'+game), (dirs['saveBase'], u'BashSettings', u'My Games\\'+game), (dirs['saveBase'], u'Messages', u'My Games\\'+game), (dirs['saveBase'], u'ModeBase', u'My Games\\'+game), (dirs['saveBase'], u'People', u'My Games\\'+game), ): tmpdir = GPath(tmpdir) for ext in (u'',u'.dat',u'.pkl',u'.html',u'.txt'): # hack so the above file list can be shorter, could include rogue files but not very likely tpath = tmpdir.join(name+ext) fpath = path.join(name+ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup #backup all files in Mopy\Data, Data\Bash Patches\ and Data\INI Tweaks for path, tmpdir in ( (dirs['l10n'], game+u'\\Mopy\\bash\\l10n'), (dirs['mods'].join(u'Bash Patches'),game+u'\\Data\\Bash Patches'), (dirs['mods'].join(u'INI Tweaks'), game+u'\\Data\\INI Tweaks'), ): tmpdir = GPath(tmpdir) for name in path.list(): if path.join(name).isfile(): self.files[tmpdir.join(name)] = path.join(name) #backup image files if told to def _isChanged(abs_path, rel_path): for ver_list in images_list.values(): if ver_list.get(rel_path.s, -1) == abs_path.size: return False return True if backup_images: # 1 is changed images only, 2 is all images onlyChanged = backup_images == 1 tmpdir = GPath(game+u'\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): fullname = path.join(name) if fullname.isfile() and not name.s.lower() == u'thumbs.db' \ and (not onlyChanged or _isChanged(fullname, name)): self.files[tmpdir.join(name)] = fullname #backup save profile settings savedir = GPath(u'My Games\\'+game) profiles = [u''] + bosh.SaveInfos.getLocalSaveDirs() for profile in profiles: pluginsTxt = (u'Saves', profile, u'plugins.txt') loadorderTxt = (u'Saves', profile, u'loadorder.txt') for txt in (pluginsTxt, loadorderTxt): tpath = savedir.join(*txt) fpath = dirs['saveBase'].join(*txt) if fpath.exists(): self.files[tpath] = fpath for ext in (u'.dat', u'.pkl'): table = (u'Saves', profile, u'Bash', u'Table' + ext) tpath = savedir.join(*table) fpath = dirs['saveBase'].join(*table) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def bookExport(fileName=None): """Export data from book to text file(s).""" fileName = GPath(fileName) init(3) # --Data from mod doImport = True modInfo = bosh.modInfos[fileName] loadFactory = bosh.LoadFactory(doImport, bosh.MreBook) modFile = bosh.ModFile(modInfo, loadFactory) modFile.load(True) data = {} texts = {} imported = {} # --Import Book texts if doImport: eid = None buffer = None reAt = re.compile("^@", re.M) reHeader = re.compile("== ?\[(\w+)\]") ins = GPath(fileName.root() + ".txt").open("r") reEndLine = re.compile("\n") for line in ins: maHeader = reHeader.match(line) if maHeader: if eid and buffer: imported[eid] = bosh.winNewLines(buffer.getvalue()) eid = maHeader.group(1) buffer = cStringIO.StringIO() addTags = True wasBlank = True firstLine = True blanks = "" elif buffer: if firstLine: firstLine = False addTags = "<" not in line if addTags: line = '<font face=1><div align="center">' + line isBlank = not bool(line.strip()) if addTags: line = reAt.sub('<div align="left">', line) line = reEndLine.sub("<br>\n", line) if isBlank: blanks += line else: buffer.write(blanks) buffer.write(line) blanks = "" ins.close() if eid and buffer: imported[eid] = bosh.winNewLines(buffer.getvalue()) # --Books from mod changed = False for book in modFile.BOOK.records: if doImport: newText = imported.get(book.eid) if newText and newText != book.text: print "Updating", book.eid book.text = newText book.setChanged() changed = True data[book.eid] = (book.eid, book.full, book.value, len(book.text)) texts[book.eid] = book.text # --Save import? if doImport and changed: modFile.askSave(True) # --Dump book info if False: textPath = GPath(fileName.root() + ".csv") out = textPath.open("w") # out.write('"Edit Id"\t"Name"\t"Value"\t"Text Len"\n') for eid in sorted(data): out.write('"%s"\t"%s"\t"%d"\t"%d"\n' % data[eid]) out.close() # --Dump Texts if True: reNewLine = re.compile("\r\n") out = GPath(fileName.root() + ".txt").open("w") for eid in sorted(data): text = reNewLine.sub("\n", texts[eid]) out.write("== [%s] %s\n" % data[eid][:2]) out.write(text) out.write("\n\n") out.close()
def GetIndexedPlugin(self, index): plugin = c_uint8_p() _CGetIndexedPlugin(self._DB, index, byref(plugin)) return GPath(_uni(plugin.value))
def __init__(self, parent=None, path=None, quit=False, backup_images=None): BaseBackupSettings.__init__(self, parent, path, quit) for path, name, tmpdir in ( (dirs['mopy'], 'Bash.ini', 'Fallout New Vegas\\Mopy'), (dirs['mods'].join('Bash'), 'Table', 'Fallout New Vegas\\Data\\Bash'), (dirs['mods'].join('Docs'), 'Bash Readme Template', 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('Docs'), 'Bashed Lists', 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('Docs'), 'wtxt_sand_small.css', 'Fallout New Vegas\\Data\\Docs'), (dirs['mods'].join('Docs'), 'wtxt_teal.css', 'Fallout New Vegas\\Data\\Docs'), (dirs['modsBash'], 'Table', 'Fallout New Vegas Mods\\Bash Mod Data'), (dirs['modsBash'].join('INI Data'), 'Table', 'Fallout New Vegas Mods\\Bash Mod Data\\INI Data'), (dirs['installers'].join('Bash'), 'Converters', 'Fallout New Vegas Mods\\Bash Installers\\Bash'), (dirs['installers'].join('Bash'), 'Installers', 'Fallout New Vegas Mods\\Bash Installers\\Bash'), (dirs['userApp'], 'Profiles', 'LocalAppData\\FalloutNV'), (dirs['userApp'], 'bash config', 'LocalAppData\\FalloutNV'), (dirs['saveBase'], 'BashProfiles', 'My Games\\FalloutNV'), (dirs['saveBase'], 'BashSettings', 'My Games\\FalloutNV'), (dirs['saveBase'], 'Messages', 'My Games\\FalloutNV'), (dirs['saveBase'], 'ModeBase', 'My Games\\FalloutNV'), (dirs['saveBase'], 'People', 'My Games\\FalloutNV'), ): tmpdir = GPath(tmpdir) for ext in ( '', '.dat', '.pkl', '.html', '.txt' ): # hack so the above file list can be shorter, could include rogue files but not very likely tpath = tmpdir.join(name + ext) fpath = path.join(name + ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup #end for #end for #backup all files in Mopy\Data, Data\Bash Patches and Data\INI Tweaks for path, tmpdir in ( (dirs['l10n'], 'Fallout New Vegas\\Mopy\\bash\\l10n'), (dirs['mods'].join('Bash Patches'), 'Fallout New Vegas\\Data\\Bash Patches'), (dirs['mods'].join('INI Tweaks'), 'Fallout New Vegas\\Data\\INI Tweaks'), ): tmpdir = GPath(tmpdir) for name in path.list(): if path.join(name).isfile(): self.files[tmpdir.join(name)] = path.join(name) #backup image files if told to if backup_images == 1: #changed images only tmpdir = GPath('Fallout New Vegas\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): fullname = path.join(name) if fullname.isfile(): changed = True for ver_list in bolt.images_list: if name.s in bolt.images_list[ ver_list] and bolt.images_list[ver_list][ name.s] == fullname.size: changed = False if changed and not name.s.lower() == 'thumbs.db': self.files[tmpdir.join(name)] = fullname elif backup_images == 2: #all images tmpdir = GPath('Fallout New Vegas\\Mopy\\bash\\images') path = dirs['images'] for name in path.list(): if path.join( name).isfile() and not name.s.lower() == 'thumbs.db': self.files[tmpdir.join(name)] = path.join(name) #backup save profile settings savedir = GPath('My Games\\FalloutNV') profiles = [''] + [ x for x in dirs['saveBase'].join('Saves').list() if dirs['saveBase']. join('Saves', x).isdir() and str(x).lower() != 'bash' ] for profile in profiles: tpath = savedir.join('Saves', profile, 'plugins.txt') fpath = dirs['saveBase'].join('Saves', profile, 'plugins.txt') if fpath.exists(): self.files[tpath] = fpath for ext in ('.dat', '.pkl'): tpath = savedir.join('Saves', profile, 'Bash', 'Table' + ext) fpath = dirs['saveBase'].join('Saves', profile, 'Bash', 'Table' + ext) if fpath.exists(): self.files[tpath] = fpath if fpath.backup.exists(): self.files[tpath.backup] = fpath.backup
def _detectGames(cli_path=u'',bashIni=None): """Detect which supported games are installed. - If Bash supports no games raise. - For each game supported by Bash check for a supported game executable in the following dirs, in decreasing precedence: - the path provided by the -o cli argument if any - the sOblivionPath Bash Ini entry if present - one directory up from Mopy If a game exe is found update the path to this game and return immediately. Return (foundGames, name) - foundGames: a dict from supported games to their paths (the path will default to the windows registry path to the game, if present) - name: the game found in the first installDir or None if no game was found - a 'suggestion' for a game to use (if no game is specified/found via -g argument). """ #--Find all supported games and all games in the windows registry foundGames_ = _supportedGames() # sets _allGames if not set if not _allGames: # if allGames is empty something goes badly wrong raise BoltError(_(u'No game support modules found in Mopy/bash/game.')) # check in order of precedence the -o argument, the ini and our parent dir installPaths = collections.OrderedDict() #key->(path, found msg, error msg) #--First: path specified via the -o command line argument if cli_path != u'': path = GPath(cli_path) if not path.isabs(): path = Path.getcwd().join(path) installPaths['cmd'] = (path, _(u'Set game mode to %(gamename)s specified via -o argument') + u': ', _(u'No known game in the path specified via -o argument: ' + u'%(path)s')) #--Second: check if sOblivionPath is specified in the ini if bashIni and bashIni.has_option(u'General', u'sOblivionPath') \ and not bashIni.get(u'General', u'sOblivionPath') == u'.': path = GPath(bashIni.get(u'General', u'sOblivionPath').strip()) if not path.isabs(): path = Path.getcwd().join(path) installPaths['ini'] = (path, _(u'Set game mode to %(gamename)s based on sOblivionPath setting ' u'in bash.ini') + u': ', _(u'No known game in the path specified in sOblivionPath ini ' u'setting: %(path)s')) #--Third: Detect what game is installed one directory up from Mopy path = Path.getcwd() if path.cs[-4:] == u'mopy': path = GPath(path.s[:-5]) if not path.isabs(): path = Path.getcwd().join(path) installPaths['upMopy'] = (path, _(u'Set game mode to %(gamename)s found in parent directory of' u' Mopy') + u': ', _(u'No known game in parent directory of Mopy: %(path)s')) #--Detect deprint(u'Detecting games via the -o argument, bash.ini and relative path:') # iterate installPaths in insert order ('cmd', 'ini', 'upMopy') for path, foundMsg, errorMsg in installPaths.itervalues(): for name, module in _allGames.items(): if path.join(module.exe).exists(): # Must be this game deprint(foundMsg % {'gamename':name}, path) foundGames_[name] = path return foundGames_, name # no game exe in this install path - print error message deprint(errorMsg % {'path': path.s}) # no game found in installPaths - foundGames are the ones from the registry return foundGames_, None
def unpack7z(srcFile, dstDir, progress=None): # extract srcFile to dstDir progress = progress or Progress() # count the files in the archive length = 0 reList = re.compile('Path = (.*?)(?:\r\n|\n)') if bosh.inisettings['EnableUnicode']: command = r'"%s" l -slt "%s"' % ( dirs['compiled'].join('7zUnicode.exe').s, srcFile.s) else: command = r'"%s" l -slt "%s"' % (dirs['compiled'].join('7z.exe').s, srcFile.s) ins, err = Popen(command, stdout=PIPE, startupinfo=startupinfo).communicate() ins = stringBuffer(ins) for line in ins: length += 1 ins.close() if progress: progress(0, _("%s\nExtracting files...") % srcFile.s) progress.setFull(1 + length) #end if if bosh.inisettings['EnableUnicode']: app7z = dirs['compiled'].join('7zUnicode.exe').s else: app7z = dirs['compiled'].join('7z.exe').s command = '"%s" x "%s" -y -o"%s"' % (app7z, srcFile.s, dstDir.s) #--Extract files ins = Popen(command, stdout=PIPE, startupinfo=startupinfo).stdout #--Error Checking, and progress feedback #--Note subArchives for recursive unpacking reExtracting = re.compile('Extracting\s+(.+)') regMatch = reExtracting.match reError = re.compile('Error: (.*)') regErrMatch = reError.match errorLine = [] index = 0 for line in ins: maExtracting = regMatch(line) if len(errorLine) or regErrMatch(line): errorLine.append(line) if maExtracting: extracted = GPath(maExtracting.group(1).strip()) if progress: progress( index, _("%s\nExtracting files...\n%s") % (srcFile.s, extracted.s)) #end if index += 1 #end if #end for result = ins.close() if result: raise StateError( _("%s: Extraction failed:\n%s") % (srcFile.s, "\n".join(errorLine)))
def exit(): try: os.close(lockfd) os.remove(pidpath.s) except OSError as e: print e # Cleanup temp installers directory import tempfile tempDir = GPath(tempfile.tempdir) for file in tempDir.list(): if file.cs.startswith(u'wryebash_'): file = tempDir.join(file) try: if file.isdir(): file.rmtree(safety=file.stail) else: file.remove() except: pass if basherImported: from basher import appRestart from basher import uacRestart if appRestart: if not hasattr(sys,'frozen'): exePath = GPath(sys.executable) sys.argv = [exePath.stail] + sys.argv if u'--restarting' not in sys.argv: sys.argv += [u'--restarting'] #--Assume if we're restarting that they don't want to be # prompted again about UAC if u'--no-uac' not in sys.argv: sys.argv += [u'--no-uac'] def updateArgv(args): if isinstance(args,(list,tuple)): if len(args) > 0 and isinstance(args[0],(list,tuple)): for arg in args: updateArgv(arg) else: found = 0 for i in xrange(len(sys.argv)): if not found and sys.argv[i] == args[0]: found = 1 elif found: if found < len(args): sys.argv[i] = args[found] found += 1 else: break else: sys.argv.extend(args) updateArgv(appRestart) try: if uacRestart: if not hasattr(sys,'frozen'): sys.argv = sys.argv[1:] import win32api if hasattr(sys,'frozen'): win32api.ShellExecute(0,'runas',sys.argv[0],u' '.join('"%s"' % x for x in sys.argv[1:]),None,True) else: args = u' '.join([u'%s',u'"%s"'][u' ' in x] % x for x in sys.argv) win32api.ShellExecute(0,'runas',exePath.s,args,None,True) return else: import subprocess if hasattr(sys,'frozen'): subprocess.Popen(sys.argv,close_fds=bolt.close_fds) else: subprocess.Popen(sys.argv, executable=exePath.s, close_fds=bolt.close_fds) #close_fds is needed for the one instance checker except Exception as error: print error print u'Error Attempting to Restart Wrye Bash!' print u'cmd line: %s %s' %(exePath.s, sys.argv) print raise