Торговец снова становится призраком после выгрузки чанка
Баг со стрима: торговец, ставший чёрно-белым и полупрозрачным, наутро снова обычный человек. Догадка была про обновление ассортимента - не подтвердилась, и это стоит записать, потому что по часам лавки модель не трогает ВООБЩЕ ничего: TraderData при сбросе переписывает только PrimaryInventory и lastInventoryUpdate, а TraderArea.SetClosed ходит по блокам TraderOnOff - двери, замки, BlockLight, динамик - и до сущности торговца не дотягивается. Настоящая причина в EntityFactory.CreateEntityOperation.CompleteEntity: `entity.entityId = ecd.id`, то есть сохранённый айди ВОССТАНАВЛИВАЕТСЯ. Торговцы стримятся на подходе и точно так же выгружаются, когда игрок уходит на ночь. Возвращается он - торговец собран заново: новый GameObject, новые рендереры, ванильные материалы, ТОТ ЖЕ entityId. А в патче стоял HashSet<int> Ghosted - "этот айди я уже обработал". Айди в наборе есть, свип проходит мимо, торговец остаётся живым человеком до конца сессии. Отсюда и "на следующее утро": симптом идёт не за часами лавки, а за чанком, в котором лавка стоит. Ghosted стал Dictionary<int, GhostBody>, где GhostBody держит массив рендереров, которые патч взял себе. IsIntact проверяет их: у Unity уничтоженный объект сравнивается с null, так что подмена модели видна прямо, и та же проверка бесплатно закрывает любую другую пересборку, не только выгрузку чанка. Prune чистит Converted и TintedMaterials от уничтоженных объектов. Без него оба списка росли бы на одного торговца за каждую пересборку, а Retint/Reapply ходили бы по обломкам. Материал, выданный через renderer.materials, принадлежит рендереру и умирает вместе с ним - одного прохода хватает на оба списка. В лог добавлена строка "entity <id> came back with a new model" - ровно та, которой не хватало, чтобы найти это за один заход вместо разбора в декомпиляторе. Счётчик в necroghost переименован: со словарём он означает "торговцев под присмотром сейчас", а не "id, которые когда-либо видели" - он теперь падает и растёт. Не проверено в игре: нужен заход к торговцу, выгрузка лавки и возвращение. --- Traders go back to being ghosts after a chunk unload Reported from the stream: a trader who had gone black-and-white and translucent was an ordinary person again the next morning. The guess was the restock - it was wrong, and that is worth recording, because nothing on the shop's clock touches the model at all: TraderData's reset rewrites PrimaryInventory and lastInventoryUpdate only, and TraderArea.SetClosed walks TraderOnOff blocks - doors, locks, BlockLight, speaker - and never reaches the trader entity. The real cause is in EntityFactory.CreateEntityOperation.CompleteEntity: `entity.entityId = ecd.id`, so the saved id is RESTORED. Traders are streamed in on approach and streamed out the same way when the player leaves for the night. On return the trader is rebuilt from scratch - new GameObject, new renderers, the game's own materials - carrying THE SAME entityId. The patch held a HashSet<int> Ghosted, meaning "this id is done". The id was still in the set, the sweep skipped him, and he stayed an ordinary person for the rest of the session. Hence "the next morning": the symptom follows the chunk the shop sits in, not the shop's clock. Ghosted is now a Dictionary<int, GhostBody>, the value holding the renderers the patch took over. IsIntact tests them: Unity's destroyed objects compare equal to null, so a swapped model is directly visible, and the same check covers any other rebuild for free. Prune drops destroyed entries from Converted and TintedMaterials. Without it both lists would grow by one trader's worth per rebuild and Retint/Reapply would be walking the wreckage. A material assigned through renderer.materials is owned by that renderer and dies with it, so one pass settles both. A log line was added - "entity <id> came back with a new model" - the exact line that was missing to find this in one visit rather than in a decompiler. The necroghost counter was reworded: with a dictionary it means "traders held as ghosts right now", not "ids ever seen" - it now falls as well as rises. Not tested in game: needs a visit, a shop unload and a return. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MnwP2Dt1vk8bUPJ452EoVL
This commit is contained in:
co-authored by
Claude Opus 5
parent
7172681353
commit
20af2bbe6c
Binary file not shown.
Reference in New Issue
Block a user