From c06683cd5729bdcb67c606cb48662dbd25943e02 Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Mon, 25 Aug 2025 10:58:21 +0600 Subject: [PATCH] * --- Src/Common/Abstract.cpp | 53 ++++---------- Src/Common/Abstract.hpp | 5 +- Src/Server/AssetsManager.cpp | 57 +++++++++++---- Src/Server/AssetsManager.hpp | 135 +++++++++++++++-------------------- Src/Server/GameServer.cpp | 4 +- Src/Server/RemoteClient.cpp | 2 +- Src/Server/RemoteClient.hpp | 4 +- 7 files changed, 123 insertions(+), 137 deletions(-) diff --git a/Src/Common/Abstract.cpp b/Src/Common/Abstract.cpp index 8da0af3..ab0538f 100644 --- a/Src/Common/Abstract.cpp +++ b/Src/Common/Abstract.cpp @@ -1540,11 +1540,6 @@ std::vector PreparedNodeState::parseTransorma PreparedModel::PreparedModel(const std::string_view modid, const js::object& profile) { - if(profile.contains("parent")) { - auto [domain, key] = parseDomainKey((const std::string) profile.at("parent").as_string(), modid); - Parent.emplace(std::move(domain), std::move(key)); - } - if(profile.contains("gui_light")) { std::string_view gui_light = profile.at("gui_light").as_string(); @@ -1744,11 +1739,11 @@ PreparedModel::PreparedModel(const std::string_view modid, const js::object& pro } } - if(boost::system::result gltf_val = profile.try_at("gltf")) { - const js::array& gltf = gltf_val->as_array(); + if(boost::system::result subModels_val = profile.try_at("sub_models")) { + const js::array& subModels = subModels_val->as_array(); - for(const js::value& sub_val : gltf) { - SubGLTF result; + for(const js::value& sub_val : subModels) { + SubModel result; const js::object& sub = sub_val.as_object(); auto [domain, key] = parseDomainKey((std::string) sub.at("path").as_string(), modid); result.Domain = std::move(domain); @@ -1767,12 +1762,6 @@ PreparedModel::PreparedModel(const std::string_view modid, const sol::table& pro PreparedModel::PreparedModel(const std::u8string& data) { Net::LinearReader lr(data); - if(lr.read()) { - std::string domain, key; - lr >> domain >> key; - Parent.emplace(std::move(domain), std::move(key)); - } - if(lr.read()) { GuiLight = (EnumGuiLight) lr.read(); } @@ -1868,34 +1857,22 @@ PreparedModel::PreparedModel(const std::u8string& data) { } lr >> size; - GLTF.reserve(size); + SubModels.reserve(size); for(int counter = 0; counter < size; counter++) { - SubGLTF sub; + SubModel sub; lr >> sub.Domain >> sub.Key; uint16_t val = lr.read(); if(val != uint16_t(-1)) { sub.Scene = val; } - GLTF.push_back(std::move(sub)); + SubModels.push_back(std::move(sub)); } } std::u8string PreparedModel::dump() const { Net::Packet result; - if(Parent.has_value()) { - result << uint8_t(1); - - assert(Parent->first.size() < 32); - result << Parent->first; - - assert(Parent->second.size() < 32); - result << Parent->second; - } else { - result << uint8_t(0); - } - if(GuiLight.has_value()) { result << uint8_t(1); result << uint8_t(GuiLight.value()); @@ -1977,15 +1954,15 @@ std::u8string PreparedModel::dump() const { } } - assert(GLTF.size() < 256); - result << uint8_t(GLTF.size()); - for(const SubGLTF& gltf : GLTF) { - assert(gltf.Domain.size() < 32); - assert(gltf.Key.size() < 32); + assert(SubModels.size() < 256); + result << uint8_t(SubModels.size()); + for(const SubModel& model : SubModels) { + assert(model.Domain.size() < 32); + assert(model.Key.size() < 32); - result << gltf.Domain << gltf.Key; - if(gltf.Scene) - result << uint16_t(*gltf.Scene); + result << model.Domain << model.Key; + if(model.Scene) + result << uint16_t(*model.Scene); else result << uint16_t(-1); } diff --git a/Src/Common/Abstract.hpp b/Src/Common/Abstract.hpp index c065126..619a729 100644 --- a/Src/Common/Abstract.hpp +++ b/Src/Common/Abstract.hpp @@ -600,7 +600,6 @@ struct PreparedModel { Default }; - std::optional> Parent; std::optional GuiLight = EnumGuiLight::Default; std::optional AmbientOcclusion = false; @@ -647,12 +646,12 @@ struct PreparedModel { std::vector Cuboids; - struct SubGLTF { + struct SubModel { std::string Domain, Key; std::optional Scene; }; - std::vector GLTF; + std::vector SubModels; // Json PreparedModel(const std::string_view modid, const js::object& profile); diff --git a/Src/Server/AssetsManager.cpp b/Src/Server/AssetsManager.cpp index c8fbee3..6d1b6a6 100644 --- a/Src/Server/AssetsManager.cpp +++ b/Src/Server/AssetsManager.cpp @@ -1,8 +1,6 @@ #include "AssetsManager.hpp" #include "Common/Abstract.hpp" -#include "boost/json/impl/parse.ipp" -#include "boost/json/object.hpp" -#include "boost/json/parser.hpp" +#include "boost/json.hpp" #include "png++/rgb_pixel.hpp" #include #include @@ -11,12 +9,27 @@ #include #include #include +#include "sol/sol.hpp" namespace LV::Server { PreparedModelCollision::PreparedModelCollision(const PreparedModel& model) { + Cuboids.reserve(model.Cuboids.size()); + for(const PreparedModel::Cuboid& cuboid : model.Cuboids) { + Cuboid result; + result.From = cuboid.From; + result.To = cuboid.To; + result.Faces = 0; + + for(const auto& [key, _] : cuboid.Faces) + result.Faces |= (1 << int(key)); + + result.Transformations = cuboid.Transformations; + } + + SubModels = model.SubModels; } PreparedModelCollision::PreparedModelCollision(const std::string& domain, const js::object& glTF) { @@ -32,7 +45,7 @@ PreparedModelCollision::PreparedModelCollision(const std::string& domain, const // Буферы } -PreparedModelCollision::PreparedModelCollision(const std::string& domain, Resource res) { +PreparedModelCollision::PreparedModelCollision(const std::string& domain, Resource glb) { } @@ -84,16 +97,32 @@ void AssetsManager::loadResourceFromFile_Animation(ResourceChangeObj& out, const void AssetsManager::loadResourceFromFile_Model(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { /* - json, glTF glB + json, glTF, glB */ // Либо это внутренний формат, либо glTF Resource res(path); + std::filesystem::file_time_type ftt = fs::last_write_time(path); - if(path.extension() == "json" || path.extension() == "gltf") { + if(path.extension() == "json") { js::object obj = js::parse(std::string_view((const char*) res.data(), res.size())).as_object(); - PreparedModelCollision pmc(domain, obj, path.extension() == "gltf"); + PreparedModel pm(domain, obj); + PreparedModelCollision pmc(pm); + std::u8string data = pm.dump(); + out.Models[domain].emplace_back(key, pmc); + out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, Resource((const uint8_t*) data.data(), data.size()), ftt); + } else if(path.extension() == "gltf") { + js::object obj = js::parse(std::string_view((const char*) res.data(), res.size())).as_object(); + PreparedModelCollision pmc(domain, obj); + out.Models[domain].emplace_back(key, pmc); + out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, res, ftt); + } else if(path.extension() == "glb") { + PreparedModelCollision pmc(domain, res); + out.Models[domain].emplace_back(key, pmc); + out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, res, ftt); + } else { + MAKE_ERROR("Не поддерживаемый формат файла"); } } @@ -130,7 +159,7 @@ void AssetsManager::loadResourceFromFile_Font(ResourceChangeObj& out, const std: void AssetsManager::loadResourceFromLua_Nodestate(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Nodestate][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Nodestate][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } @@ -139,7 +168,7 @@ void AssetsManager::loadResourceFromLua_Nodestate(ResourceChangeObj& out, const void AssetsManager::loadResourceFromLua_Particle(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Particle][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Particle][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } @@ -148,7 +177,7 @@ void AssetsManager::loadResourceFromLua_Particle(ResourceChangeObj& out, const s void AssetsManager::loadResourceFromLua_Animation(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Animation][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Animation][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } @@ -157,7 +186,7 @@ void AssetsManager::loadResourceFromLua_Animation(ResourceChangeObj& out, const void AssetsManager::loadResourceFromLua_Model(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } @@ -166,7 +195,7 @@ void AssetsManager::loadResourceFromLua_Model(ResourceChangeObj& out, const std: void AssetsManager::loadResourceFromLua_Texture(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Texture][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Texture][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } @@ -175,7 +204,7 @@ void AssetsManager::loadResourceFromLua_Texture(ResourceChangeObj& out, const st void AssetsManager::loadResourceFromLua_Sound(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Sound][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Sound][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } @@ -184,7 +213,7 @@ void AssetsManager::loadResourceFromLua_Sound(ResourceChangeObj& out, const std: void AssetsManager::loadResourceFromLua_Font(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - out.NewOrChange[(int) EnumAssets::Font][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + out.NewOrChange[(int) EnumAssets::Font][domain].emplace_back(key, Resource(*path), fs::file_time_type::min()); return; } diff --git a/Src/Server/AssetsManager.hpp b/Src/Server/AssetsManager.hpp index 05f79ad..bc5baa3 100644 --- a/Src/Server/AssetsManager.hpp +++ b/Src/Server/AssetsManager.hpp @@ -5,6 +5,7 @@ #include "Common/Net.hpp" #include "assets.hpp" #include "sha2.hpp" +#include #include #include #include @@ -17,6 +18,59 @@ namespace LV::Server { namespace fs = std::filesystem; +struct Resource { +private: + struct InlineMMap { + boost::interprocess::file_mapping MMap; + boost::interprocess::mapped_region Region; + Hash_t Hash; + + InlineMMap(fs::path path) + : MMap(path.c_str(), boost::interprocess::read_only), + Region(MMap, boost::interprocess::read_only) + { + Hash = sha2::sha256((const uint8_t*) Region.get_address(), Region.get_size()); + } + + const std::byte* data() const { return (const std::byte*) Region.get_address(); } + size_t size() const { return Region.get_size(); } + }; + + struct InlinePtr { + std::vector Data; + Hash_t Hash; + + InlinePtr(const uint8_t* data, size_t size) { + Data.resize(size); + std::copy(data, data+size, Data.data()); + Hash = sha2::sha256(data, size); + } + + const std::byte* data() const { return (const std::byte*) Data.data(); } + size_t size() const { return Data.size(); } + }; + + std::shared_ptr> In; + +public: + Resource(fs::path path) + : In(std::make_shared>(InlineMMap(path))) + {} + + Resource(const uint8_t* data, size_t size) + : In(std::make_shared>(InlinePtr(data, 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 std::visit([](auto& obj){ return obj.data(); }, *In); } + size_t size() const { return std::visit([](auto& obj){ return obj.size(); }, *In); } + Hash_t hash() const { return std::visit([](auto& obj){ return obj.Hash; }, *In); } +}; /* Используется для расчёта коллизии, @@ -27,36 +81,17 @@ namespace fs = std::filesystem; struct PreparedModelCollision { struct Cuboid { glm::vec3 From, To; - - enum EnumFace { - Down, Up, North, South, West, East - }; - - struct Face { - std::optional Cullface; - uint8_t Rotation = 0; - }; - - std::unordered_map Faces; - - struct Transformation { - enum EnumTransform { - MoveX, MoveY, MoveZ, - RotateX, RotateY, RotateZ, - MAX_ENUM - } Op; - - float Value; - }; + uint8_t Faces; - std::vector Transformations; + std::vector Transformations; }; std::vector Cuboids; + std::vector SubModels; PreparedModelCollision(const PreparedModel& model); PreparedModelCollision(const std::string& domain, const js::object& glTF); - PreparedModelCollision(const std::string& domain, Resource res); + PreparedModelCollision(const std::string& domain, Resource glb); PreparedModelCollision() = default; PreparedModelCollision(const PreparedModelCollision&) = default; @@ -73,60 +108,6 @@ struct PreparedModelCollision { */ class AssetsManager { public: - struct Resource { - private: - struct InlineMMap { - boost::interprocess::file_mapping MMap; - boost::interprocess::mapped_region Region; - Hash_t Hash; - - InlineMMap(fs::path path) - : MMap(path.c_str(), boost::interprocess::read_only), - Region(MMap, boost::interprocess::read_only) - { - Hash = sha2::sha256((const uint8_t*) Region.get_address(), Region.get_size()); - } - - const std::byte* data() const { return (const std::byte*) Region.get_address(); } - size_t size() const { return Region.get_size(); } - }; - - struct InlinePtr { - std::vector Data; - Hash_t Hash; - - InlinePtr(const uint8_t* data, size_t size) { - Data.resize(size); - std::copy(data, data+size, Data.data()); - Hash = sha2::sha256(data, size); - } - - const std::byte* data() const { return (const std::byte*) Data.data(); } - size_t size() const { return Data.size(); } - }; - - std::shared_ptr> In; - - public: - Resource(fs::path path) - : In(std::make_shared>(InlineMMap(path))) - {} - - Resource(const uint8_t* data, size_t size) - : In(std::make_shared>(InlinePtr(data, 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 std::visit([](auto& obj){ return obj.data(); }, *In); } - size_t size() const { return std::visit([](auto& obj){ return obj.size(); }, *In); } - Hash_t hash() const { return std::visit([](auto& obj){ return obj.Hash; }, *In); } - }; - struct ResourceChangeObj { // Потерянные ресурсы std::unordered_map> Lost[(int) EnumAssets::MAX_ENUM]; diff --git a/Src/Server/GameServer.cpp b/Src/Server/GameServer.cpp index cc4a6fd..c5d7bca 100644 --- a/Src/Server/GameServer.cpp +++ b/Src/Server/GameServer.cpp @@ -2397,10 +2397,10 @@ void GameServer::stepSyncContent() { full.uniq(); // Информируем о запрошенных ассетах - std::vector> resources; + std::vector> resources; for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) { for(ResourceId resId : full.AssetsInfo[type]) { - std::optional> result = Content.AM.getResource((EnumAssets) type, resId); + std::optional> result = Content.AM.getResource((EnumAssets) type, resId); if(!result) continue; diff --git a/Src/Server/RemoteClient.cpp b/Src/Server/RemoteClient.cpp index d4165b3..d8bfe28 100644 --- a/Src/Server/RemoteClient.cpp +++ b/Src/Server/RemoteClient.cpp @@ -495,7 +495,7 @@ ResourceRequest RemoteClient::pushPreparedPackets() { return std::move(nextRequest); } -void RemoteClient::informateAssets(const std::vector>& resources) +void RemoteClient::informateAssets(const std::vector>& resources) { std::vector> newForClient; diff --git a/Src/Server/RemoteClient.hpp b/Src/Server/RemoteClient.hpp index 72e1a77..0c4ac70 100644 --- a/Src/Server/RemoteClient.hpp +++ b/Src/Server/RemoteClient.hpp @@ -312,7 +312,7 @@ class RemoteClient { std::vector OnClient, ClientRequested; // Отправляемые на клиент ресурсы // Тип, домен, ключ, идентификатор, ресурс, количество отправленных байт - std::vector> ToSend; + std::vector> ToSend; } AssetsInWork; TOS::SpinlockObject NetworkAndResource; @@ -417,7 +417,7 @@ public: // Глобально их можно запросить в выдаче pushPreparedPackets() // Оповещение о запрошенных (и не только) ассетах - void informateAssets(const std::vector>& resources); + void informateAssets(const std::vector>& resources); // Игровые определения void informateDefVoxel(const std::vector>& voxels) { NetworkAndResource.lock()->informateDefVoxel(voxels); }