From 26231c627254e292b20a161bcd502f19f3f43214 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Thu, 16 Sep 2021 13:03:00 +0200 Subject: [PATCH] Fix compile issue with asio, implement Lua events --- CMakeLists.txt | 15 +++++++-------- deps/CMakeLists.txt | 7 +++++++ include/TLuaEngine.h | 15 +++++++++++---- src/LuaAPI.cpp | 11 +++++++++-- src/TLuaEngine.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- 5 files changed, 73 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b72bdb6..6e49c0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,13 @@ cmake_minimum_required(VERSION 3.0) 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) message(STATUS "MSVC -> forcing use of statically-linked runtime.") 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/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) find_package(Lua REQUIRED) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 06cef70..5504038 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -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/commandline") add_subdirectory("${PROJECT_SOURCE_DIR}/deps/sol2") diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index b80dfc3..ba66fa4 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -11,6 +11,7 @@ #include #include #include +#include #define SOL_ALL_SAFETIES_ON 1 #include @@ -44,6 +45,8 @@ public: [[nodiscard]] std::shared_ptr EnqueueScript(TLuaStateId StateID, const std::shared_ptr& Script); [[nodiscard]] std::shared_ptr EnqueueFunctionCall(TLuaStateId StateID, const std::string& FunctionName); 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> TriggerEvent(const std::string& EventName); static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND"; @@ -54,10 +57,11 @@ private: class StateThreadData : IThreaded { 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; [[nodiscard]] std::shared_ptr EnqueueScript(const std::shared_ptr& Script); [[nodiscard]] std::shared_ptr EnqueueFunctionCall(const std::string& FunctionName); + void RegisterEvent(const std::string& EventName, const std::string& FunctionName); void operator()() override; private: @@ -67,9 +71,10 @@ private: lua_State* mState; std::thread mThread; std::queue, std::shared_ptr>> mStateExecuteQueue; - std::mutex mStateExecuteQueueMutex; + std::recursive_mutex mStateExecuteQueueMutex; std::queue>> mStateFunctionQueue; - std::mutex mStateFunctionQueueMutex; + std::recursive_mutex mStateFunctionQueueMutex; + TLuaEngine* mEngine; }; TNetwork& mNetwork; @@ -78,7 +83,9 @@ private: fs::path mResourceServerPath; std::vector mLuaPlugins; std::unordered_map> mLuaStates; - std::mutex mLuaStatesMutex; + std::recursive_mutex mLuaStatesMutex; + std::unordered_map>> mEvents; + std::recursive_mutex mEventsMutex; }; #include diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index 03a7bdc..5519c2a 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -1,7 +1,7 @@ #include "LuaAPI.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()) { case sol::type::string: return Value.as(); @@ -15,10 +15,17 @@ static std::string LuaToString(const sol::object& Value) { Result << "[[table: " << Table.pointer() << "]]: {"; if (!Table.empty()) { 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"; } + for (size_t i = 0; i < Indent - 1; ++i) { + Result << "\t"; + } Result << "}"; return Result.str(); } diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 94fe614..3acc2cd 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -93,7 +93,6 @@ void TLuaEngine::FindAndParseConfig(const fs::path& Folder, TLuaPluginConfig& Co auto ConfigFile = Folder / TLuaPluginConfig::FileName; if (fs::exists(ConfigFile) && fs::is_regular_file(ConfigFile)) { beammp_debug("\"" + ConfigFile.string() + "\" found"); - // TODO use toml11 here to parse it try { auto Data = toml::parse(ConfigFile); 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) { + std::unique_lock Lock(mLuaStatesMutex); if (mLuaStates.find(StateId) == mLuaStates.end()) { beammp_debug("Creating lua state for state id \"" + StateId + "\""); - auto DataPtr = std::make_unique(Name, mShutdown, StateId); + auto DataPtr = std::make_unique(Name, mShutdown, StateId, *this); mLuaStates[StateId] = std::move(DataPtr); + RegisterEvent("onInit", StateId, "onInit"); if (!DontCallOnInit) { auto Res = EnqueueFunctionCall(StateId, "onInit"); 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> TLuaEngine::TriggerEvent(const std::string& EventName) { + std::unique_lock Lock(mEventsMutex); + std::vector> 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) , mShutdown(Shutdown) - , mStateId(StateId) { + , mStateId(StateId) + , mEngine(&Engine) { mState = luaL_newstate(); luaL_openlibs(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"); Table.set_function("GetOSName", &LuaAPI::MP::GetOSName); 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(); } @@ -156,6 +187,10 @@ std::shared_ptr TLuaEngine::StateThreadData::EnqueueFunctionCall(con return Result; } +void TLuaEngine::StateThreadData::RegisterEvent(const std::string& EventName, const std::string& FunctionName) { + mEngine->RegisterEvent(EventName, mStateId, FunctionName); +} + void TLuaEngine::StateThreadData::operator()() { RegisterThread("Lua:" + mStateId); while (!mShutdown) {