From 4c7e2c8e72eebc657abdcb3f1d78e0ee0e36dc32 Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Wed, 13 Aug 2025 11:49:56 +0600 Subject: [PATCH] * --- Src/Server/AssetsManager.cpp | 27 ++++--- Src/Server/AssetsManager.hpp | 7 +- Src/Server/ContentManager.cpp | 15 ++++ Src/Server/ContentManager.hpp | 62 +++++++++++++++ Src/Server/GameServer.cpp | 145 ++++++++++++++++++++-------------- Src/Server/GameServer.hpp | 2 + 6 files changed, 183 insertions(+), 75 deletions(-) create mode 100644 Src/Server/ContentManager.cpp create mode 100644 Src/Server/ContentManager.hpp diff --git a/Src/Server/AssetsManager.cpp b/Src/Server/AssetsManager.cpp index 0272446..f276dc4 100644 --- a/Src/Server/AssetsManager.cpp +++ b/Src/Server/AssetsManager.cpp @@ -7,14 +7,21 @@ namespace LV::Server { -coro AssetsManager::loadResourceFromFile(EnumAssets type, fs::path path) const { - co_return AssetsManager::Resource(path); +AssetsManager::Resource AssetsManager::loadResourceFromFile(EnumAssets type, fs::path path) const { + return AssetsManager::Resource(path); } -coro AssetsManager::loadResourceFromLua(EnumAssets type, void*) const { - co_return AssetsManager::Resource("assets/null"); +AssetsManager::Resource AssetsManager::loadResourceFromLua(EnumAssets type, void*) const { + return AssetsManager::Resource("assets/null"); } +AssetsManager::AssetsManager(asio::io_context& ioc) +{ + +} + +AssetsManager::~AssetsManager() = default; + std::tuple&> AssetsManager::Local::nextId(EnumAssets type) { auto& table = Table[(int) type]; ResourceId_t id = -1; @@ -45,7 +52,7 @@ std::tuple&> AssetsManager return {id, *data}; } -coro AssetsManager::recheckResources(AssetsRegister info) { +AssetsManager::Out_recheckResources AssetsManager::recheckResources(const AssetsRegister& info) { Out_recheckResources result; // Найти пропавшие ресурсы @@ -124,10 +131,10 @@ coro AssetsManager::recheckResources(Assets continue; else if(iterDomain->second.contains(key)) { // Ресурс уже есть, TODO: нужно проверить его изменение - result.NewOrChange[type][domain].emplace_back(key, co_await loadResourceFromFile((EnumAssets) type, "assets/null"), fs::file_time_type::min()); + result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, "assets/null"), fs::file_time_type::min()); } else { // Ресурс не был известен - result.NewOrChange[type][domain].emplace_back(key, co_await loadResourceFromFile((EnumAssets) type, "assets/null"), fs::file_time_type::min()); + result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, "assets/null"), fs::file_time_type::min()); } findList.insert(key); @@ -184,11 +191,11 @@ coro AssetsManager::recheckResources(Assets fs::file_time_type lwt = fs::last_write_time(file); if(lwt != entry.FileChangeTime) // Будем считать что ресурс изменился - result.NewOrChange[type][domain].emplace_back(key, co_await loadResourceFromFile((EnumAssets) type, file), lwt); + result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, file), lwt); } else { // Ресурс не был известен fs::file_time_type lwt = fs::last_write_time(file); - result.NewOrChange[type][domain].emplace_back(key, co_await loadResourceFromFile((EnumAssets) type, file), lwt); + result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, file), lwt); } findList.insert(key); @@ -198,7 +205,7 @@ coro AssetsManager::recheckResources(Assets } - co_return result; + return result; } AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const Out_recheckResources& orr) { diff --git a/Src/Server/AssetsManager.hpp b/Src/Server/AssetsManager.hpp index df053a0..7e360d4 100644 --- a/Src/Server/AssetsManager.hpp +++ b/Src/Server/AssetsManager.hpp @@ -89,8 +89,8 @@ private: Загрузка ресурса с файла. При необходимости приводится к внутреннему формату и сохраняется в кеше */ - coro loadResourceFromFile(EnumAssets type, fs::path path) const; - coro loadResourceFromLua(EnumAssets type, void*) const; + Resource loadResourceFromFile(EnumAssets type, fs::path path) const; + Resource loadResourceFromLua(EnumAssets type, void*) const; public: AssetsManager(asio::io_context& ioc); @@ -126,7 +126,7 @@ public: std::unordered_map>> NewOrChange[(int) EnumAssets::MAX_ENUM]; }; - coro recheckResources(AssetsRegister); + Out_recheckResources recheckResources(const AssetsRegister&); /* Применяет расчитанные изменения. @@ -139,7 +139,6 @@ public: Out_applyResourceChange applyResourceChange(const Out_recheckResources& orr); - /* Выдаёт идентификатор ресурса, даже если он не существует или был удалён. resource должен содержать домен и путь diff --git a/Src/Server/ContentManager.cpp b/Src/Server/ContentManager.cpp new file mode 100644 index 0000000..cb80af8 --- /dev/null +++ b/Src/Server/ContentManager.cpp @@ -0,0 +1,15 @@ +#include "ContentManager.hpp" + +namespace LV::Server { + + +ContentManager::ContentManager(asio::io_context& ioc) +{ + +} + +ContentManager::~ContentManager() = default; + + + +} \ No newline at end of file diff --git a/Src/Server/ContentManager.hpp b/Src/Server/ContentManager.hpp new file mode 100644 index 0000000..868a88f --- /dev/null +++ b/Src/Server/ContentManager.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include "Server/Abstract.hpp" + + +namespace LV::Server { + +struct DefVoxel { + +}; + +struct DefNode { + +}; + +struct DefWorld { + +}; + +struct DefPortal { + +}; + +struct DefEntity { + +}; + +struct DefItem { + +}; + +class ContentManager { + // Профили зарегистрированные модами + + // Изменения, накладываемые на профили + + // Следующие идентификаторы регистрации контента + ResourceId_t NextId[(int) EnumDefContent::MAX_ENUM] = {0}; + // Домен -> {ключ -> идентификатор} + std::unordered_map> ContentKeyToId[(int) EnumDefContent::MAX_ENUM]; + + template + struct TableEntry { + static constexpr size_t ChunkSize = 4096; + std::array, ChunkSize> Entries; + }; + + // Конечные профили контента + std::vector>> Profiles_Voxel; + std::vector>> Profiles_Node; + std::vector>> Profiles_World; + std::vector>> Profiles_Portal; + std::vector>> Profiles_Entity; + std::vector>> Profiles_Item; + +public: + ContentManager(asio::io_context& ioc); + ~ContentManager(); + +}; + +} \ No newline at end of file diff --git a/Src/Server/GameServer.cpp b/Src/Server/GameServer.cpp index c04e612..fc68c3f 100644 --- a/Src/Server/GameServer.cpp +++ b/Src/Server/GameServer.cpp @@ -3,6 +3,7 @@ #include "Common/Net.hpp" #include "Common/Packets.hpp" #include "Server/Abstract.hpp" +#include "Server/AssetsManager.hpp" #include "Server/ContentEventController.hpp" #include #include @@ -1407,15 +1408,6 @@ void GameServer::init(fs::path worldPath) { LOG.info() << "Загрузка инстансов модов"; - - // Тест луа - - - // sol::function func = res.call<>(); - // int type = func(); - - // LOG.debug() << type; - LoadedMods = mlt.LoadChain; LuaMainState.open_libraries(); @@ -1428,72 +1420,60 @@ void GameServer::init(fs::path worldPath) { ModInstances.emplace_back(info.Id, res.call()); } - LOG.info() << "Пре Инициализация"; - initLuaPre(); + std::function pushEvent = [&](const std::string& function) { + for(auto& [id, core] : ModInstances) { + std::optional func = core.get>(function); + if(func) { + sol::protected_function_result result; + try { + result = func->operator()(); + } catch(const std::exception &exc) { + MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << exc.what()); + } - for(auto& [id, core] : ModInstances) { - std::optional func = core.get>("preInit"); - if(func) { - sol::protected_function_result result; - try { - result = func->operator()(); - } catch(const std::exception &exc) { - MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << exc.what()); - } - - if(!result.valid()) { - sol::error err = result; - MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << err.what()); + if(!result.valid()) { + sol::error err = result; + MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << err.what()); + } } } + }; + + initLuaAssets(); + pushEvent("initAssets"); + for(ssize_t index = mlt.LoadChain.size(); index >= 0; index--) { + AssetsInit.Assets.push_back(mlt.LoadChain[index].Path / "assets"); } + Content.AM.applyResourceChange(Content.AM.recheckResources(AssetsInit)); + + LOG.info() << "Пре Инициализация"; + initLuaPre(); + pushEvent("lowPreInit"); + + // TODO: регистрация контента из mod/content/* + + pushEvent("preInit"); + pushEvent("highPreInit"); + + LOG.info() << "Инициализация"; initLua(); - - for(auto& [id, core] : ModInstances) { - CurrentModId = id; - std::optional func = core.get>("init"); - if(func) { - sol::protected_function_result result; - try { - result = func->operator()(); - } catch(...) { - MAKE_ERROR("Ошибка инициализации мода " << id << ":\n"); - } - - if(!result.valid()) { - sol::error err = result; - MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << err.what()); - } - } - } + pushEvent("init"); LOG.info() << "Пост Инициализация"; initLuaPost(); - - for(auto& [id, core] : ModInstances) { - CurrentModId = id; - std::optional func = core.get>("postInit"); - if(func) { - sol::protected_function_result result; - try { - result = func->operator()(); - } catch(const std::exception &exc) { - MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << exc.what()); - } - - if(!result.valid()) { - sol::error err = result; - MAKE_ERROR("Ошибка инициализации мода " << id << ":\n" << err.what()); - } - } - } + pushEvent("postInit"); // Загрузить миры с существующими профилями + LOG.info() << "Загрузка существующих миров..."; Expanse.Worlds[0] = std::make_unique(0); + LOG.info() << "Оповещаем моды о завершении загрузки"; + pushEvent("serverReady"); + + LOG.info() << "Загрузка существующих миров..."; BackingChunkPressure.Threads.resize(4); BackingChunkPressure.Worlds = &Expanse.Worlds; for(size_t iter = 0; iter < BackingChunkPressure.Threads.size(); iter++) { @@ -1652,10 +1632,53 @@ DefNode_t GameServer::createNodeProfileByLua(const sol::table& profile) { return result; } +void GameServer::initLuaAssets() { + auto &lua = LuaMainState; + std::optional core = lua["core"]; + if(!core) + core = lua.create_named_table("core"); + + std::function reg + = [this](EnumAssets type, const std::string& key, const sol::table& profile) + { + std::optional>> result_o = TOS::Str::match(key, "^(?:([\\w\\d_]+):)?([\\w\\d_]+)$"); + + if(!result_o) { + MAKE_ERROR("Недействительный идентификатор ноды: " << key); + } + + auto &result = *result_o; + if(result[1]) + AssetsInit.Custom[(int) type][*result[1]][*result[2]] = nullptr; + else + AssetsInit.Custom[(int) type][CurrentModId][*result[2]] = nullptr; + }; + + core->set_function("register_nodestate", std::bind(reg, EnumAssets::Nodestate, std::placeholders::_1, std::placeholders::_2)); + core->set_function("register_particle", std::bind(reg, EnumAssets::Patricle, std::placeholders::_1, std::placeholders::_2)); + core->set_function("register_animation", std::bind(reg, EnumAssets::Animation, std::placeholders::_1, std::placeholders::_2)); + core->set_function("register_model", std::bind(reg, EnumAssets::Model, std::placeholders::_1, std::placeholders::_2)); + core->set_function("register_texture", std::bind(reg, EnumAssets::Texture, std::placeholders::_1, std::placeholders::_2)); + core->set_function("register_sound", std::bind(reg, EnumAssets::Sound, std::placeholders::_1, std::placeholders::_2)); + core->set_function("register_font", std::bind(reg, EnumAssets::Font, std::placeholders::_1, std::placeholders::_2)); + + return resources; +} + void GameServer::initLuaPre() { auto &lua = LuaMainState; + sol::table core = lua["core"]; + + auto lambdaError = [](sol::this_state L) { + luaL_error(L.lua_state(), "Данная функция может использоваться только в стадии [assetsInit]"); + }; + + for(const char* name : {"register_nodestate", "register_particle", "register_animation", + "register_model", "register_texture", "register_sound", "register_font"}) + core.set_function(name, lambdaError); + + - sol::table core = lua.create_named_table("core"); core.set_function("register_node", [&](const std::string& id, const sol::table& profile) { std::optional>> result_o = TOS::Str::match(id, "^(?:([\\w\\d_]+):)?([\\w\\d_]+)$"); diff --git a/Src/Server/GameServer.hpp b/Src/Server/GameServer.hpp index df54169..b61724a 100644 --- a/Src/Server/GameServer.hpp +++ b/Src/Server/GameServer.hpp @@ -302,6 +302,7 @@ class GameServer : public AsyncObject { std::vector> ModInstances; // Идентификатор текущегго мода, находящевося в обработке std::string CurrentModId; + AssetsManager::AssetsRegister AssetsInit; public: GameServer(asio::io_context &ioc, fs::path worldPath); @@ -339,6 +340,7 @@ private: DefNode_t createNodeProfileByLua(const sol::table& profile); + void initLuaAssets(); void initLuaPre(); void initLua(); void initLuaPost();