Решили: хост хранит ленту боя целиком, а гость, подключившийся посреди боя, получает её с нуля — порциями по несколько чанков за кадр, под общей паузой показа.

Почему: лента адресуется номерами чанков, и приёмник считает недостающим всё от нуля до наибольшего виденного. Гость, пришедший на пятисотом, объявил бы дырами пятьсот номеров и просил бы их бесконечно: у хоста в истории лежали последние тридцать два. Получив бой целиком, он видит нумерацию непрерывной, может отмотать назад и держит на руках полный бой — то есть заодно готов повтор.

Отвергнута моя альтернатива — сдвинуть базу отсчёта к первому полученному чанку. Дешевле в байтах и не требует хранения, но гость остаётся без ленты боя и без перемотки, а «посмотреть, что было» становится отдельной работой вместо бесплатной.

Сказано: «Так почему бы не хранить все чанки последнего (и текущего боя?). А потом их стирать просто, если вдруг они тяжелые. А игрок при подключении их считывает, получает.» и «Когда кто-то пытается подключиться - все встает на паузу. “Загрузка”… пишется обоим. Ему передается вся информация, он запускает View в том месте. где были все игроки до этого. Потом отчет и продолжения. В чем проблема то?» (Макс, 04.08.2026, сессия fef16360).

Грабли: я спорила с тем, чего он не предлагал. Прочитала «передать историю» как «проиграть бой с начала» и возражала, что гость отстанет от хоста на минуты. Его «View в том месте, где были все игроки» это снимало сразу — история едет как ДАННЫЕ, показ встаёт в текущую точку. Возражай я по тому, что сказано, разговор был бы на две реплики короче.

Второе, из проверки перед работой: общей паузы показа достаточно, симуляцию останавливать не надо. Пауза у нас про показ, сим при этом убегает вперёд, но упирается в окно снимков и сам себя придерживает — «все стоят на одном кадре» выходит даром.

Третье: ReplayFileWriter написан и не подключён ни к чему — единственное упоминание конструктора в проекте было его собственное объявление. Та же болезнь, что была у курсоров.

Владелец правды: Net/Tape/TapeStreamer.cs (KeepWholeBattle, PumpBackfill), Net/Tape/TapeIntake.cs (RequestWholeBattle), тест TapeDeliveryTests.JoiningMidBattle_GetsTheWholeTape_InPortions.