Fix compile issue with asio, implement Lua events

This commit is contained in:
Lion Kortlepel 2021-09-16 13:03:00 +02:00
parent ebe3630ec8
commit 26231c6272
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
5 changed files with 73 additions and 18 deletions

View File

@ -1,6 +1,13 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
project(Server) project(Server)
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")
if (WIN32) if (WIN32)
message(STATUS "MSVC -> forcing use of statically-linked runtime.") message(STATUS "MSVC -> forcing use of statically-linked runtime.")
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE}) STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
@ -46,14 +53,6 @@ add_executable(BeamMP-Server
include/TNetwork.h src/TNetwork.cpp include/TNetwork.h src/TNetwork.cpp
include/LuaAPI.h src/LuaAPI.cpp) include/LuaAPI.h src/LuaAPI.cpp)
include_directories("${PROJECT_SOURCE_DIR}/deps/asio/asio/include")
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")
include_directories(BeamMP-Server PUBLIC ${Boost_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(BeamMP-Server PUBLIC ${Boost_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/include)
find_package(Lua REQUIRED) find_package(Lua REQUIRED)

7
deps/CMakeLists.txt vendored
View File

@ -1,3 +1,10 @@
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")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/socket.io-client-cpp") add_subdirectory("${PROJECT_SOURCE_DIR}/deps/socket.io-client-cpp")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/commandline") add_subdirectory("${PROJECT_SOURCE_DIR}/deps/commandline")
add_subdirectory("${PROJECT_SOURCE_DIR}/deps/sol2") add_subdirectory("${PROJECT_SOURCE_DIR}/deps/sol2")

View File

@ -11,6 +11,7 @@
#include <toml11/toml.hpp> #include <toml11/toml.hpp>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include <set>
#define SOL_ALL_SAFETIES_ON 1 #define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp> #include <sol/sol.hpp>
@ -44,6 +45,8 @@ public:
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(TLuaStateId StateID, const std::shared_ptr<std::string>& Script);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName);
void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false); void EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit = false);
void RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName);
[[nodiscard]] std::vector<std::shared_ptr<TLuaResult>> TriggerEvent(const std::string& EventName);
static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND"; static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND";
@ -54,10 +57,11 @@ private:
class StateThreadData : IThreaded { class StateThreadData : IThreaded {
public: public:
StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId); StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine);
StateThreadData(const StateThreadData&) = delete; StateThreadData(const StateThreadData&) = delete;
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(const std::shared_ptr<std::string>& Script); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueScript(const std::shared_ptr<std::string>& Script);
[[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const std::string& FunctionName); [[nodiscard]] std::shared_ptr<TLuaResult> EnqueueFunctionCall(const std::string& FunctionName);
void RegisterEvent(const std::string& EventName, const std::string& FunctionName);
void operator()() override; void operator()() override;
private: private:
@ -67,9 +71,10 @@ private:
lua_State* mState; lua_State* mState;
std::thread mThread; std::thread mThread;
std::queue<std::pair<std::shared_ptr<std::string>, std::shared_ptr<TLuaResult>>> mStateExecuteQueue; std::queue<std::pair<std::shared_ptr<std::string>, std::shared_ptr<TLuaResult>>> mStateExecuteQueue;
std::mutex mStateExecuteQueueMutex; std::recursive_mutex mStateExecuteQueueMutex;
std::queue<std::pair<std::string, std::shared_ptr<TLuaResult>>> mStateFunctionQueue; std::queue<std::pair<std::string, std::shared_ptr<TLuaResult>>> mStateFunctionQueue;
std::mutex mStateFunctionQueueMutex; std::recursive_mutex mStateFunctionQueueMutex;
TLuaEngine* mEngine;
}; };
TNetwork& mNetwork; TNetwork& mNetwork;
@ -78,7 +83,9 @@ private:
fs::path mResourceServerPath; fs::path mResourceServerPath;
std::vector<TLuaPlugin*> mLuaPlugins; std::vector<TLuaPlugin*> mLuaPlugins;
std::unordered_map<TLuaStateId, std::unique_ptr<StateThreadData>> mLuaStates; std::unordered_map<TLuaStateId, std::unique_ptr<StateThreadData>> mLuaStates;
std::mutex mLuaStatesMutex; std::recursive_mutex mLuaStatesMutex;
std::unordered_map<std::string /* event name */, std::unordered_map<TLuaStateId, std::set<std::string>>> mEvents;
std::recursive_mutex mEventsMutex;
}; };
#include <any> #include <any>

View File

@ -1,7 +1,7 @@
#include "LuaAPI.h" #include "LuaAPI.h"
#include "TLuaEngine.h" #include "TLuaEngine.h"
static std::string LuaToString(const sol::object& Value) { static std::string LuaToString(const sol::object& Value, size_t Indent = 1) {
switch (Value.get_type()) { switch (Value.get_type()) {
case sol::type::string: case sol::type::string:
return Value.as<std::string>(); return Value.as<std::string>();
@ -15,10 +15,17 @@ static std::string LuaToString(const sol::object& Value) {
Result << "[[table: " << Table.pointer() << "]]: {"; Result << "[[table: " << Table.pointer() << "]]: {";
if (!Table.empty()) { if (!Table.empty()) {
for (const auto& Entry : Table) { for (const auto& Entry : Table) {
Result << "\n\t" << LuaToString(Entry.first) << ": " << LuaToString(Entry.second) << ","; Result << "\n";
for (size_t i = 0; i < Indent; ++i) {
Result << "\t";
}
Result << LuaToString(Entry.first, Indent + 1) << ": " << LuaToString(Entry.second, Indent + 1) << ",";
} }
Result << "\n"; Result << "\n";
} }
for (size_t i = 0; i < Indent - 1; ++i) {
Result << "\t";
}
Result << "}"; Result << "}";
return Result.str(); return Result.str();
} }

View File

@ -93,7 +93,6 @@ void TLuaEngine::FindAndParseConfig(const fs::path& Folder, TLuaPluginConfig& Co
auto ConfigFile = Folder / TLuaPluginConfig::FileName; auto ConfigFile = Folder / TLuaPluginConfig::FileName;
if (fs::exists(ConfigFile) && fs::is_regular_file(ConfigFile)) { if (fs::exists(ConfigFile) && fs::is_regular_file(ConfigFile)) {
beammp_debug("\"" + ConfigFile.string() + "\" found"); beammp_debug("\"" + ConfigFile.string() + "\" found");
// TODO use toml11 here to parse it
try { try {
auto Data = toml::parse(ConfigFile); auto Data = toml::parse(ConfigFile);
if (Data.contains("LuaStateID")) { if (Data.contains("LuaStateID")) {
@ -112,10 +111,12 @@ void TLuaEngine::FindAndParseConfig(const fs::path& Folder, TLuaPluginConfig& Co
} }
void TLuaEngine::EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit) { void TLuaEngine::EnsureStateExists(TLuaStateId StateId, const std::string& Name, bool DontCallOnInit) {
std::unique_lock Lock(mLuaStatesMutex);
if (mLuaStates.find(StateId) == mLuaStates.end()) { if (mLuaStates.find(StateId) == mLuaStates.end()) {
beammp_debug("Creating lua state for state id \"" + StateId + "\""); beammp_debug("Creating lua state for state id \"" + StateId + "\"");
auto DataPtr = std::make_unique<StateThreadData>(Name, mShutdown, StateId); auto DataPtr = std::make_unique<StateThreadData>(Name, mShutdown, StateId, *this);
mLuaStates[StateId] = std::move(DataPtr); mLuaStates[StateId] = std::move(DataPtr);
RegisterEvent("onInit", StateId, "onInit");
if (!DontCallOnInit) { if (!DontCallOnInit) {
auto Res = EnqueueFunctionCall(StateId, "onInit"); auto Res = EnqueueFunctionCall(StateId, "onInit");
Res->WaitUntilReady(); Res->WaitUntilReady();
@ -126,10 +127,27 @@ void TLuaEngine::EnsureStateExists(TLuaStateId StateId, const std::string& Name,
} }
} }
TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId) void TLuaEngine::RegisterEvent(const std::string& EventName, TLuaStateId StateId, const std::string& FunctionName) {
std::unique_lock Lock(mEventsMutex);
mEvents[EventName][StateId].insert(FunctionName);
}
std::vector<std::shared_ptr<TLuaResult>> TLuaEngine::TriggerEvent(const std::string& EventName) {
std::unique_lock Lock(mEventsMutex);
std::vector<std::shared_ptr<TLuaResult>> Results;
for (const auto& Entry : mEvents[EventName]) {
for (const auto& Function : Entry.second) {
Results.emplace_back(EnqueueFunctionCall(Entry.first, Function));
}
}
return Results;
}
TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomic_bool& Shutdown, TLuaStateId StateId, TLuaEngine& Engine)
: mName(Name) : mName(Name)
, mShutdown(Shutdown) , mShutdown(Shutdown)
, mStateId(StateId) { , mStateId(StateId)
, mEngine(&Engine) {
mState = luaL_newstate(); mState = luaL_newstate();
luaL_openlibs(mState); luaL_openlibs(mState);
sol::state_view StateView(mState); sol::state_view StateView(mState);
@ -137,6 +155,19 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi
auto Table = StateView.create_named_table("MP"); auto Table = StateView.create_named_table("MP");
Table.set_function("GetOSName", &LuaAPI::MP::GetOSName); Table.set_function("GetOSName", &LuaAPI::MP::GetOSName);
Table.set_function("GetServerVersion", &LuaAPI::MP::GetServerVersion); Table.set_function("GetServerVersion", &LuaAPI::MP::GetServerVersion);
Table.set_function("RegisterEvent",
[this](const std::string& EventName, const std::string& FunctionName) {
RegisterEvent(EventName, FunctionName);
});
Table.set_function("");
Table.create_named("Settings",
"Debug", 0,
"Private", 1,
"MaxCars", 2,
"MaxPlayers", 3,
"Map", 4,
"Name", 5,
"Description", 6);
Start(); Start();
} }
@ -156,6 +187,10 @@ std::shared_ptr<TLuaResult> TLuaEngine::StateThreadData::EnqueueFunctionCall(con
return Result; return Result;
} }
void TLuaEngine::StateThreadData::RegisterEvent(const std::string& EventName, const std::string& FunctionName) {
mEngine->RegisterEvent(EventName, mStateId, FunctionName);
}
void TLuaEngine::StateThreadData::operator()() { void TLuaEngine::StateThreadData::operator()() {
RegisterThread("Lua:" + mStateId); RegisterThread("Lua:" + mStateId);
while (!mShutdown) { while (!mShutdown) {