*
This commit is contained in:
@@ -15,6 +15,8 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sol/forward.hpp>
|
||||
#include <sol/optional_implementation.hpp>
|
||||
#include <sol/protected_function_result.hpp>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
@@ -240,7 +242,7 @@ std::vector<std::vector<ModInfo>> rangDepends(const std::vector<ModInfo>& mods)
|
||||
std::vector<std::vector<ModInfo>> ranging;
|
||||
|
||||
std::vector<ModInfo> 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<std::vector<ModInfo>> rangDepends(const std::vector<ModInfo>& 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<ModLoadTree, std::vector<std::string>> buildLoadChain(const std::ve
|
||||
{
|
||||
std::vector<std::vector<ModInfo>> 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<const std::exception&> 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<std::streamsize>(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<sol::table>());
|
||||
}
|
||||
|
||||
LOG.info() << "Пре Инициализация";
|
||||
initLuaPre();
|
||||
|
||||
for(auto& [id, core] : ModInstances) {
|
||||
sol::function func = core.get_or<sol::function>("preInit", {});
|
||||
func();
|
||||
std::optional<sol::protected_function> func = core.get<std::optional<sol::protected_function>>("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<sol::function>("init", {});
|
||||
func();
|
||||
CurrentModId = id;
|
||||
std::optional<sol::protected_function> func = core.get<std::optional<sol::protected_function>>("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<sol::function>("postInit", {});
|
||||
func();
|
||||
CurrentModId = id;
|
||||
std::optional<sol::protected_function> func = core.get<std::optional<sol::protected_function>>("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<std::vector<std::optional<std::string>>> 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()) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define SOL_EXCEPTIONS_SAFE_PROPAGATION 1
|
||||
|
||||
#include <Common/Net.hpp>
|
||||
#include <Common/Lockable.hpp>
|
||||
#include <boost/asio/any_io_executor.hpp>
|
||||
@@ -80,8 +82,7 @@ class GameServer : public AsyncObject {
|
||||
std::unordered_map<DefEntityId_t, DefEntity_t> ContentIdToDef_Entity;
|
||||
std::unordered_map<DefItemId_t, DefItem_t> 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<ModInfo> LoadedMods;
|
||||
std::vector<std::pair<std::string, sol::table>> 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();
|
||||
|
||||
/*
|
||||
Подключение/отключение игроков
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user