Переработка менеджера ресурсов на стороне клиентов

This commit is contained in:
2026-01-07 01:58:15 +06:00
parent c13ad06ba9
commit 523f9725c0
7 changed files with 443 additions and 939 deletions

View File

@@ -64,7 +64,6 @@ AssetsPreloader::Out_checkAndPrepareResourcesUpdate AssetsPreloader::checkAndPre
ReloadStatus* status
) {
assert(idResolver);
assert(onNewResourceParsed);
bool expected = false;
assert(_Reloading.compare_exchange_strong(expected, true) && "Двойной вызов reloadResources");
@@ -287,35 +286,36 @@ AssetsPreloader::Out_checkAndPrepareResourcesUpdate AssetsPreloader::_checkAndPr
for(const auto& [key, res] : keys) {
uniqueExistsTypes.insert(res.Id);
if(res.Id >= resourceLinksTyped.size() || !std::get<bool>(resourceLinksTyped[res.Id]))
if(res.Id >= resourceLinksTyped.size() || !resourceLinksTyped[res.Id].IsExist)
{ // Если идентификатора нет в таблице или ресурс не привязан
PendingResource resource = buildResource(static_cast<AssetType>(type), domain, key, res);
onNewResourceParsed(std::move(resource.Resource), resource.Hash, res.Path);
if(onNewResourceParsed)
onNewResourceParsed(std::move(resource.Resource), resource.Hash, res.Path);
result.HashToPathNew[resource.Hash].push_back(res.Path);
if(res.Id >= result.MaxNewSize[type])
result.MaxNewSize[type] = res.Id+1;
result.ResourceUpdates[type].emplace_back(res.Id, resource.Hash, std::move(resource.Header), resource.Timestamp, res.Path);
} else if(
std::get<fs::path>(resourceLinksTyped[res.Id]) != res.Path
|| std::get<fs::file_time_type>(resourceLinksTyped[res.Id]) != res.Timestamp
} else if(resourceLinksTyped[res.Id].Path != res.Path
|| resourceLinksTyped[res.Id].LastWrite != res.Timestamp
) { // Если ресурс теперь берётся с другого места или изменилось время изменения файла
const auto& lastResource = resourceLinksTyped[res.Id];
PendingResource resource = buildResource(static_cast<AssetType>(type), domain, key, res);
if(auto lastHash = std::get<ResourceFile::Hash_t>(lastResource); lastHash != resource.Hash) {
if(lastResource.Hash != resource.Hash) {
// Хэш изменился
// Сообщаем о новом ресурсе
onNewResourceParsed(std::move(resource.Resource), resource.Hash, res.Path);
if(onNewResourceParsed)
onNewResourceParsed(std::move(resource.Resource), resource.Hash, res.Path);
// Старый хэш более не доступен по этому расположению.
result.HashToPathLost[lastHash].push_back(std::get<fs::path>(resourceLinksTyped[res.Id]));
result.HashToPathLost[lastResource.Hash].push_back(resourceLinksTyped[res.Id].Path);
// Новый хеш стал доступен по этому расположению.
result.HashToPathNew[resource.Hash].push_back(res.Path);
} else if(std::get<fs::path>(resourceLinksTyped[res.Id]) != res.Path) {
} else if(resourceLinksTyped[res.Id].Path != res.Path) {
// Изменился конечный путь.
// Хэш более не доступен по этому расположению.
result.HashToPathLost[resource.Hash].push_back(std::get<fs::path>(resourceLinksTyped[res.Id]));
result.HashToPathLost[resource.Hash].push_back(resourceLinksTyped[res.Id].Path);
// Хеш теперь доступен по этому расположению.
result.HashToPathNew[resource.Hash].push_back(res.Path);
} else {
@@ -373,13 +373,7 @@ AssetsPreloader::Out_applyResourcesUpdate AssetsPreloader::applyResourcesUpdate(
// Увеличиваем размер, если необходимо
if(orr.MaxNewSize[type] > ResourceLinks[type].size()) {
std::tuple<
ResourceFile::Hash_t,
ResourceHeader,
fs::file_time_type,
fs::path,
bool
> def{
ResourceLink def{
ResourceFile::Hash_t{0},
ResourceHeader(),
fs::file_time_type(),

View File

@@ -6,6 +6,7 @@
#include <filesystem>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
@@ -175,7 +176,7 @@ public:
Out_checkAndPrepareResourcesUpdate checkAndPrepareResourcesUpdate(
const AssetsRegister& instances,
const std::function<ResourceId(EnumAssets type, std::string_view domain, std::string_view key)>& idResolver,
const std::function<void(std::u8string&& resource, ResourceFile::Hash_t hash, fs::path resPath)>& onNewResourceParsed,
const std::function<void(std::u8string&& resource, ResourceFile::Hash_t hash, fs::path resPath)>& onNewResourceParsed = nullptr,
ReloadStatus* status = nullptr
);
@@ -223,6 +224,23 @@ public:
return result;
}
const auto& getResourceLinks() const {
return ResourceLinks;
}
struct Out_Resource {
ResourceFile::Hash_t Hash;
fs::path Path;
};
std::optional<Out_Resource> getResource(EnumAssets type, ResourceId id) const {
const auto& rl = ResourceLinks[static_cast<size_t>(type)];
if(id >= rl.size() || !rl[id].IsExist)
return std::nullopt;
return Out_Resource{rl[id].Hash, rl[id].Path};
}
private:
struct ResourceFindInfo {
// Путь к архиву (если есть), и путь до ресурса
@@ -249,6 +267,15 @@ private:
std::atomic<bool> _Reloading = false;
#endif
struct ResourceLink {
ResourceFile::Hash_t Hash; // Хэш ресурса на диске
/// TODO: клиенту не нужны хедеры
ResourceHeader Header; // Хедер ресурса (со всеми зависимостями)
fs::file_time_type LastWrite; // Время изменения ресурса на диске
fs::path Path; // Путь до ресурса
bool IsExist;
};
Out_checkAndPrepareResourcesUpdate _checkAndPrepareResourcesUpdate(
const AssetsRegister& instances,
const std::function<ResourceId(EnumAssets type, std::string_view domain, std::string_view key)>& idResolver,
@@ -258,15 +285,7 @@ private:
// Привязка Id -> Hash + Header + Timestamp + Path
std::array<
std::vector<
std::tuple<
ResourceFile::Hash_t, // Хэш ресурса на диске
ResourceHeader, // Хедер ресурса (со всеми зависимостями)
fs::file_time_type, // Время изменения ресурса на диске
fs::path, // Путь до ресурса
bool // IsExist
>
>,
std::vector<ResourceLink>,
static_cast<size_t>(AssetType::MAX_ENUM)
> ResourceLinks;
};