Исправляет первый баг-репорт мода на Nexus (youkia96581, 11.09.2026):
"Items stored in the space bracelet will disappear after leaving the game
and going online again". Причина была записана в коде как нерешённая:
PlayerVaults - обычный статический Dictionary, save/load не существовало.
ХРАНИЛИЩЕ ТЕПЕРЬ ЖИВЁТ В PlayerDataFile, рядом с рюкзаком игрока. Так
решено после вопроса пользователя "почему не сделать принцип как у ящика?":
ящик хранит вещи тем, что они лежат в чанке (у TileEntity единственный
конструктор TileEntity(Chunk)), а браслету нужен был дом в чём-то, что
движок и так сохраняет. Четыре постфикса - FromPlayer/Write/Read/ToPlayer,
блоб с магией "NECROVLT" и явной длиной дописывается после всего
ванильного. Байтовая часть - в сателлитной сборке: PooledBinaryWriter.Write
не резолвится из основного проекта (CS7069), как и у PyramidWardWriteHelper.
Два дефекта, найденные и убитые по дороге живыми тестами:
1. ModEvents.WorldShuttingDown приходит ПЕРЕД финальным сохранением игрока
(GameManager.SaveAndCleanupWorld: событие на IL_0026, SaveLocalPlayerData
на IL_00c4). Обработчик, чистивший там кэш, затирал хранилище на каждом
корректном выходе. Обработчик убран; свежесть решает авторитетность
ToPlayer, а не таймер.
2. Пустой сессионный кэш трактовался как "хранилища нет" и записывался
поверх настоящего. Путь восстановления имеет право не сработать, удалять
он права не имеет - добавлена страховка LastLoadedVault.
Проверено в игре: положил -> вышел -> запустил заново -> вещи на месте,
блоб на 54 байта сверен в .ttp побайтово.
ТОРГОВЦЫ (npcTraderJoel/Rekt/Bob/Hugh/Jen) - чёрно-белые. Шейдер НЕ
подменяется: материал клонируется со своим шейдером, меняется только
текстура альбедо на обесцвеченную копию, так что свет, нормали и скиннинг
остаются движковыми. Альбедо ищется обходом свойств шейдера, а не по имени:
тело - Game/Character/_Albedo, волосы - Game/Autodesk/_MainTex. Плюс 1%
прозрачности с сохранением _ZWrite. Опрос раз в 2 с, потому что торговцы
стримятся на подходе, а Джен собирается в рантайме.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEXvXg1FSAQJHrvYbeAKqq
Нож некроманта и Кровь некроманта получили собственные модели, а Пирамида
духов - собственную поверхность. Три разных способа, каждый выбран по тому,
как устроен сам предмет.
НОЖ И КРОВЬ - свои префабы в бандлах мода.
Форма записи "#@modfolder(...)?prefab" подтверждена живым примером; геометрия
у обоих ванильная, меняются материал и текстура. Текстуры генерируются
скриптами (см. _private/tools), а не рисуются: правка вида сводится к правке
констант и одному запуску.
Нож: состаренная кость, почти чёрная обмотка, пурпур во впадинах, плюс слой
под ручную роспись рун - он подмешивается в альбедо и в эмиссию, поэтому руны
светятся. Слой пользовательский, генератор его никогда не перезаписывает.
Положение росписи посчитано по геометрии: развёртка выгружена из меша, и
подобрано смещение, при котором вся роспись ложится на одну плоскую грань.
Раньше она перегибалась через кромку, обращённую к игроку.
Кровь: банка вместо мешка. Заодно чинится расхождение, жившее с самого начала -
описание предмета говорило "Банка, наполненная кровью", а наследуемый
medicalBloodBag показывал sackPrefab, обычный мешок. Жидкость перерисована по
маскам мешей, а не перекрашена тинтом: тинт предмета на этот меш не действует
вовсе, у шейдера Game_EntityTintMaskSSS выигрывает _Color материала.
ПИРАМИДА - своя краска в атласе блоков через собственный Harmony-патч.
Ваниль своих текстур блоков не умеет: Texture у блока это индекс в готовом
атласе, а запись краски несёт только TextureId/PaintCost/Group/SortIndex и
никогда путь к картинке. Поэтому CustomBlockPaintPatch дописывает наш слой в
массивы атласа на лету.
Путь через свою модель (Shape="ModelEntity") пробовался и отложен: там
остались нерешёнными столкновения и маджента на дальних экземплярах. Краска
лучше тем, что блок остаётся обычным Shape="New" - со всеми работающими
столкновениями, наведением по E и правильной посадкой, - а поверхность у него
своя. Побочно краска доступна кисточкой под именем "Некротический прах".
Параметры атласа не угаданы, а замерены в игре (BlockAtlasProbePatch): 512x512,
DXT1 для альбедо и DXT5 для нормалей со specular, 10 мип-уровней, массивы
нечитаемые - отсюда GPU-копирование и явные настройки импорта текстур.
Зонд оставлен намеренно: номер краски в blocks.xml (608) это длина ванильного
uvMapping, и после обновления игры он может сдвинуться - зонд печатает
фактические числа при каждом запуске.
Патчи обёрнуты целиком: они работают внутри загрузки игры, где вылетевшее
исключение срывает шаг загрузки.
Resources/necropyramid в коммит не идёт - на него никто не ссылается.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W5F3AVwsusZHMqPBcSQcVJ
Мод для 7 Days to Die 3.2: навык «Некромантия», растущий от счётчика убитых
зомби, тёмное оружие с шестью собственными модами, призывная нежить, пирамида
духов и сюжетный финал через Чёрный портал. Локализация на 13 языках.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MaNro5hAGTzcQ7rJNN2tCX