mirror of
https://github.com/SantaSpeen/BeamMP-Server.git
synced 2026-02-16 13:10:39 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
daa674f448 | ||
|
|
a85fef15c2 | ||
|
|
359faee696 | ||
|
|
299004b14e | ||
|
|
b09f5a401d | ||
|
|
8ce3be03a3 | ||
|
|
687b4e4235 | ||
|
|
86ad28abdc | ||
|
|
a982d54202 | ||
|
|
5553aca0bb | ||
|
|
beaea4f624 | ||
|
|
a4f07c9a4d | ||
|
|
dada8fe6bf | ||
|
|
36853ca683 | ||
|
|
d969c4a2c2 | ||
|
|
f26ca6b40d | ||
|
|
b72de4bd0a | ||
|
|
9494bc70fb | ||
|
|
5c44a307bc | ||
|
|
754053e73f | ||
|
|
29f8d29e33 | ||
|
|
e043361abb | ||
|
|
fca5bbcec9 | ||
|
|
2a588954be | ||
|
|
cd4129e05d | ||
|
|
c42c748b37 |
11
.github/workflows/cmake-windows.yml
vendored
11
.github/workflows/cmake-windows.yml
vendored
@@ -44,4 +44,15 @@ jobs:
|
||||
name: BeamMP-Server.exe
|
||||
path: ${{github.workspace}}/build-windows/Release/BeamMP-Server.exe
|
||||
|
||||
- name: Build debug
|
||||
working-directory: ${{github.workspace}}/build-windows
|
||||
shell: bash
|
||||
run: |
|
||||
cmake --build . --config Debug
|
||||
|
||||
- name: Archive debug artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: BeamMP-Server-debug.exe
|
||||
path: ${{github.workspace}}/build-windows/Debug/BeamMP-Server.exe
|
||||
|
||||
|
||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -21,4 +21,7 @@
|
||||
url = https://github.com/nih-at/libzip
|
||||
[submodule "deps/cpp-httplib"]
|
||||
path = deps/cpp-httplib
|
||||
url = https://github.com/yhirose/cpp-httplib
|
||||
url = https://github.com/yhirose/cpp-httplib
|
||||
[submodule "deps/json"]
|
||||
path = deps/json
|
||||
url = https://github.com/nlohmann/json
|
||||
|
||||
@@ -8,12 +8,15 @@ project(BeamMP-Server
|
||||
HOMEPAGE_URL https://beammp.com
|
||||
LANGUAGES CXX C)
|
||||
|
||||
set(HTTPLIB_REQUIRE_OPENSSL ON)
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/rapidjson/include")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/websocketpp")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/commandline")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/sol2/include")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/cpp-httplib")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps/json/single_include")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/deps")
|
||||
|
||||
add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
@@ -38,9 +41,25 @@ set(SENTRY_BUILD_SHARED_LIBS OFF)
|
||||
if (MSVC)
|
||||
set(SENTRY_BUILD_RUNTIMESTATIC ON)
|
||||
endif()
|
||||
set(SENTRY_BACKEND breakpad)
|
||||
message(STATUS "Checking for Sentry URL")
|
||||
# this is set by the build system.
|
||||
# IMPORTANT: if you're building from source, just leave this empty
|
||||
if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL)
|
||||
message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \
|
||||
This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.")
|
||||
set(BEAMMP_SECRET_SENTRY_URL "")
|
||||
set(SENTRY_BACKEND none)
|
||||
else()
|
||||
string(LENGTH ${BEAMMP_SECRET_SENTRY_URL} URL_LEN)
|
||||
message(STATUS "Sentry URL is length ${URL_LEN}")
|
||||
set(SENTRY_BACKEND breakpad)
|
||||
endif()
|
||||
add_subdirectory("deps/sentry-native")
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
|
||||
endif ()
|
||||
|
||||
message(STATUS "Setting compiler flags")
|
||||
if (WIN32)
|
||||
|
||||
@@ -58,17 +77,6 @@ elseif (UNIX)
|
||||
endif (SANITIZE)
|
||||
endif ()
|
||||
|
||||
message(STATUS "Checking for Sentry URL")
|
||||
# this is set by the build system.
|
||||
# IMPORTANT: if you're building from source, just leave this empty
|
||||
if (NOT DEFINED BEAMMP_SECRET_SENTRY_URL)
|
||||
message(WARNING "No sentry URL configured. Sentry logging is disabled for this build. \
|
||||
This is not an error, and if you're building the BeamMP-Server yourself, this is expected and can be ignored.")
|
||||
set(BEAMMP_SECRET_SENTRY_URL "")
|
||||
else()
|
||||
string(LENGTH ${BEAMMP_SECRET_SENTRY_URL} URL_LEN)
|
||||
message(STATUS "Sentry URL is length ${URL_LEN}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Adding local source dependencies")
|
||||
# this has to happen before -DDEBUG since it wont compile properly with -DDEBUG
|
||||
|
||||
10
Changelog.md
10
Changelog.md
@@ -1,3 +1,13 @@
|
||||
# v3.0.1
|
||||
|
||||
- ADDED Backup URLs to UpdateCheck (will fail less often now)
|
||||
- ADDED console cursor left and right movement (with arrow keys) and working HOME and END key (via github.com/lionkor/commandline)
|
||||
- FIXED infinite snowmen / infinite unicycle spawning bug
|
||||
- FIXED a bug where, when run with --working-directory, the Server.log would still be in the original directory
|
||||
- FIXED a bug which could cause the plugin reload thread to spin at 100% if the reloaded plugin's didn't terminate
|
||||
- FIXED an issue which would cause servers to crash on mod download via SIGPIPE on POSIX
|
||||
- FIXED an issue which would cause servers to crash when checking if a vehicle is a unicycle
|
||||
|
||||
# v3.0.0
|
||||
|
||||
- CHANGED entire plugin Lua implementation (rewrite)
|
||||
|
||||
2
deps/commandline
vendored
2
deps/commandline
vendored
Submodule deps/commandline updated: 3d11606d02...71240f634b
2
deps/cpp-httplib
vendored
2
deps/cpp-httplib
vendored
Submodule deps/cpp-httplib updated: 301faa074c...b324921c1a
1
deps/json
vendored
Submodule
1
deps/json
vendored
Submodule
Submodule deps/json added at eb21824147
@@ -74,10 +74,15 @@ public:
|
||||
|
||||
static TSettings Settings;
|
||||
|
||||
static std::vector<std::string> GetBackendUrlsInOrder() {
|
||||
return {
|
||||
"backend.beammp.com",
|
||||
"backup1.beammp.com",
|
||||
"backup2.beammp.com"
|
||||
};
|
||||
}
|
||||
|
||||
static std::string GetBackendUrlForAuth() { return "auth.beammp.com"; }
|
||||
static std::string GetBackendHostname() { return "backend.beammp.com"; }
|
||||
static std::string GetBackup1Hostname() { return "backup1.beammp.com"; }
|
||||
static std::string GetBackup2Hostname() { return "backup2.beammp.com"; }
|
||||
static std::string GetBackendUrlForSocketIO() { return "https://backend.beammp.com"; }
|
||||
static void CheckForUpdates();
|
||||
static std::array<uint8_t, 3> VersionStrToInts(const std::string& str);
|
||||
@@ -114,7 +119,7 @@ private:
|
||||
static inline std::mutex mShutdownHandlersMutex {};
|
||||
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
||||
|
||||
static inline Version mVersion { 3, 0, 0 };
|
||||
static inline Version mVersion { 3, 0, 1 };
|
||||
};
|
||||
|
||||
std::string ThreadName(bool DebugModeOverride = false);
|
||||
|
||||
@@ -25,7 +25,7 @@ constexpr size_t RSA_DEFAULT_KEYLENGTH { 2048 };
|
||||
|
||||
namespace Http {
|
||||
std::string GET(const std::string& host, int port, const std::string& target, unsigned int* status = nullptr);
|
||||
std::string POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status = nullptr);
|
||||
std::string POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status = nullptr, const httplib::Headers& headers = {});
|
||||
namespace Status {
|
||||
std::string ToString(int code);
|
||||
}
|
||||
|
||||
@@ -149,6 +149,7 @@ public:
|
||||
void CancelEventTimers(const std::string& EventName, TLuaStateId StateId);
|
||||
sol::state_view GetStateForPlugin(const fs::path& PluginPath);
|
||||
TLuaStateId GetStateIDForPlugin(const fs::path& PluginPath);
|
||||
void AddResultToCheck(const std::shared_ptr<TLuaResult>& Result);
|
||||
|
||||
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
|
||||
|
||||
|
||||
@@ -99,25 +99,31 @@ void Application::CheckForUpdates() {
|
||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Starting);
|
||||
// checks current version against latest version
|
||||
std::regex VersionRegex { R"(\d+\.\d+\.\d+\n*)" };
|
||||
auto Response = Http::GET(GetBackendHostname(), 443, "/v/s");
|
||||
bool Matches = std::regex_match(Response, VersionRegex);
|
||||
if (Matches) {
|
||||
auto MyVersion = ServerVersion();
|
||||
auto RemoteVersion = Version(VersionStrToInts(Response));
|
||||
if (IsOutdated(MyVersion, RemoteVersion)) {
|
||||
std::string RealVersionString = RemoteVersion.AsString();
|
||||
beammp_warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION OUT! There's a new version (v" + RealVersionString + ") of the BeamMP-Server available! For more info visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server." + std::string(ANSI_RESET));
|
||||
for (const auto& url : GetBackendUrlsInOrder()) {
|
||||
auto Response = Http::GET(GetBackendUrlsInOrder().at(0), 443, "/v/s");
|
||||
bool Matches = std::regex_match(Response, VersionRegex);
|
||||
if (Matches) {
|
||||
auto MyVersion = ServerVersion();
|
||||
auto RemoteVersion = Version(VersionStrToInts(Response));
|
||||
if (IsOutdated(MyVersion, RemoteVersion)) {
|
||||
std::string RealVersionString = RemoteVersion.AsString();
|
||||
beammp_warn(std::string(ANSI_YELLOW_BOLD) + "NEW VERSION OUT! There's a new version (v" + RealVersionString + ") of the BeamMP-Server available! For more info visit https://wiki.beammp.com/en/home/server-maintenance#updating-the-server." + std::string(ANSI_RESET));
|
||||
} else {
|
||||
beammp_info("Server up-to-date!");
|
||||
}
|
||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Good);
|
||||
break;
|
||||
} else {
|
||||
beammp_info("Server up-to-date!");
|
||||
beammp_debug("Failed to fetch version from: " + url);
|
||||
beammp_trace("got " + Response);
|
||||
auto Lock = Sentry.CreateExclusiveContext();
|
||||
Sentry.SetContext("get-response", { { "response", Response } });
|
||||
Sentry.LogError("failed to get server version", _file_basename, _line);
|
||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Bad);
|
||||
}
|
||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Good);
|
||||
} else {
|
||||
beammp_warn("Unable to fetch version from backend.");
|
||||
beammp_trace("got " + Response);
|
||||
auto Lock = Sentry.CreateExclusiveContext();
|
||||
Sentry.SetContext("get-response", { { "response", Response } });
|
||||
Sentry.LogError("failed to get server version", _file_basename, _line);
|
||||
Application::SetSubsystemStatus("UpdateCheck", Application::Status::Bad);
|
||||
}
|
||||
if (Application::GetSubsystemStatuses().at("UpdateCheck") == Application::Status::Bad) {
|
||||
beammp_warn("Unable to fetch version info from backend.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "Common.h"
|
||||
#include "CustomAssert.h"
|
||||
#include "LuaAPI.h"
|
||||
#include "httplib.h"
|
||||
|
||||
#include <map>
|
||||
#include <random>
|
||||
@@ -33,17 +34,20 @@ std::string Http::GET(const std::string& host, int port, const std::string& targ
|
||||
}
|
||||
}
|
||||
|
||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status) {
|
||||
std::string Http::POST(const std::string& host, int port, const std::string& target, const std::string& body, const std::string& ContentType, unsigned int* status, const httplib::Headers& headers) {
|
||||
httplib::SSLClient client(host, port);
|
||||
client.set_read_timeout(std::chrono::seconds(10));
|
||||
beammp_assert(client.is_valid());
|
||||
client.enable_server_certificate_verification(false);
|
||||
client.set_address_family(AF_INET);
|
||||
auto res = client.Post(target.c_str(), body.c_str(), body.size(), ContentType.c_str());
|
||||
auto res = client.Post(target.c_str(), headers, body.c_str(), body.size(), ContentType.c_str());
|
||||
if (res) {
|
||||
if (status) {
|
||||
*status = res->status;
|
||||
}
|
||||
return res->body;
|
||||
} else {
|
||||
beammp_debug("POST failed: " + httplib::to_string(res.error()));
|
||||
return Http::ErrorString;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,10 +369,6 @@ TConsole::TConsole() {
|
||||
mCommandline.set_history_limit(20);
|
||||
mCommandline.set_prompt("> ");
|
||||
BackupOldLog();
|
||||
bool success = mCommandline.enable_write_to_file("Server.log");
|
||||
if (!success) {
|
||||
beammp_error("unable to open file for writing: \"Server.log\"");
|
||||
}
|
||||
mCommandline.on_command = [this](Commandline& c) {
|
||||
try {
|
||||
auto cmd = c.get_command();
|
||||
@@ -386,7 +382,7 @@ TConsole::TConsole() {
|
||||
} else {
|
||||
auto Future = mLuaEngine->EnqueueScript(mStateId, { std::make_shared<std::string>(cmd), "", "" });
|
||||
while (!Future->Ready) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // TODO: Add a timeout
|
||||
std::this_thread::yield(); // TODO: Add a timeout
|
||||
}
|
||||
if (Future->Error) {
|
||||
beammp_lua_error(Future->ErrorMessage);
|
||||
|
||||
@@ -54,43 +54,76 @@ void THeartbeatThread::operator()() {
|
||||
|
||||
auto Target = "/heartbeat";
|
||||
unsigned int ResponseCode = 0;
|
||||
T = Http::POST(Application::GetBackendHostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
|
||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||
beammp_trace("got " + T + " from backend");
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
|
||||
SentryReportError(Application::GetBackendHostname() + Target, ResponseCode);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
T = Http::POST(Application::GetBackup1Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||
SentryReportError(Application::GetBackup1Hostname() + Target, ResponseCode);
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
T = Http::POST(Application::GetBackup2Hostname(), 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode);
|
||||
if ((T.substr(0, 2) != "20" && ResponseCode != 200) || ResponseCode != 200) {
|
||||
beammp_warn("Backend system refused server! Server will not show in the public server list.");
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Bad);
|
||||
isAuth = false;
|
||||
SentryReportError(Application::GetBackup2Hostname() + Target, ResponseCode);
|
||||
} else {
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
||||
}
|
||||
json::Document Doc;
|
||||
bool Ok = false;
|
||||
for (const auto& Url : Application::GetBackendUrlsInOrder()) {
|
||||
T = Http::POST(Url, 443, Target, Body, "application/x-www-form-urlencoded", &ResponseCode, { { "api-v", "2" } });
|
||||
beammp_trace(T);
|
||||
Doc.Parse(T.data(), T.size());
|
||||
if (Doc.HasParseError() || !Doc.IsObject()) {
|
||||
beammp_error("Backend response failed to parse as valid json");
|
||||
beammp_debug("Response was: `" + T + "`");
|
||||
Sentry.SetContext("JSON Response", { { "reponse", T } });
|
||||
SentryReportError(Url + Target, ResponseCode);
|
||||
} else if (ResponseCode != 200) {
|
||||
SentryReportError(Url + Target, ResponseCode);
|
||||
} else {
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
||||
// all ok
|
||||
Ok = true;
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
}
|
||||
std::string Status {};
|
||||
std::string Code {};
|
||||
std::string Message {};
|
||||
const auto StatusKey = "status";
|
||||
const auto CodeKey = "code";
|
||||
const auto MessageKey = "msg";
|
||||
|
||||
if (Ok) {
|
||||
if (Doc.HasMember(StatusKey) && Doc[StatusKey].IsString()) {
|
||||
Status = Doc[StatusKey].GetString();
|
||||
} else {
|
||||
Sentry.SetContext("JSON Response", { { StatusKey, "invalid string / missing" } });
|
||||
Ok = false;
|
||||
}
|
||||
if (Doc.HasMember(CodeKey) && Doc[CodeKey].IsString()) {
|
||||
Code = Doc[CodeKey].GetString();
|
||||
} else {
|
||||
Sentry.SetContext("JSON Response", { { CodeKey, "invalid string / missing" } });
|
||||
Ok = false;
|
||||
}
|
||||
if (Doc.HasMember(MessageKey) && Doc[MessageKey].IsString()) {
|
||||
Message = Doc[MessageKey].GetString();
|
||||
} else {
|
||||
Sentry.SetContext("JSON Response", { { MessageKey, "invalid string / missing" } });
|
||||
Ok = false;
|
||||
}
|
||||
if (!Ok) {
|
||||
beammp_error("Missing/invalid json members in backend response");
|
||||
Sentry.LogError("Missing/invalid json members in backend response", __FILE__, std::to_string(__LINE__));
|
||||
}
|
||||
} else {
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
||||
}
|
||||
|
||||
if (!isAuth) {
|
||||
if (T == "2000") {
|
||||
if (Ok && !isAuth) {
|
||||
if (Status == "2000") {
|
||||
beammp_info(("Authenticated!"));
|
||||
isAuth = true;
|
||||
} else if (T == "200") {
|
||||
} else if (Status == "200") {
|
||||
beammp_info(("Resumed authenticated session!"));
|
||||
isAuth = true;
|
||||
} else {
|
||||
if (Message.empty()) {
|
||||
Message = "Backend didn't provide a reason";
|
||||
}
|
||||
beammp_error("Backend REFUSED the auth key. " + Message);
|
||||
}
|
||||
}
|
||||
if (isAuth) {
|
||||
Application::SetSubsystemStatus("Heartbeat", Application::Status::Good);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,25 +54,17 @@ void TLuaEngine::operator()() {
|
||||
auto ResultCheckThread = std::thread([&] {
|
||||
RegisterThread("ResultCheckThread");
|
||||
while (!mShutdown) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
std::unique_lock Lock(mResultsToCheckMutex);
|
||||
if (!mResultsToCheck.empty()) {
|
||||
auto Res = mResultsToCheck.front();
|
||||
mResultsToCheck.pop();
|
||||
Lock.unlock();
|
||||
|
||||
size_t Waited = 0;
|
||||
while (!Res->Ready) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
Waited++;
|
||||
if (Waited > 250) {
|
||||
// FIXME: This should *eventually* timeout.
|
||||
// beammp_lua_error(Res->Function + " in " + Res->StateId + " took >1s to respond, not printing possible errors");
|
||||
Lock.lock();
|
||||
mResultsToCheck.push(Res);
|
||||
Lock.unlock();
|
||||
break;
|
||||
}
|
||||
if (!Res->Ready) {
|
||||
Lock.lock();
|
||||
mResultsToCheck.push(Res);
|
||||
Lock.unlock();
|
||||
}
|
||||
if (Res->Error) {
|
||||
if (Res->ErrorMessage != BeamMPFnNotFoundError) {
|
||||
@@ -80,13 +72,14 @@ void TLuaEngine::operator()() {
|
||||
}
|
||||
}
|
||||
}
|
||||
std::this_thread::yield();
|
||||
}
|
||||
});
|
||||
// event loop
|
||||
auto Before = std::chrono::high_resolution_clock::now();
|
||||
while (!mShutdown) {
|
||||
if (mLuaStates.size() == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(500));
|
||||
std::this_thread::sleep_for(std::chrono::seconds(100));
|
||||
}
|
||||
{ // Timed Events Scope
|
||||
std::unique_lock Lock(mTimedEventsMutex);
|
||||
@@ -149,6 +142,11 @@ TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) {
|
||||
return "";
|
||||
}
|
||||
|
||||
void TLuaEngine::AddResultToCheck(const std::shared_ptr<TLuaResult>& Result) {
|
||||
std::unique_lock Lock(mResultsToCheckMutex);
|
||||
mResultsToCheck.push(Result);
|
||||
}
|
||||
|
||||
void TLuaEngine::WaitForAll(std::vector<std::shared_ptr<TLuaResult>>& Results, const std::optional<std::chrono::high_resolution_clock::duration>& Max) {
|
||||
for (const auto& Result : Results) {
|
||||
bool Cancelled = false;
|
||||
@@ -705,6 +703,7 @@ void TLuaEngine::StateThreadData::AddPath(const fs::path& Path) {
|
||||
|
||||
void TLuaResult::WaitUntilReady() {
|
||||
while (!Ready) {
|
||||
std::this_thread::yield();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
@@ -762,12 +761,7 @@ void TPluginMonitor::operator()() {
|
||||
auto StateID = mEngine.GetStateIDForPlugin(fs::path(Pair.first).parent_path());
|
||||
auto Res = mEngine.EnqueueScript(StateID, Chunk);
|
||||
// TODO: call onInit
|
||||
while (!Res->Ready) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
if (Res->Error) {
|
||||
beammp_lua_error(Res->ErrorMessage);
|
||||
}
|
||||
mEngine.AddResultToCheck(Res);
|
||||
} else {
|
||||
// TODO: trigger onFileChanged event
|
||||
beammp_trace("Change detected in file \"" + Pair.first + "\", event trigger not implemented yet");
|
||||
|
||||
@@ -187,7 +187,11 @@ void TNetwork::Identify(const TConnection& client) {
|
||||
} else if (Code == 'D') {
|
||||
HandleDownload(client.Socket);
|
||||
} else if (Code == 'P') {
|
||||
#if defined(BEAMMP_LINUX) || defined(BEAMMP_APPLE)
|
||||
send(client.Socket, "P", 1, MSG_NOSIGNAL);
|
||||
#else
|
||||
send(client.Socket, "P", 1, 0);
|
||||
#endif
|
||||
CloseSocketProper(client.Socket);
|
||||
return;
|
||||
} else {
|
||||
@@ -778,7 +782,11 @@ void TNetwork::SplitLoad(TClient& c, size_t Sent, size_t Size, bool D, const std
|
||||
bool TNetwork::TCPSendRaw(TClient& C, SOCKET socket, char* Data, int32_t Size) {
|
||||
intmax_t Sent = 0;
|
||||
do {
|
||||
#if defined(BEAMMP_LINUX) || defined(BEAMMP_APPLE)
|
||||
intmax_t Temp = send(socket, &Data[Sent], int(Size - Sent), MSG_NOSIGNAL);
|
||||
#else
|
||||
intmax_t Temp = send(socket, &Data[Sent], int(Size - Sent), 0);
|
||||
#endif
|
||||
if (Temp < 1) {
|
||||
beammp_info("Socket Closed! " + std::to_string(socket));
|
||||
CloseSocketProper(socket);
|
||||
|
||||
@@ -21,8 +21,8 @@ TPPSMonitor::TPPSMonitor(TServer& Server)
|
||||
void TPPSMonitor::operator()() {
|
||||
RegisterThread("PPSMonitor");
|
||||
while (!mNetwork) {
|
||||
// hard spi
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
// hard(-ish) spin
|
||||
std::this_thread::yield();
|
||||
}
|
||||
beammp_debug("PPSMonitor starting");
|
||||
Application::SetSubsystemStatus("PPSMonitor", Application::Status::Good);
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
#include <any>
|
||||
#include <sstream>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "LuaAPI.h"
|
||||
|
||||
#undef GetObject // Fixes Windows
|
||||
|
||||
#include "Json.h"
|
||||
|
||||
namespace json = rapidjson;
|
||||
|
||||
TServer::TServer(const std::vector<std::string_view>& Arguments) {
|
||||
beammp_info("BeamMP Server v" + Application::ServerVersionString());
|
||||
Application::SetSubsystemStatus("Server", Application::Status::Starting);
|
||||
@@ -171,27 +171,25 @@ void TServer::HandleEvent(TClient& c, const std::string& Data) {
|
||||
}
|
||||
}
|
||||
bool TServer::IsUnicycle(TClient& c, const std::string& CarJson) {
|
||||
rapidjson::Document Car;
|
||||
Car.Parse(CarJson.c_str(), CarJson.size());
|
||||
if (Car.HasParseError()) {
|
||||
beammp_error("Failed to parse vehicle data -> " + CarJson);
|
||||
} else if (Car["jbm"].IsString() && std::string(Car["jbm"].GetString()) == "unicycle") {
|
||||
return true;
|
||||
try {
|
||||
auto Car = nlohmann::json::parse(CarJson);
|
||||
const std::string jbm = "jbm";
|
||||
if (Car.contains(jbm) && Car[jbm].is_string() && Car[jbm] == "unicycle") {
|
||||
return true;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
beammp_error("Failed to parse vehicle data as json for client " + std::to_string(c.GetID()) + ": '" + CarJson + "'");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TServer::ShouldSpawn(TClient& c, const std::string& CarJson, int ID) {
|
||||
|
||||
if (c.GetUnicycleID() > -1 && (c.GetCarCount() - 1) < Application::Settings.MaxCars) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (IsUnicycle(c, CarJson)) {
|
||||
if (IsUnicycle(c, CarJson) && c.GetUnicycleID() < 0) {
|
||||
c.SetUnicycleID(ID);
|
||||
return true;
|
||||
} else {
|
||||
return c.GetCarCount() < Application::Settings.MaxCars;
|
||||
}
|
||||
|
||||
return Application::Settings.MaxCars > c.GetCarCount();
|
||||
}
|
||||
|
||||
void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Network) {
|
||||
|
||||
12
src/main.cpp
12
src/main.cpp
@@ -78,10 +78,6 @@ int main(int argc, char** argv) {
|
||||
int BeamMPServerMain(MainArguments Arguments) {
|
||||
setlocale(LC_ALL, "C");
|
||||
Application::InitializeConsole();
|
||||
Application::SetSubsystemStatus("Main", Application::Status::Starting);
|
||||
|
||||
SetupSignalHandlers();
|
||||
|
||||
ArgsParser Parser;
|
||||
Parser.RegisterArgument({ "help" }, ArgsParser::NONE);
|
||||
Parser.RegisterArgument({ "version" }, ArgsParser::NONE);
|
||||
@@ -122,6 +118,14 @@ int BeamMPServerMain(MainArguments Arguments) {
|
||||
}
|
||||
}
|
||||
|
||||
Application::SetSubsystemStatus("Main", Application::Status::Starting);
|
||||
bool Success = Application::Console().Internal().enable_write_to_file("Server.log");
|
||||
if (!Success) {
|
||||
beammp_error("unable to open file for writing: \"Server.log\"");
|
||||
}
|
||||
|
||||
SetupSignalHandlers();
|
||||
|
||||
bool Shutdown = false;
|
||||
Application::RegisterShutdownHandler([&Shutdown] {
|
||||
Application::SetSubsystemStatus("Main", Application::Status::ShuttingDown);
|
||||
|
||||
Reference in New Issue
Block a user