*
This commit is contained in:
@@ -67,7 +67,7 @@ set(Boost_USE_STATIC_LIBS ON)
|
||||
set(BOOST_INCLUDE_LIBRARIES asio thread json)
|
||||
set(BOOST_ENABLE_CMAKE ON)
|
||||
set(BOOST_IOSTREAMS_ENABLE_ZLIB ON)
|
||||
set(BOOST_INCLUDE_LIBRARIES asio thread json iostreams)
|
||||
set(BOOST_INCLUDE_LIBRARIES asio thread json iostreams interprocess)
|
||||
FetchContent_Declare(
|
||||
Boost
|
||||
GIT_REPOSITORY https://github.com/boostorg/boost.git
|
||||
@@ -76,7 +76,7 @@ FetchContent_Declare(
|
||||
USES_TERMINAL_DOWNLOAD true
|
||||
)
|
||||
FetchContent_MakeAvailable(Boost)
|
||||
target_link_libraries(luavox_common INTERFACE Boost::asio Boost::thread Boost::json Boost::iostreams)
|
||||
target_link_libraries(luavox_common INTERFACE Boost::asio Boost::thread Boost::json Boost::iostreams Boost::interprocess)
|
||||
|
||||
# glm
|
||||
# find_package(glm REQUIRED)
|
||||
|
||||
@@ -388,27 +388,34 @@ struct Object_t {
|
||||
using ResourceId_t = uint32_t;
|
||||
|
||||
/*
|
||||
Bin привязывается к путю. Если по путю обновляется объект, пересчитывается его кеш и на клиентах обновляется
|
||||
*/
|
||||
Объекты, собранные из папки assets или зарегистрированные модами.
|
||||
Клиент получает полную информацию о таких объектах и при надобности
|
||||
запрашивает получение файла.
|
||||
Id -> Key + SHA256
|
||||
|
||||
enum class EnumBinResource {
|
||||
Texture, Animation, Model, Sound, Font, MAX_ENUM
|
||||
Если объекты удаляются, то сторона клиента об этом не уведомляется
|
||||
*/
|
||||
enum class EnumAssets {
|
||||
Nodestate, Patricle, Animation, Model, Texture, Sound, Font, MAX_ENUM
|
||||
};
|
||||
|
||||
using AssetsNodestate = ResourceId_t;
|
||||
using AssetsParticle = ResourceId_t;
|
||||
using AssetsAnimation = ResourceId_t;
|
||||
using AssetsModel = ResourceId_t;
|
||||
using AssetsTexture = ResourceId_t;
|
||||
using AssetsSound = ResourceId_t;
|
||||
using AssetsFont = ResourceId_t;
|
||||
|
||||
using BinaryResource = std::shared_ptr<const std::u8string>;
|
||||
|
||||
// Двоичные данные
|
||||
using BinTextureId_t = ResourceId_t;
|
||||
using BinAnimationId_t = ResourceId_t;
|
||||
using BinModelId_t = ResourceId_t;
|
||||
using BinSoundId_t = ResourceId_t;
|
||||
using BinFontId_t = ResourceId_t;
|
||||
|
||||
/*
|
||||
Определения контента, доставляются клиентам сразу
|
||||
*/
|
||||
enum class EnumDefContent {
|
||||
Voxel, Node, Generator, World, Portal, Entity, Item, MAX_ENUM
|
||||
Voxel, Node, World, Portal, Entity, Item, MAX_ENUM
|
||||
};
|
||||
|
||||
// Игровые определения
|
||||
using DefVoxelId_t = ResourceId_t;
|
||||
using DefNodeId_t = ResourceId_t;
|
||||
using DefWorldId_t = ResourceId_t;
|
||||
@@ -416,9 +423,12 @@ using DefPortalId_t = ResourceId_t;
|
||||
using DefEntityId_t = ResourceId_t;
|
||||
using DefItemId_t = ResourceId_t;
|
||||
|
||||
// Контент, основанный на игровых определениях
|
||||
/*
|
||||
Контент, основанный на определениях.
|
||||
Отдельные свойства могут менятся в самих объектах
|
||||
*/
|
||||
|
||||
using WorldId_t = ResourceId_t;
|
||||
using PortalId_t = ResourceId_t;
|
||||
|
||||
// struct LightPrism {
|
||||
// uint8_t R : 2, G : 2, B : 2;
|
||||
|
||||
11
Src/Server/AssetsManager.cpp
Normal file
11
Src/Server/AssetsManager.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "AssetsManager.hpp"
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
|
||||
coro<AssetsManager::Out_recheckResources> AssetsManager::recheckResources(AssetsRegister info) const {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
116
Src/Server/AssetsManager.hpp
Normal file
116
Src/Server/AssetsManager.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#include "Abstract.hpp"
|
||||
#include "Common/Abstract.hpp"
|
||||
#include "boost/asio/io_context.hpp"
|
||||
#include "sha2.hpp"
|
||||
#include <boost/interprocess/file_mapping.hpp>
|
||||
#include <boost/interprocess/mapped_region.hpp>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
namespace LV::Server {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
class AssetsManager {
|
||||
public:
|
||||
struct Resource {
|
||||
private:
|
||||
struct Inline {
|
||||
boost::interprocess::file_mapping MMap;
|
||||
boost::interprocess::mapped_region Region;
|
||||
Hash_t Hash;
|
||||
|
||||
Inline(fs::path path)
|
||||
: MMap(path.c_str(), boost::interprocess::read_only),
|
||||
Region(MMap, boost::interprocess::read_only)
|
||||
{}
|
||||
};
|
||||
|
||||
std::shared_ptr<Inline> In;
|
||||
|
||||
public:
|
||||
Resource(fs::path path)
|
||||
: In(std::make_shared<Inline>(path))
|
||||
{
|
||||
In->Hash = sha2::sha256((const uint8_t*) In->Region.get_address(), In->Region.get_size());
|
||||
}
|
||||
|
||||
Resource(const Resource&) = default;
|
||||
Resource(Resource&&) = default;
|
||||
Resource& operator=(const Resource&) = default;
|
||||
Resource& operator=(Resource&&) = default;
|
||||
bool operator<=>(const Resource&) const = default;
|
||||
|
||||
const std::byte* data() const { return (const std::byte*) In->Region.get_address(); }
|
||||
size_t size() const { return In->Region.get_size(); }
|
||||
Hash_t hash() const { return In->Hash; }
|
||||
};
|
||||
|
||||
private:
|
||||
// Данные об отслеживаемых файлах
|
||||
struct DataEntry {
|
||||
// Время последнего изменения файла
|
||||
size_t FileChangeTime;
|
||||
Resource Res;
|
||||
};
|
||||
|
||||
struct TableEntry {
|
||||
bool IsFull = false;
|
||||
std::bitset<4096> Empty;
|
||||
std::array<std::optional<DataEntry>, 4096> Entries;
|
||||
|
||||
TableEntry() {
|
||||
Empty.reset();
|
||||
}
|
||||
};
|
||||
|
||||
// Данные не меняются в процессе работы сервера.
|
||||
// Изменения возможны при синхронизации всего сервера
|
||||
// и перехода в режим перезагрузки модов
|
||||
|
||||
// Связь ресурсов по идентификаторам
|
||||
std::vector<std::unique_ptr<TableEntry>> Table[(int) EnumAssets::MAX_ENUM];
|
||||
// Связь домены -> {ключ -> идентификатор}
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, ResourceId_t>> KeyToId[(int) EnumAssets::MAX_ENUM];
|
||||
|
||||
DataEntry& getEntry(EnumAssets type, ResourceId_t id);
|
||||
|
||||
|
||||
public:
|
||||
AssetsManager(asio::io_context& ioc);
|
||||
~AssetsManager();
|
||||
|
||||
/*
|
||||
Перепроверка изменений ресурсов по дате изменения, пересчёт хешей.
|
||||
Обнаруженные изменения должны быть отправлены всем клиентам.
|
||||
Ресурсы будут обработаны в подходящий формат и сохранены в кеше.
|
||||
Одновременно может выполнятся только одна такая функция
|
||||
Используется в GameServer
|
||||
*/
|
||||
|
||||
struct AssetsRegister {
|
||||
/*
|
||||
Пути до активных папок assets, соответствую порядку загруженным модам.
|
||||
От последнего мода к первому.
|
||||
Тот файл, что был загружен раньше и будет использоваться
|
||||
*/
|
||||
std::vector<fs::path> Assets;
|
||||
/*
|
||||
У этих ресурсов приоритет выше, если их удастся получить,
|
||||
то использоваться будут именно они
|
||||
*/
|
||||
std::vector<std::tuple<std::string, EnumAssets, void*>> Custom;
|
||||
};
|
||||
|
||||
struct Out_recheckResources {
|
||||
std::vector<std::tuple< ResourceId_t, EnumAssets, Resource >> NewOrChange;
|
||||
std::vector<std::tuple< ResourceId_t, EnumAssets >> Lost;
|
||||
};
|
||||
|
||||
coro<Out_recheckResources> recheckResources(AssetsRegister) const;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -74,6 +74,7 @@ void BinaryResourceManager::run() {
|
||||
|
||||
if(var.index() == 0) {
|
||||
std::shared_ptr<ResourceFile> resource = std::get<0>(var);
|
||||
resource = convertFormate(resource, (EnumBinResource) type);
|
||||
resource->calcHash();
|
||||
return resource;
|
||||
} else {
|
||||
@@ -311,6 +312,10 @@ BinaryResourceManager::loadFile(const std::vector<fs::path>& assets, const std::
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ResourceFile> convertFormate(std::shared_ptr<ResourceFile> file, EnumBinResource type) {
|
||||
return file;
|
||||
}
|
||||
|
||||
BinaryResourceManager::BinaryResourceManager(asio::io_context &ioc)
|
||||
: AsyncObject(ioc), Thread(&BinaryResourceManager::run, this)
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ private:
|
||||
|
||||
// Поток сервера
|
||||
// Последовательная регистрация ресурсов
|
||||
ResourceId_t NextId[(int) EnumBinResource::MAX_ENUM] = {0};
|
||||
ResourceId_t NextId[(int) EnumAssets::MAX_ENUM] = {0};
|
||||
// Известные ресурсы, им присвоен идентификатор
|
||||
// Нужно для потока загрузки
|
||||
std::unordered_map<std::string, ResourceId_t> KnownResource[(int) EnumBinResource::MAX_ENUM];
|
||||
@@ -76,6 +76,7 @@ private:
|
||||
void run();
|
||||
std::variant<std::shared_ptr<ResourceFile>, std::string>
|
||||
loadFile(const std::vector<fs::path>& assets, const std::string& path, EnumBinResource type);
|
||||
std::shared_ptr<ResourceFile> convertFormate(std::shared_ptr<ResourceFile> file, EnumBinResource type);
|
||||
|
||||
public:
|
||||
// Если ресурс будет обновлён или загружен будет вызвано onResourceUpdate
|
||||
|
||||
@@ -277,6 +277,7 @@ public:
|
||||
Pos::Object CameraPos = {0, 0, 0};
|
||||
ToServer::PacketQuat CameraQuat = {0};
|
||||
TOS::SpinlockObject<std::queue<uint8_t>> Actions;
|
||||
ResourceId_t RecievedAssets[(int) EnumAssets::MAX_ENUM] = {0};
|
||||
|
||||
public:
|
||||
RemoteClient(asio::io_context &ioc, tcp::socket socket, const std::string username, std::vector<ResourceFile::Hash_t> &&client_cache)
|
||||
|
||||
Reference in New Issue
Block a user