*
This commit is contained in:
@@ -7,14 +7,21 @@
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
coro<AssetsManager::Resource> 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::Resource> 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<ResourceId_t, std::optional<AssetsManager::DataEntry>&> AssetsManager::Local::nextId(EnumAssets type) {
|
||||
auto& table = Table[(int) type];
|
||||
ResourceId_t id = -1;
|
||||
@@ -45,7 +52,7 @@ std::tuple<ResourceId_t, std::optional<AssetsManager::DataEntry>&> AssetsManager
|
||||
return {id, *data};
|
||||
}
|
||||
|
||||
coro<AssetsManager::Out_recheckResources> AssetsManager::recheckResources(AssetsRegister info) {
|
||||
AssetsManager::Out_recheckResources AssetsManager::recheckResources(const AssetsRegister& info) {
|
||||
Out_recheckResources result;
|
||||
|
||||
// Найти пропавшие ресурсы
|
||||
@@ -124,10 +131,10 @@ coro<AssetsManager::Out_recheckResources> 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::Out_recheckResources> 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::Out_recheckResources> AssetsManager::recheckResources(Assets
|
||||
|
||||
}
|
||||
|
||||
co_return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const Out_recheckResources& orr) {
|
||||
|
||||
@@ -89,8 +89,8 @@ private:
|
||||
Загрузка ресурса с файла. При необходимости приводится
|
||||
к внутреннему формату и сохраняется в кеше
|
||||
*/
|
||||
coro<Resource> loadResourceFromFile(EnumAssets type, fs::path path) const;
|
||||
coro<Resource> 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<std::string, std::vector<std::tuple<std::string, Resource, fs::file_time_type>>> NewOrChange[(int) EnumAssets::MAX_ENUM];
|
||||
};
|
||||
|
||||
coro<Out_recheckResources> recheckResources(AssetsRegister);
|
||||
Out_recheckResources recheckResources(const AssetsRegister&);
|
||||
|
||||
/*
|
||||
Применяет расчитанные изменения.
|
||||
@@ -139,7 +139,6 @@ public:
|
||||
|
||||
Out_applyResourceChange applyResourceChange(const Out_recheckResources& orr);
|
||||
|
||||
|
||||
/*
|
||||
Выдаёт идентификатор ресурса, даже если он не существует или был удалён.
|
||||
resource должен содержать домен и путь
|
||||
|
||||
15
Src/Server/ContentManager.cpp
Normal file
15
Src/Server/ContentManager.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "ContentManager.hpp"
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
|
||||
ContentManager::ContentManager(asio::io_context& ioc)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ContentManager::~ContentManager() = default;
|
||||
|
||||
|
||||
|
||||
}
|
||||
62
Src/Server/ContentManager.hpp
Normal file
62
Src/Server/ContentManager.hpp
Normal file
@@ -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<std::string, std::unordered_map<std::string, ResourceId_t>> ContentKeyToId[(int) EnumDefContent::MAX_ENUM];
|
||||
|
||||
template<typename T>
|
||||
struct TableEntry {
|
||||
static constexpr size_t ChunkSize = 4096;
|
||||
std::array<std::optional<T>, ChunkSize> Entries;
|
||||
};
|
||||
|
||||
// Конечные профили контента
|
||||
std::vector<std::unique_ptr<TableEntry<DefVoxel>>> Profiles_Voxel;
|
||||
std::vector<std::unique_ptr<TableEntry<DefNode>>> Profiles_Node;
|
||||
std::vector<std::unique_ptr<TableEntry<DefWorld>>> Profiles_World;
|
||||
std::vector<std::unique_ptr<TableEntry<DefPortal>>> Profiles_Portal;
|
||||
std::vector<std::unique_ptr<TableEntry<DefEntity>>> Profiles_Entity;
|
||||
std::vector<std::unique_ptr<TableEntry<DefItem>>> Profiles_Item;
|
||||
|
||||
public:
|
||||
ContentManager(asio::io_context& ioc);
|
||||
~ContentManager();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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 <algorithm>
|
||||
#include <array>
|
||||
@@ -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<sol::table>());
|
||||
}
|
||||
|
||||
LOG.info() << "Пре Инициализация";
|
||||
initLuaPre();
|
||||
std::function<void(const std::string&)> pushEvent = [&](const std::string& function) {
|
||||
for(auto& [id, core] : ModInstances) {
|
||||
std::optional<sol::protected_function> func = core.get<std::optional<sol::protected_function>>(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<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());
|
||||
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<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());
|
||||
}
|
||||
}
|
||||
}
|
||||
pushEvent("init");
|
||||
|
||||
LOG.info() << "Пост Инициализация";
|
||||
initLuaPost();
|
||||
|
||||
for(auto& [id, core] : ModInstances) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
pushEvent("postInit");
|
||||
|
||||
// Загрузить миры с существующими профилями
|
||||
LOG.info() << "Загрузка существующих миров...";
|
||||
|
||||
Expanse.Worlds[0] = std::make_unique<World>(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<sol::table> core = lua["core"];
|
||||
if(!core)
|
||||
core = lua.create_named_table("core");
|
||||
|
||||
std::function<void(EnumAssets, const std::string&, const sol::table&)> reg
|
||||
= [this](EnumAssets type, const std::string& key, const sol::table& profile)
|
||||
{
|
||||
std::optional<std::vector<std::optional<std::string>>> 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<std::vector<std::optional<std::string>>> result_o = TOS::Str::match(id, "^(?:([\\w\\d_]+):)?([\\w\\d_]+)$");
|
||||
|
||||
|
||||
@@ -302,6 +302,7 @@ class GameServer : public AsyncObject {
|
||||
std::vector<std::pair<std::string, sol::table>> 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();
|
||||
|
||||
Reference in New Issue
Block a user