From 27b5c6d8501fdfc18f018298fc671b7320a19755 Mon Sep 17 00:00:00 2001 From: Lion Kortlepel Date: Mon, 20 Sep 2021 22:45:12 +0200 Subject: [PATCH] Add GetFilename, GetExtension, --- include/LuaAPI.h | 2 ++ include/TLuaEngine.h | 18 +++++++++- include/TLuaPlugin.h | 1 + src/LuaAPI.cpp | 8 +++++ src/TLuaEngine.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 110 insertions(+), 2 deletions(-) diff --git a/include/LuaAPI.h b/include/LuaAPI.h index 2ec90c4..f825149 100644 --- a/include/LuaAPI.h +++ b/include/LuaAPI.h @@ -28,6 +28,8 @@ namespace FS { std::pair Remove(const std::string& Path); std::pair Rename(const std::string& Path, const std::string& NewPath); std::pair Copy(const std::string& Path, const std::string& NewPath); + std::string GetFilename(const std::string& Path); + std::string GetExtension(const std::string& Path); bool Exists(const std::string& Path); } } diff --git a/include/TLuaEngine.h b/include/TLuaEngine.h index 9a69113..e6bd085 100644 --- a/include/TLuaEngine.h +++ b/include/TLuaEngine.h @@ -53,6 +53,19 @@ struct TLuaChunk { std::string PluginPath; }; +class TPluginMonitor : IThreaded { +public: + TPluginMonitor(const fs::path& Path, TLuaEngine& Engine, std::atomic_bool& Shutdown); + + void operator()(); + +private: + TLuaEngine& mEngine; + fs::path mPath; + std::atomic_bool& mShutdown; + std::unordered_map mFileTimes; +}; + class TLuaEngine : IThreaded { public: TLuaEngine(); @@ -92,9 +105,11 @@ public: std::set GetEventHandlersForState(const std::string& EventName, TLuaStateId StateId); void CreateEventTimer(const std::string& EventName, TLuaStateId StateId, size_t IntervalMS); void CancelEventTimers(const std::string& EventName, TLuaStateId StateId); + sol::state_view GetStateForPlugin(const fs::path& PluginPath); + TLuaStateId GetStateIDForPlugin(const fs::path& PluginPath); static constexpr const char* BeamMPFnNotFoundError = "BEAMMP_FN_NOT_FOUND"; - + private: void CollectAndInitPlugins(); void InitializePlugin(const fs::path& Folder, const TLuaPluginConfig& Config); @@ -147,6 +162,7 @@ private: TNetwork* mNetwork; TServer* mServer; + TPluginMonitor mPluginMonitor; std::atomic_bool mShutdown { false }; fs::path mResourceServerPath; std::vector mLuaPlugins; diff --git a/include/TLuaPlugin.h b/include/TLuaPlugin.h index a4cb5bd..92d54b9 100644 --- a/include/TLuaPlugin.h +++ b/include/TLuaPlugin.h @@ -8,6 +8,7 @@ public: ~TLuaPlugin() noexcept = default; const TLuaPluginConfig& GetConfig() const { return mConfig; } + fs::path GetFolder() const { return mFolder; } private: TLuaPluginConfig mConfig; diff --git a/src/LuaAPI.cpp b/src/LuaAPI.cpp index af02a59..cfd27cc 100644 --- a/src/LuaAPI.cpp +++ b/src/LuaAPI.cpp @@ -311,3 +311,11 @@ std::pair LuaAPI::FS::Copy(const std::string& Path, const std bool LuaAPI::FS::Exists(const std::string& Path) { return fs::exists(fs::relative(Path)); } + +std::string LuaAPI::FS::GetFilename(const std::string& Path) { + return fs::path(Path).filename().string(); +} + +std::string LuaAPI::FS::GetExtension(const std::string& Path) { + return fs::path(Path).extension().string(); +} diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 6bfadca..bc49d68 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -13,7 +13,8 @@ TLuaEngine* LuaAPI::MP::Engine; -TLuaEngine::TLuaEngine() { +TLuaEngine::TLuaEngine() + : mPluginMonitor(fs::path(Application::Settings.Resource) / "Server", *this, mShutdown) { LuaAPI::MP::Engine = this; if (!fs::exists(Application::Settings.Resource)) { fs::create_directory(Application::Settings.Resource); @@ -111,6 +112,28 @@ size_t TLuaEngine::CalculateMemoryUsage() { return Usage; } +sol::state_view TLuaEngine::GetStateForPlugin(const fs::path& PluginPath) { + for (const auto& Plugin : mLuaPlugins) { + if (fs::equivalent(Plugin->GetFolder(), PluginPath)) { + std::unique_lock Lock(mLuaStatesMutex); + return mLuaStates.at(Plugin->GetConfig().StateId)->State(); + } + } + beammp_assert_not_reachable(); + return mLuaStates.begin()->second->State(); +} + +TLuaStateId TLuaEngine::GetStateIDForPlugin(const fs::path& PluginPath) { + for (const auto& Plugin : mLuaPlugins) { + if (fs::equivalent(Plugin->GetFolder(), PluginPath)) { + std::unique_lock Lock(mLuaStatesMutex); + return Plugin->GetConfig().StateId; + } + } + beammp_assert_not_reachable(); + return ""; +} + void TLuaEngine::WaitForAll(std::vector>& Results) { for (const auto& Result : Results) { while (!Result->Ready) { @@ -432,6 +455,8 @@ TLuaEngine::StateThreadData::StateThreadData(const std::string& Name, std::atomi FSTable.set_function("Remove", &LuaAPI::FS::Remove); FSTable.set_function("Rename", &LuaAPI::FS::Rename); FSTable.set_function("Copy", &LuaAPI::FS::Copy); + FSTable.set_function("GetFilename", &LuaAPI::FS::GetFilename); + FSTable.set_function("GetExtension", &LuaAPI::FS::GetExtension); Start(); } @@ -612,3 +637,59 @@ bool TLuaEngine::TimedEvent::Expired() { void TLuaEngine::TimedEvent::Reset() { LastCompletion = std::chrono::high_resolution_clock::now(); } + +TPluginMonitor::TPluginMonitor(const fs::path& Path, TLuaEngine& Engine, std::atomic_bool& Shutdown) + : mEngine(Engine) + , mPath(Path) + , mShutdown(Shutdown) { + for (const auto& Entry : fs::recursive_directory_iterator(mPath)) { + // TODO: trigger an event when a subfolder file changes + if (Entry.is_regular_file()) { + mFileTimes[Entry.path().string()] = fs::last_write_time(Entry.path()); + } + } + Start(); +} + +void TPluginMonitor::operator()() { + RegisterThread("PluginMonitor"); + beammp_info("PluginMonitor started"); + while (!mShutdown) { + std::this_thread::sleep_for(std::chrono::seconds(3)); + for (const auto& Pair : mFileTimes) { + auto CurrentTime = fs::last_write_time(Pair.first); + if (CurrentTime != Pair.second) { + mFileTimes[Pair.first] = CurrentTime; + if (fs::path(Pair.first)) { + beammp_info("File \"" + Pair.first + "\" changed, reloading"); + // is in root folder, so reload + std::ifstream FileStream(Pair.first, std::ios::in | std::ios::binary); + auto Size = std::filesystem::file_size(Pair.first); + auto Contents = std::make_shared(); + Contents->resize(Size); + FileStream.read(Contents->data(), Contents->size()); + TLuaChunk Chunk(Contents, Pair.first, fs::path(Pair.first).parent_path().string()); + auto StateID = mEngine.GetStateIDForPlugin(fs::path(Pair.first).parent_path()); + auto Res = mEngine.EnqueueScript(StateID, Chunk); + while (!Res->Ready) { + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + if (Res->Error) { + beammp_lua_error(Res->ErrorMessage); + } + } else { + beammp_trace("Change detected in file \"" + Pair.first + "\", event trigger not implemented yet"); + /* + // is in subfolder, dont reload, just trigger an event + auto Results = mEngine.TriggerEvent("onFileChanged", "", Pair.first); + mEngine.WaitForAll(Results); + for (const auto& Result : Results) { + if (Result->Error) { + beammp_lua_error(Result->ErrorMessage); + } + }*/ + } + } + } + } +}