Решили: NetworkCommandRelay удалён, на его месте BattleControlRelay поверх INetTransport.
Сетевая пауза объявляет состояние показа («стоит, поставил такой-то»), а не ставит команду в
очередь симуляции. Интент вправе прислать любой, решение объявляет хост, автором записывается
отправитель пакета, а не то, что он написал внутри.
Почему: прежний релей был NetworkBehaviour и работал по lockstep-модели — штамповал
PauseCommand с будущим TargetTick и рассылал её всем, «чтобы все применили на одном тике».
Модель отвергнута 19.06.2026: клиенты свою симуляцию не тикают вовсе, у гостя её нет — он смотрит
ленту, и применять ему нечего. Вторая причина — сборка: NetworkBehaviour требует NGO и сцены, а
кооп-код обязан жить над швом транспорта, иначе он не тестируется на loopback.
Соло уже устроено правильно, и это решило спор: паузой владеет TimeScaleService, а
CombatSimulation.SetPaused — другой факт («сим заморожен сценарием»). Сетевая пауза просто
объявляет то же состояние всем.
Отдельно принято: отклик оптимистичный (решение 6 ТЗ кооп-вертикали). Нажавший видит паузу сразу, подтверждение хоста перезаписывает состояние и автора. Для паузы это безопасно — хост в ней не отказывает, — а альтернатива «ждать полный RTT» делает кнопку вязкой на ровном месте.
Грабли: комментарий в BattleInputController.OnPauseToggle утверждает, что TimeScaleService
обнуляет Time.deltaTime, «из которого CombatLoopService копит тики». Цикл копит из
Time.unscaledDeltaTime — то есть на паузе симуляция не встаёт, она упирается в границу окна
снимков (AtWindowLimit). Поведение верное и намеренное («сим впереди, показ с лагом»), врёт
комментарий; правку оставила владельцу файла, чтобы не смешивать её с сетевым заходом.
Второе: раздача ленты после ResetBattle обязана сбрасывать нумерацию чанков. Иначе гость примет
чанки нового боя за уже применённые дубли и не увидит бой вовсе — тихо, без единой ошибки.
Владелец правды: Net/BattleControlRelay.cs, Net/Tape/BattleTapeBroadcast.cs; тесты
BattleControlRelayTests (единственность состояния, авторство, оптимистичный отклик) и
BattleTapeBroadcastTests (раздаётся только досчитанный тик, хвост один раз, рестарт обнуляет).