Basic foundation done

This commit is contained in:
Anonymous275
2022-01-19 21:36:52 +02:00
parent 62d5936f71
commit 2b73c120a8
9 changed files with 138 additions and 31 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ add_executable(${PROJECT_NAME}
src/Network/Http.cpp include/Http.h src/Network/Http.cpp include/Http.h
src/Network/Login.cpp src/Network/Update.cpp src/Network/Login.cpp src/Network/Update.cpp
src/Discord.cpp src/Config.cpp src/Discord.cpp src/Config.cpp
src/Memory/Memory.cpp include/Memory.h src/BeamNG.cpp include/BeamNG.h
) )
+2 -2
View File
@@ -5,8 +5,8 @@
#include <cstdint> #include <cstdint>
class Memory { class BeamNG {
public: public:
static size_t GetProcessID(const char* PName);
static size_t GetModuleBase(const char* Name); static size_t GetModuleBase(const char* Name);
static uint32_t GetProcessID();
}; };
+8 -2
View File
@@ -23,6 +23,7 @@ public: //constructors
Launcher(int argc, char* argv[]); Launcher(int argc, char* argv[]);
~Launcher(); ~Launcher();
public: //available functions public: //available functions
static void StaticAbort(Launcher* Instance = nullptr);
std::string Login(const std::string& fields); std::string Login(const std::string& fields);
void RunDiscordRPC(); void RunDiscordRPC();
void QueryRegistry(); void QueryRegistry();
@@ -30,6 +31,7 @@ public: //available functions
void LoadConfig(); void LoadConfig();
void LaunchGame(); void LaunchGame();
void CheckKey(); void CheckKey();
void SetupMOD();
public: //Getters public: //Getters
const std::string& getFullVersion(); const std::string& getFullVersion();
const std::string& getUserRole(); const std::string& getUserRole();
@@ -40,22 +42,26 @@ private: //functions
void RichPresence(); void RichPresence();
void WindowsInit(); void WindowsInit();
void UpdateCheck(); void UpdateCheck();
void ResetMods();
void EnableMP();
void Relaunch(); void Relaunch();
void Abort();
private: //variables private: //variables
size_t GamePID{0}; uint32_t GamePID{0};
bool EnableUI = true; bool EnableUI = true;
bool Shutdown = false;
bool LoginAuth = false; bool LoginAuth = false;
fs::path CurrentPath{}; fs::path CurrentPath{};
std::string BeamRoot{}; std::string BeamRoot{};
std::string UserRole{}; std::string UserRole{};
std::string PublicKey{}; std::string PublicKey{};
std::thread DiscordRPC{}; std::thread DiscordRPC{};
std::string MPUserPath{};
std::string BeamVersion{}; std::string BeamVersion{};
std::string BeamUserPath{}; std::string BeamUserPath{};
std::string DiscordMessage{}; std::string DiscordMessage{};
std::string Version{"3.0"}; std::string Version{"3.0"};
std::string TargetBuild{"default"}; std::string TargetBuild{"default"};
std::atomic<bool> Shutdown{false};
std::string FullVersion{Version + ".0"}; std::string FullVersion{Version + ".0"};
VersionParser SupportedVersion{"0.24.1.1"}; VersionParser SupportedVersion{"0.24.1.1"};
}; };
+4 -4
View File
@@ -5,12 +5,12 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <string> #include <string>
#include "Memory.h" #include "BeamNG.h"
#undef UNICODE #undef UNICODE
#include <windows.h> #include <windows.h>
#include <tlhelp32.h> #include <tlhelp32.h>
size_t Memory::GetProcessID(const char* PName) { uint32_t BeamNG::GetProcessID() {
SetLastError(0); SetLastError(0);
PROCESSENTRY32 pe32; PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32); pe32.dwSize = sizeof(PROCESSENTRY32);
@@ -18,7 +18,7 @@ size_t Memory::GetProcessID(const char* PName) {
if(Process32First(Snapshot, &pe32)) { if(Process32First(Snapshot, &pe32)) {
do{ do{
if(std::string(PName) == pe32.szExeFile)break; if(std::string("BeamNG.drive.x64.exe") == pe32.szExeFile)break;
}while(Process32Next(Snapshot, &pe32)); }while(Process32Next(Snapshot, &pe32));
} }
@@ -30,6 +30,6 @@ size_t Memory::GetProcessID(const char* PName) {
return pe32.th32ProcessID; return pe32.th32ProcessID;
} }
size_t Memory::GetModuleBase(const char* Name) { size_t BeamNG::GetModuleBase(const char* Name) {
return (size_t)GetModuleHandleA(Name); return (size_t)GetModuleHandleA(Name);
} }
+1 -1
View File
@@ -10,7 +10,7 @@
void Launcher::RichPresence() { void Launcher::RichPresence() {
Discord_Initialize("629743237988352010", nullptr, 1,nullptr); Discord_Initialize("629743237988352010", nullptr, 1,nullptr);
int64_t Start{}; int64_t Start{};
while(!Shutdown) { while(!Shutdown.load()) {
DiscordRichPresence discordPresence; DiscordRichPresence discordPresence;
memset(&discordPresence, 0, sizeof(discordPresence)); memset(&discordPresence, 0, sizeof(discordPresence));
discordPresence.state = DiscordMessage.c_str(); discordPresence.state = DiscordMessage.c_str();
+60 -13
View File
@@ -6,25 +6,67 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include "Launcher.h" #include "Launcher.h"
#include "Logger.h" #include "Logger.h"
#include "Memory.h" #include "BeamNG.h"
#include <windows.h> #include <windows.h>
#include <shellapi.h> #include <shellapi.h>
Launcher::Launcher(int argc, char* argv[]) : CurrentPath(std::filesystem::path(argv[0])), DiscordMessage("Just launched") { Launcher::Launcher(int argc, char* argv[]) : CurrentPath(std::filesystem::path(argv[0])), DiscordMessage("Just launched") {
Launcher::StaticAbort(this);
Log::Init(); Log::Init();
WindowsInit(); WindowsInit();
LOG(INFO) << "Starting Launcher V" << FullVersion; LOG(INFO) << "Starting Launcher V" << FullVersion;
UpdateCheck(); UpdateCheck();
} }
Launcher::~Launcher() { void Launcher::Abort() {
Shutdown = true; Shutdown.store(true);
if(DiscordRPC.joinable()) { if(DiscordRPC.joinable()) {
DiscordRPC.join(); DiscordRPC.join();
} }
if(!MPUserPath.empty()) {
ResetMods();
}
if(GamePID != 0) {
auto Handle = OpenProcess(PROCESS_TERMINATE, false, DWORD(GamePID));
TerminateProcess(Handle, 0);
CloseHandle(Handle);
}
}
Launcher::~Launcher() {
Abort();
}
BOOL WINAPI CtrlHandler(DWORD Flag) {
if((Flag >= 0 && Flag < 3) || (Flag > 4 && Flag < 7)) {
Launcher::StaticAbort();
return 1;
}
return 0;
}
void Launcher::StaticAbort(Launcher* Instance) {
static Launcher* Address;
if(Instance) {
Address = Instance;
return;
}
Address->Abort();
}
void Launcher::WindowsInit() {
system("cls");
SetConsoleTitleA(("BeamMP Launcher v" + FullVersion).c_str());
if(!SetConsoleCtrlHandler(CtrlHandler, TRUE)) {
LOG(WARNING) << "Failed to set CtrlHandler";
}
} }
void Launcher::LaunchGame() { void Launcher::LaunchGame() {
if(BeamNG::GetProcessID() != 0) {
LOG(FATAL) << "Game is already running, please close it and try again!";
throw ShutdownException("Fatal Error");
}
VersionParser GameVersion(BeamVersion); VersionParser GameVersion(BeamVersion);
if(GameVersion.data[0] > SupportedVersion.data[0]) { if(GameVersion.data[0] > SupportedVersion.data[0]) {
LOG(FATAL) << "BeamNG V" << BeamVersion << " not yet supported, please wait until we update BeamMP!"; LOG(FATAL) << "BeamNG V" << BeamVersion << " not yet supported, please wait until we update BeamMP!";
@@ -43,20 +85,22 @@ void Launcher::LaunchGame() {
} }
void Launcher::WaitForGame() { void Launcher::WaitForGame() {
LOG(INFO) << "Waiting for game launch"; LOG(INFO) << "Waiting for the game, please start BeamNG manually in case of steam issues";
do{ do{
GamePID = Memory::GetProcessID("BeamNG.drive.x64.exe"); GamePID = BeamNG::GetProcessID();
std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::this_thread::sleep_for(std::chrono::seconds(2));
}while(GamePID == 0 && !Shutdown); }while(GamePID == 0 && !Shutdown.load());
if(Shutdown.load())return;
if(GamePID == 0) { if(GamePID == 0) {
LOG(FATAL) << "Game process not found! aborting"; LOG(FATAL) << "Game process not found! aborting";
throw ShutdownException("Fatal Error"); throw ShutdownException("Fatal Error");
}else LOG(INFO) << "Game found! PID " << GamePID; }
} LOG(INFO) << "Game found! PID " << GamePID;
//TODO: Inject then start IPC
void Launcher::WindowsInit() { while(!Shutdown.load() && BeamNG::GetProcessID() != 0) {
system("cls"); std::this_thread::sleep_for(std::chrono::seconds(2));
SetConsoleTitleA(("BeamMP Launcher v" + FullVersion).c_str()); }
LOG(INFO) << "Game process was lost";
} }
std::string QueryValue(HKEY& hKey, const char* Name) { std::string QueryValue(HKEY& hKey, const char* Name) {
@@ -95,6 +139,9 @@ void Launcher::QueryRegistry() {
VersionParser GameVer(BeamVersion); VersionParser GameVer(BeamVersion);
BeamUserPath += GameVer.split[0] + '.' + GameVer.split[1] + '\\'; BeamUserPath += GameVer.split[0] + '.' + GameVer.split[1] + '\\';
} }
if(!BeamUserPath.empty()) {
MPUserPath = BeamUserPath + "mods\\multiplayer";
}
if(!BeamRoot.empty() && !BeamVersion.empty() && !BeamUserPath.empty())return; if(!BeamRoot.empty() && !BeamVersion.empty() && !BeamUserPath.empty())return;
} }
LOG(FATAL) << "Please launch the game at least once, failed to read registry key Software\\BeamNG\\BeamNG.drive"; LOG(FATAL) << "Please launch the game at least once, failed to read registry key Software\\BeamNG\\BeamNG.drive";
+4 -5
View File
@@ -82,7 +82,7 @@ bool HTTP::ProgressBar(size_t c, size_t t){
static double progress_bar_adv; static double progress_bar_adv;
progress_bar_adv = round(double(c) / double(t) * 25); progress_bar_adv = round(double(c) / double(t) * 25);
std::cout << "\r"; std::cout << "\r";
std::cout << "Progress : [ "; std::cout << "Progress: [ ";
std::cout << round(double(c) / double(t) * 100); std::cout << round(double(c) / double(t) * 100);
std::cout << "% ] ["; std::cout << "% ] [";
int i; int i;
@@ -102,15 +102,14 @@ bool HTTP::Download(const std::string &IP, const std::string &Path) {
isDownload = false; isDownload = false;
if(Ret.empty())return false; if(Ret.empty())return false;
std::cout << "\n";
std::ofstream File(Path, std::ios::binary); std::ofstream File(Path, std::ios::binary);
if(File.is_open()) { if(File.is_open()) {
File << Ret; File << Ret;
File.close(); File.close();
std::cout << "\n"; LOG(INFO) << "Download complete!";
LOG(INFO) << "Download Complete!";
} else { } else {
LOG(INFO) << "Failed to open file directory: " << Path; LOG(ERROR) << "Failed to open file directory: " << Path;
return false; return false;
} }
return true; return true;
+55
View File
@@ -6,6 +6,7 @@
#include "Launcher.h" #include "Launcher.h"
#include "Logger.h" #include "Logger.h"
#include "Http.h" #include "Http.h"
#include "Json.h"
VersionParser::VersionParser(const std::string &from_string) { VersionParser::VersionParser(const std::string &from_string) {
std::string token; std::string token;
@@ -78,3 +79,57 @@ void Launcher::UpdateCheck() {
Relaunch(); Relaunch();
}else LOG(INFO) << "Launcher version is up to date"; }else LOG(INFO) << "Launcher version is up to date";
} }
size_t DirCount(const std::filesystem::path& path){
return (size_t)std::distance(std::filesystem::directory_iterator{path}, std::filesystem::directory_iterator{});
}
void Launcher::ResetMods() {
if (!fs::exists(MPUserPath)) {
fs::create_directories(MPUserPath);
return;
}
if (DirCount(fs::path(MPUserPath)) > 3) {
LOG(WARNING) << "mods/multiplayer will be cleared in 15 seconds, close to abort";
std::this_thread::sleep_for(std::chrono::seconds(15));
}
fs::remove_all(MPUserPath);
fs::create_directories(MPUserPath);
}
void Launcher::EnableMP() {
std::string File(BeamUserPath + "mods\\db.json");
if(!fs::exists(File))return;
auto Size = fs::file_size(File);
if(Size < 2)return;
std::ifstream db(File);
if(db.is_open()) {
std::string Data(Size, 0);
db.read(&Data[0], std::streamsize(Size));
db.close();
Json::Document d;
d.Parse(Data.c_str());
if(Data.at(0) != '{' || d.HasParseError())return;
if(!d["mods"].IsNull() && !d["mods"]["multiplayerbeammp"].IsNull()){
d["mods"]["multiplayerbeammp"]["active"] = true;
Json::StringBuffer buffer;
Json::Writer<Json::StringBuffer> writer(buffer);
d.Accept(writer);
std::ofstream ofs(File);
if(ofs.is_open()){
ofs << buffer.GetString();
ofs.close();
} else {
LOG(ERROR) << "Failed to write " << File;
}
}
}
}
void Launcher::SetupMOD() {
ResetMods();
EnableMP();
LOG(INFO) << "Downloading mod please wait";
HTTP::Download("https://backend.beammp.com/builds/client?download=true"
"&pk=" + PublicKey + "&branch=" + TargetBuild, MPUserPath + "\\BeamMP.zip");
}
+3 -3
View File
@@ -14,15 +14,15 @@ int main(int argc, char* argv[]) {
launcher.CheckKey(); launcher.CheckKey();
launcher.QueryRegistry(); launcher.QueryRegistry();
//UI call //UI call
//download mod launcher.SetupMOD();
launcher.LaunchGame(); launcher.LaunchGame();
launcher.WaitForGame(); launcher.WaitForGame();
LOG(INFO) << "Launcher shutting down";
} catch (const ShutdownException& e) { } catch (const ShutdownException& e) {
LOG(INFO) << "Launcher shutting down with reason: " << e.what(); LOG(INFO) << "Launcher shutting down with reason: " << e.what();
} catch (const std::exception& e) { } catch (const std::exception& e) {
LOG(FATAL) << e.what(); LOG(FATAL) << e.what();
} }
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0; return 0;
} }