From e54f04f62e2a97c5f22237627b2d0586296c4cac Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Tue, 12 Aug 2025 01:58:08 +0600 Subject: [PATCH] * --- Src/Server/AssetsManager.cpp | 150 +++++++++++++++++++++++++++++++++++ Src/Server/AssetsManager.hpp | 16 ++-- assets/null | 0 3 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 assets/null diff --git a/Src/Server/AssetsManager.cpp b/Src/Server/AssetsManager.cpp index 7c8340c..16b6480 100644 --- a/Src/Server/AssetsManager.cpp +++ b/Src/Server/AssetsManager.cpp @@ -1,11 +1,161 @@ #include "AssetsManager.hpp" +#include "Common/Abstract.hpp" +#include +#include +#include namespace LV::Server { coro AssetsManager::recheckResources(AssetsRegister info) const { + Out_recheckResources result; + // Найти пропавшие ресурсы + for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) { + for(auto& [domain, resources] : KeyToId[type]) { + for(auto& [key, id] : resources) { + bool exists = false; + + for(const fs::path& path : info.Assets) { + fs::path file = path / domain; + + switch ((EnumAssets) type) { + case EnumAssets::Nodestate: file /= "nodestate"; break; + case EnumAssets::Patricle: file /= "particle"; break; + case EnumAssets::Animation: file /= "animation"; break; + case EnumAssets::Model: file /= "model"; break; + case EnumAssets::Texture: file /= "texture"; break; + case EnumAssets::Sound: file /= "sound"; break; + case EnumAssets::Font: file /= "font"; break; + default: + assert(false); + } + + file /= key; + + if(fs::exists(file) && !fs::is_directory(file)) { + exists = true; + break; + } + } + + if(exists) continue; + + auto iterDomain = info.Custom[type].find(domain); + if(iterDomain == info.Custom[type].end()) { + result.Lost[type][domain].push_back(key); + } else { + auto iterData = iterDomain->second.find(key); + if(iterData == iterDomain->second.end()) { + result.Lost[type][domain].push_back(key); + } + } + } + } + } + + // Если ресурс уже был найден более приоритетными директориями, то пропускаем его + std::unordered_map> findedResources[(int) EnumAssets::MAX_ENUM]; + + // Найти новые или изменённые ресурсы + for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) { + const auto& keyToId = KeyToId[type]; + + for(auto& [domain, resources] : info.Custom[type]) { + auto iterDomain = keyToId.find(domain); + auto& findList = findedResources[type][domain]; + + if(iterDomain == keyToId.end()) { + // Ресурсы данного домена неизвестны + auto& domainList = result.NewOrChange[type][domain]; + for(auto& [key, id] : resources) { + // Подобрать идентификатор + // TODO: реализовать регистрации ресурсов из lua + domainList.emplace_back(key, Resource("assets/null")); + findList.insert(key); + } + } else { + for(auto& [key, id] : resources) { + if(findList.contains(key)) + // Ресурс уже был найден в вышестоящей директории + continue; + else if(iterDomain->second.contains(key)) { + // Ресурс уже есть, TODO: нужно проверить его изменение + } else { + // Ресурс не был известен + result.NewOrChange[type][domain].emplace_back(key, Resource("assets/null")); + } + + findList.insert(key); + } + } + } + } + + for(const fs::path& path : info.Assets) { + for(auto begin = fs::directory_iterator(path), end = fs::directory_iterator(); begin != end; begin++) { + if(!begin->is_directory()) + continue; + + fs::path domainPath = begin->path(); + std::string domain = domainPath.filename(); + + for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) { + fs::path resourcesPath = domainPath; + + switch ((EnumAssets) type) { + case EnumAssets::Nodestate: resourcesPath /= "nodestate"; break; + case EnumAssets::Patricle: resourcesPath /= "particle"; break; + case EnumAssets::Animation: resourcesPath /= "animation"; break; + case EnumAssets::Model: resourcesPath /= "model"; break; + case EnumAssets::Texture: resourcesPath /= "texture"; break; + case EnumAssets::Sound: resourcesPath /= "sound"; break; + case EnumAssets::Font: resourcesPath /= "font"; break; + default: + assert(false); + } + + auto& findList = findedResources[type][domain]; + auto iterDomain = KeyToId[type].find(domain); + + if(!fs::exists(resourcesPath) || !fs::is_directory(resourcesPath)) + continue; + + // Рекурсивно загрузить ресурсы внутри папки resourcesPath + for(auto begin = fs::recursive_directory_iterator(resourcesPath), end = fs::recursive_directory_iterator(); begin != end; begin++) { + if(begin->is_directory()) + continue; + + fs::path file = begin->path(); + std::string key = fs::relative(begin->path(), resourcesPath).string(); + if(findList.contains(key)) + // Ресурс уже был найден в вышестоящей директории + continue; + + else if(iterDomain != KeyToId[type].end() && iterDomain->second.contains(key)) { + // Ресурс уже есть, TODO: нужно проверить его изменение + ResourceId_t id = iterDomain->second.at(key); + DataEntry& entry = *Table[type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; + + fs::file_time_type lwt = fs::last_write_time(file); + if(lwt <= entry.FileChangeTime) + continue; + + + } else { + // Ресурс не был известен + result.NewOrChange[type][domain].emplace_back(key, Resource("assets/null")); + } + + findList.insert(key); + } + } + } + + } + + co_return result; } } \ No newline at end of file diff --git a/Src/Server/AssetsManager.hpp b/Src/Server/AssetsManager.hpp index 4c8b044..70aba5c 100644 --- a/Src/Server/AssetsManager.hpp +++ b/Src/Server/AssetsManager.hpp @@ -53,14 +53,15 @@ private: // Данные об отслеживаемых файлах struct DataEntry { // Время последнего изменения файла - size_t FileChangeTime; + fs::file_time_type FileChangeTime; Resource Res; }; struct TableEntry { + static constexpr size_t ChunkSize = 4096; bool IsFull = false; - std::bitset<4096> Empty; - std::array, 4096> Entries; + std::bitset Empty; + std::array, ChunkSize> Entries; TableEntry() { Empty.reset(); @@ -101,13 +102,16 @@ public: /* У этих ресурсов приоритет выше, если их удастся получить, то использоваться будут именно они + Domain -> {key + data} */ - std::vector> Custom; + std::unordered_map> Custom[(int) EnumAssets::MAX_ENUM]; }; struct Out_recheckResources { - std::vector> NewOrChange; - std::vector> Lost; + // Потерянные ресурсы + std::unordered_map> Lost[(int) EnumAssets::MAX_ENUM]; + // Домен и ключ ресурса + std::unordered_map>> NewOrChange[(int) EnumAssets::MAX_ENUM]; }; coro recheckResources(AssetsRegister) const; diff --git a/assets/null b/assets/null new file mode 100644 index 0000000..e69de29