From e5cfdd3787150d5910f03de95e4dda52f511254b Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Tue, 5 Aug 2025 18:07:41 +0600 Subject: [PATCH] * --- Src/Server/GameServer.cpp | 117 ++++++++++++++++++++++++++++++++++---- Src/Server/GameServer.hpp | 29 +++++++++- 2 files changed, 134 insertions(+), 12 deletions(-) diff --git a/Src/Server/GameServer.cpp b/Src/Server/GameServer.cpp index 73a77f6..fef331b 100644 --- a/Src/Server/GameServer.cpp +++ b/Src/Server/GameServer.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -240,7 +242,7 @@ std::vector> rangDepends(const std::vector& mods) std::vector> ranging; std::vector state, next = mods; - while(true) { + while(!next.empty()) { state = std::move(next); for(size_t index = 0; index < state.size(); index++) { @@ -267,8 +269,7 @@ std::vector> rangDepends(const std::vector& mods) // Циклическая зависимость ranging.push_back(std::move(next)); break; - } else if(next.empty()) - break; + } ranging.push_back(std::move(state)); } @@ -381,7 +382,7 @@ std::variant> buildLoadChain(const std::ve { std::vector> rangeLoad = rangDepends(toLoad); for(auto begin = rangeLoad.rbegin(), end = rangeLoad.rend(); begin != end; begin++) { - unloadChain.insert(unloadChain.end(), begin->begin(), begin->end()); + loadChain.insert(loadChain.end(), begin->begin(), begin->end()); } } @@ -1262,6 +1263,22 @@ std::string GameServer::deBuildTexturePipeline(const TexturePipeline& pipeline) return ""; } +int my_exception_handler(lua_State* lua, sol::optional maybe_exception, sol::string_view description) { + std::cout << "An exception occurred in a function, here's what it says "; + if (maybe_exception) { + std::cout << "(straight from the exception): "; + const std::exception& ex = *maybe_exception; + std::cout << ex.what() << std::endl; + } + else { + std::cout << "(from the description parameter): "; + std::cout.write(description.data(), static_cast(description.size())); + std::cout << std::endl; + } + + return sol::stack::push(lua, description); +} + void GameServer::init(fs::path worldPath) { // world.json @@ -1403,32 +1420,75 @@ void GameServer::init(fs::path worldPath) { LoadedMods = mlt.LoadChain; LuaMainState.open_libraries(); + LuaMainState.set_exception_handler(&my_exception_handler); for(const ModInfo& info : mlt.LoadChain) { LOG.info() << info.Id; + CurrentModId = info.Id; sol::load_result res = LuaMainState.load_file(info.Path / "init.lua"); ModInstances.emplace_back(info.Id, res.call()); } LOG.info() << "Пре Инициализация"; + initLuaPre(); for(auto& [id, core] : ModInstances) { - sol::function func = core.get_or("preInit", {}); - func(); + 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()); + } + } } LOG.info() << "Инициализация"; + initLua(); for(auto& [id, core] : ModInstances) { - sol::function func = core.get_or("init", {}); - func(); + 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()); + } + } } LOG.info() << "Пост Инициализация"; + initLuaPost(); for(auto& [id, core] : ModInstances) { - sol::function func = core.get_or("postInit", {}); - func(); + 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()); + } + } } // Загрузить миры с существующими профилями @@ -1537,6 +1597,43 @@ void GameServer::run() { LOG.info() << "Сервер завершил работу"; } +void GameServer::initLuaPre() { + auto &lua = LuaMainState; + + 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_]+)$"); + + if(!result_o) { + MAKE_ERROR("Недействительный идентификатор ноды: " << id); + } + + auto &result = *result_o; + + if(result[1]) + Content.registerContent(id, EnumDefContent::Node); + else + Content.registerContent(CurrentModId+":"+*result[2], EnumDefContent::Node); + }); +} + +void GameServer::initLua() { + auto &lua = LuaMainState; + + sol::table core = lua["core"]; + + auto lambdaError = [](sol::this_state L) { + luaL_error(L.lua_state(), "Данная функция может использоваться только в стадии [preInit]"); + }; + + for(const char* name : {"register_node"}) + core.set_function(name, lambdaError); +} + +void GameServer::initLuaPost() { + +} + void GameServer::stepConnections() { // Подключить новых игроков if(!External.NewConnectedPlayers.no_lock_readable().empty()) { diff --git a/Src/Server/GameServer.hpp b/Src/Server/GameServer.hpp index c830872..33bf6ef 100644 --- a/Src/Server/GameServer.hpp +++ b/Src/Server/GameServer.hpp @@ -1,5 +1,7 @@ #pragma once +#define SOL_EXCEPTIONS_SAFE_PROPAGATION 1 + #include #include #include @@ -80,8 +82,7 @@ class GameServer : public AsyncObject { std::unordered_map ContentIdToDef_Entity; std::unordered_map ContentIdToDef_Item; - - ResourceId_t getContentDefId(const std::string& key, EnumDefContent def) { + ResourceId_t registerContent(const std::string& key, EnumDefContent def) { int index = int(def); assert(index < (int) EnumDefContent::MAX_ENUM); @@ -94,6 +95,19 @@ class GameServer : public AsyncObject { return nextId; } + MAKE_ERROR("Повторная регистрация контента: " << key << " тип " << int(def)); + } + + ResourceId_t getContentDefId(const std::string& key, EnumDefContent def) { + int index = int(def); + assert(index < (int) EnumDefContent::MAX_ENUM); + + auto &container = ContentKeyToId[index]; + auto iter = container.find(key); + if(iter == container.end()) { + return ResourceId_t(-1); + } + return iter->second; } @@ -284,6 +298,12 @@ class GameServer : public AsyncObject { sol::state LuaMainState; std::vector LoadedMods; std::vector> ModInstances; + // Идентификатор текущегго мода, находящевося в обработке + std::string CurrentModId; + + struct { + + }; public: GameServer(asio::io_context &ioc, fs::path worldPath); @@ -318,6 +338,11 @@ private: void prerun(); void run(); + + void initLuaPre(); + void initLua(); + void initLuaPost(); + /* Подключение/отключение игроков */