Merge pull request #79 from BeamMP/hotfix-stuff

Fixup various bits
This commit is contained in:
Lion 2024-06-15 21:46:07 +02:00 committed by GitHub
commit 46690b5bbf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
66 changed files with 161 additions and 337 deletions

View File

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(Launcher) project(Launcher)
if (WIN32) if (WIN32)
@ -18,25 +19,14 @@ find_package(nlohmann_json CONFIG REQUIRED)
add_executable(${PROJECT_NAME} ${source_files}) add_executable(${PROJECT_NAME} ${source_files})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher") set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher")
if (WIN32) if (WIN32)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
#-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static
set(VcpkgRoot ${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET})
include_directories(${VcpkgRoot}/include)
link_directories(${VcpkgRoot}/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE target_link_libraries(${PROJECT_NAME} PRIVATE
ZLIB::ZLIB OpenSSL::SSL OpenSSL::Crypto ws2_32 httplib::httplib nlohmann_json::nlohmann_json) ZLIB::ZLIB OpenSSL::SSL OpenSSL::Crypto ws2_32 httplib::httplib nlohmann_json::nlohmann_json)
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_libraries(${PROJECT_NAME} PRIVATE ${VcpkgRoot}/lib/discord-rpc.lib)
else ()
target_link_libraries(${PROJECT_NAME} PRIVATE ${VcpkgRoot}/debug/lib/discord-rpc.lib)
endif()
else(WIN32) #MINGW else(WIN32) #MINGW
add_definitions("-D_WIN32_WINNT=0x0600") add_definitions("-D_WIN32_WINNT=0x0600")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -s --static") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -s --static")
target_link_libraries(${PROJECT_NAME} discord-rpc ssl crypto ws2_32 ssp crypt32 z) target_link_libraries(${PROJECT_NAME} ssl crypto ws2_32 ssp crypt32 z)
endif(WIN32) endif(WIN32)
target_include_directories(${PROJECT_NAME} PRIVATE "include") target_include_directories(${PROJECT_NAME} PRIVATE "include")

View File

@ -2,6 +2,10 @@
The launcher is the way we communitcate to outside the game, it does a few automated actions such as but not limited to: downloading the mod, launching the game, and create a connection to a server. The launcher is the way we communitcate to outside the game, it does a few automated actions such as but not limited to: downloading the mod, launching the game, and create a connection to a server.
## How to build
1. `cmake . -B bin -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static`
2. `cmake --build bin --parallel`
Copyright (c) 2019-present Anonymous275. Copyright (c) 2019-present Anonymous275.
BeamMP Launcher code is not in the public domain and is not free software. BeamMP Launcher code is not in the public domain and is not free software.

View File

@ -1,15 +0,0 @@
// Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
///
/// Created by Anonymous275 on 7/16/2020
///
#pragma once
#include <string>
void Discord_Main();
std::string GetDName();
std::string GetDTag();
std::string GetDID();
void DAboard();

View File

@ -1,26 +0,0 @@
#pragma once
#if defined(DISCORD_DYNAMIC_LIB)
#if defined(_WIN32)
#if defined(DISCORD_BUILDING_SDK)
#define DISCORD_EXPORT __declspec(dllexport)
#else
#define DISCORD_EXPORT __declspec(dllimport)
#endif
#else
#define DISCORD_EXPORT __attribute__((visibility("default")))
#endif
#else
#define DISCORD_EXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
DISCORD_EXPORT void Discord_Register(const char* applicationId, const char* command);
DISCORD_EXPORT void Discord_RegisterSteamGame(const char* applicationId, const char* steamId);
#ifdef __cplusplus
}
#endif

View File

@ -1,87 +0,0 @@
#pragma once
#include <cstdint>
// clang-format off
#if defined(DISCORD_DYNAMIC_LIB)
# if defined(_WIN32)
# if defined(DISCORD_BUILDING_SDK)
# define DISCORD_EXPORT __declspec(dllexport)
# else
# define DISCORD_EXPORT __declspec(dllimport)
# endif
# else
# define DISCORD_EXPORT __attribute__((visibility("default")))
# endif
#else
# define DISCORD_EXPORT
#endif
// clang-format on
#ifdef __cplusplus
extern "C" {
#endif
typedef struct DiscordRichPresence {
const char* state; /* max 128 bytes */
const char* details; /* max 128 bytes */
int64_t startTimestamp;
int64_t endTimestamp;
const char* largeImageKey; /* max 32 bytes */
const char* largeImageText; /* max 128 bytes */
const char* smallImageKey; /* max 32 bytes */
const char* smallImageText; /* max 128 bytes */
const char* partyId; /* max 128 bytes */
int partySize;
int partyMax;
const char* matchSecret; /* max 128 bytes */
const char* joinSecret; /* max 128 bytes */
const char* spectateSecret; /* max 128 bytes */
int8_t instance;
} DiscordRichPresence;
typedef struct DiscordUser {
const char* userId;
const char* username;
const char* discriminator;
const char* avatar;
} DiscordUser;
typedef struct DiscordEventHandlers {
void (*ready)(const DiscordUser* request);
void (*disconnected)(int errorCode, const char* message);
void (*errored)(int errorCode, const char* message);
void (*joinGame)(const char* joinSecret);
void (*spectateGame)(const char* spectateSecret);
void (*joinRequest)(const DiscordUser* request);
} DiscordEventHandlers;
#define DISCORD_REPLY_NO 0
#define DISCORD_REPLY_YES 1
#define DISCORD_REPLY_IGNORE 2
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
DiscordEventHandlers* handlers,
int autoRegister,
const char* optionalSteamId);
DISCORD_EXPORT void Discord_Shutdown(void);
/* checks for incoming messages, dispatches callbacks */
DISCORD_EXPORT void Discord_RunCallbacks(void);
/* If you disable the lib starting its own io thread, you'll need to call this from your own */
#ifdef DISCORD_DISABLE_IO_THREAD
DISCORD_EXPORT void Discord_UpdateConnection(void);
#endif
DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* presence);
DISCORD_EXPORT void Discord_ClearPresence(void);
DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);
DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);
#ifdef __cplusplus
} /* extern "C" */
#endif

0
include/Http.h Executable file → Normal file
View File

1
include/Logger.h Executable file → Normal file
View File

@ -15,3 +15,4 @@ void debug(const std::string& toPrint);
void error(const std::string& toPrint); void error(const std::string& toPrint);
void info(const std::string& toPrint); void info(const std::string& toPrint);
void warn(const std::string& toPrint); void warn(const std::string& toPrint);
std::string getDate();

0
include/Network/network.h Executable file → Normal file
View File

0
include/Security/Game.h Executable file → Normal file
View File

0
include/Security/Init.h Executable file → Normal file
View File

0
include/Startup.h Executable file → Normal file
View File

0
include/Zlib/Compressor.h Executable file → Normal file
View File

0
include/rapidjson/allocators.h Executable file → Normal file
View File

0
include/rapidjson/cursorstreamwrapper.h Executable file → Normal file
View File

0
include/rapidjson/document.h Executable file → Normal file
View File

0
include/rapidjson/encodedstream.h Executable file → Normal file
View File

0
include/rapidjson/encodings.h Executable file → Normal file
View File

0
include/rapidjson/error/en.h Executable file → Normal file
View File

0
include/rapidjson/error/error.h Executable file → Normal file
View File

0
include/rapidjson/filereadstream.h Executable file → Normal file
View File

0
include/rapidjson/filewritestream.h Executable file → Normal file
View File

0
include/rapidjson/fwd.h Executable file → Normal file
View File

0
include/rapidjson/internal/biginteger.h Executable file → Normal file
View File

0
include/rapidjson/internal/clzll.h Executable file → Normal file
View File

0
include/rapidjson/internal/diyfp.h Executable file → Normal file
View File

0
include/rapidjson/internal/dtoa.h Executable file → Normal file
View File

0
include/rapidjson/internal/ieee754.h Executable file → Normal file
View File

0
include/rapidjson/internal/itoa.h Executable file → Normal file
View File

0
include/rapidjson/internal/meta.h Executable file → Normal file
View File

0
include/rapidjson/internal/pow10.h Executable file → Normal file
View File

0
include/rapidjson/internal/regex.h Executable file → Normal file
View File

0
include/rapidjson/internal/stack.h Executable file → Normal file
View File

0
include/rapidjson/internal/strfunc.h Executable file → Normal file
View File

0
include/rapidjson/internal/strtod.h Executable file → Normal file
View File

0
include/rapidjson/internal/swap.h Executable file → Normal file
View File

0
include/rapidjson/istreamwrapper.h Executable file → Normal file
View File

0
include/rapidjson/memorybuffer.h Executable file → Normal file
View File

0
include/rapidjson/memorystream.h Executable file → Normal file
View File

0
include/rapidjson/msinttypes/inttypes.h Executable file → Normal file
View File

0
include/rapidjson/msinttypes/stdint.h Executable file → Normal file
View File

0
include/rapidjson/ostreamwrapper.h Executable file → Normal file
View File

0
include/rapidjson/pointer.h Executable file → Normal file
View File

0
include/rapidjson/prettywriter.h Executable file → Normal file
View File

0
include/rapidjson/rapidjson.h Executable file → Normal file
View File

0
include/rapidjson/reader.h Executable file → Normal file
View File

0
include/rapidjson/schema.h Executable file → Normal file
View File

0
include/rapidjson/stream.h Executable file → Normal file
View File

0
include/rapidjson/stringbuffer.h Executable file → Normal file
View File

0
include/rapidjson/writer.h Executable file → Normal file
View File

0
src/Compressor.cpp Executable file → Normal file
View File

0
src/Config.cpp Executable file → Normal file
View File

View File

@ -1,111 +0,0 @@
// Copyright (c) 2019-present Anonymous275.
// BeamMP Launcher code is not in the public domain and is not free software.
// One must be granted explicit permission by the copyright holder in order to modify or distribute any part of the source or binaries.
// Anything else is prohibited. Modified works may not be published and have be upstreamed to the official repository.
///
/// Created by Anonymous275 on 7/16/2020
///
#include "Discord/discord_rpc.h"
#include "Logger.h"
#include <cstring>
#include <thread>
#include <ctime>
struct DInfo{
std::string Name;
std::string Tag;
std::string DID;
};
DInfo* DiscordInfo = nullptr;
int64_t StartTime;
void updateDiscordPresence(){
//if (SendPresence) {
//char buffer[256];
DiscordRichPresence discordPresence;
memset(&discordPresence, 0, sizeof(discordPresence));
std::string P = "Playing with friends!"; ///to be revisited
discordPresence.state = P.c_str();
//sprintf(buffer, "Frustration level: %d", FrustrationLevel);
//discordPresence.details = buffer;
discordPresence.startTimestamp = StartTime;
//discordPresence.endTimestamp = time(0) + 5 * 60;
discordPresence.largeImageKey = "mainlogo";
//discordPresence.smallImageKey = "logo";
//discordPresence.partyId = "party1234";
//discordPresence.partySize = 1;
//discordPresence.partyMax = 6;
//discordPresence.matchSecret = "xyzzy";
//discordPresence.joinSecret = "join";
//discordPresence.spectateSecret = "look";
//discordPresence.instance = 0;
Discord_UpdatePresence(&discordPresence);
//}
//else {
// Discord_ClearPresence();
//}
}
void handleDiscordReady(const DiscordUser* User){
DiscordInfo = new DInfo{
User->username,
User->discriminator,
User->userId
};
}
void discordInit(){
DiscordEventHandlers handlers;
memset(&handlers, 0, sizeof(handlers));
handlers.ready = handleDiscordReady;
/*handlers.disconnected = handleDiscordDisconnected;
handlers.errored = handleDiscordError;
handlers.joinGame = handleDiscordJoin;
handlers.spectateGame = handleDiscordSpectate;
handlers.joinRequest = handleDiscordJoinRequest;*/
Discord_Initialize("629743237988352010", &handlers, 1,nullptr);
}
[[noreturn]] void Loop(){
StartTime = time(nullptr);
while (true) {
updateDiscordPresence();
#ifdef DISCORD_DISABLE_IO_THREAD
Discord_UpdateConnection();
#endif
Discord_RunCallbacks();
if(DiscordInfo == nullptr){
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}else std::this_thread::sleep_for(std::chrono::seconds(2));
}
}
void DMain(){
discordInit();
Loop();
}
std::string GetDName(){
return DiscordInfo->Name;
}
std::string GetDTag(){
return DiscordInfo->Tag;
}
std::string GetDID(){
return DiscordInfo->DID;
}
void DAboard(){
DiscordInfo = nullptr;
}
void ErrorAboard(){
error("Discord timeout! please start the discord app and try again after 30 secs");
std::this_thread::sleep_for(std::chrono::seconds(5));
exit(6);
}
void Discord_Main(){
/*std::thread t1(DMain);
t1.detach();*/
/*info("Connecting to discord client...");
int C = 0;
while(DiscordInfo == nullptr && C < 80){
std::this_thread::sleep_for(std::chrono::milliseconds(300));
C++;
}
if(DiscordInfo == nullptr)ErrorAboard();*/
}

0
src/GameStart.cpp Executable file → Normal file
View File

0
src/Logger.cpp Executable file → Normal file
View File

0
src/Network/Core.cpp Executable file → Normal file
View File

0
src/Network/DNS.cpp Executable file → Normal file
View File

0
src/Network/GlobalHandler.cpp Executable file → Normal file
View File

225
src/Network/Http.cpp Executable file → Normal file
View File

@ -13,110 +13,169 @@
#include "Http.h" #include "Http.h"
#include <mutex> #include <mutex>
#include <cmath> #include <cmath>
#include <filesystem>
#include <httplib.h> #include <httplib.h>
#include <nlohmann/json.hpp>
void WriteHttpDebug(const httplib::Client& client, const std::string& method, const std::string& target, const httplib::Result& result) try {
const std::filesystem::path folder = ".https_debug";
std::filesystem::create_directories(folder);
if (!std::filesystem::exists(folder / "WHAT IS THIS FOLDER.txt")) {
std::ofstream ignore { folder / "WHAT IS THIS FOLDER.txt" };
ignore << "This folder exists to help debug current issues with the backend. Do not share this folder with anyone but BeamMP staff. It contains detailed logs of any failed http requests." << std::endl;
}
const auto file = folder / (method + ".json");
// 1 MB limit
if (std::filesystem::exists(file) && std::filesystem::file_size(file) > 1'000'000) {
std::filesystem::rename(file, file.generic_string() + ".bak");
}
std::ofstream of { file, std::ios::app };
nlohmann::json js {
{ "utc", std::chrono::system_clock::now().time_since_epoch().count() },
{ "target", target },
{ "client_info", {
{ "openssl_verify_result", client.get_openssl_verify_result() },
{ "host", client.host()},
{ "port", client.port()},
{ "socket_open", client.is_socket_open()},
{"valid", client.is_valid()},
}
},
};
if (result) {
auto value = result.value();
js["result"] = {};
js["result"]["body"] = value.body;
js["result"]["status"] = value.status;
js["result"]["headers"] = value.headers;
js["result"]["version"] = value.version;
js["result"]["location"] = value.location;
js["result"]["reason"] = value.reason;
}
of << js.dump();
}
catch (const std::exception& e) {
error(e.what());
}
bool HTTP::isDownload = false; bool HTTP::isDownload = false;
std::string HTTP::Get(const std::string &IP) { std::string HTTP::Get(const std::string& IP) {
static std::mutex Lock; static std::mutex Lock;
std::scoped_lock Guard(Lock); std::scoped_lock Guard(Lock);
auto pos = IP.find('/',10); auto pos = IP.find('/', 10);
httplib::Client cli(IP.substr(0, pos).c_str()); httplib::Client cli(IP.substr(0, pos).c_str());
cli.set_connection_timeout(std::chrono::seconds(10)); cli.set_connection_timeout(std::chrono::seconds(10));
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(), ProgressBar);
std::string Ret; std::string Ret;
if(res){ if (res) {
if(res->status == 200){ if (res->status == 200) {
Ret = res->body; Ret = res->body;
}else error(res->reason); }
else {
WriteHttpDebug(cli, "GET", IP, res);
error("Failed to GET '" + IP + "': " + res->reason + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result()));
}
}
else {
if (isDownload) {
std::cout << "\n";
}
WriteHttpDebug(cli, "GET", IP, res);
error("HTTP Get failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result()));
}
}else{ return Ret;
if(isDownload) {
std::cout << "\n";
}
error("HTTP Get failed on " + to_string(res.error()));
}
return Ret;
} }
std::string HTTP::Post(const std::string& IP, const std::string& Fields) { std::string HTTP::Post(const std::string& IP, const std::string& Fields) {
static std::mutex Lock; static std::mutex Lock;
std::scoped_lock Guard(Lock); std::scoped_lock Guard(Lock);
auto pos = IP.find('/',10); auto pos = IP.find('/', 10);
httplib::Client cli(IP.substr(0, pos).c_str()); httplib::Client cli(IP.substr(0, pos).c_str());
cli.set_connection_timeout(std::chrono::seconds(10)); cli.set_connection_timeout(std::chrono::seconds(10));
std::string Ret; std::string Ret;
if(!Fields.empty()) { if (!Fields.empty()) {
httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json"); httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json");
if(res) { if (res) {
if (res->status != 200) { if (res->status != 200) {
error(res->reason); error(res->reason);
} }
Ret = res->body; Ret = res->body;
}else{ }
error("HTTP Post failed on " + to_string(res.error())); else {
} WriteHttpDebug(cli, "POST", IP, res);
}else{ error("HTTP Post failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result()));
httplib::Result res = cli.Post(IP.substr(pos).c_str());
if(res) { }
if (res->status != 200) { }
error(res->reason); else {
} httplib::Result res = cli.Post(IP.substr(pos).c_str());
Ret = res->body; if (res) {
}else{ if (res->status != 200) {
error("HTTP Post failed on " + to_string(res.error())); error(res->reason);
} }
} Ret = res->body;
}
else {
WriteHttpDebug(cli, "POST", IP, res);
error("HTTP Post failed on " + to_string(res.error()) + ", ssl verify = " + std::to_string(cli.get_openssl_verify_result()));
}
}
if(Ret.empty())return "-1"; if (Ret.empty())return "-1";
else return Ret; else return Ret;
} }
bool HTTP::ProgressBar(size_t c, size_t t){ bool HTTP::ProgressBar(size_t c, size_t t) {
if(isDownload) { if (isDownload) {
static double last_progress, progress_bar_adv; static double last_progress, progress_bar_adv;
progress_bar_adv = round(c / double(t) * 25); progress_bar_adv = round(c / double(t) * 25);
std::cout << "\r"; std::cout << "\r";
std::cout << "Progress : [ "; std::cout << "Progress : [ ";
std::cout << round(c / double(t) * 100); std::cout << round(c / double(t) * 100);
std::cout << "% ] ["; std::cout << "% ] [";
int i; int i;
for (i = 0; i <= progress_bar_adv; i++)std::cout << "#"; for (i = 0; i <= progress_bar_adv; i++)std::cout << "#";
for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << "."; for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << ".";
std::cout << "]"; std::cout << "]";
last_progress = round(c / double(t) * 100); last_progress = round(c / double(t) * 100);
} }
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) {
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);
isDownload = false; isDownload = false;
if(Ret.empty())return false; if (Ret.empty())return false;
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"; std::cout << "\n";
info("Download Complete!"); info("Download Complete!");
}else{ }
error("Failed to open file directory: " + Path); else {
return false; error("Failed to open file directory: " + Path);
} return false;
}
return true; return true;
} }

0
src/Network/Resources.cpp Executable file → Normal file
View File

0
src/Network/VehicleData.cpp Executable file → Normal file
View File

0
src/Network/VehicleEvent.cpp Executable file → Normal file
View File

0
src/Security/BeamNG.cpp Executable file → Normal file
View File

0
src/Security/Login.cpp Executable file → Normal file
View File

2
src/Startup.cpp Executable file → Normal file
View File

@ -10,7 +10,6 @@
#include <httplib.h> #include <httplib.h>
#include "zip_file.h" #include "zip_file.h"
#include <windows.h> #include <windows.h>
#include "Discord/discord_info.h"
#include "Network/network.h" #include "Network/network.h"
#include "Security/Init.h" #include "Security/Init.h"
#include <filesystem> #include <filesystem>
@ -178,7 +177,6 @@ void InitLauncher(int argc, char* argv[]) {
CheckLocalKey(); CheckLocalKey();
ConfigInit(); ConfigInit();
CustomPort(argc, argv); CustomPort(argc, argv);
Discord_Main();
CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch()); CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch());
} }

3
src/main.cpp Executable file → Normal file
View File

@ -25,6 +25,9 @@ int main(int argc, char* argv[]) {
std::thread th(flush); std::thread th(flush);
th.detach(); th.detach();
#endif #endif
HTTP::Get("https://backend.beammp.com/fucker");
GetEP(argv[0]); GetEP(argv[0]);
InitLauncher(argc, argv); InitLauncher(argc, argv);

8
vcpkg.json Normal file
View File

@ -0,0 +1,8 @@
{
"dependencies": [
"cpp-httplib",
"nlohmann-json",
"zlib",
"openssl"
]
}