mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Split game settings into new GameSettings class.
I added some conversion functions to minimise changes in the rest of the code, they might be replaced by some other way of handling things though. The code files may also be moved into a subdirectory.
This commit is contained in:
@@ -87,6 +87,7 @@ set (LOOT_SRC "${CMAKE_SOURCE_DIR}/src/backend/metadata/conditional_metadata.c
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/plugin_metadata.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/tag.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata_list.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/masterlist.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/plugin.cpp"
|
||||
@@ -108,6 +109,7 @@ set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_grammar.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/plugin_metadata.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/tag.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata_list.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/masterlist.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/plugin.h"
|
||||
|
||||
+2
-1
@@ -99,7 +99,8 @@ struct _loot_db_int : public loot::Game {
|
||||
extStringArraySize(0),
|
||||
extRevisionID(nullptr),
|
||||
extRevisionDate(nullptr) {
|
||||
this->SetDetails("", "", "", "", gamePath, "").Init(false, gameLocalDataPath);
|
||||
this->SetDetails("", "", "", "", gamePath, "");
|
||||
this->Init(false, gameLocalDataPath);
|
||||
}
|
||||
|
||||
~_loot_db_int() {
|
||||
|
||||
+35
-220
@@ -40,143 +40,44 @@ namespace fs = boost::filesystem;
|
||||
namespace lc = boost::locale;
|
||||
|
||||
namespace loot {
|
||||
std::list<Game> GetGames(YAML::Node& settings) {
|
||||
list<Game> games;
|
||||
Game::Game() : GameSettings(), gh(nullptr) {}
|
||||
|
||||
if (settings["games"])
|
||||
games = settings["games"].as< list<Game> >();
|
||||
|
||||
if (find(games.begin(), games.end(), Game(Game::tes4)) == games.end())
|
||||
games.push_back(Game(Game::tes4));
|
||||
|
||||
if (find(games.begin(), games.end(), Game(Game::tes5)) == games.end())
|
||||
games.push_back(Game(Game::tes5));
|
||||
|
||||
if (find(games.begin(), games.end(), Game(Game::fo3)) == games.end())
|
||||
games.push_back(Game(Game::fo3));
|
||||
|
||||
if (find(games.begin(), games.end(), Game(Game::fonv)) == games.end())
|
||||
games.push_back(Game(Game::fonv));
|
||||
|
||||
// If there were any missing defaults, make sure they're in settings now.
|
||||
settings["games"] = games;
|
||||
|
||||
return games;
|
||||
Game::Game(const GameSettings& gameSettings) : Game(gameSettings.Id(), gameSettings.FolderName()) {
|
||||
this->SetDetails(gameSettings.Name(),
|
||||
gameSettings.Master(),
|
||||
gameSettings.RepoURL(),
|
||||
gameSettings.RepoBranch(),
|
||||
gameSettings.GamePath().string(),
|
||||
gameSettings.RegistryKey());
|
||||
}
|
||||
|
||||
// Game member functions
|
||||
//----------------------
|
||||
|
||||
Game::Game() : id(Game::autodetect), gh(nullptr) {}
|
||||
|
||||
Game::Game(const unsigned int gameCode, const std::string& folder) : id(gameCode), gh(nullptr) {
|
||||
Game::Game(const unsigned int gameCode, const std::string& folder) : GameSettings(gameCode, folder), gh(nullptr) {
|
||||
if (Id() == Game::tes4) {
|
||||
_name = "TES IV: Oblivion";
|
||||
registryKey = "Software\\Bethesda Softworks\\Oblivion\\Installed Path";
|
||||
lootFolderName = "Oblivion";
|
||||
_masterFile = "Oblivion.esm";
|
||||
espm_settings = espm::Settings("tes4");
|
||||
_repositoryURL = "https://github.com/loot/oblivion.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
else if (Id() == Game::tes5) {
|
||||
_name = "TES V: Skyrim";
|
||||
registryKey = "Software\\Bethesda Softworks\\Skyrim\\Installed Path";
|
||||
lootFolderName = "Skyrim";
|
||||
_masterFile = "Skyrim.esm";
|
||||
espm_settings = espm::Settings("tes5");
|
||||
_repositoryURL = "https://github.com/loot/skyrim.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
else if (Id() == Game::fo3) {
|
||||
_name = "Fallout 3";
|
||||
registryKey = "Software\\Bethesda Softworks\\Fallout3\\Installed Path";
|
||||
lootFolderName = "Fallout3";
|
||||
_masterFile = "Fallout3.esm";
|
||||
espm_settings = espm::Settings("fo3");
|
||||
_repositoryURL = "https://github.com/loot/fallout3.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
else if (Id() == Game::fonv) {
|
||||
_name = "Fallout: New Vegas";
|
||||
registryKey = "Software\\Bethesda Softworks\\FalloutNV\\Installed Path";
|
||||
lootFolderName = "FalloutNV";
|
||||
_masterFile = "FalloutNV.esm";
|
||||
espm_settings = espm::Settings("fonv");
|
||||
_repositoryURL = "https://github.com/loot/falloutnv.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
|
||||
if (!folder.empty())
|
||||
lootFolderName = folder;
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
lo_destroy_handle(gh);
|
||||
}
|
||||
|
||||
Game& Game::SetDetails(const std::string& name, const std::string& masterFile,
|
||||
const std::string& repositoryURL, const std::string& repositoryBranch, const std::string& path, const std::string& registry) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Setting new details for game: " << _name;
|
||||
|
||||
if (!name.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting name to: " << name;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
if (!masterFile.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting master file to: " << masterFile;
|
||||
_masterFile = masterFile;
|
||||
}
|
||||
|
||||
if (!repositoryURL.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting repo URL to: " << repositoryURL;
|
||||
_repositoryURL = repositoryURL;
|
||||
}
|
||||
|
||||
if (!repositoryBranch.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting repo branch to: " << repositoryBranch;
|
||||
_repositoryBranch = repositoryBranch;
|
||||
}
|
||||
|
||||
if (!path.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting game path to: " << path;
|
||||
gamePath = path;
|
||||
}
|
||||
|
||||
if (!registry.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting registry key to: " << registry;
|
||||
registryKey = registry;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Game& Game::Init(bool createFolder, const boost::filesystem::path& gameLocalAppData) {
|
||||
if (id != Game::tes4 && id != Game::tes5 && id != Game::fo3 && id != Game::fonv) {
|
||||
if (Id() != Game::tes4 && Id() != Game::tes5 && Id() != Game::fo3 && Id() != Game::fonv) {
|
||||
throw error(error::invalid_args, lc::translate("Invalid game ID supplied.").str());
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << _name;
|
||||
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << Name();
|
||||
|
||||
//First look for local install, then look for Registry.
|
||||
if (gamePath.empty() || !fs::exists(gamePath / "Data" / _masterFile)) {
|
||||
if (fs::exists(fs::path("..") / "Data" / _masterFile)) {
|
||||
gamePath = "..";
|
||||
#ifdef _WIN32
|
||||
}
|
||||
else {
|
||||
string path;
|
||||
string key_parent = fs::path(registryKey).parent_path().string();
|
||||
string key_name = fs::path(registryKey).filename().string();
|
||||
path = RegKeyStringValue("HKEY_LOCAL_MACHINE", key_parent, key_name);
|
||||
if (!path.empty() && fs::exists(fs::path(path) / "Data" / _masterFile))
|
||||
gamePath = fs::path(path);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (gamePath.empty()) {
|
||||
if (!this->IsInstalled()) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Game path could not be detected.";
|
||||
throw error(error::path_not_found, lc::translate("Game path could not be detected.").str());
|
||||
}
|
||||
@@ -194,81 +95,16 @@ namespace loot {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Game::IsInstalled() const {
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking if game \"" << _name << "\" is installed.";
|
||||
if (!gamePath.empty() && fs::exists(gamePath / "Data" / _masterFile))
|
||||
return true;
|
||||
|
||||
if (fs::exists(fs::path("..") / "Data" / _masterFile))
|
||||
return true;
|
||||
|
||||
#ifdef _WIN32
|
||||
string path;
|
||||
string key_parent = fs::path(registryKey).parent_path().string();
|
||||
string key_name = fs::path(registryKey).filename().string();
|
||||
path = RegKeyStringValue("HKEY_LOCAL_MACHINE", key_parent, key_name);
|
||||
if (!path.empty() && fs::exists(fs::path(path) / "Data" / _masterFile))
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
catch (exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Error while checking if game \"" << _name << "\" is installed: " << e.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
bool Game::operator == (const Game& rhs) const {
|
||||
return (boost::iequals(Name(), rhs.Name()) || boost::iequals(FolderName(), rhs.FolderName()));
|
||||
}
|
||||
|
||||
bool Game::operator == (const Game& rhs) const {
|
||||
return (boost::iequals(_name, rhs.Name()) || boost::iequals(lootFolderName, rhs.FolderName()));
|
||||
bool Game::operator == (const GameSettings& rhs) const {
|
||||
return (boost::iequals(Name(), rhs.Name()) || boost::iequals(FolderName(), rhs.FolderName()));
|
||||
}
|
||||
|
||||
bool Game::operator == (const std::string& nameOrFolderName) const {
|
||||
return (boost::iequals(_name, nameOrFolderName) || boost::iequals(lootFolderName, nameOrFolderName));
|
||||
}
|
||||
|
||||
unsigned int Game::Id() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
string Game::Name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
string Game::FolderName() const {
|
||||
return lootFolderName;
|
||||
}
|
||||
|
||||
std::string Game::Master() const {
|
||||
return _masterFile;
|
||||
}
|
||||
|
||||
std::string Game::RegistryKey() const {
|
||||
return registryKey;
|
||||
}
|
||||
|
||||
std::string Game::RepoURL() const {
|
||||
return _repositoryURL;
|
||||
}
|
||||
|
||||
std::string Game::RepoBranch() const {
|
||||
return _repositoryBranch;
|
||||
}
|
||||
|
||||
fs::path Game::GamePath() const {
|
||||
return gamePath;
|
||||
}
|
||||
|
||||
fs::path Game::DataPath() const {
|
||||
return GamePath() / "Data";
|
||||
}
|
||||
|
||||
fs::path Game::MasterlistPath() const {
|
||||
return g_path_local / lootFolderName / "masterlist.yaml";
|
||||
}
|
||||
|
||||
fs::path Game::UserlistPath() const {
|
||||
return g_path_local / lootFolderName / "userlist.yaml";
|
||||
return (boost::iequals(Name(), nameOrFolderName) || boost::iequals(FolderName(), nameOrFolderName));
|
||||
}
|
||||
|
||||
void Game::InitLibloHandle() {
|
||||
@@ -285,13 +121,13 @@ namespace loot {
|
||||
|
||||
int ret;
|
||||
if (Id() == Game::tes4)
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_TES4, gamePath.string().c_str(), gameLocalDataPath);
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_TES4, GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (Id() == Game::tes5)
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_TES5, gamePath.string().c_str(), gameLocalDataPath);
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_TES5, GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (Id() == Game::fo3)
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_FO3, gamePath.string().c_str(), gameLocalDataPath);
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_FO3, GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (Id() == Game::fonv)
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_FNV, gamePath.string().c_str(), gameLocalDataPath);
|
||||
ret = lo_create_handle(&gh, LIBLO_GAME_FNV, GamePath().string().c_str(), gameLocalDataPath);
|
||||
else
|
||||
ret = LIBLO_ERROR_INVALID_ARGS;
|
||||
|
||||
@@ -311,8 +147,8 @@ namespace loot {
|
||||
throw error(error::liblo_error, err);
|
||||
}
|
||||
|
||||
if (id != Game::tes5) {
|
||||
ret = lo_set_game_master(gh, _masterFile.c_str());
|
||||
if (Id() != Game::tes5) {
|
||||
ret = lo_set_game_master(gh, Master().c_str());
|
||||
if (ret != LIBLO_OK && ret != LIBLO_WARN_BAD_FILENAME && ret != LIBLO_WARN_INVALID_LIST && ret != LIBLO_WARN_LO_MISMATCH) {
|
||||
const char * e = nullptr;
|
||||
string err;
|
||||
@@ -335,7 +171,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
void Game::RefreshActivePluginsList() {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Refreshing active plugins list for game: " << _name;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Refreshing active plugins list for game: " << Name();
|
||||
|
||||
char ** pluginArr;
|
||||
size_t pluginArrSize;
|
||||
@@ -363,7 +199,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
void Game::GetLoadOrder(std::list<std::string>& loadOrder) const {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Getting load order for game: " << _name;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Getting load order for game: " << Name();
|
||||
|
||||
char ** pluginArr;
|
||||
size_t pluginArrSize;
|
||||
@@ -392,7 +228,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
void Game::SetLoadOrder(const char * const * const loadOrder, const size_t numPlugins) const {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Setting load order for game: " << _name;
|
||||
BOOST_LOG_TRIVIAL(debug) << "Setting load order for game: " << Name();
|
||||
|
||||
unsigned int ret = lo_set_load_order(gh, loadOrder, numPlugins);
|
||||
if (ret != LIBLO_OK && ret != LIBLO_WARN_BAD_FILENAME && ret != LIBLO_WARN_INVALID_LIST && ret != LIBLO_WARN_LO_MISMATCH) {
|
||||
@@ -440,7 +276,7 @@ namespace loot {
|
||||
}
|
||||
|
||||
void Game::RedatePlugins() {
|
||||
if (id != tes5)
|
||||
if (Id() != tes5)
|
||||
return;
|
||||
|
||||
list<string> loadorder;
|
||||
@@ -539,7 +375,7 @@ namespace loot {
|
||||
bool Game::HasBeenLoaded() {
|
||||
// Easy way to check is by checking the game's master file,
|
||||
// which definitely shouldn't be empty.
|
||||
auto pairIt = plugins.find(boost::locale::to_lower(_masterFile));
|
||||
auto pairIt = plugins.find(boost::locale::to_lower(Master()));
|
||||
|
||||
if (pairIt != plugins.end())
|
||||
return !pairIt->second.FormIDs().empty();
|
||||
@@ -547,18 +383,6 @@ namespace loot {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::CreateLOOTGameFolder() {
|
||||
//Make sure that the LOOT game path exists.
|
||||
try {
|
||||
if (fs::exists(g_path_local) && !fs::exists(g_path_local / lootFolderName))
|
||||
fs::create_directory(g_path_local / lootFolderName);
|
||||
}
|
||||
catch (fs::filesystem_error& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not create LOOT folder for game. Details: " << e.what();
|
||||
throw error(error::path_write_fail, lc::translate("Could not create LOOT folder for game. Details:").str() + " " + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Plugin> Game::Sort(const unsigned int language, std::function<void(const std::string&)> progressCallback) {
|
||||
//Create a plugin graph containing the plugin and masterlist data.
|
||||
loot::PluginGraph graph;
|
||||
@@ -608,21 +432,12 @@ namespace loot {
|
||||
progressCallback(lc::translate("Adding edges to plugin graph and performing topological sort..."));
|
||||
return loot::Sort(graph, loadorder);
|
||||
}
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
Emitter& operator << (Emitter& out, const loot::Game& rhs) {
|
||||
out << BeginMap
|
||||
<< Key << "type" << Value << YAML::SingleQuoted << loot::Game(rhs.Id()).FolderName()
|
||||
<< Key << "folder" << Value << YAML::SingleQuoted << rhs.FolderName()
|
||||
<< Key << "name" << Value << YAML::SingleQuoted << rhs.Name()
|
||||
<< Key << "master" << Value << YAML::SingleQuoted << rhs.Master()
|
||||
<< Key << "repo" << Value << YAML::SingleQuoted << rhs.RepoURL()
|
||||
<< Key << "branch" << Value << YAML::SingleQuoted << rhs.RepoBranch()
|
||||
<< Key << "path" << Value << YAML::SingleQuoted << rhs.GamePath().string()
|
||||
<< Key << "registry" << Value << YAML::SingleQuoted << rhs.RegistryKey()
|
||||
<< EndMap;
|
||||
|
||||
return out;
|
||||
std::list<Game> ToGames(const std::list<GameSettings>& settings) {
|
||||
return list<Game>(settings.begin(), settings.end());
|
||||
}
|
||||
}
|
||||
|
||||
std::list<GameSettings> ToGameSettings(const std::list<Game>& games) {
|
||||
return list<GameSettings>(games.begin(), games.end());
|
||||
}
|
||||
}
|
||||
|
||||
+8
-97
@@ -25,6 +25,7 @@
|
||||
#ifndef __LOOT_GAME__
|
||||
#define __LOOT_GAME__
|
||||
|
||||
#include "game_settings.h"
|
||||
#include "plugin.h"
|
||||
#include "metadata_list.h"
|
||||
#include "masterlist.h"
|
||||
@@ -43,36 +44,21 @@
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
namespace loot {
|
||||
class Game {
|
||||
class Game : public GameSettings {
|
||||
public:
|
||||
//Game functions.
|
||||
Game(); //Sets game to LOOT_Game::autodetect, with all other vars being empty.
|
||||
Game(const GameSettings& gameSettings);
|
||||
Game(const unsigned int baseGameCode, const std::string& lootFolder = "");
|
||||
~Game();
|
||||
|
||||
Game& SetDetails(const std::string& name, const std::string& masterFile,
|
||||
const std::string& repositoryURL, const std::string& repositoryBranch,
|
||||
const std::string& path, const std::string& registry);
|
||||
Game& Init(bool createFolder, const boost::filesystem::path& gameLocalAppData = "");
|
||||
|
||||
bool IsInstalled() const;
|
||||
|
||||
bool operator == (const Game& rhs) const; //Compares names and folder names.
|
||||
//Compare names and folder names.
|
||||
bool operator == (const Game& rhs) const;
|
||||
bool operator == (const GameSettings& rhs) const;
|
||||
bool operator == (const std::string& nameOrFolderName) const;
|
||||
|
||||
unsigned int Id() const;
|
||||
std::string Name() const; //Returns the game's name, eg. "TES IV: Oblivion".
|
||||
std::string FolderName() const;
|
||||
std::string Master() const;
|
||||
std::string RegistryKey() const;
|
||||
std::string RepoURL() const;
|
||||
std::string RepoBranch() const;
|
||||
|
||||
boost::filesystem::path GamePath() const;
|
||||
boost::filesystem::path DataPath() const;
|
||||
boost::filesystem::path MasterlistPath() const;
|
||||
boost::filesystem::path UserlistPath() const;
|
||||
|
||||
void GetLoadOrder(std::list<std::string>& loadOrder) const;
|
||||
void SetLoadOrder(const std::list<std::string>& loadOrder) const; //Modifies game load order, even though const.
|
||||
void SetLoadOrder(const char * const * const loadOrder, const size_t numPlugins) const; // For API.
|
||||
@@ -95,91 +81,16 @@ namespace loot {
|
||||
std::unordered_map<std::string, Plugin> plugins; //Map so that plugin data can be edited.
|
||||
|
||||
espm::Settings espm_settings;
|
||||
|
||||
static const unsigned int autodetect = 0;
|
||||
static const unsigned int tes4 = 1;
|
||||
static const unsigned int tes5 = 2;
|
||||
static const unsigned int fo3 = 3;
|
||||
static const unsigned int fonv = 4;
|
||||
private:
|
||||
unsigned int id;
|
||||
std::string _name;
|
||||
std::string _masterFile;
|
||||
|
||||
std::string registryKey;
|
||||
|
||||
std::string lootFolderName;
|
||||
std::string _repositoryURL;
|
||||
std::string _repositoryBranch;
|
||||
|
||||
boost::filesystem::path gamePath; //Path to the game's folder.
|
||||
boost::filesystem::path _gameLocalDataPath; // Path to the game's folder in %LOCALAPPDATA%.
|
||||
|
||||
lo_game_handle gh;
|
||||
|
||||
//Creates directory in LOOT folder for LOOT's game-specific files.
|
||||
void CreateLOOTGameFolder();
|
||||
|
||||
void InitLibloHandle();
|
||||
};
|
||||
|
||||
std::list<Game> GetGames(YAML::Node& settings);
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
struct convert < loot::Game > {
|
||||
static Node encode(const loot::Game& rhs) {
|
||||
Node node;
|
||||
|
||||
node["type"] = loot::Game(rhs.Id()).FolderName();
|
||||
node["name"] = rhs.Name();
|
||||
node["folder"] = rhs.FolderName();
|
||||
node["master"] = rhs.Master();
|
||||
node["repo"] = rhs.RepoURL();
|
||||
node["branch"] = rhs.RepoBranch();
|
||||
node["path"] = rhs.GamePath().string();
|
||||
node["registry"] = rhs.RegistryKey();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, loot::Game& rhs) {
|
||||
if (!node.IsMap() || !node["folder"] || !node["type"])
|
||||
return false;
|
||||
|
||||
if (node["type"].as<std::string>() == loot::Game(loot::Game::tes4).FolderName())
|
||||
rhs = loot::Game(loot::Game::tes4, node["folder"].as<std::string>());
|
||||
else if (node["type"].as<std::string>() == loot::Game(loot::Game::tes5).FolderName())
|
||||
rhs = loot::Game(loot::Game::tes5, node["folder"].as<std::string>());
|
||||
else if (node["type"].as<std::string>() == loot::Game(loot::Game::fo3).FolderName())
|
||||
rhs = loot::Game(loot::Game::fo3, node["folder"].as<std::string>());
|
||||
else if (node["type"].as<std::string>() == loot::Game(loot::Game::fonv).FolderName())
|
||||
rhs = loot::Game(loot::Game::fonv, node["folder"].as<std::string>());
|
||||
else
|
||||
return false;
|
||||
|
||||
std::string name, master, repo, branch, path, registry;
|
||||
if (node["name"])
|
||||
name = node["name"].as<std::string>();
|
||||
if (node["master"])
|
||||
master = node["master"].as<std::string>();
|
||||
if (node["repo"])
|
||||
repo = node["repo"].as<std::string>();
|
||||
if (node["branch"])
|
||||
branch = node["branch"].as<std::string>();
|
||||
if (node["path"])
|
||||
path = node["path"].as<std::string>();
|
||||
if (node["registry"])
|
||||
registry = node["registry"].as<std::string>();
|
||||
|
||||
rhs.SetDetails(name, master, repo, branch, path, registry);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::Game& rhs);
|
||||
std::list<Game> ToGames(const std::list<GameSettings>& settings);
|
||||
std::list<GameSettings> ToGameSettings(const std::list<Game>& games);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2015 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "game_settings.h"
|
||||
#include "globals.h"
|
||||
#include "helpers.h"
|
||||
#include "error.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
namespace lc = boost::locale;
|
||||
|
||||
namespace loot {
|
||||
GameSettings::GameSettings() : _id(GameSettings::autodetect) {}
|
||||
|
||||
GameSettings::GameSettings(const unsigned int gameCode, const std::string& folder) : _id(gameCode) {
|
||||
if (Id() == GameSettings::tes4) {
|
||||
_name = "TES IV: Oblivion";
|
||||
_registryKey = "Software\\Bethesda Softworks\\Oblivion\\Installed Path";
|
||||
_lootFolderName = "Oblivion";
|
||||
_masterFile = "Oblivion.esm";
|
||||
_repositoryURL = "https://github.com/loot/oblivion.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
else if (Id() == GameSettings::tes5) {
|
||||
_name = "TES V: Skyrim";
|
||||
_registryKey = "Software\\Bethesda Softworks\\Skyrim\\Installed Path";
|
||||
_lootFolderName = "Skyrim";
|
||||
_masterFile = "Skyrim.esm";
|
||||
_repositoryURL = "https://github.com/loot/skyrim.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
else if (Id() == GameSettings::fo3) {
|
||||
_name = "Fallout 3";
|
||||
_registryKey = "Software\\Bethesda Softworks\\Fallout3\\Installed Path";
|
||||
_lootFolderName = "Fallout3";
|
||||
_masterFile = "Fallout3.esm";
|
||||
_repositoryURL = "https://github.com/loot/fallout3.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
else if (Id() == GameSettings::fonv) {
|
||||
_name = "Fallout: New Vegas";
|
||||
_registryKey = "Software\\Bethesda Softworks\\FalloutNV\\Installed Path";
|
||||
_lootFolderName = "FalloutNV";
|
||||
_masterFile = "FalloutNV.esm";
|
||||
_repositoryURL = "https://github.com/loot/falloutnv.git";
|
||||
_repositoryBranch = "master";
|
||||
}
|
||||
|
||||
if (!folder.empty())
|
||||
_lootFolderName = folder;
|
||||
}
|
||||
|
||||
GameSettings& GameSettings::SetDetails(const std::string& name, const std::string& masterFile,
|
||||
const std::string& repositoryURL, const std::string& repositoryBranch, const std::string& path, const std::string& registry) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Setting new details for game: " << _name;
|
||||
|
||||
if (!name.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting name to: " << name;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
if (!masterFile.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting master file to: " << masterFile;
|
||||
_masterFile = masterFile;
|
||||
}
|
||||
|
||||
if (!repositoryURL.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting repo URL to: " << repositoryURL;
|
||||
_repositoryURL = repositoryURL;
|
||||
}
|
||||
|
||||
if (!repositoryBranch.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting repo branch to: " << repositoryBranch;
|
||||
_repositoryBranch = repositoryBranch;
|
||||
}
|
||||
|
||||
if (!path.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting game path to: " << path;
|
||||
_gamePath = path;
|
||||
}
|
||||
|
||||
if (!registry.empty()) {
|
||||
BOOST_LOG_TRIVIAL(trace) << '\t' << "Setting registry key to: " << registry;
|
||||
_registryKey = registry;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool GameSettings::IsInstalled() {
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking if game \"" << _name << "\" is installed.";
|
||||
if (!_gamePath.empty() && fs::exists(_gamePath / "Data" / _masterFile))
|
||||
return true;
|
||||
|
||||
if (fs::exists(fs::path("..") / "Data" / _masterFile)) {
|
||||
_gamePath = "..";
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
string path;
|
||||
string key_parent = fs::path(_registryKey).parent_path().string();
|
||||
string key_name = fs::path(_registryKey).filename().string();
|
||||
path = RegKeyStringValue("HKEY_LOCAL_MACHINE", key_parent, key_name);
|
||||
if (!path.empty() && fs::exists(fs::path(path) / "Data" / _masterFile)) {
|
||||
_gamePath = path;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Error while checking if game \"" << _name << "\" is installed: " << e.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GameSettings::operator == (const GameSettings& rhs) const {
|
||||
return (boost::iequals(_name, rhs.Name()) || boost::iequals(_lootFolderName, rhs.FolderName()));
|
||||
}
|
||||
|
||||
bool GameSettings::operator == (const std::string& nameOrFolderName) const {
|
||||
return (boost::iequals(_name, nameOrFolderName) || boost::iequals(_lootFolderName, nameOrFolderName));
|
||||
}
|
||||
|
||||
unsigned int GameSettings::Id() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
string GameSettings::Name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
string GameSettings::FolderName() const {
|
||||
return _lootFolderName;
|
||||
}
|
||||
|
||||
std::string GameSettings::Master() const {
|
||||
return _masterFile;
|
||||
}
|
||||
|
||||
std::string GameSettings::RegistryKey() const {
|
||||
return _registryKey;
|
||||
}
|
||||
|
||||
std::string GameSettings::RepoURL() const {
|
||||
return _repositoryURL;
|
||||
}
|
||||
|
||||
std::string GameSettings::RepoBranch() const {
|
||||
return _repositoryBranch;
|
||||
}
|
||||
|
||||
fs::path GameSettings::GamePath() const {
|
||||
return _gamePath;
|
||||
}
|
||||
|
||||
fs::path GameSettings::DataPath() const {
|
||||
return _gamePath / "Data";
|
||||
}
|
||||
|
||||
fs::path GameSettings::MasterlistPath() const {
|
||||
return g_path_local / _lootFolderName / "masterlist.yaml";
|
||||
}
|
||||
|
||||
fs::path GameSettings::UserlistPath() const {
|
||||
return g_path_local / _lootFolderName / "userlist.yaml";
|
||||
}
|
||||
|
||||
void GameSettings::CreateLOOTGameFolder() {
|
||||
//Make sure that the LOOT game path exists.
|
||||
try {
|
||||
if (fs::exists(g_path_local) && !fs::exists(g_path_local / _lootFolderName))
|
||||
fs::create_directory(g_path_local / _lootFolderName);
|
||||
}
|
||||
catch (fs::filesystem_error& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not create LOOT folder for game. Details: " << e.what();
|
||||
throw error(error::path_write_fail, lc::translate("Could not create LOOT folder for game. Details:").str() + " " + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::list<GameSettings> GetGameSettings(YAML::Node& settings) {
|
||||
list<GameSettings> games;
|
||||
|
||||
if (settings["games"])
|
||||
games = settings["games"].as< list<GameSettings> >();
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::tes4)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::tes4));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::tes5)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::tes5));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::fo3)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::fo3));
|
||||
|
||||
if (find(games.begin(), games.end(), GameSettings(GameSettings::fonv)) == games.end())
|
||||
games.push_back(GameSettings(GameSettings::fonv));
|
||||
|
||||
// If there were any missing defaults, make sure they're in settings now.
|
||||
settings["games"] = games;
|
||||
|
||||
return games;
|
||||
}
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
Emitter& operator << (Emitter& out, const loot::GameSettings& rhs) {
|
||||
out << BeginMap
|
||||
<< Key << "type" << Value << YAML::SingleQuoted << loot::GameSettings(rhs.Id()).FolderName()
|
||||
<< Key << "folder" << Value << YAML::SingleQuoted << rhs.FolderName()
|
||||
<< Key << "name" << Value << YAML::SingleQuoted << rhs.Name()
|
||||
<< Key << "master" << Value << YAML::SingleQuoted << rhs.Master()
|
||||
<< Key << "repo" << Value << YAML::SingleQuoted << rhs.RepoURL()
|
||||
<< Key << "branch" << Value << YAML::SingleQuoted << rhs.RepoBranch()
|
||||
<< Key << "path" << Value << YAML::SingleQuoted << rhs.GamePath().string()
|
||||
<< Key << "registry" << Value << YAML::SingleQuoted << rhs.RegistryKey()
|
||||
<< EndMap;
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2015 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __LOOT_GAME_SETTINGS__
|
||||
#define __LOOT_GAME_SETTINGS__
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
namespace loot {
|
||||
class GameSettings {
|
||||
public:
|
||||
//Game functions.
|
||||
GameSettings(); //Sets game to LOOT_Game::autodetect, with all other vars being empty.
|
||||
GameSettings(const unsigned int baseGameCode, const std::string& lootFolder = "");
|
||||
|
||||
GameSettings& SetDetails(const std::string& name, const std::string& masterFile,
|
||||
const std::string& repositoryURL, const std::string& repositoryBranch,
|
||||
const std::string& path, const std::string& registry);
|
||||
|
||||
bool IsInstalled(); //Sets gamePath if the current value is not valid and a valid path is found.
|
||||
|
||||
bool operator == (const GameSettings& rhs) const; //Compares names and folder names.
|
||||
bool operator == (const std::string& nameOrFolderName) const;
|
||||
|
||||
unsigned int Id() const;
|
||||
std::string Name() const; //Returns the game's name, eg. "TES IV: Oblivion".
|
||||
std::string FolderName() const;
|
||||
std::string Master() const;
|
||||
std::string RegistryKey() const;
|
||||
std::string RepoURL() const;
|
||||
std::string RepoBranch() const;
|
||||
|
||||
boost::filesystem::path GamePath() const;
|
||||
boost::filesystem::path DataPath() const;
|
||||
boost::filesystem::path MasterlistPath() const;
|
||||
boost::filesystem::path UserlistPath() const;
|
||||
|
||||
static const unsigned int autodetect = 0;
|
||||
static const unsigned int tes4 = 1;
|
||||
static const unsigned int tes5 = 2;
|
||||
static const unsigned int fo3 = 3;
|
||||
static const unsigned int fonv = 4;
|
||||
protected:
|
||||
//Creates directory in LOOT folder for LOOT's game-specific files.
|
||||
void CreateLOOTGameFolder();
|
||||
private:
|
||||
unsigned int _id;
|
||||
std::string _name;
|
||||
std::string _masterFile;
|
||||
|
||||
std::string _registryKey;
|
||||
|
||||
std::string _lootFolderName;
|
||||
std::string _repositoryURL;
|
||||
std::string _repositoryBranch;
|
||||
|
||||
boost::filesystem::path _gamePath; //Path to the game's folder.
|
||||
};
|
||||
|
||||
std::list<GameSettings> GetGameSettings(YAML::Node& settings);
|
||||
}
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
struct convert < loot::GameSettings > {
|
||||
static Node encode(const loot::GameSettings& rhs) {
|
||||
Node node;
|
||||
|
||||
node["type"] = loot::GameSettings(rhs.Id()).FolderName();
|
||||
node["name"] = rhs.Name();
|
||||
node["folder"] = rhs.FolderName();
|
||||
node["master"] = rhs.Master();
|
||||
node["repo"] = rhs.RepoURL();
|
||||
node["branch"] = rhs.RepoBranch();
|
||||
node["path"] = rhs.GamePath().string();
|
||||
node["registry"] = rhs.RegistryKey();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, loot::GameSettings& rhs) {
|
||||
if (!node.IsMap() || !node["folder"] || !node["type"])
|
||||
return false;
|
||||
|
||||
if (node["type"].as<std::string>() == loot::GameSettings(loot::GameSettings::tes4).FolderName())
|
||||
rhs = loot::GameSettings(loot::GameSettings::tes4, node["folder"].as<std::string>());
|
||||
else if (node["type"].as<std::string>() == loot::GameSettings(loot::GameSettings::tes5).FolderName())
|
||||
rhs = loot::GameSettings(loot::GameSettings::tes5, node["folder"].as<std::string>());
|
||||
else if (node["type"].as<std::string>() == loot::GameSettings(loot::GameSettings::fo3).FolderName())
|
||||
rhs = loot::GameSettings(loot::GameSettings::fo3, node["folder"].as<std::string>());
|
||||
else if (node["type"].as<std::string>() == loot::GameSettings(loot::GameSettings::fonv).FolderName())
|
||||
rhs = loot::GameSettings(loot::GameSettings::fonv, node["folder"].as<std::string>());
|
||||
else
|
||||
return false;
|
||||
|
||||
std::string name, master, repo, branch, path, registry;
|
||||
if (node["name"])
|
||||
name = node["name"].as<std::string>();
|
||||
if (node["master"])
|
||||
master = node["master"].as<std::string>();
|
||||
if (node["repo"])
|
||||
repo = node["repo"].as<std::string>();
|
||||
if (node["branch"])
|
||||
branch = node["branch"].as<std::string>();
|
||||
if (node["path"])
|
||||
path = node["path"].as<std::string>();
|
||||
if (node["registry"])
|
||||
registry = node["registry"].as<std::string>();
|
||||
|
||||
rhs.SetDetails(name, master, repo, branch, path, registry);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::GameSettings& rhs);
|
||||
}
|
||||
|
||||
#endif
|
||||
+1
-1
@@ -259,7 +259,7 @@ namespace loot {
|
||||
// It will be restored when LOOT is next loaded.
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Updating games object.";
|
||||
list<Game> games(request["args"][0]["games"].as< list<Game> >());
|
||||
list<GameSettings> games(request["args"][0]["games"].as< list<GameSettings> >());
|
||||
_lootState.UpdateGames(games);
|
||||
|
||||
// Also enable/disable debug logging as required.
|
||||
|
||||
+11
-16
@@ -137,14 +137,14 @@ namespace loot {
|
||||
//Detect installed games.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Detecting installed games.";
|
||||
try {
|
||||
_games = GetGames(_settings);
|
||||
_games = ToGames(GetGameSettings(_settings));
|
||||
}
|
||||
catch (YAML::Exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Games' settings parsing failed. " << e.what();
|
||||
_initErrors.push_back((format(translate("Error: Games' settings parsing failed. %1%")) % e.what()).str());
|
||||
// Now redo, but with no games settings, so only the hardcoded defaults get loaded. It means the user can
|
||||
// at least still then edit them.
|
||||
_games = GetGames(YAML::Node());
|
||||
_games = ToGames(GetGameSettings(YAML::Node()));
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -153,7 +153,7 @@ namespace loot {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Initialising game-specific settings.";
|
||||
_currentGame->Init(true);
|
||||
// Update game path in settings object.
|
||||
_settings["games"] = _games;
|
||||
_settings["games"] = ToGameSettings(_games);
|
||||
}
|
||||
catch (loot::error &e) {
|
||||
if (e.code() == loot::error::no_game_detected) {
|
||||
@@ -171,7 +171,7 @@ namespace loot {
|
||||
return _initErrors;
|
||||
}
|
||||
|
||||
void LootState::UpdateGames(std::list<Game>& games) {
|
||||
void LootState::UpdateGames(std::list<GameSettings>& games) {
|
||||
// Acquire the lock for the scope of this method.
|
||||
base::AutoLock lock_scope(_lock);
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace loot {
|
||||
// Re-initialise the current game in case the game path setting was changed.
|
||||
_currentGame->Init(true);
|
||||
// Update game path in settings object.
|
||||
_settings["games"] = _games;
|
||||
_settings["games"] = ToGameSettings(_games);
|
||||
}
|
||||
|
||||
void LootState::ChangeGame(const std::string& newGameFolder) {
|
||||
@@ -220,7 +220,7 @@ namespace loot {
|
||||
_currentGame->Init(true);
|
||||
|
||||
// Update game path in settings object.
|
||||
_settings["games"] = _games;
|
||||
_settings["games"] = ToGameSettings(_games);
|
||||
BOOST_LOG_TRIVIAL(debug) << "New game is " << _currentGame->Name();
|
||||
}
|
||||
|
||||
@@ -231,9 +231,9 @@ namespace loot {
|
||||
return *_currentGame;
|
||||
}
|
||||
|
||||
std::vector<std::string> LootState::InstalledGames() const {
|
||||
std::vector<std::string> LootState::InstalledGames() {
|
||||
vector<string> installedGames;
|
||||
for (const auto &game : _games) {
|
||||
for (auto &game : _games) {
|
||||
if (game.IsInstalled())
|
||||
installedGames.push_back(game.FolderName());
|
||||
}
|
||||
@@ -393,14 +393,9 @@ namespace loot {
|
||||
root["enableDebugLogging"] = false;
|
||||
root["updateMasterlist"] = true;
|
||||
|
||||
std::list<Game> games;
|
||||
games.push_back(Game(Game::tes4));
|
||||
games.push_back(Game(Game::tes5));
|
||||
games.push_back(Game(Game::fo3));
|
||||
games.push_back(Game(Game::fonv));
|
||||
games.push_back(Game(Game::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation"));
|
||||
|
||||
root["games"] = games;
|
||||
// Add base game definitions, and Nehrim.
|
||||
GetGameSettings(root);
|
||||
root["games"].push_back(GameSettings(GameSettings::tes4, "Nehrim").SetDetails("Nehrim - At Fate's Edge", "Nehrim.esm", "https://github.com/loot/oblivion.git", "master", "", "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Nehrim - At Fate's Edge_is1\\InstallLocation"));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ namespace loot {
|
||||
|
||||
Game& CurrentGame();
|
||||
void ChangeGame(const std::string& newGameFolder);
|
||||
void UpdateGames(std::list<Game>& games);
|
||||
void UpdateGames(std::list<GameSettings>& games);
|
||||
// Get the folder names of the installed games.
|
||||
std::vector<std::string> InstalledGames() const;
|
||||
std::vector<std::string> InstalledGames();
|
||||
|
||||
const YAML::Node& GetSettings() const;
|
||||
void UpdateSettings(const YAML::Node& settings);
|
||||
|
||||
Reference in New Issue
Block a user