Решили: система повторов боя — это запись ВЫХОДА (боевая лента BattleTape), положенная на
диск, а не «сид + пересимуляция». Файл повтора — заголовок-конверт плюс поток записей (паспорта
состава и чанки ленты), тем же кодеком, которым кооп раздаёт бой по сети. Воспроизведение —
третий наполнитель той же ленты после живого сима и гостя по сети: ReplayFilePlayer кормит
ленту из файла, показ рисует, ничего не зная об источнике.
Почему: реплей обязан пережить балансные правки — иначе заготовки боёв за меню (и будущее «посмотреть бой») ломались бы каждым тюнингом чисел. Пересим даёт тот же бой ТОЛЬКО на той же версии: правка баланса, порядка RNG или обхода систем — рассинхрон, и вся RTS-индустрия версионно замыкает такие реплеи. Лента же держит разрешённые факты (позиции, HP, урон, смерти), а не рецепт их вывода, поэтому правка чисел в новой версии старую запись не касается — стойкость к балансу выходит даром. Цена — файл толще (десятки КБ на бой), принята. Отвергнут и промежуточный «запечь арт в файл, чтобы пережить удаление контента»: состав едет id-строкой и резолвится реестром, удаление id пропускает бойца (деградация), а не рушит бой — этого достаточно, запекать тяжёлый арт не стоит.
Сказано: «Давай не будем делать костыли а сделаем норм реализацию “повторов”, ибо это нам понадобится в будущем» и «Показываем только реальный баланс в бою. Не страшно если потом поедет» (04.08.2026, сессия 0768278b). Отменяет прежнее «записи боя нет и не будет: ядро детерминировано, пресет плюс сид дают тот же бой покадрово» — оно было верно для «дешёвого фона на текущей версии» и неверно для повторов как фичи.
Грабли:
- Резолв скоупа не проверяет ни один тест.
CoopBattleWiringTestsсобирает компоненты руками, минуя VContainer, поэтому DI-ошибка вCombatLifetimeScope.Configureвсплывает только в play mode (та же природа, что у саги сIReadyGate). Компонентную связку реплея покрываютReplayFileTests; сборку ролиReplayдоказывает лишь редактор. - Кольцо снимков ленты — 12 секунд. Влить весь бой из файла разом нельзя: начало вытеснится
раньше, чем показ до него дойдёт. Плеер кормит потоково, держа фронт ленты на опережение впереди
ViewTick— тот же лаг, что у хоста и гостя. - Нарезка чанков была прибита к транспорту. Правило «сколько тиков в чанк, как делить при
переполнении» жило в
TapeStreamer; файловому писателю оно нужно то же. Дублировать — завести второго владельца (тихо битый чанк вместо ошибки). Вынесено вTapeChunkPump(sink и предел параметром); стример на нём, поведение байт-в-байт (93/93 Net-тестов). BattleUnitRegistryтребовалCombatSimulationтолько ради подписки на спавн. Реплею сим не нужен вовсе — сделан необязательным (null → состав только черезRegisterRemote), иначе реплей- скоуп таскал бы бесполезную симуляцию.
Владелец правды: Net/Tape/ReplayFile.cs, ReplayFileWriter.cs, ReplayFilePlayer.cs,
TapeChunkPump.cs, тесты ReplayFileTests, TapeChunkCodecTests, CoopBattleWiringTests.