#pragma once #include #include #include #include #include #include #include #include #include #include #include #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; 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 Header; }; struct BindResult { AssetId LocalId = 0; bool Changed = false; bool NewBinding = false; std::optional ReboundFrom; }; struct PackRegister { std::vector 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, static_cast(AssetType::MAX_ENUM)> ChangeOrAdd; std::array, static_cast(AssetType::MAX_ENUM)> Lost; }; struct ParsedHeader { AssetType Type{}; std::vector ModelDeps; std::vector TextureDeps; std::vector> 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 header); std::optional unbindServerResource(AssetType type, AssetId serverId); void clearServerBindings(); const BindInfo* getBind(AssetType type, AssetId localId) const; std::vector rebindHeader(AssetType type, const std::vector& header, bool serverIds = true); static std::optional parseHeader(AssetType type, const std::vector& header); void pushResources(std::vector resources) { Cache->pushResources(std::move(resources)); } void pushReads(std::vector reads); std::vector>> pullReads(); AssetId getOrCreateLocalId(AssetType type, std::string_view domain, std::string_view key); AssetId getOrCreateLocalFromServer(AssetType type, AssetId serverId); std::optional 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, detail::TSVHash, detail::TSVEq>; using PackTable = std::unordered_map< std::string, std::unordered_map, detail::TSVHash, detail::TSVEq>; AssetsManager(asio::io_context& ioc, const fs::path& cachePath, size_t maxCacheDirectorySize, size_t maxLifeTime); AssetId allocateLocalId(AssetType type); AssetId ensureServerLocalId(AssetType type, AssetId serverId); AssetId resolveLocalIdMutable(AssetType type, AssetId localId); AssetId resolveLocalId(AssetType type, AssetId localId) const; void unionLocalIds(AssetType type, AssetId fromId, AssetId toId, std::optional* reboundFrom); std::optional findPackResource(AssetType type, std::string_view domain, std::string_view key) const; Logger LOG = "Client>AssetsManager"; AssetsCacheManager::Ptr Cache; std::array(AssetType::MAX_ENUM)> DKToLocal; std::array, static_cast(AssetType::MAX_ENUM)> LocalToDK; std::array, static_cast(AssetType::MAX_ENUM)> LocalParent; std::array, static_cast(AssetType::MAX_ENUM)> ServerToLocal; std::array>, static_cast(AssetType::MAX_ENUM)> BindInfos; std::array(AssetType::MAX_ENUM)> PackResources; std::array(AssetType::MAX_ENUM)> NextLocalId{}; std::unordered_map> PendingReadsByHash; std::vector>> ReadyReads; }; } // namespace LV::Client