def _detect_game(opts, backup_bash_ini): # Read the bash.ini file either from Mopy or from the backup location bashIni = _bash_ini_parser(backup_bash_ini) # if uArg is None, then get the UserPath from the ini file user_path = opts.userPath or None ##: not sure why this must be set first if user_path is None: ini_user_path = bass.get_ini_option(bashIni, u'sUserPath') if ini_user_path and not ini_user_path == u'.': user_path = ini_user_path if user_path: drive, path = os.path.splitdrive(user_path) os.environ['HOMEDRIVE'] = drive os.environ['HOMEPATH'] = path # Detect the game we're running for --------------------------------------- bush_game = _import_bush_and_set_game(opts, bashIni) if not bush_game: return None, None, None #--Initialize Directories to perform backup/restore operations #--They depend on setting the bash.ini and the game game_ini_path = initialization.init_dirs(bashIni, opts.personalPath, opts.localAppDataPath, bush_game) return bashIni, bush_game, game_ini_path
def _detectGames(cli_path=u'', bash_ini_=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'': test_path = GPath(cli_path) if not test_path.isabs(): test_path = Path.getcwd().join(test_path) installPaths['cmd'] = ( test_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 ini_game_path = get_ini_option(bash_ini_, u'sOblivionPath') if ini_game_path and not ini_game_path == u'.': test_path = GPath(ini_game_path.strip()) if not test_path.isabs(): test_path = Path.getcwd().join(test_path) installPaths['ini'] = ( test_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 test_path = Path.getcwd() if test_path.cs[-4:] == u'mopy': test_path = GPath(test_path.s[:-5]) if not test_path.isabs(): test_path = Path.getcwd().join(test_path) installPaths['upMopy'] = ( test_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 test_path, foundMsg, errorMsg in installPaths.itervalues(): for name, info in _allGames.items(): if test_path.join(*info.game_detect_file).exists(): # Must be this game deprint(foundMsg % {'gamename': name}, test_path) foundGames_[name] = test_path return foundGames_, name # no game exe in this install path - print error message deprint(errorMsg % {'path': test_path.s}) # no game found in installPaths - foundGames are the ones from the registry return foundGames_, None
def get_path_from_ini(bash_ini_, option_key, section_key=u'General'): get_value = get_ini_option(bash_ini_, option_key, section_key) get_value = (get_value and get_value.strip()) or u'.' return GPath(get_value) if get_value != u'.' else None
def init_dirs(bashIni_, personal, localAppData, game_info): if not mopy_dirs_initialized: raise BoltError(u'init_dirs: Mopy dirs uninitialized') #--Oblivion (Application) Directories dirs['app'] = game_info.gamePath dirs['defaultPatches'] = dirs['mopy'].join(u'Bash Patches', game_info.fsName) # Personal personal = getPersonalPath(bashIni_, personal) dirs['saveBase'] = personal.join(u'My Games', game_info.fsName) # Local Application Data localAppData = getLocalAppDataPath(bashIni_, localAppData) dirs['userApp'] = localAppData.join(game_info.fsName) # Use local copy of the oblivion.ini if present # see: http://en.uesp.net/wiki/Oblivion:Ini_Settings # Oblivion reads the Oblivion.ini in the directory where it exists # first, and only if bUseMyGames is non-existent or set to 1 does it # then look for My Documents\My Games\Oblivion.ini. In other words, # both can exist simultaneously, and only the value of bUseMyGames in # the Oblivion.ini directory where Oblivion.exe is run from will # actually matter. # Utumno: not sure how/if this applies to other games data_oblivion_ini = dirs['app'].join(game_info.iniFiles[0]) game_ini_path = dirs['saveBase'].join(game_info.iniFiles[0]) dirs['mods'] = dirs['app'].join(u'Data') if data_oblivion_ini.exists(): oblivionIni = ConfigParser() oblivionIni.read(data_oblivion_ini.s) # is bUseMyGamesDirectory set to 0? if get_ini_option(oblivionIni, u'bUseMyGamesDirectory') == u'0': game_ini_path = data_oblivion_ini # Set the save game folder to the Oblivion directory dirs['saveBase'] = dirs['app'] # Set the data folder to sLocalMasterPath dirs['mods'] = dirs['app'].join( get_ini_option(oblivionIni, u'SLocalMasterPath') or u'Data') # these are relative to the mods path so they must be set here dirs['patches'] = dirs['mods'].join(u'Bash Patches') dirs['tweaks'] = dirs['mods'].join(u'INI Tweaks') #--Mod Data, Installers oblivionMods, oblivionModsSrc = getOblivionModsPath(bashIni_, game_info) dirs['modsBash'], modsBashSrc = getBashModDataPath(bashIni_, game_info) dirs['modsBash'], modsBashSrc = getLegacyPathWithSource( dirs['modsBash'], dirs['app'].join(u'Data', u'Bash'), modsBashSrc, u'Relative Path') dirs['installers'] = oblivionMods.join(u'Bash Installers') dirs['installers'] = getLegacyPath(dirs['installers'], dirs['app'].join(u'Installers')) dirs['bainData'], bainDataSrc = getBainDataPath(bashIni_) dirs['bsaCache'] = dirs['bainData'].join(u'BSA Cache') dirs['converters'] = dirs['installers'].join(u'Bain Converters') dirs['dupeBCFs'] = dirs['converters'].join(u'--Duplicates') dirs['corruptBCFs'] = dirs['converters'].join(u'--Corrupt') # create bash user folders, keep these in order keys = ('modsBash', 'installers', 'converters', 'dupeBCFs', 'corruptBCFs', 'bainData', 'bsaCache') try: env.shellMakeDirs([dirs[key] for key in keys]) except NonExistentDriveError as e: # NonExistentDriveError is thrown by shellMakeDirs if any of the # directories cannot be created due to residing on a non-existing # drive. Find which keys are causing the errors badKeys = set() # List of dirs[key] items that are invalid # First, determine which dirs[key] items are causing it for key in keys: if dirs[key] in e.failed_paths: badKeys.add(key) # Now, work back from those to determine which setting created those msg = _(u'Error creating required Wrye Bash directories.') + u' ' + _( u'Please check the settings for the following paths in your ' u'bash.ini, the drive does not exist') + u':\n\n' relativePathError = [] if 'modsBash' in badKeys: if isinstance(modsBashSrc, list): msg += (u' '.join(modsBashSrc) + u'\n ' + dirs['modsBash'].s + u'\n') else: relativePathError.append(dirs['modsBash']) if {'installers', 'converters', 'dupeBCFs', 'corruptBCFs'} & badKeys: # All derived from oblivionMods -> getOblivionModsPath if isinstance(oblivionModsSrc, list): msg += (u' '.join(oblivionModsSrc) + u'\n ' + oblivionMods.s + u'\n') else: relativePathError.append(oblivionMods) if {'bainData', 'bsaCache'} & badKeys: # Both derived from 'bainData' -> getBainDataPath # Sometimes however, getBainDataPath falls back to oblivionMods, # So check to be sure we haven't already added a message about that if bainDataSrc != oblivionModsSrc: if isinstance(bainDataSrc, list): msg += (u' '.join(bainDataSrc) + u'\n ' + dirs['bainData'].s + u'\n') else: relativePathError.append(dirs['bainData']) if relativePathError: msg += u'\n' + _(u'A path error was the result of relative paths.') msg += u' ' + _( u'The following paths are causing the errors, ' u'however usually a relative path should be fine.') msg += u' ' + _(u'Check your setup to see if you are using ' u'symbolic links or NTFS Junctions') + u':\n\n' msg += u'\n'.join([u'%s' % x for x in relativePathError]) raise BoltError(msg) global bash_dirs_initialized bash_dirs_initialized = True return game_ini_path