mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2025-07-04 00:47:23 +00:00
Merge pull request #39 from SamZahreddine/v3
fix auto detect on first launch
This commit is contained in:
commit
4e8421a515
@ -39,3 +39,4 @@ SpacesInSquareBrackets: false
|
|||||||
Standard: Latest
|
Standard: Latest
|
||||||
TabWidth: 2
|
TabWidth: 2
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
ColumnLimit: 0
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
typedef bool (*DownloadProgress) (size_t c, size_t t);
|
||||||
class HTTP {
|
class HTTP {
|
||||||
public:
|
public:
|
||||||
static bool Download(const std::string& IP, const std::string& Path);
|
static bool Download(const std::string& IP, const std::string& Path, DownloadProgress DP = ProgressBar);
|
||||||
static std::string Post(const std::string& IP, const std::string& Fields);
|
static std::string Post(const std::string& IP, const std::string& Fields);
|
||||||
static std::string Get(const std::string& IP);
|
static std::string Get(const std::string& IP, DownloadProgress DP = ProgressBar);
|
||||||
static bool ProgressBar(size_t c, size_t t);
|
static bool ProgressBar(size_t c, size_t t);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -37,6 +37,8 @@ class Launcher {
|
|||||||
void LaunchGame();
|
void LaunchGame();
|
||||||
void CheckKey();
|
void CheckKey();
|
||||||
void SetupMOD();
|
void SetupMOD();
|
||||||
|
static void AdminRelaunch();
|
||||||
|
static void Relaunch();
|
||||||
static std::string QueryValue(HKEY& hKey, const char* Name);
|
static std::string QueryValue(HKEY& hKey, const char* Name);
|
||||||
|
|
||||||
public: // Getters and Setters
|
public: // Getters and Setters
|
||||||
@ -54,19 +56,19 @@ class Launcher {
|
|||||||
void HandleIPC(const std::string& Data);
|
void HandleIPC(const std::string& Data);
|
||||||
std::string GetLocalAppdata();
|
std::string GetLocalAppdata();
|
||||||
void UpdatePresence();
|
void UpdatePresence();
|
||||||
void AdminRelaunch();
|
|
||||||
void RichPresence();
|
void RichPresence();
|
||||||
void WindowsInit();
|
void WindowsInit();
|
||||||
void UpdateCheck();
|
void UpdateCheck();
|
||||||
void ResetMods();
|
void ResetMods();
|
||||||
void EnableMP();
|
void EnableMP();
|
||||||
void Relaunch();
|
|
||||||
void ListenIPC();
|
void ListenIPC();
|
||||||
void Abort();
|
void Abort();
|
||||||
|
|
||||||
public: // variables
|
public: // variables
|
||||||
static inline std::thread EntryThread{};
|
static inline std::thread EntryThread{};
|
||||||
static inline VersionParser SupportedVersion{"0.25.4.0"};
|
static inline VersionParser SupportedVersion{"0.25.4.0"};
|
||||||
|
static inline std::string Version{"2.0"};
|
||||||
|
static inline std::string FullVersion{Version + ".1"};
|
||||||
|
|
||||||
private: // variables
|
private: // variables
|
||||||
uint32_t GamePID{0};
|
uint32_t GamePID{0};
|
||||||
@ -83,14 +85,12 @@ class Launcher {
|
|||||||
std::string BeamVersion{};
|
std::string BeamVersion{};
|
||||||
std::string BeamUserPath{};
|
std::string BeamUserPath{};
|
||||||
std::string DiscordMessage{};
|
std::string DiscordMessage{};
|
||||||
std::string Version{"2.0"};
|
|
||||||
Server ServerHandler{this};
|
Server ServerHandler{this};
|
||||||
std::string TargetBuild{"default"};
|
std::string TargetBuild{"default"};
|
||||||
std::string GameConfigPath{};
|
std::string GameConfigPath{};
|
||||||
std::string ProfileConfigPath{};
|
std::string ProfileConfigPath{};
|
||||||
std::string CacheConfigPath{};
|
std::string CacheConfigPath{};
|
||||||
static inline std::atomic<bool> Shutdown{false}, Exit{false};
|
static inline std::atomic<bool> Shutdown{false}, Exit{false};
|
||||||
std::string FullVersion{Version + ".99"};
|
|
||||||
std::unique_ptr<IPC> IPCToGame{};
|
std::unique_ptr<IPC> IPCToGame{};
|
||||||
std::unique_ptr<IPC> IPCFromGame{};
|
std::unique_ptr<IPC> IPCFromGame{};
|
||||||
};
|
};
|
||||||
|
@ -237,14 +237,14 @@ void Launcher::QueryRegistry() {
|
|||||||
|
|
||||||
void Launcher::AdminRelaunch() {
|
void Launcher::AdminRelaunch() {
|
||||||
system("cls");
|
system("cls");
|
||||||
ShellExecuteA(nullptr, "runas", CurrentPath.string().c_str(), nullptr,
|
ShellExecuteA(nullptr, "runas", fs::current_path().string().c_str(), nullptr,
|
||||||
nullptr, SW_SHOWNORMAL);
|
nullptr, SW_SHOWNORMAL);
|
||||||
ShowWindow(GetConsoleWindow(), 0);
|
ShowWindow(GetConsoleWindow(), 0);
|
||||||
throw ShutdownException("Relaunching");
|
throw ShutdownException("Relaunching");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::Relaunch() {
|
void Launcher::Relaunch() {
|
||||||
ShellExecuteA(nullptr, "open", CurrentPath.string().c_str(), nullptr,
|
ShellExecuteA(nullptr, "open", fs::current_path().string().c_str(), nullptr,
|
||||||
nullptr, SW_SHOWNORMAL);
|
nullptr, SW_SHOWNORMAL);
|
||||||
ShowWindow(GetConsoleWindow(), 0);
|
ShowWindow(GetConsoleWindow(), 0);
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
bool HTTP::isDownload = false;
|
bool HTTP::isDownload = false;
|
||||||
std::atomic<httplib::Client*> CliRef = nullptr;
|
std::atomic<httplib::Client*> CliRef = nullptr;
|
||||||
std::string HTTP::Get(const std::string& IP) {
|
std::string HTTP::Get(const std::string& IP, DownloadProgress DP) {
|
||||||
static std::mutex Lock;
|
static std::mutex Lock;
|
||||||
std::scoped_lock Guard(Lock);
|
std::scoped_lock Guard(Lock);
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ std::string HTTP::Get(const std::string& IP) {
|
|||||||
CliRef.store(&cli);
|
CliRef.store(&cli);
|
||||||
cli.set_connection_timeout(std::chrono::seconds(5));
|
cli.set_connection_timeout(std::chrono::seconds(5));
|
||||||
cli.set_follow_location(true);
|
cli.set_follow_location(true);
|
||||||
auto res = cli.Get(IP.substr(pos).c_str(), ProgressBar);
|
auto res = cli.Get(IP.substr(pos).c_str(), DP);
|
||||||
std::string Ret;
|
std::string Ret;
|
||||||
|
|
||||||
if (res.error() == httplib::Error::Success) {
|
if (res.error() == httplib::Error::Success) {
|
||||||
@ -105,12 +105,12 @@ bool HTTP::ProgressBar(size_t c, size_t t) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HTTP::Download(const std::string& IP, const std::string& Path) {
|
bool HTTP::Download(const std::string& IP, const std::string& Path, DownloadProgress DP) {
|
||||||
static std::mutex Lock;
|
static std::mutex Lock;
|
||||||
std::scoped_lock Guard(Lock);
|
std::scoped_lock Guard(Lock);
|
||||||
|
|
||||||
isDownload = true;
|
isDownload = true;
|
||||||
std::string Ret = Get(IP);
|
std::string Ret = Get(IP, DP);
|
||||||
isDownload = false;
|
isDownload = false;
|
||||||
|
|
||||||
if (Ret.empty()) return false;
|
if (Ret.empty()) return false;
|
||||||
|
263
src/gui/Gui.cpp
263
src/gui/Gui.cpp
@ -2,6 +2,7 @@
|
|||||||
/// Created by Anonymous275 on 12/27/21
|
/// Created by Anonymous275 on 12/27/21
|
||||||
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
/// Copyright (c) 2021-present Anonymous275 read the LICENSE file for more info.
|
||||||
///
|
///
|
||||||
|
// clang-format off
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include <wx/dc.h>
|
#include <wx/dc.h>
|
||||||
@ -24,6 +25,7 @@
|
|||||||
#include "HttpAPI.h"
|
#include "HttpAPI.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
/*/////////// TestFrame class ///////////
|
/*/////////// TestFrame class ///////////
|
||||||
class MyTestFrame : public wxFrame {
|
class MyTestFrame : public wxFrame {
|
||||||
@ -63,6 +65,9 @@ class MyMainFrame : public wxFrame {
|
|||||||
static void GameVersionLabel();
|
static void GameVersionLabel();
|
||||||
static inline MyAccountFrame* AccountFrame;
|
static inline MyAccountFrame* AccountFrame;
|
||||||
static inline MyMainFrame* MainFrameInstance;
|
static inline MyMainFrame* MainFrameInstance;
|
||||||
|
static inline std::thread UpdateThread;
|
||||||
|
wxGauge* UpdateBar;
|
||||||
|
wxStaticText* txtUpdate;
|
||||||
wxBitmapButton* BitAccount;
|
wxBitmapButton* BitAccount;
|
||||||
void OnClickAccount(wxCommandEvent& event);
|
void OnClickAccount(wxCommandEvent& event);
|
||||||
|
|
||||||
@ -89,7 +94,6 @@ class MySettingsFrame : public wxFrame {
|
|||||||
void UpdateProfileDirectory(const std::string& path);
|
void UpdateProfileDirectory(const std::string& path);
|
||||||
void UpdateCacheDirectory(const std::string& path);
|
void UpdateCacheDirectory(const std::string& path);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxCheckBox* checkConsole;
|
wxCheckBox* checkConsole;
|
||||||
wxDirPickerCtrl *ctrlGameDirectory, *ctrlProfileDirectory, *ctrlCacheDirectory;
|
wxDirPickerCtrl *ctrlGameDirectory, *ctrlProfileDirectory, *ctrlCacheDirectory;
|
||||||
@ -108,6 +112,7 @@ class MySettingsFrame : public wxFrame {
|
|||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
/////////// Event Tables ///////////
|
/////////// Event Tables ///////////
|
||||||
// MainFrame (ID range 1 to 99):
|
// MainFrame (ID range 1 to 99):
|
||||||
wxBEGIN_EVENT_TABLE(MyMainFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(MyMainFrame, wxFrame)
|
||||||
@ -134,7 +139,8 @@ wxBEGIN_EVENT_TABLE(MyMainFrame, wxFrame)
|
|||||||
EVT_BUTTON(205, MySettingsFrame::OnResetCache)
|
EVT_BUTTON(205, MySettingsFrame::OnResetCache)
|
||||||
EVT_CHOICE(206, MySettingsFrame::OnChangedBuild)
|
EVT_CHOICE(206, MySettingsFrame::OnChangedBuild)
|
||||||
EVT_CHECKBOX(207, MySettingsFrame::OnClickConsole)
|
EVT_CHECKBOX(207, MySettingsFrame::OnClickConsole)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE();
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
/////////// Get Stats Function ///////////
|
/////////// Get Stats Function ///////////
|
||||||
void MyMainFrame::GetStats() {
|
void MyMainFrame::GetStats() {
|
||||||
@ -191,6 +197,81 @@ void MySettingsFrame::UpdateCacheDirectory(const std::string& path) {
|
|||||||
UIData::CachePath = path;
|
UIData::CachePath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////// UpdateConfig Function ///////////
|
||||||
|
template<typename ValueType>
|
||||||
|
void UpdateConfig(const std::string& key, ValueType&& value) {
|
||||||
|
if (fs::exists("Launcher.toml")) {
|
||||||
|
toml::parse_result config = toml::parse_file("Launcher.toml");
|
||||||
|
config.insert_or_assign(key, value);
|
||||||
|
|
||||||
|
std::ofstream tml("Launcher.toml");
|
||||||
|
if (tml.is_open()) {
|
||||||
|
tml << config;
|
||||||
|
tml.close();
|
||||||
|
} else wxMessageBox("Failed to modify config file", "Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////// Auto Detect Game Function ///////////
|
||||||
|
std::string AutoDetectGame() {
|
||||||
|
HKEY BeamNG;
|
||||||
|
std::string GamePath;
|
||||||
|
LONG RegRes =
|
||||||
|
RegOpenKeyExA(HKEY_CURRENT_USER, R"(Software\BeamNG\BeamNG.drive)", 0,
|
||||||
|
KEY_READ, &BeamNG);
|
||||||
|
if (RegRes == ERROR_SUCCESS) {
|
||||||
|
GamePath = Launcher::QueryValue(BeamNG, "rootpath");
|
||||||
|
RegCloseKey(BeamNG);
|
||||||
|
}
|
||||||
|
if (!GamePath.empty()) {
|
||||||
|
if (GamePath.ends_with('\\')) GamePath.pop_back();
|
||||||
|
UpdateConfig("GamePath", GamePath);
|
||||||
|
return GamePath;
|
||||||
|
} else {
|
||||||
|
wxMessageBox("Please launch the game at least once, failed to read registry key Software\\BeamNG\\BeamNG.drive", "Error");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////// Auto Detect Profile Function ///////////
|
||||||
|
std::string AutoDetectProfile() {
|
||||||
|
HKEY BeamNG;
|
||||||
|
std::string ProfilePath;
|
||||||
|
LONG RegRes =
|
||||||
|
RegOpenKeyExA(HKEY_CURRENT_USER, R"(Software\BeamNG\BeamNG.drive)", 0,
|
||||||
|
KEY_READ, &BeamNG);
|
||||||
|
if (RegRes == ERROR_SUCCESS) {
|
||||||
|
ProfilePath = Launcher::QueryValue(BeamNG, "userpath_override");
|
||||||
|
RegCloseKey(BeamNG);
|
||||||
|
}
|
||||||
|
if (ProfilePath.empty()) {
|
||||||
|
PWSTR folderPath = nullptr;
|
||||||
|
HRESULT hr =
|
||||||
|
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &folderPath);
|
||||||
|
|
||||||
|
if (!SUCCEEDED(hr)) {
|
||||||
|
wxMessageBox(
|
||||||
|
"Please launch the game at least once, failed to read registry key Software\\BeamNG\\BeamNG.drive",
|
||||||
|
"Error");
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
_bstr_t bstrPath(folderPath);
|
||||||
|
std::string Path((char*)bstrPath);
|
||||||
|
CoTaskMemFree(folderPath);
|
||||||
|
ProfilePath = Path + "\\BeamNG.drive";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateConfig("ProfilePath", ProfilePath);
|
||||||
|
return ProfilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////// Reset Cache Function ///////////
|
||||||
|
std::string ResetCache() {
|
||||||
|
std::string CachePath = fs::current_path().append("Resources").string();
|
||||||
|
UpdateConfig("CachePath", CachePath);
|
||||||
|
return CachePath;
|
||||||
|
}
|
||||||
|
|
||||||
/////////// Load Config Function ///////////
|
/////////// Load Config Function ///////////
|
||||||
void LoadConfig() {
|
void LoadConfig() {
|
||||||
if (fs::exists("Launcher.toml")) {
|
if (fs::exists("Launcher.toml")) {
|
||||||
@ -227,11 +308,14 @@ void LoadConfig() {
|
|||||||
if (tml.is_open()) {
|
if (tml.is_open()) {
|
||||||
tml << "UI = true\n"
|
tml << "UI = true\n"
|
||||||
"Build = 'Default'\n"
|
"Build = 'Default'\n"
|
||||||
"GamePath = 'C:\\Program Files'\n"
|
"GamePath = ''\n"
|
||||||
"ProfilePath = 'C:\\Program Files'\n"
|
"ProfilePath = ''\n"
|
||||||
"CachePath = 'Resources'\n"
|
"CachePath = ''\n"
|
||||||
"Console = false";
|
"Console = false";
|
||||||
tml.close();
|
tml.close();
|
||||||
|
AutoDetectGame();
|
||||||
|
AutoDetectProfile();
|
||||||
|
ResetCache();
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
} else wxMessageBox("Failed to create config file", "Error");
|
} else wxMessageBox("Failed to create config file", "Error");
|
||||||
}
|
}
|
||||||
@ -305,10 +389,9 @@ void CheckKey() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WindowsConsole(bool isChecked);
|
void WindowsConsole(bool isChecked);
|
||||||
|
void UpdateCheck();
|
||||||
/////////// OnInit Function ///////////
|
/////////// OnInit Function ///////////
|
||||||
bool MyApp::OnInit() {
|
bool MyApp::OnInit() {
|
||||||
|
|
||||||
if (!fs::exists("icons")) {
|
if (!fs::exists("icons")) {
|
||||||
fs::create_directory("icons");
|
fs::create_directory("icons");
|
||||||
}
|
}
|
||||||
@ -321,6 +404,8 @@ bool MyApp::OnInit() {
|
|||||||
|
|
||||||
auto* MainFrame = new MyMainFrame();
|
auto* MainFrame = new MyMainFrame();
|
||||||
MyMainFrame::MainFrameInstance = MainFrame;
|
MyMainFrame::MainFrameInstance = MainFrame;
|
||||||
|
MyMainFrame::UpdateThread = std::thread (UpdateCheck);
|
||||||
|
|
||||||
MainFrame->SetIcon(wxIcon("icons/BeamMP_black.png", wxBITMAP_TYPE_PNG));
|
MainFrame->SetIcon(wxIcon("icons/BeamMP_black.png", wxBITMAP_TYPE_PNG));
|
||||||
|
|
||||||
// Set MainFrame properties:
|
// Set MainFrame properties:
|
||||||
@ -330,8 +415,7 @@ bool MyApp::OnInit() {
|
|||||||
if (wxSystemSettings::GetAppearance().IsDark()) {
|
if (wxSystemSettings::GetAppearance().IsDark()) {
|
||||||
MainFrame->SetBackgroundColour(wxColour(40, 40, 40));
|
MainFrame->SetBackgroundColour(wxColour(40, 40, 40));
|
||||||
MainFrame->SetForegroundColour(wxColour(255, 255, 255));
|
MainFrame->SetForegroundColour(wxColour(255, 255, 255));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
MainFrame->SetBackgroundColour(wxColour("white"));
|
MainFrame->SetBackgroundColour(wxColour("white"));
|
||||||
MainFrame->SetForegroundColour(wxColour("white"));
|
MainFrame->SetForegroundColour(wxColour("white"));
|
||||||
}
|
}
|
||||||
@ -369,8 +453,7 @@ void WindowsConsole (bool isChecked) {
|
|||||||
::freopen_s(&pNewStdout, "CONOUT$", "w", stdout);
|
::freopen_s(&pNewStdout, "CONOUT$", "w", stdout);
|
||||||
::freopen_s(&pNewStderr, "CONOUT$", "w", stderr);
|
::freopen_s(&pNewStderr, "CONOUT$", "w", stderr);
|
||||||
::freopen_s(&pNewStdin, "CONIN$", "r", stdin);
|
::freopen_s(&pNewStdin, "CONIN$", "r", stdin);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
FreeConsole();
|
FreeConsole();
|
||||||
::fclose(stdout);
|
::fclose(stdout);
|
||||||
::fclose(stderr);
|
::fclose(stderr);
|
||||||
@ -395,8 +478,7 @@ std::string jsonRead () {
|
|||||||
std::ifstream ifs(path);
|
std::ifstream ifs(path);
|
||||||
nlohmann::json jf = nlohmann::json::parse(ifs, nullptr, false);
|
nlohmann::json jf = nlohmann::json::parse(ifs, nullptr, false);
|
||||||
if (!jf.is_discarded() && !jf.empty()) return jf["version"];
|
if (!jf.is_discarded() && !jf.empty()) return jf["version"];
|
||||||
}
|
} else wxMessageBox("Couldn't read game version, check game path in settings", "Error");
|
||||||
else wxMessageBox("Couldn't read game version, check game path in settings", "Error");
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,6 +501,63 @@ std::string GetPictureName () {
|
|||||||
return entry.path().string();
|
return entry.path().string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProgressBar (size_t c, size_t t) {
|
||||||
|
int Percent = int(round(double(c) / double(t) * 100));
|
||||||
|
MyMainFrame::MainFrameInstance->UpdateBar->SetValue(Percent);
|
||||||
|
MyMainFrame::MainFrameInstance->txtUpdate->SetLabel("Downloading " + std::to_string(Percent) + "%");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////// Update Check Function ///////////
|
||||||
|
void UpdateCheck() {
|
||||||
|
std::string link;
|
||||||
|
std::string HTTP = HTTP::Get("https://beammp.com/builds/launcher?version=true");
|
||||||
|
bool fallback = false;
|
||||||
|
if (HTTP.find_first_of("0123456789") == std::string::npos) {
|
||||||
|
HTTP = HTTP::Get("https://backup1.beammp.com/builds/launcher?version=true");
|
||||||
|
fallback = true;
|
||||||
|
if (HTTP.find_first_of("0123456789") == std::string::npos)
|
||||||
|
wxMessageBox("Primary Servers Offline! sorry for the inconvenience!", "Error");
|
||||||
|
}
|
||||||
|
if (fallback) {
|
||||||
|
link = "https://backup1.beammp.com/builds/launcher?download=true";
|
||||||
|
} else link = "https://beammp.com/builds/launcher?download=true";
|
||||||
|
auto CurrentPath = fs::current_path();
|
||||||
|
std::string EP(CurrentPath.append("BeamMP-Launcher.exe").string()), Back(CurrentPath.append("BeamMP-Launcher.back").string());
|
||||||
|
LOG(INFO) <<EP + " AND " + Back;
|
||||||
|
|
||||||
|
if (fs::exists(Back)) remove(Back.c_str());
|
||||||
|
std::string RemoteVer;
|
||||||
|
for (char& c : HTTP) {
|
||||||
|
if (std::isdigit(c) || c == '.') {
|
||||||
|
RemoteVer += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (VersionParser(RemoteVer) > VersionParser(Launcher::FullVersion)) {
|
||||||
|
system("cls");
|
||||||
|
MyMainFrame::MainFrameInstance->txtUpdate->SetLabel("Downloading...");
|
||||||
|
if (std::rename(EP.c_str(), Back.c_str())) {
|
||||||
|
wxMessageBox("Failed to create a backup!", "Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HTTP::Download(link, EP, ProgressBar)) {
|
||||||
|
wxMessageBox("Launcher Update failed! trying again...", "Error");
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(2));
|
||||||
|
|
||||||
|
if (!HTTP::Download(link, EP, ProgressBar)) {
|
||||||
|
wxMessageBox("Launcher Update failed!", "Error");
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(5));
|
||||||
|
Launcher::AdminRelaunch();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Launcher::Relaunch();
|
||||||
|
} else MyMainFrame::MainFrameInstance->txtUpdate->SetLabel("BeamMP V" + Launcher::FullVersion);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// TestFrame Function ///////////
|
/////////// TestFrame Function ///////////
|
||||||
@ -461,11 +600,11 @@ MyMainFrame::MyMainFrame() :
|
|||||||
auto* HyperPatreon = new wxHyperlinkCtrl(panel, wxID_ANY, wxT("Patreon"), wxT("https://www.patreon.com/BeamMP"), wxPoint(240, 10));
|
auto* HyperPatreon = new wxHyperlinkCtrl(panel, wxID_ANY, wxT("Patreon"), wxT("https://www.patreon.com/BeamMP"), wxPoint(240, 10));
|
||||||
|
|
||||||
// Update:
|
// Update:
|
||||||
auto* txtUpdate = new wxStaticText(panel, wxID_ANY, wxT("Updating BeamMP "), wxPoint(10, 490));
|
txtUpdate = new wxStaticText(panel, wxID_ANY, wxT("Updating BeamMP "), wxPoint(10, 490));
|
||||||
|
|
||||||
auto* UpdateBar = new wxGauge(panel, wxID_ANY, 100, wxPoint(10, 520), wxSize(127, -1));
|
UpdateBar = new wxGauge(panel, wxID_ANY, 100, wxPoint(10, 520), wxSize(127, -1));
|
||||||
UpdateBar->SetValue(0);
|
UpdateBar->SetValue(0);
|
||||||
while (UpdateBar->GetValue() <76) {
|
while (UpdateBar->GetValue() < 101) {
|
||||||
txtUpdate->SetLabel(wxT("Updating BeamMP: " + std::to_string(UpdateBar->GetValue()) + "%"));
|
txtUpdate->SetLabel(wxT("Updating BeamMP: " + std::to_string(UpdateBar->GetValue()) + "%"));
|
||||||
UpdateBar->SetValue(UpdateBar->GetValue() + 1);
|
UpdateBar->SetValue(UpdateBar->GetValue() + 1);
|
||||||
}
|
}
|
||||||
@ -534,8 +673,7 @@ MyMainFrame::MyMainFrame() :
|
|||||||
// Logo:
|
// Logo:
|
||||||
auto* logo = new wxBitmapButton(panel, 4, wxBitmapBundle(wxImage("icons/BeamMP_white.png", wxBITMAP_TYPE_PNG).Scale(100, 100, wxIMAGE_QUALITY_HIGH)), wxPoint(850, -15), wxSize(100, 100), wxBORDER_NONE);
|
auto* logo = new wxBitmapButton(panel, 4, wxBitmapBundle(wxImage("icons/BeamMP_white.png", wxBITMAP_TYPE_PNG).Scale(100, 100, wxIMAGE_QUALITY_HIGH)), wxPoint(850, -15), wxSize(100, 100), wxBORDER_NONE);
|
||||||
logo->SetBackgroundColour(wxColour(40, 40, 40));
|
logo->SetBackgroundColour(wxColour(40, 40, 40));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Logo:
|
// Logo:
|
||||||
auto* logo = new wxBitmapButton(panel, 4, wxBitmapBundle(wxImage("icons/BeamMP_black.png", wxBITMAP_TYPE_PNG).Scale(100, 100, wxIMAGE_QUALITY_HIGH)), wxPoint(850, -15), wxSize(100, 100), wxBORDER_NONE);
|
auto* logo = new wxBitmapButton(panel, 4, wxBitmapBundle(wxImage("icons/BeamMP_black.png", wxBITMAP_TYPE_PNG).Scale(100, 100, wxIMAGE_QUALITY_HIGH)), wxPoint(850, -15), wxSize(100, 100), wxBORDER_NONE);
|
||||||
logo->SetBackgroundColour("white");
|
logo->SetBackgroundColour("white");
|
||||||
@ -544,7 +682,8 @@ MyMainFrame::MyMainFrame() :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/////////// Account Frame Content ///////////
|
/////////// Account Frame Content ///////////
|
||||||
MyAccountFrame::MyAccountFrame() : wxFrame(nullptr, wxID_ANY, "Account Manager", wxDefaultPosition,wxDefaultSize,
|
MyAccountFrame::MyAccountFrame() :
|
||||||
|
wxFrame(nullptr, wxID_ANY, "Account Manager", wxDefaultPosition, wxDefaultSize,
|
||||||
wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX) {
|
wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX) {
|
||||||
MyAccountFrame::SetFocus();
|
MyAccountFrame::SetFocus();
|
||||||
auto* handler = new wxPNGHandler;
|
auto* handler = new wxPNGHandler;
|
||||||
@ -567,8 +706,7 @@ MyAccountFrame::MyAccountFrame() : wxFrame(nullptr, wxID_ANY, "Account Manager",
|
|||||||
// Text:
|
// Text:
|
||||||
txtName->SetForegroundColour("white");
|
txtName->SetForegroundColour("white");
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
image->SetBitmap(wxBitmapBundle(wxImage("icons/default.png", wxBITMAP_TYPE_PNG).Scale(120, 120, wxIMAGE_QUALITY_HIGH)));
|
image->SetBitmap(wxBitmapBundle(wxImage("icons/default.png", wxBITMAP_TYPE_PNG).Scale(120, 120, wxIMAGE_QUALITY_HIGH)));
|
||||||
|
|
||||||
auto* txtLogin = new wxStaticText(panel, wxID_ANY, wxT("Login with your BeamMP account."), wxPoint(150, 200));
|
auto* txtLogin = new wxStaticText(panel, wxID_ANY, wxT("Login with your BeamMP account."), wxPoint(150, 200));
|
||||||
@ -638,21 +776,6 @@ MySettingsFrame::MySettingsFrame() :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// UpdateConfig Function ///////////
|
|
||||||
template <typename ValueType>
|
|
||||||
void UpdateConfig (const std::string& key, ValueType&& value) {
|
|
||||||
if (fs::exists("Launcher.toml")) {
|
|
||||||
toml::parse_result config = toml::parse_file("Launcher.toml");
|
|
||||||
config.insert_or_assign(key, value);
|
|
||||||
|
|
||||||
std::ofstream tml("Launcher.toml");
|
|
||||||
if (tml.is_open()) {
|
|
||||||
tml << config;
|
|
||||||
tml.close();
|
|
||||||
} else wxMessageBox("Failed to modify config file", "Error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////// Game Version Label Function ///////////
|
/////////// Game Version Label Function ///////////
|
||||||
void MyMainFrame::GameVersionLabel() {
|
void MyMainFrame::GameVersionLabel() {
|
||||||
std::string read = jsonRead();
|
std::string read = jsonRead();
|
||||||
@ -680,8 +803,7 @@ void MyMainFrame::OnClickAccount(wxCommandEvent& event WXUNUSED(event)) {
|
|||||||
if (wxSystemSettings::GetAppearance().IsDark()) {
|
if (wxSystemSettings::GetAppearance().IsDark()) {
|
||||||
AccountFrame->SetBackgroundColour(wxColour(40, 40, 40));
|
AccountFrame->SetBackgroundColour(wxColour(40, 40, 40));
|
||||||
AccountFrame->SetForegroundColour(wxColour(255, 255, 255));
|
AccountFrame->SetForegroundColour(wxColour(255, 255, 255));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
AccountFrame->SetBackgroundColour(wxColour("white"));
|
AccountFrame->SetBackgroundColour(wxColour("white"));
|
||||||
AccountFrame->SetForegroundColour(wxColour("white"));
|
AccountFrame->SetForegroundColour(wxColour("white"));
|
||||||
}
|
}
|
||||||
@ -698,8 +820,7 @@ void MyMainFrame::OnClickSettings(wxCommandEvent& event WXUNUSED(event)) {
|
|||||||
if (wxSystemSettings::GetAppearance().IsDark()) {
|
if (wxSystemSettings::GetAppearance().IsDark()) {
|
||||||
SettingsFrame->SetBackgroundColour(wxColour(40, 40, 40));
|
SettingsFrame->SetBackgroundColour(wxColour(40, 40, 40));
|
||||||
SettingsFrame->SetForegroundColour(wxColour(255, 255, 255));
|
SettingsFrame->SetForegroundColour(wxColour(255, 255, 255));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
SettingsFrame->SetBackgroundColour(wxColour("white"));
|
SettingsFrame->SetBackgroundColour(wxColour("white"));
|
||||||
SettingsFrame->SetForegroundColour(wxColour("white"));
|
SettingsFrame->SetForegroundColour(wxColour("white"));
|
||||||
}
|
}
|
||||||
@ -806,71 +927,35 @@ void MySettingsFrame::OnChangedBuild(wxCommandEvent& event) {
|
|||||||
|
|
||||||
/////////// AutoDetect Game Function ///////////
|
/////////// AutoDetect Game Function ///////////
|
||||||
void MySettingsFrame::OnAutoDetectGame(wxCommandEvent& event) {
|
void MySettingsFrame::OnAutoDetectGame(wxCommandEvent& event) {
|
||||||
HKEY BeamNG;
|
UpdateGameDirectory(AutoDetectGame());
|
||||||
std::string GamePath;
|
|
||||||
LONG RegRes =
|
|
||||||
RegOpenKeyExA(HKEY_CURRENT_USER, R"(Software\BeamNG\BeamNG.drive)", 0,
|
|
||||||
KEY_READ, &BeamNG);
|
|
||||||
if (RegRes == ERROR_SUCCESS) {
|
|
||||||
GamePath = Launcher::QueryValue(BeamNG, "rootpath");
|
|
||||||
RegCloseKey(BeamNG);
|
|
||||||
}
|
|
||||||
if (!GamePath.empty()) {
|
|
||||||
if (GamePath.ends_with('\\')) GamePath.pop_back();
|
|
||||||
UpdateConfig("GamePath", GamePath);
|
|
||||||
UpdateGameDirectory(GamePath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
wxMessageBox("Please launch the game at least once, failed to read registry key Software\\BeamNG\\BeamNG.drive", "Error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// AutoDetect Profile Function ///////////
|
/////////// AutoDetect Profile Function ///////////
|
||||||
void MySettingsFrame::OnAutoDetectProfile(wxCommandEvent& event) {
|
void MySettingsFrame::OnAutoDetectProfile(wxCommandEvent& event) {
|
||||||
HKEY BeamNG;
|
UpdateProfileDirectory(AutoDetectProfile());
|
||||||
std::string ProfilePath;
|
|
||||||
LONG RegRes =
|
|
||||||
RegOpenKeyExA(HKEY_CURRENT_USER, R"(Software\BeamNG\BeamNG.drive)", 0,
|
|
||||||
KEY_READ, &BeamNG);
|
|
||||||
if (RegRes == ERROR_SUCCESS) {
|
|
||||||
ProfilePath = Launcher::QueryValue(BeamNG, "userpath_override");
|
|
||||||
RegCloseKey(BeamNG);
|
|
||||||
}
|
|
||||||
if (ProfilePath.empty()) {
|
|
||||||
PWSTR folderPath = nullptr;
|
|
||||||
HRESULT hr =
|
|
||||||
SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &folderPath);
|
|
||||||
|
|
||||||
if (!SUCCEEDED(hr)) {
|
|
||||||
wxMessageBox(
|
|
||||||
"Please launch the game at least once, failed to read registry key Software\\BeamNG\\BeamNG.drive",
|
|
||||||
"Error");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_bstr_t bstrPath(folderPath);
|
|
||||||
std::string Path((char*)bstrPath);
|
|
||||||
CoTaskMemFree(folderPath);
|
|
||||||
ProfilePath = Path + "\\BeamNG.drive";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UpdateConfig("ProfilePath", ProfilePath);
|
|
||||||
ctrlProfileDirectory->SetPath(ProfilePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// Reset Cache Function ///////////
|
/////////// Reset Cache Function ///////////
|
||||||
void MySettingsFrame::OnResetCache(wxCommandEvent& event) {
|
void MySettingsFrame::OnResetCache(wxCommandEvent& event) {
|
||||||
std::string CachePath = fs::current_path().append("Resources").string();
|
UpdateCacheDirectory(ResetCache());
|
||||||
UpdateConfig("CachePath", CachePath);
|
|
||||||
ctrlCacheDirectory->SetPath(CachePath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// MAIN FUNCTION ///////////
|
/////////// MAIN FUNCTION ///////////
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
|
||||||
wxDisableAsserts();
|
wxDisableAsserts();
|
||||||
wxLog::SetLogLevel(wxLOG_Info);
|
wxLog::SetLogLevel(wxLOG_Info);
|
||||||
|
int result = 0;
|
||||||
|
try {
|
||||||
new MyApp();
|
new MyApp();
|
||||||
int result = wxEntry(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
|
result = wxEntry(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
|
||||||
if (Launcher::EntryThread.joinable())
|
if (Launcher::EntryThread.joinable())
|
||||||
Launcher::EntryThread.join();
|
Launcher::EntryThread.join();
|
||||||
|
if (MyMainFrame::UpdateThread.joinable())
|
||||||
|
MyMainFrame::UpdateThread.join();
|
||||||
|
} catch (const ShutdownException& e) {
|
||||||
|
LOG(INFO) << "Launcher shutting down with reason: " << e.what();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
LOG(FATAL) << e.what();
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user