Более нормализованная обработка ресурсов на клиенте

This commit is contained in:
2026-01-07 13:56:10 +06:00
parent 5135aa30a7
commit a29e772f35
5 changed files with 102 additions and 290 deletions

View File

@@ -1662,7 +1662,7 @@ void VulkanRenderSession::pushStageTickSync() {
CP.pushStageTickSync();
}
void VulkanRenderSession::tickSync(const TickSyncData& data) {
void VulkanRenderSession::tickSync(TickSyncData& data) {
// Изменение ассетов
// Профили
// Чанки
@@ -1680,77 +1680,16 @@ void VulkanRenderSession::tickSync(const TickSyncData& data) {
if(auto iter = data.Profiles_Lost.find(EnumDefContent::Voxel); iter != data.Profiles_Lost.end())
mcpData.ChangedVoxels.insert(mcpData.ChangedVoxels.end(), iter->second.begin(), iter->second.end());
std::vector<const AssetEntry*> modelResources;
std::vector<AssetsModel> modelLost;
if(auto iter = data.Assets_ChangeOrAdd.find(EnumAssets::Model); iter != data.Assets_ChangeOrAdd.end()) {
const auto& list = ServerSession->Assets[EnumAssets::Model];
for(ResourceId id : iter->second) {
auto entryIter = list.find(id);
if(entryIter == list.end())
continue;
modelResources.push_back(&entryIter->second);
}
}
if(auto iter = data.Assets_Lost.find(EnumAssets::Model); iter != data.Assets_Lost.end())
modelLost.insert(modelLost.end(), iter->second.begin(), iter->second.end());
std::vector<AssetsModel> changedModels;
if(!modelResources.empty() || !modelLost.empty()) {
const auto& modelAssets = ServerSession->Assets[EnumAssets::Model];
changedModels = MP.onModelChanges(std::move(modelResources), std::move(modelLost), &modelAssets);
}
if(!data.AssetsModels.empty())
changedModels = MP.onModelChanges(std::move(data.AssetsModels));
if(TP) {
std::vector<TextureProvider::TextureUpdate> textureResources;
std::vector<AssetsTexture> textureLost;
if(auto iter = data.Assets_ChangeOrAdd.find(EnumAssets::Texture); iter != data.Assets_ChangeOrAdd.end()) {
const auto& list = ServerSession->Assets[EnumAssets::Texture];
for(ResourceId id : iter->second) {
auto entryIter = list.find(id);
if(entryIter == list.end())
continue;
textureResources.push_back({
.Id = id,
.Width = entryIter->second.Width,
.Height = entryIter->second.Height,
.Pixels = entryIter->second.Pixels,
.Domain = entryIter->second.Domain,
.Key = entryIter->second.Key
});
}
}
if(auto iter = data.Assets_Lost.find(EnumAssets::Texture); iter != data.Assets_Lost.end())
textureLost.insert(textureLost.end(), iter->second.begin(), iter->second.end());
if(!textureResources.empty() || !textureLost.empty())
TP->onTexturesChanges(std::move(textureResources), std::move(textureLost));
}
if(TP && !data.AssetsTextures.empty())
TP->onTexturesChanges(std::move(data.AssetsTextures));
std::vector<AssetsNodestate> changedNodestates;
if(NSP) {
std::vector<const AssetEntry*> nodestateResources;
std::vector<AssetsNodestate> nodestateLost;
if(auto iter = data.Assets_ChangeOrAdd.find(EnumAssets::Nodestate); iter != data.Assets_ChangeOrAdd.end()) {
const auto& list = ServerSession->Assets[EnumAssets::Nodestate];
for(ResourceId id : iter->second) {
auto entryIter = list.find(id);
if(entryIter == list.end())
continue;
nodestateResources.push_back(&entryIter->second);
}
}
if(auto iter = data.Assets_Lost.find(EnumAssets::Nodestate); iter != data.Assets_Lost.end())
nodestateLost.insert(nodestateLost.end(), iter->second.begin(), iter->second.end());
if(!nodestateResources.empty() || !nodestateLost.empty() || !changedModels.empty())
changedNodestates = NSP->onNodestateChanges(std::move(nodestateResources), std::move(nodestateLost), changedModels);
if(NSP && (!data.AssetsNodestates.empty() || !changedModels.empty())) {
changedNodestates = NSP->onNodestateChanges(std::move(data.AssetsNodestates), std::move(changedModels));
}
if(!changedNodestates.empty()) {
@@ -2050,29 +1989,7 @@ void VulkanRenderSession::ensureEntityTexture() {
if(EntityTextureReady || !TP || !NSP)
return;
auto iter = ServerSession->Assets.find(EnumAssets::Texture);
if(iter == ServerSession->Assets.end() || iter->second.empty())
return;
const AssetEntry* picked = nullptr;
for(const auto& [id, entry] : iter->second) {
if(entry.Key == "default.png") {
picked = &entry;
break;
}
}
if(!picked) {
for(const auto& [id, entry] : iter->second) {
if(entry.Key == "grass.png") {
picked = &entry;
break;
}
}
}
if(!picked)
picked = &iter->second.begin()->second;
updateTestQuadTexture(NSP->getTextureId(picked->Id));
return;
}
void VulkanRenderSession::ensureAtlasLayerPreview() {

View File

@@ -89,11 +89,8 @@ public:
}
// Применяет изменения, возвращая все затронутые модели
std::vector<AssetsModel> onModelChanges(std::vector<const AssetEntry*> newOrChanged,
std::vector<AssetsModel> lost,
const std::unordered_map<ResourceId, AssetEntry>* modelAssets) {
std::vector<AssetsModel> onModelChanges(std::vector<AssetsModelUpdate> entries) {
std::vector<AssetsModel> result;
(void)modelAssets;
std::move_only_function<void(ResourceId)> makeUnready;
makeUnready = [&](ResourceId id) {
@@ -124,29 +121,15 @@ public:
iterModel->second.Ready = false;
};
for(ResourceId lostId : lost) {
makeUnready(lostId);
}
for(ResourceId lostId : lost) {
auto iterModel = Models.find(lostId);
if(iterModel == Models.end())
continue;
Models.erase(iterModel);
}
for(const AssetEntry* entry : newOrChanged) {
if(!entry)
continue;
const AssetsModel key = entry->Id;
for(const AssetsModelUpdate& entry : entries) {
const AssetsModel key = entry.Id;
result.push_back(key);
makeUnready(key);
ModelObject model;
const HeadlessModel& hm = entry->Model;
const HeadlessModel::Header& header = entry->ModelHeader;
const HeadlessModel& hm = entry.Model;
const HeadlessModel::Header& header = entry.Header;
try {
model.TextureMap.clear();
@@ -587,30 +570,25 @@ public:
}
// Применяет изменения, возвращая все затронутые модели
std::vector<AssetsTexture> onTexturesChanges(std::vector<TextureUpdate> newOrChanged, std::vector<AssetsTexture> lost) {
std::vector<AssetsTexture> onTexturesChanges(std::vector<AssetsTextureUpdate> entries) {
std::lock_guard lock(Mutex);
std::vector<AssetsTexture> result;
for(auto& update : newOrChanged) {
const AssetsTexture key = update.Id;
for(auto& entry : entries) {
const AssetsTexture key = entry.Id;
result.push_back(key);
if(update.Width == 0 || update.Height == 0 || update.Pixels.empty())
if(entry.Width == 0 || entry.Height == 0 || entry.Pixels.empty())
continue;
Atlas->updateTexture(key, StoredTexture(
update.Width,
update.Height,
std::move(update.Pixels)
entry.Width,
entry.Height,
std::move(entry.Pixels)
));
bool animated = false;
if(auto anim = getDefaultAnimation(update.Key, update.Width, update.Height)) {
AnimatedSources[key] = *anim;
animated = true;
} else {
AnimatedSources.erase(key);
}
AnimatedSources.erase(key);
NeedsUpload = true;
@@ -618,19 +596,11 @@ public:
uint32_t idx = debugTextureLogCount.fetch_add(1);
if(idx < 128) {
LOG.debug() << "Texture loaded id=" << key
<< " key=" << update.Domain << ':' << update.Key
<< " size=" << update.Width << 'x' << update.Height
<< " size=" << entry.Width << 'x' << entry.Height
<< " animated=" << (animated ? 1 : 0);
}
}
for(AssetsTexture key : lost) {
result.push_back(key);
Atlas->freeTexture(key);
AnimatedSources.erase(key);
NeedsUpload = true;
}
std::sort(result.begin(), result.end());
auto eraseIter = std::unique(result.begin(), result.end());
result.erase(eraseIter, result.end());
@@ -844,27 +814,16 @@ public:
{}
// Применяет изменения, возвращает изменённые описания состояний
std::vector<AssetsNodestate> onNodestateChanges(std::vector<const AssetEntry*> newOrChanged, std::vector<AssetsNodestate> lost, std::vector<AssetsModel> changedModels) {
std::vector<AssetsNodestate> onNodestateChanges(std::vector<AssetsNodestateUpdate> newOrChanged, std::vector<AssetsModel> changedModels) {
std::vector<AssetsNodestate> result;
for(ResourceId lostId : lost) {
auto iterNodestate = Nodestates.find(lostId);
if(iterNodestate == Nodestates.end())
continue;
result.push_back(lostId);
Nodestates.erase(iterNodestate);
}
for(const AssetEntry* entry : newOrChanged) {
if(!entry)
continue;
const AssetsNodestate key = entry->Id;
for(const AssetsNodestateUpdate& entry : newOrChanged) {
const AssetsNodestate key = entry.Id;
result.push_back(key);
PreparedNodeState nodestate;
static_cast<HeadlessNodeState&>(nodestate) = entry->Nodestate;
nodestate.LocalToModel.assign(entry->NodestateHeader.Models.begin(), entry->NodestateHeader.Models.end());
static_cast<HeadlessNodeState&>(nodestate) = entry.Nodestate;
nodestate.LocalToModel.assign(entry.Header.Models.begin(), entry.Header.Models.end());
Nodestates.insert_or_assign(key, std::move(nodestate));
if(key < 64) {
@@ -1321,7 +1280,7 @@ public:
virtual void prepareTickSync() override;
virtual void pushStageTickSync() override;
virtual void tickSync(const TickSyncData& data) override;
virtual void tickSync(TickSyncData& data) override;
virtual void setCameraPos(WorldId_t worldId, Pos::Object pos, glm::quat quat) override;