mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-05-18 23:50:36 +00:00
User folder parsing updates (#208)
This PR adds support for the changes made to the BeamNG userfolder path location. 1. Registry check for userfolder removed 2. New ini file is checked for userfolder 3. Ini parser now supports global keys --- By creating this pull request, I understand that code that is AI generated or otherwise automatically generated may be rejected without further discussion. I declare that I fully understand all code I pushed into this PR, and wrote all this code myself and own the rights to this code.
This commit is contained in:
+12
-10
@@ -14,6 +14,7 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -108,8 +109,8 @@ namespace Utils {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
inline std::map<std::string, std::map<std::string, std::string>> ParseINI(const std::string& contents) {
|
inline std::map<std::string, std::variant<std::map<std::string, std::string>, std::string>> ParseINI(const std::string& contents) {
|
||||||
std::map<std::string, std::map<std::string, std::string>> ini;
|
std::map<std::string, std::variant<std::map<std::string, std::string>, std::string>> ini;
|
||||||
|
|
||||||
std::string currentSection;
|
std::string currentSection;
|
||||||
auto sections = Split(contents, "\n");
|
auto sections = Split(contents, "\n");
|
||||||
@@ -136,18 +137,19 @@ namespace Utils {
|
|||||||
if (line[0] == '[') {
|
if (line[0] == '[') {
|
||||||
currentSection = line.substr(1, line.find(']') - 1);
|
currentSection = line.substr(1, line.find(']') - 1);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (currentSection.empty()) {
|
|
||||||
invalidLineLog();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string key, value;
|
std::string key, value;
|
||||||
size_t pos = line.find('=');
|
size_t pos = line.find('=');
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
key = line.substr(0, pos);
|
key = line.substr(0, pos);
|
||||||
|
|
||||||
|
key = key.substr(0, key.find_last_not_of(" \t") + 1);
|
||||||
|
|
||||||
value = line.substr(pos + 1);
|
value = line.substr(pos + 1);
|
||||||
ini[currentSection][key] = value;
|
if (currentSection.empty()) {
|
||||||
|
ini[key] = value;
|
||||||
|
} else {
|
||||||
|
std::get<std::map<std::string, std::string>>(ini[currentSection])[key] = value;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidLineLog();
|
invalidLineLog();
|
||||||
continue;
|
continue;
|
||||||
@@ -157,7 +159,7 @@ namespace Utils {
|
|||||||
value.erase(0, value.find_first_not_of(" \t"));
|
value.erase(0, value.find_first_not_of(" \t"));
|
||||||
value.erase(value.find_last_not_of(" \t") + 1);
|
value.erase(value.find_last_not_of(" \t") + 1);
|
||||||
|
|
||||||
ini[currentSection][key] = value;
|
std::get<std::map<std::string, std::string>>(ini[currentSection])[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
-20
@@ -54,10 +54,10 @@ std::filesystem::path GetGamePath() {
|
|||||||
debug("Successfully parsed startup.ini");
|
debug("Successfully parsed startup.ini");
|
||||||
|
|
||||||
std::wstring userPath;
|
std::wstring userPath;
|
||||||
if (ini.contains("filesystem") && ini["filesystem"].contains("UserPath"))
|
if (ini.contains("filesystem") && std::get<std::map<std::string, std::string>>(ini["filesystem"]).contains("UserPath"))
|
||||||
userPath = Utils::ToWString(ini["filesystem"]["UserPath"]);
|
userPath = Utils::ToWString(std::get<std::map<std::string, std::string>>(ini["filesystem"])["UserPath"]);
|
||||||
|
|
||||||
if (!userPath.empty())
|
if (!userPath.empty() && Path.empty())
|
||||||
if (userPath = Utils::ExpandEnvVars(userPath); std::filesystem::exists(userPath)) {
|
if (userPath = Utils::ExpandEnvVars(userPath); std::filesystem::exists(userPath)) {
|
||||||
Path = userPath;
|
Path = userPath;
|
||||||
debug(L"Using custom user folder path from startup.ini: " + Path.wstring());
|
debug(L"Using custom user folder path from startup.ini: " + Path.wstring());
|
||||||
@@ -66,32 +66,54 @@ std::filesystem::path GetGamePath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Path.empty()) {
|
if (Path.empty()) {
|
||||||
HKEY hKey;
|
wchar_t* appDataPath = new wchar_t[MAX_PATH];
|
||||||
LPCTSTR sk = "Software\\BeamNG\\BeamNG.drive";
|
HRESULT result = SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataPath);
|
||||||
LONG openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey);
|
|
||||||
if (openRes != ERROR_SUCCESS) {
|
if (!SUCCEEDED(result)) {
|
||||||
fatal("Please launch the game at least once!");
|
fatal("Cannot get Local Appdata directory");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BeamNGAppdataPath = std::filesystem::path(appDataPath) / "BeamNG";
|
||||||
|
|
||||||
|
if (const auto beamngIniPath = BeamNGAppdataPath / "BeamNG.Drive.ini"; exists(beamngIniPath)) {
|
||||||
|
if (std::ifstream beamngIni(beamngIniPath); beamngIni.is_open()) {
|
||||||
|
std::string contents((std::istreambuf_iterator(beamngIni)), std::istreambuf_iterator<char>());
|
||||||
|
beamngIni.close();
|
||||||
|
|
||||||
|
auto ini = Utils::ParseINI(contents);
|
||||||
|
if (ini.empty())
|
||||||
|
warn("Failed to parse BeamNG.Drive.ini");
|
||||||
|
else
|
||||||
|
debug("Successfully parsed BeamNG.Drive.ini");
|
||||||
|
|
||||||
|
std::wstring userPath;
|
||||||
|
|
||||||
|
if (ini.contains("userFolder")) {
|
||||||
|
userPath = Utils::ToWString(std::get<std::string>(ini["userFolder"]));
|
||||||
|
userPath.erase(0, userPath.find_first_not_of(L" \t"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userPath.empty() && Path.empty())
|
||||||
|
if (userPath = std::filesystem::path(Utils::ExpandEnvVars(userPath)); std::filesystem::exists(userPath)) {
|
||||||
|
Path = userPath;
|
||||||
|
debug(L"Using custom user folder path from BeamNG.Drive.ini: " + Path.wstring());
|
||||||
|
} else
|
||||||
|
warn(L"Found custom user folder path (" + userPath + L") in BeamNG.Drive.ini but it doesn't exist, skipping");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Path = QueryKey(hKey, 4);
|
|
||||||
|
|
||||||
if (Path.empty()) {
|
if (Path.empty()) {
|
||||||
wchar_t* appDataPath = new wchar_t[MAX_PATH];
|
Path = BeamNGAppdataPath / "BeamNG.drive";
|
||||||
HRESULT result = SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataPath);
|
|
||||||
|
|
||||||
if (!SUCCEEDED(result)) {
|
|
||||||
fatal("Cannot get Local Appdata directory");
|
|
||||||
}
|
|
||||||
|
|
||||||
Path = std::filesystem::path(appDataPath) / "BeamNG.drive";
|
|
||||||
|
|
||||||
delete[] appDataPath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete[] appDataPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Ver = CheckVer(GetGameDir());
|
std::string Ver = CheckVer(GetGameDir());
|
||||||
Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1));
|
Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1));
|
||||||
Path /= Utils::ToWString(Ver);
|
Path /= Utils::ToWString("current");
|
||||||
return Path;
|
return Path;
|
||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
|||||||
Reference in New Issue
Block a user