Files
LuaVox/Src/Client/AssetsManager.hpp

151 lines
4.9 KiB
C++

#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>
#include "Client/AssetsCacheManager.hpp"
#include "Common/Abstract.hpp"
#include "TOSLib.hpp"
namespace LV::Client {
namespace fs = std::filesystem;
class AssetsManager {
public:
using Ptr = std::shared_ptr<AssetsManager>;
using AssetType = EnumAssets;
using AssetId = ResourceId;
struct ResourceKey {
Hash_t Hash{};
AssetType Type{};
std::string Domain;
std::string Key;
AssetId Id = 0;
};
struct BindInfo {
AssetType Type{};
AssetId LocalId = 0;
std::string Domain;
std::string Key;
Hash_t Hash{};
std::vector<uint8_t> Header;
};
struct BindResult {
AssetId LocalId = 0;
bool Changed = false;
bool NewBinding = false;
std::optional<AssetId> ReboundFrom;
};
struct PackRegister {
std::vector<fs::path> Packs;
};
struct PackResource {
AssetType Type{};
AssetId LocalId = 0;
std::string Domain;
std::string Key;
Resource Res;
Hash_t Hash{};
std::u8string Header;
};
struct PackReloadResult {
std::array<std::vector<AssetId>, static_cast<size_t>(AssetType::MAX_ENUM)> ChangeOrAdd;
std::array<std::vector<AssetId>, static_cast<size_t>(AssetType::MAX_ENUM)> Lost;
};
struct ParsedHeader {
AssetType Type{};
std::vector<AssetId> ModelDeps;
std::vector<AssetId> TextureDeps;
std::vector<std::vector<uint8_t>> TexturePipelines;
};
static Ptr Create(asio::io_context& ioc, const fs::path& cachePath,
size_t maxCacheDirectorySize = 8 * 1024 * 1024 * 1024ULL,
size_t maxLifeTime = 7 * 24 * 60 * 60) {
return Ptr(new AssetsManager(ioc, cachePath, maxCacheDirectorySize, maxLifeTime));
}
PackReloadResult reloadPacks(const PackRegister& reg);
BindResult bindServerResource(AssetType type, AssetId serverId, std::string domain, std::string key,
const Hash_t& hash, std::vector<uint8_t> header);
std::optional<AssetId> unbindServerResource(AssetType type, AssetId serverId);
void clearServerBindings();
const BindInfo* getBind(AssetType type, AssetId localId) const;
std::vector<uint8_t> rebindHeader(AssetType type, const std::vector<uint8_t>& header, bool serverIds = true);
static std::optional<ParsedHeader> parseHeader(AssetType type, const std::vector<uint8_t>& header);
void pushResources(std::vector<Resource> resources) {
Cache->pushResources(std::move(resources));
}
void pushReads(std::vector<ResourceKey> reads);
std::vector<std::pair<ResourceKey, std::optional<Resource>>> pullReads();
AssetId getOrCreateLocalId(AssetType type, std::string_view domain, std::string_view key);
std::optional<AssetId> getLocalIdFromServer(AssetType type, AssetId serverId) const;
private:
struct DomainKey {
std::string Domain;
std::string Key;
bool Known = false;
};
using IdTable = std::unordered_map<
std::string,
std::unordered_map<std::string, AssetId, detail::TSVHash, detail::TSVEq>,
detail::TSVHash,
detail::TSVEq>;
using PackTable = std::unordered_map<
std::string,
std::unordered_map<std::string, PackResource, detail::TSVHash, detail::TSVEq>,
detail::TSVHash,
detail::TSVEq>;
AssetsManager(asio::io_context& ioc, const fs::path& cachePath,
size_t maxCacheDirectorySize, size_t maxLifeTime);
AssetId allocateLocalId(AssetType type);
AssetId resolveLocalIdMutable(AssetType type, AssetId localId);
AssetId resolveLocalId(AssetType type, AssetId localId) const;
void unionLocalIds(AssetType type, AssetId fromId, AssetId toId, std::optional<AssetId>* reboundFrom);
std::optional<PackResource> findPackResource(AssetType type, std::string_view domain, std::string_view key) const;
Logger LOG = "Client>AssetsManager";
AssetsCacheManager::Ptr Cache;
std::array<IdTable, static_cast<size_t>(AssetType::MAX_ENUM)> DKToLocal;
std::array<std::vector<DomainKey>, static_cast<size_t>(AssetType::MAX_ENUM)> LocalToDK;
std::array<std::vector<AssetId>, static_cast<size_t>(AssetType::MAX_ENUM)> LocalParent;
std::array<std::vector<AssetId>, static_cast<size_t>(AssetType::MAX_ENUM)> ServerToLocal;
std::array<std::vector<std::optional<BindInfo>>, static_cast<size_t>(AssetType::MAX_ENUM)> BindInfos;
std::array<PackTable, static_cast<size_t>(AssetType::MAX_ENUM)> PackResources;
std::array<AssetId, static_cast<size_t>(AssetType::MAX_ENUM)> NextLocalId{};
std::unordered_map<Hash_t, std::vector<ResourceKey>> PendingReadsByHash;
std::vector<std::pair<ResourceKey, std::optional<Resource>>> ReadyReads;
};
} // namespace LV::Client