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)
project(Launcher)
if (WIN32)
@ -18,25 +19,14 @@ find_package(nlohmann_json CONFIG REQUIRED)
add_executable(${PROJECT_NAME} ${source_files})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher")
if (WIN32)
find_package(ZLIB 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
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
add_definitions("-D_WIN32_WINNT=0x0600")
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)
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.
## 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.
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 info(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 <mutex>
#include <cmath>
#include <filesystem>
#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;
std::string HTTP::Get(const std::string &IP) {
static std::mutex Lock;
std::scoped_lock Guard(Lock);
std::string HTTP::Get(const std::string& IP) {
static std::mutex 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());
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;
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;
if(res){
if(res->status == 200){
Ret = res->body;
}else error(res->reason);
if (res) {
if (res->status == 200) {
Ret = res->body;
}
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{
if(isDownload) {
std::cout << "\n";
}
error("HTTP Get failed on " + to_string(res.error()));
}
return Ret;
return Ret;
}
std::string HTTP::Post(const std::string& IP, const std::string& Fields) {
static std::mutex Lock;
std::scoped_lock Guard(Lock);
static std::mutex 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());
cli.set_connection_timeout(std::chrono::seconds(10));
std::string Ret;
httplib::Client cli(IP.substr(0, pos).c_str());
cli.set_connection_timeout(std::chrono::seconds(10));
std::string Ret;
if(!Fields.empty()) {
httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json");
if (!Fields.empty()) {
httplib::Result res = cli.Post(IP.substr(pos).c_str(), Fields, "application/json");
if(res) {
if (res->status != 200) {
error(res->reason);
}
Ret = res->body;
}else{
error("HTTP Post failed on " + to_string(res.error()));
}
}else{
httplib::Result res = cli.Post(IP.substr(pos).c_str());
if(res) {
if (res->status != 200) {
error(res->reason);
}
Ret = res->body;
}else{
error("HTTP Post failed on " + to_string(res.error()));
}
}
if (res) {
if (res->status != 200) {
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()));
}
}
else {
httplib::Result res = cli.Post(IP.substr(pos).c_str());
if (res) {
if (res->status != 200) {
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";
else return Ret;
if (Ret.empty())return "-1";
else return Ret;
}
bool HTTP::ProgressBar(size_t c, size_t t){
if(isDownload) {
static double last_progress, progress_bar_adv;
progress_bar_adv = round(c / double(t) * 25);
std::cout << "\r";
std::cout << "Progress : [ ";
std::cout << round(c / double(t) * 100);
std::cout << "% ] [";
int i;
for (i = 0; i <= progress_bar_adv; i++)std::cout << "#";
for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << ".";
std::cout << "]";
last_progress = round(c / double(t) * 100);
}
return true;
bool HTTP::ProgressBar(size_t c, size_t t) {
if (isDownload) {
static double last_progress, progress_bar_adv;
progress_bar_adv = round(c / double(t) * 25);
std::cout << "\r";
std::cout << "Progress : [ ";
std::cout << round(c / double(t) * 100);
std::cout << "% ] [";
int i;
for (i = 0; i <= progress_bar_adv; i++)std::cout << "#";
for (i = 0; i < 25 - progress_bar_adv; i++)std::cout << ".";
std::cout << "]";
last_progress = round(c / double(t) * 100);
}
return true;
}
bool HTTP::Download(const std::string &IP, const std::string &Path) {
static std::mutex Lock;
std::scoped_lock Guard(Lock);
bool HTTP::Download(const std::string& IP, const std::string& Path) {
static std::mutex Lock;
std::scoped_lock Guard(Lock);
isDownload = true;
std::string Ret = Get(IP);
isDownload = false;
isDownload = true;
std::string Ret = Get(IP);
isDownload = false;
if(Ret.empty())return false;
if (Ret.empty())return false;
std::ofstream File(Path, std::ios::binary);
if(File.is_open()) {
File << Ret;
File.close();
std::cout << "\n";
info("Download Complete!");
}else{
error("Failed to open file directory: " + Path);
return false;
}
std::ofstream File(Path, std::ios::binary);
if (File.is_open()) {
File << Ret;
File.close();
std::cout << "\n";
info("Download Complete!");
}
else {
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 "zip_file.h"
#include <windows.h>
#include "Discord/discord_info.h"
#include "Network/network.h"
#include "Security/Init.h"
#include <filesystem>
@ -178,7 +177,6 @@ void InitLauncher(int argc, char* argv[]) {
CheckLocalKey();
ConfigInit();
CustomPort(argc, argv);
Discord_Main();
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);
th.detach();
#endif
HTTP::Get("https://backend.beammp.com/fucker");
GetEP(argv[0]);
InitLauncher(argc, argv);

8
vcpkg.json Normal file
View File

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