mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2026-07-13 18:24:16 +00:00
Compare commits
29 Commits
v3.8.4
...
update-lua
| Author | SHA1 | Date | |
|---|---|---|---|
| 43e86a1e22 | |||
| 70fc8436ed | |||
| 6f196aca64 | |||
| 99476a2c77 | |||
| 9fa9974159 | |||
| 3ef816845d | |||
| 6ec4106ec7 | |||
| b094e35f8c | |||
| 83afafc0c3 | |||
| 31122abe10 | |||
| 0615b57a37 | |||
| 4a8378427a | |||
| b74f0c7ca8 | |||
| 420c64f6cf | |||
| add45c085b | |||
| 372076a4ef | |||
| eb2deb73c1 | |||
| 21874afb87 | |||
| 184d50bf8c | |||
| c4c894c1f7 | |||
| 039a44bba5 | |||
| add0b86b37 | |||
| 403c1d5f78 | |||
| 6318ca79e7 | |||
| 2bd4ee9321 | |||
| 22c0a966bb | |||
| 731599f16e | |||
| 52a1d9a99e | |||
| 2f577a2358 |
@@ -19,8 +19,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- distro: debian
|
|
||||||
version: 11
|
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -48,6 +46,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -90,8 +89,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- distro: debian
|
|
||||||
version: 11
|
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -119,6 +116,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- distro: debian
|
|
||||||
version: 11
|
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -67,6 +65,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -109,8 +108,6 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- distro: debian
|
|
||||||
version: 11
|
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: 12
|
version: 12
|
||||||
- distro: ubuntu
|
- distro: ubuntu
|
||||||
@@ -141,6 +138,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Git config safe directory
|
- name: Git config safe directory
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -194,6 +192,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup vcpkg
|
- name: Setup vcpkg
|
||||||
uses: lukka/run-vcpkg@v11
|
uses: lukka/run-vcpkg@v11
|
||||||
|
|||||||
+8
-4
@@ -80,14 +80,15 @@ set(PRJ_SOURCES
|
|||||||
src/ChronoWrapper.cpp
|
src/ChronoWrapper.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Lua REQUIRED)
|
# fix for sol2
|
||||||
|
find_path(LUAJIT_INCLUDE_DIR lua.hpp PATH_SUFFIXES luajit)
|
||||||
|
|
||||||
# set the source file containing main()
|
# set the source file containing main()
|
||||||
set(PRJ_MAIN src/main.cpp)
|
set(PRJ_MAIN src/main.cpp)
|
||||||
# set the source file containing the test's main
|
# set the source file containing the test's main
|
||||||
set(PRJ_TEST_MAIN test/test_main.cpp)
|
set(PRJ_TEST_MAIN test/test_main.cpp)
|
||||||
# set include paths not part of libraries
|
# set include paths not part of libraries
|
||||||
set(PRJ_INCLUDE_DIRS ${LUA_INCLUDE_DIR})
|
set(PRJ_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIR})
|
||||||
# set compile features (e.g. standard version)
|
# set compile features (e.g. standard version)
|
||||||
set(PRJ_COMPILE_FEATURES cxx_std_20)
|
set(PRJ_COMPILE_FEATURES cxx_std_20)
|
||||||
# set #defines (test enable/disable not included here)
|
# set #defines (test enable/disable not included here)
|
||||||
@@ -105,9 +106,11 @@ set(PRJ_LIBRARIES
|
|||||||
libzip::zip
|
libzip::zip
|
||||||
OpenSSL::SSL OpenSSL::Crypto
|
OpenSSL::SSL OpenSSL::Crypto
|
||||||
CURL::libcurl
|
CURL::libcurl
|
||||||
${LUA_LIBRARIES}
|
lua51
|
||||||
)
|
)
|
||||||
|
|
||||||
|
link_directories(${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/lib)
|
||||||
|
|
||||||
# add dependency find_package calls and similar here
|
# add dependency find_package calls and similar here
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
@@ -148,7 +151,8 @@ if(UNIX)
|
|||||||
endif(UNIX)
|
endif(UNIX)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
add_compile_options("-D_WIN32_WINNT=0x0601")
|
add_compile_definitions(_WIN32_WINNT=0x0A00)
|
||||||
|
|
||||||
add_compile_options("/bigobj")
|
add_compile_options("/bigobj")
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -24,6 +24,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "BoostAliases.h"
|
#include "BoostAliases.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
@@ -56,14 +57,14 @@ public:
|
|||||||
~TClient();
|
~TClient();
|
||||||
TClient& operator=(const TClient&) = delete;
|
TClient& operator=(const TClient&) = delete;
|
||||||
|
|
||||||
void AddNewCar(int Ident, const std::string& Data);
|
void AddNewCar(int Ident, const nlohmann::json& Data);
|
||||||
void SetCarData(int Ident, const std::string& Data);
|
void SetCarData(int Ident, const nlohmann::json& Data);
|
||||||
void SetCarPosition(int Ident, const std::string& Data);
|
void SetCarPosition(int Ident, const std::string& Data);
|
||||||
TVehicleDataLockPair GetAllCars();
|
TVehicleDataLockPair GetAllCars();
|
||||||
void SetName(const std::string& Name) { mName = Name; }
|
void SetName(const std::string& Name) { mName = Name; }
|
||||||
void SetRoles(const std::string& Role) { mRole = Role; }
|
void SetRoles(const std::string& Role) { mRole = Role; }
|
||||||
void SetIdentifier(const std::string& key, const std::string& value) { mIdentifiers[key] = value; }
|
void SetIdentifier(const std::string& key, const std::string& value) { mIdentifiers[key] = value; }
|
||||||
std::string GetCarData(int Ident);
|
nlohmann::json GetCarData(int Ident);
|
||||||
std::string GetCarPositionRaw(int Ident);
|
std::string GetCarPositionRaw(int Ident);
|
||||||
void SetUDPAddr(const ip::udp::endpoint& Addr) { mUDPAddress = Addr; }
|
void SetUDPAddr(const ip::udp::endpoint& Addr) { mUDPAddress = Addr; }
|
||||||
void SetTCPSock(ip::tcp::socket&& CSock) { mSocket = std::move(CSock); }
|
void SetTCPSock(ip::tcp::socket&& CSock) { mSocket = std::move(CSock); }
|
||||||
@@ -101,6 +102,8 @@ public:
|
|||||||
[[nodiscard]] TServer& Server() const;
|
[[nodiscard]] TServer& Server() const;
|
||||||
void UpdatePingTime();
|
void UpdatePingTime();
|
||||||
int SecondsSinceLastPing();
|
int SecondsSinceLastPing();
|
||||||
|
void SetMagic(std::vector<uint8_t> magic) { mMagic = std::move(magic); }
|
||||||
|
[[nodiscard]] const std::vector<uint8_t>& GetMagic() const { return mMagic; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InsertVehicle(int ID, const std::string& Data);
|
void InsertVehicle(int ID, const std::string& Data);
|
||||||
@@ -125,6 +128,7 @@ private:
|
|||||||
std::string mDID;
|
std::string mDID;
|
||||||
int mID = -1;
|
int mID = -1;
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> mLastPingTime = std::chrono::high_resolution_clock::now();
|
std::chrono::time_point<std::chrono::high_resolution_clock> mLastPingTime = std::chrono::high_resolution_clock::now();
|
||||||
|
std::vector<uint8_t> mMagic;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<std::weak_ptr<TClient>> GetClient(class TServer& Server, int ID);
|
std::optional<std::weak_ptr<TClient>> GetClient(class TServer& Server, int ID);
|
||||||
|
|||||||
+4
-2
@@ -74,7 +74,7 @@ public:
|
|||||||
static TConsole& Console() { return mConsole; }
|
static TConsole& Console() { return mConsole; }
|
||||||
static std::string ServerVersionString();
|
static std::string ServerVersionString();
|
||||||
static const Version& ServerVersion() { return mVersion; }
|
static const Version& ServerVersion() { return mVersion; }
|
||||||
static Version ClientMinimumVersion() { return Version { 2, 2, 0 }; }
|
static Version ClientMinimumVersion() { return Version { 2, 7, 0 }; }
|
||||||
static std::string PPS() { return mPPS; }
|
static std::string PPS() { return mPPS; }
|
||||||
static void SetPPS(const std::string& NewPPS) { mPPS = NewPPS; }
|
static void SetPPS(const std::string& NewPPS) { mPPS = NewPPS; }
|
||||||
|
|
||||||
@@ -86,6 +86,8 @@ public:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string GetServerCheckUrl() { return "https://check.beammp.com"; }
|
||||||
|
|
||||||
static std::string GetBackendUrlForAuth() { return "https://auth.beammp.com"; }
|
static std::string GetBackendUrlForAuth() { return "https://auth.beammp.com"; }
|
||||||
static std::string GetBackendUrlForSocketIO() { return "https://backend.beammp.com"; }
|
static std::string GetBackendUrlForSocketIO() { return "https://backend.beammp.com"; }
|
||||||
static void CheckForUpdates();
|
static void CheckForUpdates();
|
||||||
@@ -127,7 +129,7 @@ private:
|
|||||||
static inline std::mutex mShutdownHandlersMutex {};
|
static inline std::mutex mShutdownHandlersMutex {};
|
||||||
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
static inline std::deque<TShutdownHandler> mShutdownHandlers {};
|
||||||
|
|
||||||
static inline Version mVersion { 3, 8, 4 };
|
static inline Version mVersion { 3, 9, 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
void SplitString(std::string const& str, const char delim, std::vector<std::string>& out);
|
void SplitString(std::string const& str, const char delim, std::vector<std::string>& out);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace MP {
|
|||||||
std::pair<bool, std::string> DropPlayer(int ID, std::optional<std::string> MaybeReason);
|
std::pair<bool, std::string> DropPlayer(int ID, std::optional<std::string> MaybeReason);
|
||||||
std::pair<bool, std::string> SendChatMessage(int ID, const std::string& Message);
|
std::pair<bool, std::string> SendChatMessage(int ID, const std::string& Message);
|
||||||
std::pair<bool, std::string> SendNotification(int ID, const std::string& Message, const std::string& Icon, const std::string& Category);
|
std::pair<bool, std::string> SendNotification(int ID, const std::string& Message, const std::string& Icon, const std::string& Category);
|
||||||
|
std::pair<bool, std::string> ConfirmationDialog(int ID, const std::string& Title, const std::string& Body, const sol::table& buttons, const std::string& InteractionID, const bool& warning = false, const bool& reportToServer = true, const bool& reportToExtensions = true);
|
||||||
std::pair<bool, std::string> RemoveVehicle(int PlayerID, int VehicleID);
|
std::pair<bool, std::string> RemoveVehicle(int PlayerID, int VehicleID);
|
||||||
void Set(int ConfigID, sol::object NewValue);
|
void Set(int ConfigID, sol::object NewValue);
|
||||||
TLuaValue Get(int ConfigID);
|
TLuaValue Get(int ConfigID);
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ private:
|
|||||||
void Command_Version(const std::string& cmd, const std::vector<std::string>& args);
|
void Command_Version(const std::string& cmd, const std::vector<std::string>& args);
|
||||||
void Command_ProtectMod(const std::string& cmd, const std::vector<std::string>& args);
|
void Command_ProtectMod(const std::string& cmd, const std::vector<std::string>& args);
|
||||||
void Command_ReloadMods(const std::string& cmd, const std::vector<std::string>& args);
|
void Command_ReloadMods(const std::string& cmd, const std::vector<std::string>& args);
|
||||||
|
void Command_NetTest(const std::string& cmd, const std::vector<std::string>& args);
|
||||||
|
|
||||||
void Command_Say(const std::string& FullCommand);
|
void Command_Say(const std::string& FullCommand);
|
||||||
bool EnsureArgsCount(const std::vector<std::string>& args, size_t n);
|
bool EnsureArgsCount(const std::vector<std::string>& args, size_t n);
|
||||||
@@ -81,6 +82,7 @@ private:
|
|||||||
{ "version", [this](const auto& a, const auto& b) { Command_Version(a, b); } },
|
{ "version", [this](const auto& a, const auto& b) { Command_Version(a, b); } },
|
||||||
{ "protectmod", [this](const auto& a, const auto& b) { Command_ProtectMod(a, b); } },
|
{ "protectmod", [this](const auto& a, const auto& b) { Command_ProtectMod(a, b); } },
|
||||||
{ "reloadmods", [this](const auto& a, const auto& b) { Command_ReloadMods(a, b); } },
|
{ "reloadmods", [this](const auto& a, const auto& b) { Command_ReloadMods(a, b); } },
|
||||||
|
{ "nettest", [this](const auto& a, const auto& b) { Command_NetTest(a, b); } },
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Commandline> mCommandline { nullptr };
|
std::unique_ptr<Commandline> mCommandline { nullptr };
|
||||||
|
|||||||
@@ -192,9 +192,7 @@ public:
|
|||||||
for (const auto& Event : mLuaEvents.at(EventName)) {
|
for (const auto& Event : mLuaEvents.at(EventName)) {
|
||||||
for (const auto& Function : Event.second) {
|
for (const auto& Function : Event.second) {
|
||||||
if (Event.first != IgnoreId) {
|
if (Event.first != IgnoreId) {
|
||||||
auto Result = EnqueueFunctionCall(Event.first, Function, Arguments, EventName);
|
Results.push_back(EnqueueFunctionCall(Event.first, Function, Arguments, EventName));
|
||||||
Results.push_back(Result);
|
|
||||||
AddResultToCheck(Result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -44,7 +44,7 @@ public:
|
|||||||
void ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
|
void ForEachClient(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
|
||||||
size_t ClientCount() const;
|
size_t ClientCount() const;
|
||||||
|
|
||||||
void GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TPPSMonitor& PPSMonitor, TNetwork& Network);
|
void GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TPPSMonitor& PPSMonitor, TNetwork& Network, bool udp);
|
||||||
static void HandleEvent(TClient& c, const std::string& Data);
|
static void HandleEvent(TClient& c, const std::string& Data);
|
||||||
RWMutex& GetClientMutex() const { return mClientsMutex; }
|
RWMutex& GetClientMutex() const { return mClientsMutex; }
|
||||||
|
|
||||||
|
|||||||
@@ -18,11 +18,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class TVehicleData final {
|
class TVehicleData final {
|
||||||
public:
|
public:
|
||||||
TVehicleData(int ID, std::string Data);
|
TVehicleData(int ID, nlohmann::json Data);
|
||||||
~TVehicleData();
|
~TVehicleData();
|
||||||
// We cannot delete this, since vector needs to be able to copy when it resizes.
|
// We cannot delete this, since vector needs to be able to copy when it resizes.
|
||||||
// Deleting this causes some wacky template errors which are hard to decipher,
|
// Deleting this causes some wacky template errors which are hard to decipher,
|
||||||
@@ -32,14 +33,16 @@ public:
|
|||||||
[[nodiscard]] bool IsInvalid() const { return mID == -1; }
|
[[nodiscard]] bool IsInvalid() const { return mID == -1; }
|
||||||
[[nodiscard]] int ID() const { return mID; }
|
[[nodiscard]] int ID() const { return mID; }
|
||||||
|
|
||||||
[[nodiscard]] std::string Data() const { return mData; }
|
[[nodiscard]] nlohmann::json Data() const { return mData; }
|
||||||
void SetData(const std::string& Data) { mData = Data; }
|
[[nodiscard]] std::string DataAsPacket(const std::string& Role, const std::string& Name, int ID) const;
|
||||||
|
|
||||||
|
void SetData(const nlohmann::json& Data) { mData = Data; }
|
||||||
|
|
||||||
bool operator==(const TVehicleData& v) const { return mID == v.mID; }
|
bool operator==(const TVehicleData& v) const { return mID == v.mID; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mID { -1 };
|
int mID { -1 };
|
||||||
std::string mData;
|
nlohmann::json mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: unused now, remove?
|
// TODO: unused now, remove?
|
||||||
|
|||||||
+4
-4
@@ -57,7 +57,7 @@ int TClient::GetOpenCarID() const {
|
|||||||
return OpenID;
|
return OpenID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TClient::AddNewCar(int Ident, const std::string& Data) {
|
void TClient::AddNewCar(int Ident, const nlohmann::json& Data) {
|
||||||
std::unique_lock lock(mVehicleDataMutex);
|
std::unique_lock lock(mVehicleDataMutex);
|
||||||
mVehicleData.emplace_back(Ident, Data);
|
mVehicleData.emplace_back(Ident, Data);
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ void TClient::SetCarPosition(int Ident, const std::string& Data) {
|
|||||||
mVehiclePosition[size_t(Ident)] = Data;
|
mVehiclePosition[size_t(Ident)] = Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TClient::GetCarData(int Ident) {
|
nlohmann::json TClient::GetCarData(int Ident) {
|
||||||
{ // lock
|
{ // lock
|
||||||
std::unique_lock lock(mVehicleDataMutex);
|
std::unique_lock lock(mVehicleDataMutex);
|
||||||
for (auto& v : mVehicleData) {
|
for (auto& v : mVehicleData) {
|
||||||
@@ -108,10 +108,10 @@ std::string TClient::GetCarData(int Ident) {
|
|||||||
}
|
}
|
||||||
} // unlock
|
} // unlock
|
||||||
DeleteCar(Ident);
|
DeleteCar(Ident);
|
||||||
return "";
|
return nlohmann::detail::value_t::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TClient::SetCarData(int Ident, const std::string& Data) {
|
void TClient::SetCarData(int Ident, const nlohmann::json& Data) {
|
||||||
{ // lock
|
{ // lock
|
||||||
std::unique_lock lock(mVehicleDataMutex);
|
std::unique_lock lock(mVehicleDataMutex);
|
||||||
for (auto& v : mVehicleData) {
|
for (auto& v : mVehicleData) {
|
||||||
|
|||||||
+43
-1
@@ -241,6 +241,48 @@ std::pair<bool, std::string> LuaAPI::MP::SendNotification(int ID, const std::str
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, std::string> LuaAPI::MP::ConfirmationDialog(int ID, const std::string& Title, const std::string& Body, const sol::table& buttons, const std::string& InteractionID, const bool& warning, const bool& reportToServer, const bool& reportToExtensions) {
|
||||||
|
std::pair<bool, std::string> Result;
|
||||||
|
|
||||||
|
const nlohmann::json PacketBody = {
|
||||||
|
{ "title", Title },
|
||||||
|
{ "body", Body },
|
||||||
|
{ "buttons", nlohmann::json::parse(JsonEncode(buttons), nullptr, false) },
|
||||||
|
{ "interactionID", InteractionID },
|
||||||
|
{ "class", warning ? "experimental" : "" },
|
||||||
|
{ "reportToServer", reportToServer },
|
||||||
|
{ "reportToExtensions", reportToExtensions }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string Packet = "D" + PacketBody.dump();
|
||||||
|
if (ID == -1) {
|
||||||
|
Engine->Network().SendToAll(nullptr, StringToVector(Packet), true, true);
|
||||||
|
Result.first = true;
|
||||||
|
} else {
|
||||||
|
auto MaybeClient = GetClient(Engine->Server(), ID);
|
||||||
|
if (MaybeClient) {
|
||||||
|
auto c = MaybeClient.value().lock();
|
||||||
|
if (!c->IsSynced()) {
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Player is not synced yet";
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
if (!Engine->Network().Respond(*c, StringToVector(Packet), true)) {
|
||||||
|
beammp_errorf("Failed to send confirmation dialog to player (id {}) - did the player disconnect?", ID);
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Failed to send packet";
|
||||||
|
}
|
||||||
|
Result.first = true;
|
||||||
|
} else {
|
||||||
|
beammp_lua_error("ConfirmationDialog invalid argument [1] invalid ID");
|
||||||
|
Result.first = false;
|
||||||
|
Result.second = "Invalid Player ID";
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<bool, std::string> LuaAPI::MP::RemoveVehicle(int PID, int VID) {
|
std::pair<bool, std::string> LuaAPI::MP::RemoveVehicle(int PID, int VID) {
|
||||||
std::pair<bool, std::string> Result;
|
std::pair<bool, std::string> Result;
|
||||||
auto MaybeClient = GetClient(Engine->Server(), PID);
|
auto MaybeClient = GetClient(Engine->Server(), PID);
|
||||||
@@ -251,7 +293,7 @@ std::pair<bool, std::string> LuaAPI::MP::RemoveVehicle(int PID, int VID) {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
auto c = MaybeClient.value().lock();
|
auto c = MaybeClient.value().lock();
|
||||||
if (!c->GetCarData(VID).empty()) {
|
if (c->GetCarData(VID) != nlohmann::detail::value_t::null) {
|
||||||
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
std::string Destroy = "Od:" + std::to_string(PID) + "-" + std::to_string(VID);
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", PID, VID));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehicleDeleted", "", PID, VID));
|
||||||
Engine->Network().SendToAll(nullptr, StringToVector(Destroy), true, true);
|
Engine->Network().SendToAll(nullptr, StringToVector(Destroy), true, true);
|
||||||
|
|||||||
+30
-6
@@ -24,6 +24,7 @@
|
|||||||
#include "CustomAssert.h"
|
#include "CustomAssert.h"
|
||||||
#include "LuaAPI.h"
|
#include "LuaAPI.h"
|
||||||
#include "TLuaEngine.h"
|
#include "TLuaEngine.h"
|
||||||
|
#include "Http.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <lua.hpp>
|
#include <lua.hpp>
|
||||||
@@ -159,7 +160,7 @@ void TConsole::ChangeToRegularConsole() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TConsole::EnsureArgsCount(const std::vector<std::string>& args, size_t n) {
|
bool TConsole::EnsureArgsCount(const std::vector<std::string>& args, size_t n) {
|
||||||
if (n == 0 && args.size() != 0) {
|
if (n == 0 && !args.empty()) {
|
||||||
Application::Console().WriteRaw("This command expects no arguments.");
|
Application::Console().WriteRaw("This command expects no arguments.");
|
||||||
return false;
|
return false;
|
||||||
} else if (args.size() != n) {
|
} else if (args.size() != n) {
|
||||||
@@ -197,7 +198,7 @@ void TConsole::Command_Lua(const std::string&, const std::vector<std::string>& a
|
|||||||
} else {
|
} else {
|
||||||
Application::Console().WriteRaw("Lua state '" + NewStateId + "' is not a known state. Didn't switch to Lua.");
|
Application::Console().WriteRaw("Lua state '" + NewStateId + "' is not a known state. Didn't switch to Lua.");
|
||||||
}
|
}
|
||||||
} else if (args.size() == 0) {
|
} else if (args.empty()) {
|
||||||
ChangeToLuaConsole(mDefaultStateId);
|
ChangeToLuaConsole(mDefaultStateId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,8 +260,7 @@ void TConsole::Command_Version(const std::string& cmd, const std::vector<std::st
|
|||||||
|
|
||||||
Application::Console().WriteRaw("Platform: " + platform);
|
Application::Console().WriteRaw("Platform: " + platform);
|
||||||
Application::Console().WriteRaw("Server: v" + Application::ServerVersionString());
|
Application::Console().WriteRaw("Server: v" + Application::ServerVersionString());
|
||||||
std::string lua_version = fmt::format("Lua: v{}.{}.{}", LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
|
Application::Console().WriteRaw(LUA_RELEASE);
|
||||||
Application::Console().WriteRaw(lua_version);
|
|
||||||
std::string openssl_version = fmt::format("OpenSSL: v{}.{}.{}", OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH);
|
std::string openssl_version = fmt::format("OpenSSL: v{}.{}.{}", OPENSSL_VERSION_MAJOR, OPENSSL_VERSION_MINOR, OPENSSL_VERSION_PATCH);
|
||||||
Application::Console().WriteRaw(openssl_version);
|
Application::Console().WriteRaw(openssl_version);
|
||||||
}
|
}
|
||||||
@@ -291,6 +291,30 @@ void TConsole::Command_ReloadMods(const std::string& cmd, const std::vector<std:
|
|||||||
Application::Console().WriteRaw("Mods reloaded.");
|
Application::Console().WriteRaw("Mods reloaded.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TConsole::Command_NetTest(const std::string& cmd, const std::vector<std::string>& args) {
|
||||||
|
unsigned int status = 0;
|
||||||
|
|
||||||
|
std::string T = Http::GET(
|
||||||
|
Application::GetServerCheckUrl() + "/api/v2/beammp/" + std::to_string(Application::Settings.getAsInt(Settings::Key::General_Port)), &status
|
||||||
|
);
|
||||||
|
|
||||||
|
beammp_debugf("Status and response from Server Check API: {0}, {1}", status, T);
|
||||||
|
|
||||||
|
auto Doc = nlohmann::json::parse(T, nullptr, false);
|
||||||
|
|
||||||
|
if (Doc.is_discarded() || !Doc.is_object()) {
|
||||||
|
beammp_warn("Failed to parse Server Check API response, however the server will most likely still work correctly.");
|
||||||
|
} else {
|
||||||
|
std::string status = Doc["status"];
|
||||||
|
std::string details = "Response from Server Check API: " + std::string(Doc["details"]);
|
||||||
|
if (status == "ok") {
|
||||||
|
beammp_info(details);
|
||||||
|
} else {
|
||||||
|
beammp_warn(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TConsole::Command_Kick(const std::string&, const std::vector<std::string>& args) {
|
void TConsole::Command_Kick(const std::string&, const std::vector<std::string>& args) {
|
||||||
if (!EnsureArgsCount(args, 1, size_t(-1))) {
|
if (!EnsureArgsCount(args, 1, size_t(-1))) {
|
||||||
return;
|
return;
|
||||||
@@ -398,7 +422,7 @@ void TConsole::Command_Settings(const std::string&, const std::vector<std::strin
|
|||||||
settings set <category> <setting> <value> sets specified setting to value
|
settings set <category> <setting> <value> sets specified setting to value
|
||||||
)";
|
)";
|
||||||
|
|
||||||
if (args.size() == 0) {
|
if (args.empty()) {
|
||||||
beammp_errorf("No arguments specified for command 'settings'!");
|
beammp_errorf("No arguments specified for command 'settings'!");
|
||||||
Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString));
|
Application::Console().WriteRaw("BeamMP-Server Console: " + std::string(sHelpString));
|
||||||
return;
|
return;
|
||||||
@@ -680,7 +704,7 @@ void TConsole::RunAsCommand(const std::string& cmd, bool IgnoreNotACommand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (NonNilFutures.size() == 0) {
|
if (NonNilFutures.empty()) {
|
||||||
if (!IgnoreNotACommand) {
|
if (!IgnoreNotACommand) {
|
||||||
Application::Console().WriteRaw("Error: Unknown command: '" + cmd + "'. Type 'help' to see a list of valid commands.");
|
Application::Console().WriteRaw("Error: Unknown command: '" + cmd + "'. Type 'help' to see a list of valid commands.");
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-29
@@ -30,16 +30,12 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <optional>
|
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <sol/stack_core.hpp>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
TLuaEngine* LuaAPI::MP::Engine;
|
TLuaEngine* LuaAPI::MP::Engine;
|
||||||
|
|
||||||
static sol::protected_function AddTraceback(sol::state_view StateView, sol::protected_function RawFn);
|
|
||||||
|
|
||||||
TLuaEngine::TLuaEngine()
|
TLuaEngine::TLuaEngine()
|
||||||
: mResourceServerPath(fs::path(Application::Settings.getAsString(Settings::Key::General_ResourceFolder)) / "Server") {
|
: mResourceServerPath(fs::path(Application::Settings.getAsString(Settings::Key::General_ResourceFolder)) / "Server") {
|
||||||
Application::SetSubsystemStatus("LuaEngine", Application::Status::Starting);
|
Application::SetSubsystemStatus("LuaEngine", Application::Status::Starting);
|
||||||
@@ -69,7 +65,7 @@ TEST_CASE("TLuaEngine ctor & dtor") {
|
|||||||
void TLuaEngine::operator()() {
|
void TLuaEngine::operator()() {
|
||||||
RegisterThread("LuaEngine");
|
RegisterThread("LuaEngine");
|
||||||
// lua engine main thread
|
// lua engine main thread
|
||||||
beammp_infof("Lua v{}.{}.{}", LUA_VERSION_MAJOR, LUA_VERSION_MINOR, LUA_VERSION_RELEASE);
|
beammp_infof(LUA_RELEASE);
|
||||||
CollectAndInitPlugins();
|
CollectAndInitPlugins();
|
||||||
|
|
||||||
Application::SetSubsystemStatus("LuaEngine", Application::Status::Good);
|
Application::SetSubsystemStatus("LuaEngine", Application::Status::Good);
|
||||||
@@ -131,7 +127,7 @@ void TLuaEngine::operator()() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mLuaStates.size() == 0) {
|
if (mLuaStates.empty()) {
|
||||||
beammp_trace("No Lua states, event loop running extremely sparsely");
|
beammp_trace("No Lua states, event loop running extremely sparsely");
|
||||||
Application::SleepSafeSeconds(10);
|
Application::SleepSafeSeconds(10);
|
||||||
} else {
|
} else {
|
||||||
@@ -496,7 +492,6 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string
|
|||||||
sol::variadic_results LocalArgs = JsonStringToArray(Str);
|
sol::variadic_results LocalArgs = JsonStringToArray(Str);
|
||||||
for (const auto& Handler : MyHandlers) {
|
for (const auto& Handler : MyHandlers) {
|
||||||
auto Fn = mStateView[Handler];
|
auto Fn = mStateView[Handler];
|
||||||
Fn = AddTraceback(mStateView, Fn);
|
|
||||||
if (Fn.valid()) {
|
if (Fn.valid()) {
|
||||||
auto LuaResult = Fn(LocalArgs);
|
auto LuaResult = Fn(LocalArgs);
|
||||||
auto Result = std::make_shared<TLuaResult>();
|
auto Result = std::make_shared<TLuaResult>();
|
||||||
@@ -505,9 +500,7 @@ sol::table TLuaEngine::StateThreadData::Lua_TriggerGlobalEvent(const std::string
|
|||||||
Result->Result = LuaResult;
|
Result->Result = LuaResult;
|
||||||
} else {
|
} else {
|
||||||
Result->Error = true;
|
Result->Error = true;
|
||||||
sol::error Err = LuaResult;
|
Result->ErrorMessage = "Function result in TriggerGlobalEvent was invalid";
|
||||||
Result->ErrorMessage = Err.what();
|
|
||||||
beammp_errorf("An error occured while executing local event handler \"{}\" for event \"{}\": {}", Handler, EventName, Result->ErrorMessage);
|
|
||||||
}
|
}
|
||||||
Result->MarkAsReady();
|
Result->MarkAsReady();
|
||||||
Return.push_back(Result);
|
Return.push_back(Result);
|
||||||
@@ -668,7 +661,7 @@ sol::table TLuaEngine::StateThreadData::Lua_GetPlayerVehicles(int ID) {
|
|||||||
sol::state_view StateView(mState);
|
sol::state_view StateView(mState);
|
||||||
sol::table Result = StateView.create_table();
|
sol::table Result = StateView.create_table();
|
||||||
for (const auto& v : VehicleData) {
|
for (const auto& v : VehicleData) {
|
||||||
Result[v.ID()] = v.Data().substr(3);
|
Result[v.ID()] = v.DataAsPacket(Client->GetRoles(), Client->GetName(), Client->GetID()).substr(3);
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
} else
|
} else
|
||||||
@@ -876,6 +869,12 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, TLuaStateI
|
|||||||
beammp_lua_error("SendNotification expects 2, 3 or 4 arguments.");
|
beammp_lua_error("SendNotification expects 2, 3 or 4 arguments.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
MPTable.set_function("ConfirmationDialog", sol::overload(
|
||||||
|
&LuaAPI::MP::ConfirmationDialog,
|
||||||
|
[&](const int& ID, const std::string& Title, const std::string& Body, const sol::table& Buttons, const std::string& InteractionID) {
|
||||||
|
LuaAPI::MP::ConfirmationDialog(ID, Title, Body, Buttons, InteractionID);
|
||||||
|
}
|
||||||
|
));
|
||||||
MPTable.set_function("GetPlayers", [&]() -> sol::table {
|
MPTable.set_function("GetPlayers", [&]() -> sol::table {
|
||||||
return Lua_GetPlayers();
|
return Lua_GetPlayers();
|
||||||
});
|
});
|
||||||
@@ -1083,21 +1082,6 @@ void TLuaEngine::StateThreadData::RegisterEvent(const std::string& EventName, co
|
|||||||
mEngine->RegisterEvent(EventName, mStateId, FunctionName);
|
mEngine->RegisterEvent(EventName, mStateId, FunctionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sol::protected_function AddTraceback(sol::state_view StateView, sol::protected_function RawFn) {
|
|
||||||
StateView["INTERNAL_ERROR_HANDLER"] = [](lua_State *L) {
|
|
||||||
auto Error = sol::stack::get<std::optional<std::string>>(L);
|
|
||||||
std::string ErrorString = "<Unknown error>";
|
|
||||||
if (Error.has_value()) {
|
|
||||||
ErrorString = Error.value();
|
|
||||||
}
|
|
||||||
auto DebugTracebackFn = sol::state_view(L).globals().get<sol::table>("debug").get<sol::protected_function>("traceback");
|
|
||||||
// 2 = start collecting the trace one above the current function (1=current function)
|
|
||||||
std::string Traceback = DebugTracebackFn(ErrorString, 2);
|
|
||||||
return sol::stack::push(L, Traceback);
|
|
||||||
};
|
|
||||||
return sol::protected_function(RawFn, StateView["INTERNAL_ERROR_HANDLER"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TLuaEngine::StateThreadData::operator()() {
|
void TLuaEngine::StateThreadData::operator()() {
|
||||||
RegisterThread("Lua:" + mStateId);
|
RegisterThread("Lua:" + mStateId);
|
||||||
while (!Application::IsShuttingDown()) {
|
while (!Application::IsShuttingDown()) {
|
||||||
@@ -1162,8 +1146,8 @@ void TLuaEngine::StateThreadData::operator()() {
|
|||||||
// TODO: Use TheQueuedFunction.EventName for errors, warnings, etc
|
// TODO: Use TheQueuedFunction.EventName for errors, warnings, etc
|
||||||
Result->StateId = mStateId;
|
Result->StateId = mStateId;
|
||||||
sol::state_view StateView(mState);
|
sol::state_view StateView(mState);
|
||||||
auto RawFn = StateView[FnName];
|
auto Fn = StateView[FnName];
|
||||||
if (RawFn.valid() && RawFn.get_type() == sol::type::function) {
|
if (Fn.valid() && Fn.get_type() == sol::type::function) {
|
||||||
std::vector<sol::object> LuaArgs;
|
std::vector<sol::object> LuaArgs;
|
||||||
for (const auto& Arg : Args) {
|
for (const auto& Arg : Args) {
|
||||||
if (Arg.valueless_by_exception()) {
|
if (Arg.valueless_by_exception()) {
|
||||||
@@ -1198,7 +1182,6 @@ void TLuaEngine::StateThreadData::operator()() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto Fn = AddTraceback(StateView, RawFn);
|
|
||||||
auto Res = Fn(sol::as_args(LuaArgs));
|
auto Res = Fn(sol::as_args(LuaArgs));
|
||||||
if (Res.valid()) {
|
if (Res.valid()) {
|
||||||
Result->Error = false;
|
Result->Error = false;
|
||||||
|
|||||||
+36
-14
@@ -32,6 +32,8 @@
|
|||||||
#include <boost/asio/ip/address_v6.hpp>
|
#include <boost/asio/ip/address_v6.hpp>
|
||||||
#include <boost/asio/ip/v6_only.hpp>
|
#include <boost/asio/ip/v6_only.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/rand.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option;
|
typedef boost::asio::detail::socket_option::integer<SOL_SOCKET, SO_RCVTIMEO> rcv_timeout_option;
|
||||||
@@ -146,23 +148,30 @@ void TNetwork::UDPServerMain() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Client->GetID() == ID) {
|
if (Client->GetID() == ID) {
|
||||||
// not initialized yet
|
if (Client->GetUDPAddr() == ip::udp::endpoint {} && !Client->IsUDPConnected() && !Client->GetMagic().empty()) {
|
||||||
if (Client->GetUDPAddr() == ip::udp::endpoint {} || !Client->IsUDPConnected()) {
|
if (Data.size() != 66) {
|
||||||
// same IP (just a sanity check)
|
beammp_debugf("Invalid size for UDP value. IP: {} ID: {}", remote_client_ep.address().to_string(), ID);
|
||||||
if (remote_client_ep.address() == Client->GetTCPSock().remote_endpoint().address()) {
|
|
||||||
Client->SetUDPAddr(remote_client_ep);
|
|
||||||
Client->SetIsUDPConnected(true);
|
|
||||||
beammp_debugf("UDP connected for client {}", ID);
|
|
||||||
} else {
|
|
||||||
beammp_debugf("Denied initial UDP packet due to IP mismatch");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector Magic(Data.begin() + 2, Data.end());
|
||||||
|
|
||||||
|
if (Magic != Client->GetMagic()) {
|
||||||
|
beammp_debugf("Invalid value for UDP IP: {} ID: {}", remote_client_ep.address().to_string(), ID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Client->SetMagic({});
|
||||||
|
Client->SetUDPAddr(remote_client_ep);
|
||||||
|
Client->SetIsUDPConnected(true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Client->GetUDPAddr() == remote_client_ep) {
|
if (Client->GetUDPAddr() == remote_client_ep) {
|
||||||
Data.erase(Data.begin(), Data.begin() + 2);
|
Data.erase(Data.begin(), Data.begin() + 2);
|
||||||
mServer.GlobalParser(ClientPtr, std::move(Data), mPPSMonitor, *this);
|
mServer.GlobalParser(ClientPtr, std::move(Data), mPPSMonitor, *this, true);
|
||||||
} else {
|
} else {
|
||||||
beammp_debugf("Ignored UDP packet due to remote address mismatch");
|
beammp_debugf("Ignored UDP packet for Client {} due to remote address mismatch. Source: {}, Client: {}", ID, remote_client_ep.address().to_string(), Client->GetUDPAddr().address().to_string());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,10 +243,11 @@ void TNetwork::TCPServerMain() {
|
|||||||
ip::tcp::socket ClientSocket = Acceptor.accept(ClientEp, ec);
|
ip::tcp::socket ClientSocket = Acceptor.accept(ClientEp, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
beammp_errorf("Failed to accept() new client: {}", ec.message());
|
beammp_errorf("Failed to accept() new client: {}", ec.message());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
TConnection Conn { std::move(ClientSocket), ClientEp };
|
TConnection Conn { std::move(ClientSocket), ClientEp };
|
||||||
std::thread ID(&TNetwork::Identify, this, std::move(Conn));
|
std::thread ID(&TNetwork::Identify, this, std::move(Conn));
|
||||||
ID.detach(); // TODO: Add to a queue and attempt to join periodically
|
ID.detach();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
beammp_errorf("Exception in accept routine: {}", e.what());
|
beammp_errorf("Exception in accept routine: {}", e.what());
|
||||||
}
|
}
|
||||||
@@ -660,7 +670,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
|
|||||||
Client->Disconnect("TCPRcv failed");
|
Client->Disconnect("TCPRcv failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this);
|
mServer.GlobalParser(c, std::move(res), mPPSMonitor, *this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QueueSync.joinable())
|
if (QueueSync.joinable())
|
||||||
@@ -751,6 +761,18 @@ void TNetwork::OnConnect(const std::weak_ptr<TClient>& c) {
|
|||||||
SyncResources(*LockedClient);
|
SyncResources(*LockedClient);
|
||||||
if (LockedClient->IsDisconnected())
|
if (LockedClient->IsDisconnected())
|
||||||
return;
|
return;
|
||||||
|
std::vector<unsigned char> buf(64);
|
||||||
|
int ret = RAND_bytes(buf.data(), buf.size());
|
||||||
|
if (ret != 1) {
|
||||||
|
unsigned long error = ERR_get_error();
|
||||||
|
beammp_errorf("RAND_bytes failed with error code {}", error);
|
||||||
|
beammp_assert(ret != 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LockedClient->SetMagic(buf);
|
||||||
|
buf.insert(buf.begin(), 'U');
|
||||||
|
(void)Respond(*LockedClient, buf, true);
|
||||||
(void)Respond(*LockedClient, StringToVector("M" + Application::Settings.getAsString(Settings::Key::General_Map)), true); // Send the Map on connect
|
(void)Respond(*LockedClient, StringToVector("M" + Application::Settings.getAsString(Settings::Key::General_Map)), true); // Send the Map on connect
|
||||||
beammp_info(LockedClient->GetName() + " : Connected");
|
beammp_info(LockedClient->GetName() + " : Connected");
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", "", LockedClient->GetID()));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onPlayerJoining", "", LockedClient->GetID()));
|
||||||
@@ -974,7 +996,7 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
|
|||||||
res = false;
|
res = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
res = Respond(*LockedClient, StringToVector(v.Data()), true, true);
|
res = Respond(*LockedClient, StringToVector(v.DataAsPacket(client->GetRoles(), client->GetName(), client->GetID())), true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+80
-31
@@ -161,7 +161,7 @@ size_t TServer::ClientCount() const {
|
|||||||
return mClients.size();
|
return mClients.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TPPSMonitor& PPSMonitor, TNetwork& Network) {
|
void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TPPSMonitor& PPSMonitor, TNetwork& Network, bool udp) {
|
||||||
constexpr std::string_view ABG = "ABG:";
|
constexpr std::string_view ABG = "ABG:";
|
||||||
if (Packet.size() >= ABG.size() && std::equal(Packet.begin(), Packet.begin() + ABG.size(), ABG.begin(), ABG.end())) {
|
if (Packet.size() >= ABG.size() && std::equal(Packet.begin(), Packet.begin() + ABG.size(), ABG.begin(), ABG.end())) {
|
||||||
Packet.erase(Packet.begin(), Packet.begin() + ABG.size());
|
Packet.erase(Packet.begin(), Packet.begin() + ABG.size());
|
||||||
@@ -195,12 +195,29 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
|
|
||||||
// V to Y
|
// V to Y
|
||||||
if (Code <= 89 && Code >= 86) {
|
if (Code <= 89 && Code >= 86) {
|
||||||
|
int PID = -1;
|
||||||
|
int VID = -1;
|
||||||
|
|
||||||
|
auto pidVidPart = StringPacket.substr(3);
|
||||||
|
auto MaybePidVid = GetPidVid(pidVidPart.substr(0, pidVidPart.find(':')));
|
||||||
|
if (MaybePidVid) {
|
||||||
|
std::tie(PID, VID) = MaybePidVid.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PID == -1 || VID == -1 || PID != LockedClient->GetID()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PPSMonitor.IncrementInternalPPS();
|
PPSMonitor.IncrementInternalPPS();
|
||||||
Network.SendToAll(LockedClient.get(), Packet, false, false);
|
Network.SendToAll(LockedClient.get(), Packet, false, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (Code) {
|
switch (Code) {
|
||||||
case 'H': // initial connection
|
case 'H': // initial connection
|
||||||
|
if (udp) {
|
||||||
|
beammp_debugf("Received 'H' packet over UDP from client '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!Network.SyncClient(Client)) {
|
if (!Network.SyncClient(Client)) {
|
||||||
// TODO handle
|
// TODO handle
|
||||||
}
|
}
|
||||||
@@ -214,12 +231,20 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 'O':
|
case 'O':
|
||||||
|
if (udp) {
|
||||||
|
beammp_debugf("Received 'O' packet over UDP from client '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Packet.size() > 1000) {
|
if (Packet.size() > 1000) {
|
||||||
beammp_debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.size()));
|
beammp_debug(("Received data from: ") + LockedClient->GetName() + (" Size: ") + std::to_string(Packet.size()));
|
||||||
}
|
}
|
||||||
ParseVehicle(*LockedClient, StringPacket, Network);
|
ParseVehicle(*LockedClient, StringPacket, Network);
|
||||||
return;
|
return;
|
||||||
case 'C': {
|
case 'C': {
|
||||||
|
if (udp) {
|
||||||
|
beammp_debugf("Received 'C' packet over UDP from client '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (Packet.size() < 4 || std::find(Packet.begin() + 3, Packet.end(), ':') == Packet.end())
|
if (Packet.size() < 4 || std::find(Packet.begin() + 3, Packet.end(), ':') == Packet.end())
|
||||||
break;
|
break;
|
||||||
const auto PacketAsString = std::string(reinterpret_cast<const char*>(Packet.data()), Packet.size());
|
const auto PacketAsString = std::string(reinterpret_cast<const char*>(Packet.data()), Packet.size());
|
||||||
@@ -232,6 +257,10 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
beammp_debugf("Empty chat message received from '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
beammp_debugf("Empty chat message received from '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (Message.size() > 500) {
|
||||||
|
beammp_debugf("Chat message too long from '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", "", LockedClient->GetID(), LockedClient->GetName(), Message);
|
auto Futures = LuaAPI::MP::Engine->TriggerEvent("onChatMessage", "", LockedClient->GetID(), LockedClient->GetName(), Message);
|
||||||
TLuaEngine::WaitForAll(Futures);
|
TLuaEngine::WaitForAll(Futures);
|
||||||
LogChatMessage(LockedClient->GetName(), LockedClient->GetID(), PacketAsString.substr(PacketAsString.find(':', 3) + 1));
|
LogChatMessage(LockedClient->GetName(), LockedClient->GetID(), PacketAsString.substr(PacketAsString.find(':', 3) + 1));
|
||||||
@@ -250,16 +279,35 @@ void TServer::GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case 'E':
|
case 'E':
|
||||||
|
if (udp) {
|
||||||
|
beammp_debugf("Received 'E' packet over UDP from client '{}' ({}), ignoring it", LockedClient->GetName(), LockedClient->GetID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
HandleEvent(*LockedClient, StringPacket);
|
HandleEvent(*LockedClient, StringPacket);
|
||||||
return;
|
return;
|
||||||
case 'N':
|
case 'N':
|
||||||
Network.SendToAll(LockedClient.get(), Packet, false, true);
|
Network.SendToAll(LockedClient.get(), Packet, false, true);
|
||||||
return;
|
return;
|
||||||
case 'Z': // position packet
|
case 'Z': { // position packet
|
||||||
PPSMonitor.IncrementInternalPPS();
|
PPSMonitor.IncrementInternalPPS();
|
||||||
|
|
||||||
|
int PID = -1;
|
||||||
|
int VID = -1;
|
||||||
|
|
||||||
|
auto pidVidPart = StringPacket.substr(3);
|
||||||
|
auto MaybePidVid = GetPidVid(pidVidPart.substr(0, pidVidPart.find(':')));
|
||||||
|
if (MaybePidVid) {
|
||||||
|
std::tie(PID, VID) = MaybePidVid.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PID == -1 || VID == -1 || PID != LockedClient->GetID()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Network.SendToAll(LockedClient.get(), Packet, false, false);
|
Network.SendToAll(LockedClient.get(), Packet, false, false);
|
||||||
HandlePosition(*LockedClient, StringPacket);
|
HandlePosition(*LockedClient, StringPacket);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -278,6 +326,15 @@ void TServer::HandleEvent(TClient& c, const std::string& RawData) {
|
|||||||
}
|
}
|
||||||
std::string Name = RawData.substr(2, NameDataSep - 2);
|
std::string Name = RawData.substr(2, NameDataSep - 2);
|
||||||
std::string Data = RawData.substr(NameDataSep + 1);
|
std::string Data = RawData.substr(NameDataSep + 1);
|
||||||
|
|
||||||
|
std::vector<std::string> exclude = {"onInit", "onFileChanged","onVehicleDeleted","onConsoleInput","onPlayerAuth","postPlayerAuth", "onPlayerDisconnect",
|
||||||
|
"onPlayerConnecting","onPlayerJoining","onPlayerJoin","onChatMessage","postChatMessage","onVehicleSpawn","postVehicleSpawn","onVehicleEdited", "postVehicleEdited",
|
||||||
|
"onVehicleReset","onVehiclePaintChanged","onShutdown"};
|
||||||
|
|
||||||
|
if (std::ranges::find(exclude, Name) != exclude.end()) {
|
||||||
|
beammp_debugf("Excluded event triggered by client '{}' ({}): '{}', ignoring.", c.GetName(), c.GetID(), Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent(Name, "", c.GetID(), Data));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent(Name, "", c.GetID(), Data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,8 +385,9 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
});
|
});
|
||||||
|
|
||||||
bool SpawnConfirmed = false;
|
bool SpawnConfirmed = false;
|
||||||
if (ShouldSpawn(c, CarJson, CarID) && !ShouldntSpawn) {
|
auto CarJsonDoc = nlohmann::json::parse(CarJson, nullptr, false);
|
||||||
c.AddNewCar(CarID, Packet);
|
if (ShouldSpawn(c, CarJson, CarID) && !ShouldntSpawn && !CarJsonDoc.is_discarded()) {
|
||||||
|
c.AddNewCar(CarID, CarJsonDoc);
|
||||||
Network.SendToAll(nullptr, StringToVector(Packet), true, true);
|
Network.SendToAll(nullptr, StringToVector(Packet), true, true);
|
||||||
SpawnConfirmed = true;
|
SpawnConfirmed = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -446,6 +504,17 @@ void TServer::ParseVehicle(TClient& c, const std::string& Pckt, TNetwork& Networ
|
|||||||
Data = Data.substr(Data.find('['));
|
Data = Data.substr(Data.find('['));
|
||||||
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehiclePaintChanged", "", c.GetID(), VID, Data));
|
LuaAPI::MP::Engine->ReportErrors(LuaAPI::MP::Engine->TriggerEvent("onVehiclePaintChanged", "", c.GetID(), VID, Data));
|
||||||
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
Network.SendToAll(&c, StringToVector(Packet), false, true);
|
||||||
|
|
||||||
|
auto CarData = c.GetCarData(VID);
|
||||||
|
if (CarData == nlohmann::detail::value_t::null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (CarData.contains("vcf") && CarData.at("vcf").is_object())
|
||||||
|
if (CarData.at("vcf").contains("paints") && CarData.at("vcf").at("paints").is_array()) {
|
||||||
|
CarData.at("vcf")["paints"] = nlohmann::json::parse(Data);
|
||||||
|
c.SetCarData(VID, CarData);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -461,42 +530,22 @@ void TServer::Apply(TClient& c, int VID, const std::string& pckt) {
|
|||||||
beammp_error("Malformed packet received, no '{' found");
|
beammp_error("Malformed packet received, no '{' found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Packet = pckt.substr(FoundPos);
|
std::string Packet = pckt.substr(FoundPos);
|
||||||
std::string VD = c.GetCarData(VID);
|
nlohmann::json VD = c.GetCarData(VID);
|
||||||
if (VD.empty()) {
|
if (VD == nlohmann::detail::value_t::null) {
|
||||||
beammp_error("Tried to apply change to vehicle that does not exist");
|
beammp_error("Tried to apply change to vehicle that does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string Header = VD.substr(0, VD.find('{'));
|
|
||||||
|
|
||||||
FoundPos = VD.find('{');
|
nlohmann::json Pack = nlohmann::json::parse(Packet, nullptr, false);
|
||||||
if (FoundPos == std::string::npos) {
|
|
||||||
return;
|
if (Pack.is_discarded()) {
|
||||||
}
|
|
||||||
VD = VD.substr(FoundPos);
|
|
||||||
rapidjson::Document Veh, Pack;
|
|
||||||
Veh.Parse(VD.c_str());
|
|
||||||
if (Veh.HasParseError()) {
|
|
||||||
beammp_error("Could not get vehicle config!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Pack.Parse(Packet.c_str());
|
|
||||||
if (Pack.HasParseError() || Pack.IsNull()) {
|
|
||||||
beammp_error("Could not get active vehicle config!");
|
beammp_error("Could not get active vehicle config!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& M : Pack.GetObject()) {
|
c.SetCarData(VID, Pack);
|
||||||
if (Veh[M.name].IsNull()) {
|
|
||||||
Veh.AddMember(M.name, M.value, Veh.GetAllocator());
|
|
||||||
} else {
|
|
||||||
Veh[M.name] = Pack[M.name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rapidjson::StringBuffer Buffer;
|
|
||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(Buffer);
|
|
||||||
Veh.Accept(writer);
|
|
||||||
c.SetCarData(VID, Header + Buffer.GetString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TServer::InsertClient(const std::shared_ptr<TClient>& NewClient) {
|
void TServer::InsertClient(const std::shared_ptr<TClient>& NewClient) {
|
||||||
|
|||||||
+5
-1
@@ -21,7 +21,7 @@
|
|||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
TVehicleData::TVehicleData(int ID, std::string Data)
|
TVehicleData::TVehicleData(int ID, nlohmann::json Data)
|
||||||
: mID(ID)
|
: mID(ID)
|
||||||
, mData(std::move(Data)) {
|
, mData(std::move(Data)) {
|
||||||
beammp_trace("vehicle " + std::to_string(mID) + " constructed");
|
beammp_trace("vehicle " + std::to_string(mID) + " constructed");
|
||||||
@@ -30,3 +30,7 @@ TVehicleData::TVehicleData(int ID, std::string Data)
|
|||||||
TVehicleData::~TVehicleData() {
|
TVehicleData::~TVehicleData() {
|
||||||
beammp_trace("vehicle " + std::to_string(mID) + " destroyed");
|
beammp_trace("vehicle " + std::to_string(mID) + " destroyed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string TVehicleData::DataAsPacket(const std::string& Role, const std::string& Name, const int ID) const {
|
||||||
|
return "Os:" + Role + ":" + Name + ":" + std::to_string(ID) + "-" + std::to_string(this->mID) + ":" + this->mData.dump();
|
||||||
|
}
|
||||||
+1
-1
Submodule vcpkg updated: 6978381401...5bf0c55239
+10
-2
@@ -14,6 +14,14 @@
|
|||||||
"openssl",
|
"openssl",
|
||||||
"rapidjson",
|
"rapidjson",
|
||||||
"sol2",
|
"sol2",
|
||||||
"curl"
|
"curl",
|
||||||
]
|
"luajit"
|
||||||
|
],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"name": "sol2",
|
||||||
|
"version": "3.3.1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"builtin-baseline": "5bf0c55239da398b8c6f450818c9e28d36bf9966"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user