From 33b2030f975fcdc8cb3861267dbc47b8a22a0a16 Mon Sep 17 00:00:00 2001 From: Tixx <83774803+WiserTixx@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:10:16 +0200 Subject: [PATCH 1/2] Support global keys in ini --- include/Utils.h | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/include/Utils.h b/include/Utils.h index c0f4e21..28f0986 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifdef _WIN32 @@ -108,8 +109,8 @@ namespace Utils { return result; } #endif - inline std::map> ParseINI(const std::string& contents) { - std::map> ini; + inline std::map, std::string>> ParseINI(const std::string& contents) { + std::map, std::string>> ini; std::string currentSection; auto sections = Split(contents, "\n"); @@ -136,18 +137,19 @@ namespace Utils { if (line[0] == '[') { currentSection = line.substr(1, line.find(']') - 1); } else { - - if (currentSection.empty()) { - invalidLineLog(); - continue; - } - std::string key, value; size_t pos = line.find('='); if (pos != std::string::npos) { key = line.substr(0, pos); + + key = key.substr(0, key.find_last_not_of(" \t") + 1); + value = line.substr(pos + 1); - ini[currentSection][key] = value; + if (currentSection.empty()) { + ini[key] = value; + } else { + std::get>(ini[currentSection])[key] = value; + } } else { invalidLineLog(); continue; @@ -157,7 +159,7 @@ namespace Utils { value.erase(0, value.find_first_not_of(" \t")); value.erase(value.find_last_not_of(" \t") + 1); - ini[currentSection][key] = value; + std::get>(ini[currentSection])[key] = value; } } From 8a0f87f476916c12ec9c2b2db89b75ee6dd1ae5e Mon Sep 17 00:00:00 2001 From: Tixx <83774803+WiserTixx@users.noreply.github.com> Date: Tue, 16 Sep 2025 16:11:26 +0200 Subject: [PATCH 2/2] Remove registry check and add support for new ini file --- src/GameStart.cpp | 62 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/GameStart.cpp b/src/GameStart.cpp index ea33395..834628d 100644 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -54,10 +54,10 @@ std::filesystem::path GetGamePath() { debug("Successfully parsed startup.ini"); std::wstring userPath; - if (ini.contains("filesystem") && ini["filesystem"].contains("UserPath")) - userPath = Utils::ToWString(ini["filesystem"]["UserPath"]); + if (ini.contains("filesystem") && std::get>(ini["filesystem"]).contains("UserPath")) + userPath = Utils::ToWString(std::get>(ini["filesystem"])["UserPath"]); - if (!userPath.empty()) + if (!userPath.empty() && Path.empty()) if (userPath = Utils::ExpandEnvVars(userPath); std::filesystem::exists(userPath)) { Path = userPath; debug(L"Using custom user folder path from startup.ini: " + Path.wstring()); @@ -66,32 +66,54 @@ std::filesystem::path GetGamePath() { } if (Path.empty()) { - HKEY hKey; - LPCTSTR sk = "Software\\BeamNG\\BeamNG.drive"; - LONG openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); - if (openRes != ERROR_SUCCESS) { - fatal("Please launch the game at least once!"); + wchar_t* appDataPath = new wchar_t[MAX_PATH]; + HRESULT result = SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataPath); + + if (!SUCCEEDED(result)) { + 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()); + 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(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()) { - wchar_t* appDataPath = new wchar_t[MAX_PATH]; - 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; + Path = BeamNGAppdataPath / "BeamNG.drive"; } + + delete[] appDataPath; } } std::string Ver = CheckVer(GetGameDir()); Ver = Ver.substr(0, Ver.find('.', Ver.find('.') + 1)); - Path /= Utils::ToWString(Ver); + Path /= Utils::ToWString("current"); return Path; } #elif defined(__linux__)