mirror of
https://github.com/BeamMP/BeamMP-Launcher.git
synced 2026-04-03 06:16:15 +00:00
Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
811b04485c | ||
|
|
a64fead653 | ||
|
|
399461d1b1 | ||
|
|
ec5e8ed5b3 | ||
|
|
5655164e60 | ||
|
|
3d9b7c2d67 | ||
|
|
764e3ab5c1 | ||
|
|
3314362faf | ||
|
|
e483f520db | ||
|
|
c92e32c0e1 | ||
|
|
cb872f8a41 | ||
|
|
0aae245054 | ||
|
|
480a7d038f | ||
|
|
f62f44d4c0 | ||
|
|
e316b89fb1 | ||
|
|
3b2dbcac1b | ||
|
|
d881c9faf6 | ||
|
|
11d9375f36 | ||
|
|
4207d7adcf | ||
|
|
832b1d66a0 | ||
|
|
cd829f9f22 | ||
|
|
f7c70eb6df | ||
|
|
01960f6470 | ||
|
|
f6065a1c00 | ||
|
|
ba3b7f0ed0 | ||
|
|
056eadbef2 | ||
|
|
2bb2dc9040 | ||
|
|
17553fd412 | ||
|
|
08c1c0f682 | ||
|
|
84959ae9c9 | ||
|
|
c90c102097 | ||
|
|
5b004426ce | ||
|
|
69c9060dd2 | ||
|
|
49870639ff | ||
|
|
0843862af9 | ||
|
|
71a9a567bc | ||
|
|
a6e3d0fad9 | ||
|
|
411d0786a5 | ||
|
|
acb6b11e24 | ||
|
|
1739393a73 | ||
|
|
298ef33ab7 | ||
|
|
d2433cceca | ||
|
|
705e0ab9c4 | ||
|
|
53c40a2bc3 | ||
|
|
96c60ef05a | ||
|
|
61759b8531 | ||
|
|
691be8cd08 | ||
|
|
082445c295 | ||
|
|
f4bda81be0 | ||
|
|
1ad8e0b8e5 | ||
|
|
6c673e78e5 | ||
|
|
09abe75fbb | ||
|
|
b45e4b40f2 | ||
|
|
15d1539a92 | ||
|
|
14a5f47549 | ||
|
|
584998277d |
4
.github/workflows/cmake-windows.yml
vendored
4
.github/workflows/cmake-windows.yml
vendored
@@ -15,12 +15,12 @@ jobs:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Restore artifacts, or run vcpkg, build and cache artifacts
|
||||
uses: lukka/run-vcpkg@main
|
||||
uses: lukka/run-vcpkg@v7
|
||||
id: runvcpkg
|
||||
with:
|
||||
vcpkgArguments: 'discord-rpc zlib rapidjson openssl'
|
||||
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
|
||||
vcpkgGitCommitId: '75522bb1f2e7d863078bcd06322348f053a9e33f'
|
||||
vcpkgGitCommitId: '06b5f4a769d848d1a20fa0acd556019728b56273'
|
||||
vcpkgTriplet: 'x64-windows-static'
|
||||
|
||||
- name: Create Build Environment
|
||||
|
||||
2
.github/workflows/release-build.yml
vendored
2
.github/workflows/release-build.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
with:
|
||||
vcpkgArguments: 'discord-rpc zlib rapidjson openssl'
|
||||
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
|
||||
vcpkgGitCommitId: '75522bb1f2e7d863078bcd06322348f053a9e33f'
|
||||
vcpkgGitCommitId: '06b5f4a769d848d1a20fa0acd556019728b56273'
|
||||
vcpkgTriplet: 'x64-windows-static'
|
||||
|
||||
- name: Create Build Environment
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,3 +2,6 @@ cmake-build-debug
|
||||
cmake-build-release
|
||||
/.idea/
|
||||
*.log
|
||||
/*.sh
|
||||
/*.obj
|
||||
/*.exe
|
||||
@@ -8,7 +8,7 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include "Logger.h"
|
||||
class HTTP{
|
||||
class HTTP {
|
||||
public:
|
||||
static bool Download(const std::string &IP, const std::string &Path);
|
||||
static std::string Post(const std::string& IP, const std::string& Fields);
|
||||
@@ -12,7 +12,8 @@
|
||||
void NetReset();
|
||||
extern bool Dev;
|
||||
extern int ping;
|
||||
void CoreNetwork();
|
||||
|
||||
[[noreturn]] void CoreNetwork();
|
||||
extern int ClientID;
|
||||
extern int LastPort;
|
||||
extern bool ModLoaded;
|
||||
|
||||
5710
include/zip_file.h
Normal file
5710
include/zip_file.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,6 @@ void ParseConfig(const json::Document& d){
|
||||
if(d["Port"].IsInt()){
|
||||
DEFAULT_PORT = d["Port"].GetInt();
|
||||
}
|
||||
|
||||
//Default -1
|
||||
//Release 1
|
||||
//EA 2
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <windows.h>
|
||||
#include "Startup.h"
|
||||
#include "Logger.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
unsigned long GamePID = 0;
|
||||
@@ -36,7 +35,9 @@ std::string GetGamePath(){
|
||||
Path = QueryKey(hKey,5);
|
||||
Path += "\\BeamNG.drive\\";
|
||||
}
|
||||
Path += CheckVer(GetGameDir()) + "\\";
|
||||
std::string Ver = CheckVer(GetGameDir());
|
||||
Ver = Ver.substr(0,Ver.find('.',Ver.find('.')+1));
|
||||
Path += Ver + "\\";
|
||||
return Path;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,16 +14,8 @@
|
||||
#include <thread>
|
||||
|
||||
std::string getDate() {
|
||||
typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>::type> days;
|
||||
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
|
||||
std::chrono::system_clock::duration tp = now.time_since_epoch();
|
||||
days d = std::chrono::duration_cast<days>(tp);tp -= d;
|
||||
auto h = std::chrono::duration_cast<std::chrono::hours>(tp);tp -= h;
|
||||
auto m = std::chrono::duration_cast<std::chrono::minutes>(tp);tp -= m;
|
||||
auto s = std::chrono::duration_cast<std::chrono::seconds>(tp);tp -= s;
|
||||
time_t tt = std::chrono::system_clock::to_time_t(now);
|
||||
tm local_tm{};
|
||||
localtime_s(&local_tm,&tt);
|
||||
time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
tm local_tm = *localtime(&tt);
|
||||
std::stringstream date;
|
||||
int S = local_tm.tm_sec;
|
||||
int M = local_tm.tm_min;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "Network/network.h"
|
||||
#include "Security/Init.h"
|
||||
|
||||
#include "http.h"
|
||||
#include "Http.h"
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "Startup.h"
|
||||
@@ -58,7 +58,7 @@ void Parse(std::string Data,SOCKET CSocket){
|
||||
NetReset();
|
||||
Terminate = true;
|
||||
TCPTerminate = true;
|
||||
Data = Code + HTTP::Post("https://backend.beammp.com/servers","");
|
||||
Data = Code + HTTP::Get("https://backend.beammp.com/servers-info");
|
||||
break;
|
||||
case 'C':
|
||||
ListOfMods.clear();
|
||||
@@ -240,8 +240,8 @@ int Handle(EXCEPTION_POINTERS *ep){
|
||||
}
|
||||
|
||||
|
||||
void CoreNetwork(){
|
||||
while(TraceBack >= 4){
|
||||
[[noreturn]] void CoreNetwork(){
|
||||
while(true) {
|
||||
#ifndef __MINGW32__
|
||||
__try{
|
||||
#endif
|
||||
|
||||
@@ -75,7 +75,7 @@ void ServerSend(std::string Data, bool Rel){
|
||||
int DLen = int(Data.length());
|
||||
if(DLen > 3)C = Data.at(0);
|
||||
if (C == 'O' || C == 'T')Ack = true;
|
||||
if(C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C')Rel = true;
|
||||
if(C == 'N' || C == 'W' || C == 'Y' || C == 'V' || C == 'E' || C == 'C')Rel = true;
|
||||
if(Ack || Rel){
|
||||
if(Ack || DLen > 1000)SendLarge(Data);
|
||||
else TCPSend(Data,TCPSock);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <iostream>
|
||||
#include <Logger.h>
|
||||
#include <fstream>
|
||||
#include "http.h"
|
||||
#include "Http.h"
|
||||
#include <mutex>
|
||||
#include <cmath>
|
||||
#include <httplib.h>
|
||||
@@ -31,6 +31,7 @@ std::string HTTP::Get(const std::string &IP) {
|
||||
|
||||
httplib::Client cli(IP.substr(0, pos).c_str());
|
||||
cli.set_connection_timeout(std::chrono::seconds(10));
|
||||
cli.set_follow_location(true);
|
||||
auto res = cli.Get(IP.substr(pos).c_str(), ProgressBar);
|
||||
std::string Ret;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ std::string Auth(SOCKET Sock){
|
||||
|
||||
auto Res = TCPRcv(Sock);
|
||||
|
||||
if(Res.empty() || Res[0] == 'E'){
|
||||
if(Res.empty() || Res[0] == 'E' || Res[0] == 'K'){
|
||||
Abord();
|
||||
return "";
|
||||
}
|
||||
@@ -87,7 +87,7 @@ std::string Auth(SOCKET Sock){
|
||||
|
||||
Res = TCPRcv(Sock);
|
||||
|
||||
if(Res[0] == 'E'){
|
||||
if(Res[0] == 'E' || Res[0] == 'K'){
|
||||
Abord();
|
||||
return "";
|
||||
}
|
||||
@@ -109,11 +109,10 @@ void UpdateUl(bool D,const std::string&msg){
|
||||
|
||||
void AsyncUpdate(uint64_t& Rcv,uint64_t Size,const std::string& Name){
|
||||
do {
|
||||
double pr = Rcv / double(Size) * 100;
|
||||
double pr = double(Rcv) / double(Size) * 100;
|
||||
std::string Per = std::to_string(trunc(pr * 10) / 10);
|
||||
UpdateUl(true, Name + " (" + Per.substr(0, Per.find('.') + 2) + "%)");
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
}while(!Terminate && Rcv < Size);
|
||||
}
|
||||
|
||||
@@ -176,8 +175,7 @@ std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::s
|
||||
|
||||
uint64_t GRcv = 0, MSize = Size/2, DSize = Size - MSize;
|
||||
|
||||
std::thread Au(AsyncUpdate,std::ref(GRcv),Size,Name);
|
||||
Au.detach();
|
||||
std::thread Au(AsyncUpdate,std::ref(GRcv), Size, Name);
|
||||
|
||||
std::packaged_task<char*()> task([&] { return TCPRcvRaw(MSock,GRcv,MSize); });
|
||||
std::future<char*> f1 = task.get_future();
|
||||
@@ -198,6 +196,7 @@ std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::s
|
||||
MultiKill(MSock,DSock);
|
||||
return "";
|
||||
}
|
||||
|
||||
if(Au.joinable())Au.join();
|
||||
|
||||
|
||||
@@ -212,6 +211,11 @@ std::string MultiDownload(SOCKET MSock,SOCKET DSock, uint64_t Size, const std::s
|
||||
return Ret;
|
||||
}
|
||||
|
||||
void InvalidResource(const std::string& File){
|
||||
UUl("Invalid mod \"" + File + "\"");
|
||||
warn("The server tried to sync \"" + File + "\" that is not a .zip file!");
|
||||
Terminate = true;
|
||||
}
|
||||
|
||||
void SyncResources(SOCKET Sock){
|
||||
std::string Ret = Auth(Sock);
|
||||
@@ -238,6 +242,11 @@ void SyncResources(SOCKET Sock){
|
||||
t.clear();
|
||||
for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) {
|
||||
auto pos = FN->find_last_of('/');
|
||||
auto ZIP = FN->find(".zip");
|
||||
if (ZIP == std::string::npos || FN->length() - ZIP != 4) {
|
||||
InvalidResource(*FN);
|
||||
return;
|
||||
}
|
||||
if (pos == std::string::npos)continue;
|
||||
Amount++;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ std::string TCPRcv(SOCKET Sock){
|
||||
#ifdef DEBUG
|
||||
//debug("Parsing from server -> " + std::to_string(Ret.size()));
|
||||
#endif
|
||||
if(Ret[0] == 'E')UUl(Ret.substr(1));
|
||||
if(Ret[0] == 'E' || Ret[0] == 'K')UUl(Ret.substr(1));
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ void lowExit(int code){
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
exit(2);
|
||||
}
|
||||
void Exit(int code){
|
||||
/*void Exit(int code){
|
||||
TraceBack = 0;
|
||||
std::string msg =
|
||||
"Sorry. We do not support cracked copies report this if you believe this is a mistake code ";
|
||||
@@ -43,9 +43,9 @@ void SteamExit(int code){
|
||||
error(msg+std::to_string(code));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||
exit(4);
|
||||
}
|
||||
}*/
|
||||
std::string GetGameDir(){
|
||||
if(TraceBack != 4)Exit(0);
|
||||
//if(TraceBack != 4)Exit(0);
|
||||
return GameDir.substr(0,GameDir.find_last_of('\\'));
|
||||
}
|
||||
LONG OpenKey(HKEY root,const char* path,PHKEY hKey){
|
||||
@@ -244,25 +244,23 @@ std::string GetManifest(const std::string& Man){
|
||||
bool IDCheck(std::string Man, std::string steam){
|
||||
bool a = false,b = true;
|
||||
int pos = int(Man.rfind("steamapps"));
|
||||
if(pos == -1)Exit(5);
|
||||
// if(pos == -1)Exit(5);
|
||||
Man = Man.substr(0,pos+9) + "\\appmanifest_284160.acf";
|
||||
steam += "\\config\\loginusers.vdf";
|
||||
if(fs::exists(Man) && fs::exists(steam)){
|
||||
for(const std::string&ID : GetID(steam)){
|
||||
if(ID == GetManifest(Man))b = false;
|
||||
}
|
||||
if(b)Exit(6);
|
||||
//if(b)Exit(6);
|
||||
}else a = true;
|
||||
return a;
|
||||
}
|
||||
void LegitimacyCheck(){
|
||||
std::string Result,T;
|
||||
std::string K1 = R"(Software\Valve\Steam)";
|
||||
std::string K2 = R"(Software\Valve\Steam\Apps\284160)";
|
||||
std::string K3 = R"(Software\BeamNG\BeamNG.drive)";
|
||||
HKEY hKey;
|
||||
|
||||
LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey);
|
||||
//std::string K1 = R"(Software\Valve\Steam)";
|
||||
//std::string K2 = R"(Software\Valve\Steam\Apps\284160)";
|
||||
|
||||
/*LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey);
|
||||
|
||||
if(dwRegOPenKey == ERROR_SUCCESS) {
|
||||
Result = QueryKey(hKey, 1);
|
||||
@@ -287,19 +285,22 @@ void LegitimacyCheck(){
|
||||
TraceBack++;
|
||||
}else lowExit(2);
|
||||
K2.clear();
|
||||
RegCloseKey(hKey);
|
||||
dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K3.c_str(), &hKey);
|
||||
RegCloseKey(hKey);*/
|
||||
std::string Result;
|
||||
std::string K3 = R"(Software\BeamNG\BeamNG.drive)";
|
||||
HKEY hKey;
|
||||
LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K3.c_str(), &hKey);
|
||||
if(dwRegOPenKey == ERROR_SUCCESS) {
|
||||
Result = QueryKey(hKey, 3);
|
||||
if(Result.empty())lowExit(3);
|
||||
if(IDCheck(Result,T))lowExit(5);
|
||||
//if(IDCheck(Result,T))lowExit(5);
|
||||
GameDir = Result;
|
||||
TraceBack++;
|
||||
//TraceBack++;
|
||||
}else lowExit(4);
|
||||
K3.clear();
|
||||
Result.clear();
|
||||
RegCloseKey(hKey);
|
||||
if(TraceBack < 3)exit(-1);
|
||||
//if(TraceBack < 3)exit(-1);
|
||||
}
|
||||
std::string CheckVer(const std::string &dir){
|
||||
std::string temp,Path = dir + "\\integrity.json";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/// Created by Anonymous275 on 11/26/2020
|
||||
///
|
||||
|
||||
#include "http.h"
|
||||
#include "Http.h"
|
||||
#include <filesystem>
|
||||
#include "Logger.h"
|
||||
#include <fstream>
|
||||
@@ -18,7 +18,7 @@ extern bool LoginAuth;
|
||||
std::string Role;
|
||||
|
||||
void UpdateKey(const char* newKey){
|
||||
if(newKey){
|
||||
if(newKey && std::isalnum(newKey[0])){
|
||||
std::ofstream Key("key");
|
||||
if(Key.is_open()){
|
||||
Key << newKey;
|
||||
@@ -88,13 +88,21 @@ void CheckLocalKey(){
|
||||
Key.read(&Buffer[0], Size);
|
||||
Key.close();
|
||||
|
||||
for (char& c : Buffer) {
|
||||
if (!std::isalnum(c) && c != '-') {
|
||||
UpdateKey(nullptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer = HTTP::Post("https://auth.beammp.com/userlogin", R"({"pk":")" + Buffer + "\"}");
|
||||
|
||||
json::Document d;
|
||||
d.Parse(Buffer.c_str());
|
||||
if (Buffer == "-1" || Buffer.at(0) != '{' || d.HasParseError()) {
|
||||
error(Buffer);
|
||||
fatal("Invalid answer from authentication servers, please try again later!");
|
||||
info("Invalid answer from authentication servers.");
|
||||
UpdateKey(nullptr);
|
||||
}
|
||||
if(d["success"].GetBool()){
|
||||
LoginAuth = true;
|
||||
|
||||
122
src/Startup.cpp
122
src/Startup.cpp
@@ -5,6 +5,7 @@
|
||||
///
|
||||
/// Created by Anonymous275 on 7/16/2020
|
||||
///
|
||||
#include "zip_file.h"
|
||||
#include <windows.h>
|
||||
#include "Discord/discord_info.h"
|
||||
#include "Network/network.h"
|
||||
@@ -12,8 +13,10 @@
|
||||
#include <filesystem>
|
||||
#include "Startup.h"
|
||||
#include "Logger.h"
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include "http.h"
|
||||
#include "Http.h"
|
||||
#include "Json.h"
|
||||
|
||||
extern int TraceBack;
|
||||
bool Dev = false;
|
||||
@@ -26,8 +29,9 @@ std::string GetVer(){
|
||||
return "2.0";
|
||||
}
|
||||
std::string GetPatch(){
|
||||
return ".2";
|
||||
return ".81";
|
||||
}
|
||||
|
||||
std::string GetEP(char*P){
|
||||
static std::string Ret = [&](){
|
||||
std::string path(P);
|
||||
@@ -120,27 +124,78 @@ void CustomPort(int argc, char* argv[]){
|
||||
if(argc > 2)Dev = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LinuxPatch(){
|
||||
HKEY hKey = nullptr;
|
||||
LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, R"(Software\Wine)", 0, KEY_READ, &hKey);
|
||||
if (result != ERROR_SUCCESS || getenv("USER") == nullptr)return;
|
||||
RegCloseKey(hKey);
|
||||
info("Wine/Proton Detected! If you are on windows delete HKEY_CURRENT_USER\\Software\\Wine in regedit");
|
||||
info("Applying patches...");
|
||||
|
||||
result = RegCreateKey(HKEY_CURRENT_USER, R"(Software\Valve\Steam\Apps\284160)", &hKey);
|
||||
|
||||
if (result != ERROR_SUCCESS){
|
||||
fatal(R"(failed to create HKEY_CURRENT_USER\Software\Valve\Steam\Apps\284160)");
|
||||
return;
|
||||
}
|
||||
|
||||
result = RegSetValueEx(hKey, "Name", 0, REG_SZ, (BYTE*)"BeamNG.drive", 12);
|
||||
|
||||
if (result != ERROR_SUCCESS){
|
||||
fatal(R"(failed to create the value "Name" under HKEY_CURRENT_USER\Software\Valve\Steam\Apps\284160)");
|
||||
return;
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
|
||||
std::string Path = R"(Z:\home\)" + std::string(getenv("USER")) + R"(\.steam\steam\Steam.exe)";
|
||||
|
||||
if(!fs::exists(Path)) {
|
||||
std::ofstream ofs(Path);
|
||||
if (!ofs.is_open()) {
|
||||
fatal("Failed to create file \"" + Path + "\"");
|
||||
return;
|
||||
} else ofs.close();
|
||||
}
|
||||
|
||||
result = RegOpenKeyEx(HKEY_CURRENT_USER, R"(Software\Valve\Steam)", 0, KEY_ALL_ACCESS, &hKey);
|
||||
if (result != ERROR_SUCCESS){
|
||||
fatal(R"(failed to open HKEY_CURRENT_USER\Software\Valve\Steam)");
|
||||
return;
|
||||
}
|
||||
|
||||
result = RegSetValueEx(hKey, "SteamExe", 0, REG_SZ, (BYTE*)Path.c_str(), Path.size());
|
||||
|
||||
if (result != ERROR_SUCCESS){
|
||||
fatal(R"(failed to create the value "Name" under HKEY_CURRENT_USER\Software\Valve\Steam\Apps\284160)");
|
||||
return;
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
info("Patched!");
|
||||
}
|
||||
|
||||
void InitLauncher(int argc, char* argv[]) {
|
||||
system("cls");
|
||||
SetConsoleTitleA(("BeamMP Launcher v" + std::string(GetVer()) + GetPatch()).c_str());
|
||||
InitLog();
|
||||
CheckName(argc, argv);
|
||||
LinuxPatch();
|
||||
CheckLocalKey();
|
||||
ConfigInit();
|
||||
CustomPort(argc, argv);
|
||||
Discord_Main();
|
||||
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
|
||||
}
|
||||
|
||||
size_t DirCount(const std::filesystem::path& path){
|
||||
return (size_t)std::distance(std::filesystem::directory_iterator{path}, std::filesystem::directory_iterator{});
|
||||
}
|
||||
|
||||
void CheckMP(const std::string& Path) {
|
||||
if (!fs::exists(Path))return;
|
||||
size_t c = DirCount(fs::path(Path));
|
||||
if (c > 3) {
|
||||
warn(std::to_string(c - 1) + " multiplayer mods will be wiped from mods/multiplayer! Close this if you don't want that!");
|
||||
std::this_thread::sleep_for(std::chrono::seconds(15));
|
||||
}
|
||||
try {
|
||||
for (auto& p : fs::directory_iterator(Path)){
|
||||
if(p.exists() && !p.is_directory()){
|
||||
@@ -154,15 +209,43 @@ void CheckMP(const std::string& Path) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EnableMP(){
|
||||
std::string File(GetGamePath() + "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], Size);
|
||||
db.close();
|
||||
json::Document d;
|
||||
d.Parse(Data.c_str());
|
||||
if(Data.at(0) != '{' || d.HasParseError()){
|
||||
//error("Failed to parse " + File); //TODO illegal formatting
|
||||
return;
|
||||
}
|
||||
if(!d["mods"].IsNull() && !d["mods"]["multiplayerbeammp"].IsNull()){
|
||||
d["mods"]["multiplayerbeammp"]["active"] = true;
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
d.Accept(writer);
|
||||
std::ofstream ofs(File);
|
||||
if(ofs.is_open()){
|
||||
ofs << buffer.GetString();
|
||||
ofs.close();
|
||||
}else{
|
||||
error("Failed to write " + File);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PreGame(const std::string& GamePath){
|
||||
const std::string CurrVer("0.22.1.0");
|
||||
std::string GameVer = CheckVer(GamePath);
|
||||
info("Game Version : " + GameVer);
|
||||
if(GameVer < CurrVer){
|
||||
fatal("Game version is old! Please update.");
|
||||
}else if(GameVer > CurrVer){
|
||||
warn("Game is newer than recommended, multiplayer may not work as intended!");
|
||||
}
|
||||
|
||||
CheckMP(GetGamePath() + "mods/multiplayer");
|
||||
|
||||
if(!Dev) {
|
||||
@@ -171,15 +254,22 @@ void PreGame(const std::string& GamePath){
|
||||
if (!fs::exists(GetGamePath() + "mods/multiplayer")) {
|
||||
fs::create_directories(GetGamePath() + "mods/multiplayer");
|
||||
}
|
||||
EnableMP();
|
||||
}catch(std::exception&e){
|
||||
fatal(e.what());
|
||||
}
|
||||
std::string ZipPath(GetGamePath() + R"(mods\multiplayer\BeamMP.zip)");
|
||||
|
||||
HTTP::Download("https://backend.beammp.com/builds/client?download=true"
|
||||
"&pk=" + PublicKey +
|
||||
"&branch=" + Branch, GetGamePath() + R"(mods\multiplayer\BeamMP.zip)");
|
||||
HTTP::Download("https://backend.beammp.com/builds/client?download=true"
|
||||
"&pk=" + PublicKey + "&branch=" + Branch, ZipPath);
|
||||
|
||||
std::string Target(GetGamePath() + "mods/unpacked/beammp");
|
||||
|
||||
if(fs::is_directory(Target)) {
|
||||
fs::remove_all(Target);
|
||||
}
|
||||
|
||||
//HTTP::Download("beammp.com/builds/client", GetGamePath() + R"(mods\multiplayer\BeamMP.zip)");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <iostream>
|
||||
#include "Logger.h"
|
||||
#include <thread>
|
||||
#include "http.h"
|
||||
#include "Http.h"
|
||||
|
||||
[[noreturn]] void flush(){
|
||||
while(true){
|
||||
@@ -20,7 +20,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
#ifdef DEBUG
|
||||
std::thread th(flush);
|
||||
|
||||
Reference in New Issue
Block a user