mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Move GameSettings into GUI code and split Game
GameSettings is only needed by the LOOT GUI, and many functions in Game could also be GUI-specific, so they were moved to a new loot::gui::Game class (the namespace is temporary, to prevent conflicts until the loot::Game class is hidden inside the API). This also involved minor modifications to LoadOrderHandler, the removal of Masterlist::Update(Game& game), and the (re)addition of a new API function for specifying the game's main master file.
This commit is contained in:
+12
-5
@@ -176,7 +176,6 @@ set (LOOT_SRC "${CMAKE_BINARY_DIR}/generated/loot_version.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/tag.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game_cache.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/load_order_handler.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata_list.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/masterlist.cpp"
|
||||
@@ -191,7 +190,6 @@ set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_evaluator.
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_grammar.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game_cache.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/load_order_handler.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata_list.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/masterlist.h"
|
||||
@@ -236,6 +234,8 @@ set (LOOT_GUI_SRC "${CMAKE_SOURCE_DIR}/src/gui/main.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_app.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_scheme_handler_factory.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query_handler.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/game.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/game_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_state.cpp"
|
||||
@@ -278,6 +278,8 @@ set (LOOT_GUI_HEADERS "${CMAKE_SOURCE_DIR}/src/gui/editor_message.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/sort_plugins_query.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/update_masterlist_query.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query_handler.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/game.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/game_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_state.h"
|
||||
@@ -311,7 +313,6 @@ set (LOOT_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/tests/backend/main.cpp")
|
||||
|
||||
set (LOOT_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/backend/game/game_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/game/game_cache_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/game/game_settings_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/game/load_order_handler_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/git_helper_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/backend/helpers/helpers_test.h"
|
||||
@@ -343,14 +344,20 @@ set(LOOT_API_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/tests/api/api_game_operatio
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/api/is_compatible_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/common_game_test_fixture.h")
|
||||
|
||||
set(LOOT_GUI_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.cpp"
|
||||
set(LOOT_GUI_TESTS_SRC "${CMAKE_SOURCE_DIR}/src/gui/state/game.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/game_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_settings.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_state.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/main.cpp")
|
||||
|
||||
set (LOOT_GUI_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.h"
|
||||
set (LOOT_GUI_TESTS_HEADERS "${CMAKE_SOURCE_DIR}/src/gui/state/game.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/game_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_paths.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_settings.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/state/loot_state.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/state/game_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/state/game_settings_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/state/loot_paths_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/state/loot_settings_test.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/tests/gui/state/loot_state_test.h")
|
||||
|
||||
@@ -70,6 +70,13 @@ public:
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Identify the game's main master file.
|
||||
* @details When sorting, LOOT always only loads the headers of the game's
|
||||
* main master file as a performance optimisation.
|
||||
*/
|
||||
virtual void IdentifyMainMasterFile(const std::string& masterFile) = 0;
|
||||
|
||||
/**
|
||||
* @brief Calculates a new load order for the game's installed plugins
|
||||
* (including inactive plugins) and outputs the sorted order.
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
|
||||
namespace loot {
|
||||
ApiDatabase::ApiDatabase(const GameType game, const std::string& gamePath, const std::string& gameLocalDataPath)
|
||||
: game_(Game(GameSettings(GameType(game)), "", gameLocalDataPath)) {
|
||||
game_.SetGamePath(gamePath);
|
||||
: game_(game, gamePath, gameLocalDataPath) {
|
||||
game_.Init();
|
||||
}
|
||||
|
||||
@@ -85,13 +84,17 @@ void ApiDatabase::EvalLists() {
|
||||
game_.GetUserlist() = userTemp;
|
||||
}
|
||||
|
||||
void ApiDatabase::IdentifyMainMasterFile(const std::string& masterFile) {
|
||||
masterFile_ = masterFile;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// LOOT Functionality Functions
|
||||
////////////////////////////////////
|
||||
|
||||
std::vector<std::string> ApiDatabase::SortPlugins(const std::vector<std::string>& plugins) {
|
||||
// Always reload all the plugins.
|
||||
game_.LoadPlugins(plugins, false);
|
||||
game_.LoadPlugins(plugins, masterFile_, false);
|
||||
|
||||
//Sort plugins into their load order.
|
||||
PluginSorter sorter;
|
||||
|
||||
@@ -43,6 +43,8 @@ struct ApiDatabase : public DatabaseInterface {
|
||||
|
||||
void EvalLists();
|
||||
|
||||
void IdentifyMainMasterFile(const std::string& masterFile);
|
||||
|
||||
std::vector<std::string> SortPlugins(const std::vector<std::string>& plugins);
|
||||
|
||||
bool UpdateMasterlist(const std::string& masterlist_path,
|
||||
@@ -64,6 +66,8 @@ struct ApiDatabase : public DatabaseInterface {
|
||||
private:
|
||||
Game game_;
|
||||
|
||||
std::string masterFile_;
|
||||
|
||||
Masterlist unevaluatedMasterlist_;
|
||||
MetadataList unevaluatedUserlist_;
|
||||
};
|
||||
|
||||
+22
-186
@@ -58,103 +58,36 @@ using std::vector;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace loot {
|
||||
Game::Game(const GameSettings& gameSettings,
|
||||
const boost::filesystem::path& lootDataPath,
|
||||
Game::Game(const GameType gameType,
|
||||
const boost::filesystem::path& gamePath,
|
||||
const boost::filesystem::path& localDataPath) :
|
||||
GameSettings(gameSettings),
|
||||
lootDataPath_(lootDataPath),
|
||||
localDataPath_(localDataPath),
|
||||
pluginsFullyLoaded_(false) {
|
||||
this->SetName(gameSettings.Name())
|
||||
.SetMaster(gameSettings.Master())
|
||||
.SetRepoURL(gameSettings.RepoURL())
|
||||
.SetRepoBranch(gameSettings.RepoBranch())
|
||||
.SetGamePath(gameSettings.GamePath())
|
||||
.SetRegistryKey(gameSettings.RegistryKey());
|
||||
type_(gameType),
|
||||
gamePath_(gamePath),
|
||||
localDataPath_(localDataPath) {}
|
||||
|
||||
GameType Game::Type() const {
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool Game::IsInstalled() {
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking if game \"" << Name() << "\" is installed.";
|
||||
if (!GamePath().empty() && fs::exists(GamePath() / "Data" / Master()))
|
||||
return true;
|
||||
boost::filesystem::path Game::DataPath() const {
|
||||
return gamePath_ / "Data";
|
||||
}
|
||||
|
||||
if (fs::exists(fs::path("..") / "Data" / Master())) {
|
||||
SetGamePath("..");
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string path;
|
||||
std::string key_parent = fs::path(RegistryKey()).parent_path().string();
|
||||
std::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" / Master())) {
|
||||
SetGamePath(path);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
} catch (std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Error while checking if game \"" << Name() << "\" is installed: " << e.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
std::string Game::GetArchiveFileExtension() const {
|
||||
if (type_ == GameType::fo4)
|
||||
return ".ba2";
|
||||
else
|
||||
return ".bsa";
|
||||
}
|
||||
|
||||
void Game::Init() {
|
||||
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << Name();
|
||||
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game of type " << (int) type_ << " at: " << gamePath_;
|
||||
|
||||
if (!this->IsInstalled()) {
|
||||
throw GameDetectionError("Game path could not be detected.");
|
||||
}
|
||||
|
||||
if (!lootDataPath_.empty()) {
|
||||
//Make sure that the LOOT game path exists.
|
||||
try {
|
||||
if (!fs::exists(lootDataPath_ / FolderName()))
|
||||
fs::create_directories(lootDataPath_ / FolderName());
|
||||
} catch (fs::filesystem_error& e) {
|
||||
throw FileAccessError((boost::format("Could not create LOOT folder for game. Details: %1%") % e.what()).str());
|
||||
}
|
||||
}
|
||||
|
||||
loadOrderHandler_.Init(*this, localDataPath_);
|
||||
loadOrderHandler_.Init(type_, gamePath_, localDataPath_);
|
||||
StoreLoadOrder(loadOrderHandler_.GetLoadOrder());
|
||||
}
|
||||
|
||||
void Game::RedatePlugins() {
|
||||
if (Type() != GameType::tes5 && Type() != GameType::tes5se) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Cannot redate plugins for game " << Name();
|
||||
return;
|
||||
}
|
||||
|
||||
vector<string> loadorder = GetLoadOrder();
|
||||
if (!loadorder.empty()) {
|
||||
time_t lastTime = 0;
|
||||
for (const auto &pluginName : loadorder) {
|
||||
fs::path filepath = DataPath() / pluginName;
|
||||
if (!fs::exists(filepath)) {
|
||||
if (fs::exists(filepath.string() + ".ghost"))
|
||||
filepath += ".ghost";
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
time_t thisTime = fs::last_write_time(filepath);
|
||||
BOOST_LOG_TRIVIAL(info) << "Current timestamp for \"" << filepath.filename().string() << "\": " << thisTime;
|
||||
if (thisTime >= lastTime) {
|
||||
lastTime = thisTime;
|
||||
BOOST_LOG_TRIVIAL(trace) << "No need to redate \"" << filepath.filename().string() << "\".";
|
||||
} else {
|
||||
lastTime += 60;
|
||||
fs::last_write_time(filepath, lastTime); //Space timestamps by a minute.
|
||||
BOOST_LOG_TRIVIAL(info) << "Redated \"" << filepath.filename().string() << "\" to: " << lastTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::LoadPlugins(const std::vector<std::string>& plugins, bool headersOnly) {
|
||||
void Game::LoadPlugins(const std::vector<std::string>& plugins, const std::string& masterFile, bool headersOnly) {
|
||||
uintmax_t meanFileSize = 0;
|
||||
std::multimap<uintmax_t, string> sizeMap;
|
||||
|
||||
@@ -206,7 +139,7 @@ void Game::LoadPlugins(const std::vector<std::string>& plugins, bool headersOnly
|
||||
threads.push_back(thread([&]() {
|
||||
for (auto pluginName : pluginGroup) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Loading " << pluginName;
|
||||
if (boost::iequals(pluginName, Master()))
|
||||
if (boost::iequals(pluginName, masterFile))
|
||||
AddPlugin(Plugin(*this, pluginName, true));
|
||||
else
|
||||
AddPlugin(Plugin(*this, pluginName, headersOnly));
|
||||
@@ -219,28 +152,6 @@ void Game::LoadPlugins(const std::vector<std::string>& plugins, bool headersOnly
|
||||
if (thread.joinable())
|
||||
thread.join();
|
||||
}
|
||||
|
||||
pluginsFullyLoaded_ = !headersOnly;
|
||||
}
|
||||
|
||||
void Game::LoadAllInstalledPlugins(bool headersOnly) {
|
||||
std::vector<std::string> plugins;
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Scanning for plugins in " << this->DataPath();
|
||||
for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) {
|
||||
if (fs::is_regular_file(it->status()) && Plugin::IsValid(it->path().filename().string(), *this)) {
|
||||
string name = it->path().filename().string();
|
||||
BOOST_LOG_TRIVIAL(info) << "Found plugin: " << name;
|
||||
|
||||
plugins.push_back(name);
|
||||
}
|
||||
}
|
||||
|
||||
LoadPlugins(plugins, headersOnly);
|
||||
}
|
||||
|
||||
bool Game::ArePluginsFullyLoaded() const {
|
||||
return pluginsFullyLoaded_;
|
||||
}
|
||||
|
||||
bool Game::IsPluginActive(const std::string& pluginName) const {
|
||||
@@ -251,91 +162,16 @@ bool Game::IsPluginActive(const std::string& pluginName) const {
|
||||
}
|
||||
}
|
||||
|
||||
short Game::GetActiveLoadOrderIndex(const std::string & pluginName) const {
|
||||
return GetActiveLoadOrderIndex(pluginName, GetLoadOrder());
|
||||
}
|
||||
|
||||
short Game::GetActiveLoadOrderIndex(const std::string & pluginName, const std::vector<std::string>& loadOrder) const {
|
||||
// Get the full load order, then count the number of active plugins until the
|
||||
// given plugin is encountered. If the plugin isn't active or in the load
|
||||
// order, return -1.
|
||||
|
||||
if (!IsPluginActive(pluginName))
|
||||
return -1;
|
||||
|
||||
short numberOfActivePlugins = 0;
|
||||
for (const std::string& plugin : loadOrder) {
|
||||
if (boost::iequals(plugin, pluginName))
|
||||
return numberOfActivePlugins;
|
||||
|
||||
if (IsPluginActive(plugin))
|
||||
++numberOfActivePlugins;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<std::string> Game::GetLoadOrder() const {
|
||||
auto loadOrder = GameCache::GetLoadOrder();
|
||||
if (loadOrder.empty())
|
||||
return loadOrderHandler_.GetLoadOrder();
|
||||
|
||||
return loadOrder;
|
||||
}
|
||||
|
||||
void Game::SetLoadOrder(const std::vector<std::string>& loadOrder) {
|
||||
loadOrderHandler_.BackupLoadOrder(GetLoadOrder(), lootDataPath_ / FolderName());
|
||||
loadOrderHandler_.SetLoadOrder(loadOrder);
|
||||
StoreLoadOrder(loadOrder);
|
||||
}
|
||||
|
||||
fs::path Game::MasterlistPath() const {
|
||||
if (lootDataPath_.empty() || FolderName().empty())
|
||||
return "";
|
||||
else
|
||||
return lootDataPath_ / FolderName() / "masterlist.yaml";
|
||||
}
|
||||
|
||||
fs::path Game::UserlistPath() const {
|
||||
if (lootDataPath_.empty() || FolderName().empty())
|
||||
return "";
|
||||
else
|
||||
return lootDataPath_ / FolderName() / "userlist.yaml";
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string Game::RegKeyStringValue(const std::string& keyStr, const std::string& subkey, const std::string& value) {
|
||||
HKEY hKey = NULL;
|
||||
DWORD len = MAX_PATH;
|
||||
std::wstring wstr(MAX_PATH, 0);
|
||||
|
||||
if (keyStr == "HKEY_CLASSES_ROOT")
|
||||
hKey = HKEY_CLASSES_ROOT;
|
||||
else if (keyStr == "HKEY_CURRENT_CONFIG")
|
||||
hKey = HKEY_CURRENT_CONFIG;
|
||||
else if (keyStr == "HKEY_CURRENT_USER")
|
||||
hKey = HKEY_CURRENT_USER;
|
||||
else if (keyStr == "HKEY_LOCAL_MACHINE")
|
||||
hKey = HKEY_LOCAL_MACHINE;
|
||||
else if (keyStr == "HKEY_USERS")
|
||||
hKey = HKEY_USERS;
|
||||
else
|
||||
throw std::invalid_argument("Invalid registry key given.");
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Getting string for registry key, subkey and value: " << keyStr << " + " << subkey << " + " << value;
|
||||
LONG ret = RegGetValue(hKey,
|
||||
ToWinWide(subkey).c_str(),
|
||||
ToWinWide(value).c_str(),
|
||||
RRF_RT_REG_SZ | KEY_WOW64_32KEY,
|
||||
NULL,
|
||||
&wstr[0],
|
||||
&len);
|
||||
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Found string: " << wstr.c_str();
|
||||
return FromWinWide(wstr.c_str()); // Passing c_str() cuts off any unused buffer.
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "Failed to get string value.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+10
-23
@@ -30,45 +30,32 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "backend/game/game_cache.h"
|
||||
#include "backend/game/game_settings.h"
|
||||
#include "backend/game/load_order_handler.h"
|
||||
|
||||
namespace loot {
|
||||
class Game : public GameSettings, public GameCache {
|
||||
class Game : public GameCache {
|
||||
public:
|
||||
Game(const GameSettings& gameSettings,
|
||||
const boost::filesystem::path& lootDataPath,
|
||||
Game(const GameType gameType,
|
||||
const boost::filesystem::path& gamePath,
|
||||
const boost::filesystem::path& localDataPath = "");
|
||||
|
||||
bool IsInstalled(); //Sets gamePath if the current value is not valid and a valid path is found.
|
||||
GameType Type() const;
|
||||
boost::filesystem::path DataPath() const;
|
||||
std::string GetArchiveFileExtension() const;
|
||||
|
||||
void Init();
|
||||
|
||||
void RedatePlugins(); //Change timestamps to match load order (Skyrim only).
|
||||
void LoadPlugins(const std::vector<std::string>& plugins, const std::string& masterFile, bool headersOnly);
|
||||
|
||||
void LoadPlugins(const std::vector<std::string>& plugins, bool headersOnly);
|
||||
void LoadAllInstalledPlugins(bool headersOnly); //Loads all installed plugins.
|
||||
bool ArePluginsFullyLoaded() const; // Checks if the game's plugins have already been loaded.
|
||||
|
||||
// Check if the plugin is active by using the cached value if
|
||||
// available, and otherwise asking the load order handler.
|
||||
bool IsPluginActive(const std::string& pluginName) const;
|
||||
short GetActiveLoadOrderIndex(const std::string & pluginName) const;
|
||||
short GetActiveLoadOrderIndex(const std::string & pluginName, const std::vector<std::string>& loadOrder) const;
|
||||
|
||||
std::vector<std::string> GetLoadOrder() const;
|
||||
void SetLoadOrder(const std::vector<std::string>& loadOrder);
|
||||
|
||||
boost::filesystem::path MasterlistPath() const;
|
||||
boost::filesystem::path UserlistPath() const;
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
std::string RegKeyStringValue(const std::string& keyStr, const std::string& subkey, const std::string& value);
|
||||
#endif
|
||||
|
||||
const boost::filesystem::path lootDataPath_;
|
||||
const GameType type_;
|
||||
const boost::filesystem::path gamePath_;
|
||||
const boost::filesystem::path localDataPath_;
|
||||
|
||||
bool pluginsFullyLoaded_;
|
||||
LoadOrderHandler loadOrderHandler_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,8 +40,10 @@ LoadOrderHandler::~LoadOrderHandler() {
|
||||
lo_destroy_handle(gh_);
|
||||
}
|
||||
|
||||
void LoadOrderHandler::Init(const GameSettings& game, const boost::filesystem::path& gameLocalAppData) {
|
||||
if (game.GamePath().empty()) {
|
||||
void LoadOrderHandler::Init(const GameType& gameType,
|
||||
const boost::filesystem::path& gamePath,
|
||||
const boost::filesystem::path& gameLocalAppData) {
|
||||
if (gamePath.empty()) {
|
||||
throw std::invalid_argument("Game path is not initialised.");
|
||||
}
|
||||
|
||||
@@ -57,18 +59,18 @@ void LoadOrderHandler::Init(const GameSettings& game, const boost::filesystem::p
|
||||
}
|
||||
|
||||
int ret;
|
||||
if (game.Type() == GameType::tes4)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_TES4, game.GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (game.Type() == GameType::tes5)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_TES5, game.GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (game.Type() == GameType::tes5se)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_TES5SE, game.GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (game.Type() == GameType::fo3)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_FO3, game.GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (game.Type() == GameType::fonv)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_FNV, game.GamePath().string().c_str(), gameLocalDataPath);
|
||||
else if (game.Type() == GameType::fo4)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_FO4, game.GamePath().string().c_str(), gameLocalDataPath);
|
||||
if (gameType == GameType::tes4)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_TES4, gamePath.string().c_str(), gameLocalDataPath);
|
||||
else if (gameType == GameType::tes5)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_TES5, gamePath.string().c_str(), gameLocalDataPath);
|
||||
else if (gameType == GameType::tes5se)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_TES5SE, gamePath.string().c_str(), gameLocalDataPath);
|
||||
else if (gameType == GameType::fo3)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_FO3, gamePath.string().c_str(), gameLocalDataPath);
|
||||
else if (gameType == GameType::fonv)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_FNV, gamePath.string().c_str(), gameLocalDataPath);
|
||||
else if (gameType == GameType::fo4)
|
||||
ret = lo_create_handle(&gh_, LIBLO_GAME_FO4, gamePath.string().c_str(), gameLocalDataPath);
|
||||
else
|
||||
ret = LIBLO_ERROR_INVALID_ARGS;
|
||||
|
||||
@@ -166,23 +168,4 @@ void LoadOrderHandler::SetLoadOrder(const std::vector<std::string>& loadOrder) c
|
||||
throw std::system_error(ret, libloadorder_category(), err);
|
||||
}
|
||||
}
|
||||
void LoadOrderHandler::BackupLoadOrder(const std::vector<std::string>& loadOrder,
|
||||
const boost::filesystem::path & backupDirectory) {
|
||||
const int maxBackupIndex = 2;
|
||||
boost::format filenameFormat = boost::format("loadorder.bak.%1%");
|
||||
|
||||
boost::filesystem::path backupFilePath = backupDirectory / (filenameFormat % 2).str();
|
||||
if (boost::filesystem::exists(backupFilePath))
|
||||
boost::filesystem::remove(backupFilePath);
|
||||
|
||||
for (int i = maxBackupIndex - 1; i > -1; --i) {
|
||||
const boost::filesystem::path backupFilePath = backupDirectory / (filenameFormat % i).str();
|
||||
if (boost::filesystem::exists(backupFilePath))
|
||||
boost::filesystem::rename(backupFilePath, backupDirectory / (filenameFormat % (i + 1)).str());
|
||||
}
|
||||
|
||||
boost::filesystem::ofstream out(backupDirectory / (filenameFormat % 0).str());
|
||||
for (const auto &plugin : loadOrder)
|
||||
out << plugin << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <libloadorder/libloadorder.h>
|
||||
|
||||
#include "backend/game/game_settings.h"
|
||||
#include "loot/enum/game_type.h"
|
||||
|
||||
namespace loot {
|
||||
class LoadOrderHandler {
|
||||
@@ -40,16 +40,15 @@ public:
|
||||
LoadOrderHandler();
|
||||
~LoadOrderHandler();
|
||||
|
||||
void Init(const GameSettings& game, const boost::filesystem::path& gameLocalAppData = "");
|
||||
void Init(const GameType& game,
|
||||
const boost::filesystem::path& gamePath,
|
||||
const boost::filesystem::path& gameLocalAppData = "");
|
||||
|
||||
std::vector<std::string> GetLoadOrder() const;
|
||||
|
||||
bool IsPluginActive(const std::string& pluginName) const;
|
||||
|
||||
void SetLoadOrder(const std::vector<std::string>& loadOrder) const;
|
||||
|
||||
static void BackupLoadOrder(const std::vector<std::string>& loadOrder,
|
||||
const boost::filesystem::path& backupDirectory);
|
||||
private:
|
||||
lo_game_handle gh_;
|
||||
};
|
||||
|
||||
@@ -84,10 +84,6 @@ MasterlistInfo Masterlist::GetInfo(const boost::filesystem::path& path, bool sho
|
||||
return info;
|
||||
}
|
||||
|
||||
bool Masterlist::Update(const Game& game) {
|
||||
return Update(game.MasterlistPath(), game.RepoURL(), game.RepoBranch());
|
||||
}
|
||||
|
||||
bool Masterlist::Update(const boost::filesystem::path& path, const std::string& repoUrl, const std::string& repoBranch) {
|
||||
GitHelper git;
|
||||
fs::path repoPath = path.parent_path();
|
||||
|
||||
@@ -37,7 +37,6 @@ class Game;
|
||||
|
||||
class Masterlist : public MetadataList {
|
||||
public:
|
||||
bool Update(const Game& game);
|
||||
bool Update(const boost::filesystem::path& path,
|
||||
const std::string& repoURL,
|
||||
const std::string& repoBranch);
|
||||
|
||||
@@ -25,7 +25,7 @@ along with LOOT. If not, see
|
||||
#ifndef LOOT_GUI_QUERY_CLEAR_ALL_METADATA_QUERY
|
||||
#define LOOT_GUI_QUERY_CLEAR_ALL_METADATA_QUERY
|
||||
|
||||
#include "backend/game/game.h"
|
||||
#include "gui/state/game.h"
|
||||
#include "gui/query/json.h"
|
||||
#include "gui/query/metadata_query.h"
|
||||
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
return "[]";
|
||||
}
|
||||
|
||||
Game& game_;
|
||||
gui::Game& game_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ along with LOOT. If not, see
|
||||
#ifndef LOOT_GUI_QUERY_CLEAR_PLUGIN_METADATA_QUERY
|
||||
#define LOOT_GUI_QUERY_CLEAR_PLUGIN_METADATA_QUERY
|
||||
|
||||
#include "backend/game/game.h"
|
||||
#include "gui/state/game.h"
|
||||
#include "gui/query/json.h"
|
||||
#include "gui/query/metadata_query.h"
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Game& game_;
|
||||
gui::Game& game_;
|
||||
const std::string pluginName_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ along with LOOT. If not, see
|
||||
#ifndef LOOT_GUI_QUERY_GET_CONFLICTING_PLUGINS_QUERY
|
||||
#define LOOT_GUI_QUERY_GET_CONFLICTING_PLUGINS_QUERY
|
||||
|
||||
#include "backend/game/game.h"
|
||||
#include "gui/state/game.h"
|
||||
#include "gui/query/json.h"
|
||||
#include "gui/query/metadata_query.h"
|
||||
|
||||
@@ -75,7 +75,7 @@ private:
|
||||
return pluginNode;
|
||||
}
|
||||
|
||||
Game& game_;
|
||||
gui::Game& game_;
|
||||
const std::string pluginName_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ along with LOOT. If not, see
|
||||
#ifndef LOOT_GUI_QUERY_GET_GAME_TYPES_QUERY
|
||||
#define LOOT_GUI_QUERY_GET_GAME_TYPES_QUERY
|
||||
|
||||
#include "backend/game/game_settings.h"
|
||||
#include "gui/state/game_settings.h"
|
||||
#include "gui/query/json.h"
|
||||
#include "gui/query/query.h"
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ along with LOOT. If not, see
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "backend/game/game.h"
|
||||
#include "backend/plugin/plugin.h"
|
||||
#include "gui/query/query.h"
|
||||
#include "loot/exception/file_access_error.h"
|
||||
|
||||
@@ -25,7 +25,7 @@ along with LOOT. If not, see
|
||||
#ifndef LOOT_GUI_QUERY_UPDATE_MASTERLIST_QUERY
|
||||
#define LOOT_GUI_QUERY_UPDATE_MASTERLIST_QUERY
|
||||
|
||||
#include "backend/game/game.h"
|
||||
#include "gui/state/game.h"
|
||||
#include "gui/query/json.h"
|
||||
#include "gui/query/metadata_query.h"
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
private:
|
||||
bool updateMasterlist() {
|
||||
try {
|
||||
return game_.GetMasterlist().Update(game_);
|
||||
return game_.GetMasterlist().Update(game_.MasterlistPath(), game_.RepoURL(), game_.RepoBranch());
|
||||
} catch (std::exception&) {
|
||||
try {
|
||||
game_.GetMasterlist().Load(game_.MasterlistPath());
|
||||
@@ -104,7 +104,7 @@ private:
|
||||
return pluginNode;
|
||||
}
|
||||
|
||||
Game& game_;
|
||||
gui::Game& game_;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 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
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "gui/state/game.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include "loot/exception/file_access_error.h"
|
||||
#include "loot/exception/game_detection_error.h"
|
||||
#include "backend/helpers/helpers.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef UNICODE
|
||||
# define UNICODE
|
||||
# endif
|
||||
# ifndef _UNICODE
|
||||
# define _UNICODE
|
||||
# endif
|
||||
# define NOMINMAX
|
||||
# include "windows.h"
|
||||
# include "shlobj.h"
|
||||
# include "shlwapi.h"
|
||||
#endif
|
||||
|
||||
using std::list;
|
||||
using std::string;
|
||||
using std::thread;
|
||||
using std::vector;
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace loot {
|
||||
namespace gui {
|
||||
Game::Game(const GameSettings& gameSettings,
|
||||
const boost::filesystem::path& lootDataPath,
|
||||
const boost::filesystem::path& localDataPath) :
|
||||
loot::Game(gameSettings.Type(), gameSettings.GamePath(), localDataPath),
|
||||
GameSettings(gameSettings),
|
||||
lootDataPath_(lootDataPath),
|
||||
pluginsFullyLoaded_(false) {}
|
||||
|
||||
bool Game::IsInstalled() {
|
||||
try {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Checking if game \"" << Name() << "\" is installed.";
|
||||
if (!GamePath().empty() && fs::exists(GamePath() / "Data" / Master()))
|
||||
return true;
|
||||
|
||||
if (fs::exists(fs::path("..") / "Data" / Master())) {
|
||||
SetGamePath("..");
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string path;
|
||||
std::string key_parent = fs::path(RegistryKey()).parent_path().string();
|
||||
std::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" / Master())) {
|
||||
SetGamePath(path);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
} catch (std::exception &e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Error while checking if game \"" << Name() << "\" is installed: " << e.what();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Game::Init() {
|
||||
BOOST_LOG_TRIVIAL(info) << "Initialising filesystem-related data for game: " << Name();
|
||||
|
||||
if (!this->IsInstalled()) {
|
||||
throw GameDetectionError("Game path could not be detected.");
|
||||
}
|
||||
|
||||
if (!lootDataPath_.empty()) {
|
||||
//Make sure that the LOOT game path exists.
|
||||
try {
|
||||
if (!fs::exists(lootDataPath_ / FolderName()))
|
||||
fs::create_directories(lootDataPath_ / FolderName());
|
||||
} catch (fs::filesystem_error& e) {
|
||||
throw FileAccessError((boost::format("Could not create LOOT folder for game. Details: %1%") % e.what()).str());
|
||||
}
|
||||
}
|
||||
|
||||
loot::Game::Init();
|
||||
}
|
||||
|
||||
void Game::RedatePlugins() {
|
||||
if (Type() != GameType::tes5 && Type() != GameType::tes5se) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Cannot redate plugins for game " << Name();
|
||||
return;
|
||||
}
|
||||
|
||||
vector<string> loadorder = GetLoadOrder();
|
||||
if (!loadorder.empty()) {
|
||||
time_t lastTime = 0;
|
||||
for (const auto &pluginName : loadorder) {
|
||||
fs::path filepath = DataPath() / pluginName;
|
||||
if (!fs::exists(filepath)) {
|
||||
if (fs::exists(filepath.string() + ".ghost"))
|
||||
filepath += ".ghost";
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
time_t thisTime = fs::last_write_time(filepath);
|
||||
BOOST_LOG_TRIVIAL(info) << "Current timestamp for \"" << filepath.filename().string() << "\": " << thisTime;
|
||||
if (thisTime >= lastTime) {
|
||||
lastTime = thisTime;
|
||||
BOOST_LOG_TRIVIAL(trace) << "No need to redate \"" << filepath.filename().string() << "\".";
|
||||
} else {
|
||||
lastTime += 60;
|
||||
fs::last_write_time(filepath, lastTime); //Space timestamps by a minute.
|
||||
BOOST_LOG_TRIVIAL(info) << "Redated \"" << filepath.filename().string() << "\" to: " << lastTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Game::LoadAllInstalledPlugins(bool headersOnly) {
|
||||
std::vector<std::string> plugins;
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Scanning for plugins in " << this->DataPath();
|
||||
for (fs::directory_iterator it(this->DataPath()); it != fs::directory_iterator(); ++it) {
|
||||
if (fs::is_regular_file(it->status()) && Plugin::IsValid(it->path().filename().string(), *this)) {
|
||||
string name = it->path().filename().string();
|
||||
BOOST_LOG_TRIVIAL(info) << "Found plugin: " << name;
|
||||
|
||||
plugins.push_back(name);
|
||||
}
|
||||
}
|
||||
|
||||
LoadPlugins(plugins, Master(), headersOnly);
|
||||
|
||||
pluginsFullyLoaded_ = !headersOnly;
|
||||
}
|
||||
|
||||
bool Game::ArePluginsFullyLoaded() const {
|
||||
return pluginsFullyLoaded_;
|
||||
}
|
||||
|
||||
fs::path Game::MasterlistPath() const {
|
||||
if (lootDataPath_.empty() || FolderName().empty())
|
||||
return "";
|
||||
else
|
||||
return lootDataPath_ / FolderName() / "masterlist.yaml";
|
||||
}
|
||||
|
||||
fs::path Game::UserlistPath() const {
|
||||
if (lootDataPath_.empty() || FolderName().empty())
|
||||
return "";
|
||||
else
|
||||
return lootDataPath_ / FolderName() / "userlist.yaml";
|
||||
}
|
||||
|
||||
short Game::GetActiveLoadOrderIndex(const std::string & pluginName) const {
|
||||
return GetActiveLoadOrderIndex(pluginName, GetLoadOrder());
|
||||
}
|
||||
|
||||
short Game::GetActiveLoadOrderIndex(const std::string & pluginName, const std::vector<std::string>& loadOrder) const {
|
||||
// Get the full load order, then count the number of active plugins until the
|
||||
// given plugin is encountered. If the plugin isn't active or in the load
|
||||
// order, return -1.
|
||||
|
||||
if (!IsPluginActive(pluginName))
|
||||
return -1;
|
||||
|
||||
short numberOfActivePlugins = 0;
|
||||
for (const std::string& plugin : loadOrder) {
|
||||
if (boost::iequals(plugin, pluginName))
|
||||
return numberOfActivePlugins;
|
||||
|
||||
if (IsPluginActive(plugin))
|
||||
++numberOfActivePlugins;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Game::BackupLoadOrder(const std::vector<std::string>& loadOrder,
|
||||
const boost::filesystem::path & backupDirectory) {
|
||||
const int maxBackupIndex = 2;
|
||||
boost::format filenameFormat = boost::format("loadorder.bak.%1%");
|
||||
|
||||
boost::filesystem::path backupFilePath = backupDirectory / (filenameFormat % 2).str();
|
||||
if (boost::filesystem::exists(backupFilePath))
|
||||
boost::filesystem::remove(backupFilePath);
|
||||
|
||||
for (int i = maxBackupIndex - 1; i > -1; --i) {
|
||||
const boost::filesystem::path backupFilePath = backupDirectory / (filenameFormat % i).str();
|
||||
if (boost::filesystem::exists(backupFilePath))
|
||||
boost::filesystem::rename(backupFilePath, backupDirectory / (filenameFormat % (i + 1)).str());
|
||||
}
|
||||
|
||||
boost::filesystem::ofstream out(backupDirectory / (filenameFormat % 0).str());
|
||||
for (const auto &plugin : loadOrder)
|
||||
out << plugin << std::endl;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string Game::RegKeyStringValue(const std::string& keyStr, const std::string& subkey, const std::string& value) {
|
||||
HKEY hKey = NULL;
|
||||
DWORD len = MAX_PATH;
|
||||
std::wstring wstr(MAX_PATH, 0);
|
||||
|
||||
if (keyStr == "HKEY_CLASSES_ROOT")
|
||||
hKey = HKEY_CLASSES_ROOT;
|
||||
else if (keyStr == "HKEY_CURRENT_CONFIG")
|
||||
hKey = HKEY_CURRENT_CONFIG;
|
||||
else if (keyStr == "HKEY_CURRENT_USER")
|
||||
hKey = HKEY_CURRENT_USER;
|
||||
else if (keyStr == "HKEY_LOCAL_MACHINE")
|
||||
hKey = HKEY_LOCAL_MACHINE;
|
||||
else if (keyStr == "HKEY_USERS")
|
||||
hKey = HKEY_USERS;
|
||||
else
|
||||
throw std::invalid_argument("Invalid registry key given.");
|
||||
|
||||
BOOST_LOG_TRIVIAL(trace) << "Getting string for registry key, subkey and value: " << keyStr << " + " << subkey << " + " << value;
|
||||
LONG ret = RegGetValue(hKey,
|
||||
ToWinWide(subkey).c_str(),
|
||||
ToWinWide(value).c_str(),
|
||||
RRF_RT_REG_SZ | KEY_WOW64_32KEY,
|
||||
NULL,
|
||||
&wstr[0],
|
||||
&len);
|
||||
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Found string: " << wstr.c_str();
|
||||
return FromWinWide(wstr.c_str()); // Passing c_str() cuts off any unused buffer.
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << "Failed to get string value.";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 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
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_GUI_STATE_GAME
|
||||
#define LOOT_GUI_STATE_GAME
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "backend/game/game.h"
|
||||
#include "gui/state/game_settings.h"
|
||||
|
||||
namespace loot {
|
||||
namespace gui {
|
||||
class Game : public loot::Game, public GameSettings {
|
||||
public:
|
||||
Game(const GameSettings& gameSettings,
|
||||
const boost::filesystem::path& lootDataPath,
|
||||
const boost::filesystem::path& localDataPath = "");
|
||||
|
||||
using GameSettings::Type;
|
||||
|
||||
bool IsInstalled(); //Sets gamePath if the current value is not valid and a valid path is found.
|
||||
void Init();
|
||||
|
||||
void RedatePlugins(); //Change timestamps to match load order (Skyrim only).
|
||||
|
||||
void LoadAllInstalledPlugins(bool headersOnly); //Loads all installed plugins.
|
||||
bool ArePluginsFullyLoaded() const; // Checks if the game's plugins have already been loaded.
|
||||
|
||||
boost::filesystem::path MasterlistPath() const;
|
||||
boost::filesystem::path UserlistPath() const;
|
||||
|
||||
short GetActiveLoadOrderIndex(const std::string & pluginName) const;
|
||||
short GetActiveLoadOrderIndex(const std::string & pluginName, const std::vector<std::string>& loadOrder) const;
|
||||
|
||||
static void BackupLoadOrder(const std::vector<std::string>& loadOrder,
|
||||
const boost::filesystem::path& backupDirectory);
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
std::string RegKeyStringValue(const std::string& keyStr, const std::string& subkey, const std::string& value);
|
||||
#endif
|
||||
|
||||
const boost::filesystem::path lootDataPath_;
|
||||
|
||||
bool pluginsFullyLoaded_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,7 +22,7 @@
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "backend/game/game_settings.h"
|
||||
#include "gui/state/game_settings.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/locale.hpp>
|
||||
@@ -124,20 +124,6 @@ fs::path GameSettings::GamePath() const {
|
||||
return gamePath_;
|
||||
}
|
||||
|
||||
fs::path GameSettings::DataPath() const {
|
||||
if (gamePath_.empty())
|
||||
return "";
|
||||
else
|
||||
return gamePath_ / "Data";
|
||||
}
|
||||
|
||||
std::string GameSettings::GetArchiveFileExtension() const {
|
||||
if (type_ == GameType::fo4)
|
||||
return ".ba2";
|
||||
else
|
||||
return ".bsa";
|
||||
}
|
||||
|
||||
GameSettings& GameSettings::SetName(const std::string& name) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Setting \"" << name_ << "\" name to: " << name;
|
||||
name_ = name;
|
||||
@@ -22,8 +22,8 @@
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_BACKEND_GAME_GAME_SETTINGS
|
||||
#define LOOT_BACKEND_GAME_GAME_SETTINGS
|
||||
#ifndef LOOT_GUI_STATE_GAME_SETTINGS
|
||||
#define LOOT_GUI_STATE_GAME_SETTINGS
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
@@ -50,11 +50,7 @@ public:
|
||||
std::string RegistryKey() const;
|
||||
std::string RepoURL() const;
|
||||
std::string RepoBranch() const;
|
||||
|
||||
boost::filesystem::path GamePath() const;
|
||||
boost::filesystem::path DataPath() const;
|
||||
|
||||
std::string GetArchiveFileExtension() const;
|
||||
|
||||
GameSettings& SetName(const std::string& name);
|
||||
GameSettings& SetMaster(const std::string& masterFile);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user