Решили: состав боевого скоупа выбирает роль сеанса. IBattleAuthority, NetBattleAuthority и
BattleRole удалены целиком вместе с пятью ветвлениями, которые их спрашивали.
Почему это стало можно: обоснование интерфейса было честным и записано в его же докстринге — бой поднимался на буте, в главном меню, когда сети ещё нет, и решить роль регистрацией было нельзя. Причина отпала сегодняшним заходом: бой рождается по требованию внутри мероприятия, мероприятие — внутри сеанса, а роль сеанса выбрана в момент открытия и за его жизнь не меняется.
Соло отдельной ролью НЕ стало, хотя напрашивалось. Соло — это тот же владелец, просто без
поднятого транспорта: разница между «играю один» и «играю хостом» вся в том, есть ли кому слать.
Заведи мы третью роль — включение лобби посреди забега потребовало бы переоткрыть сеанс, то есть
пересобрать состояние ради одного флага. Цена решения названа: у вещателя ленты осталась одна
проверка, и она спрашивает соединение (IsRunning), а не роль.
Что развело классы. BattleRosterRelay делал обе стороны в одном теле и потому обязан был
спрашивать роль. Разделён на BattleRosterAnnouncer (владелец объявляет спавны) и
BattleRosterIntake (гость складывает паспорта). Тем же резом из CombatLoopService ушла гостевая
ветка: у гостя теперь GuestPlaybackLoop — не «цикл с выключенным тиком», а другой класс на десять
строк.
Роль спрашивается у предка, а не приезжает параметром боя: она свойство сеанса, бой её только
читает. Parent.Container к моменту Configure уже заполнен — это проверено по исходнику VContainer
1.18 ещё в заходе про арену. Сеанса нет вовсе (одиночная боевая сцена) — собираем владельческий
состав: там некому быть хостом и нечего принимать.
Что стало с тестами. «Гость не раздаёт» проверять больше негде и незачем: у гостя вещателя нет как объекта — это сильнее теста, ровно как «у гостя нет сервиса, пишущего сейв». Осталась вторая половина того же правила, которую составом не решить: соло не должен платить нарезкой чанков в пустоту, и она проверяется узлом с закрытым соединением.
Побочно закрылось: долг §3.22 (повторный бой у гостя не начинался, потому что сбросить приёмник и реестр было некому) сменил способ починки. Сброса больше не нужно вовсе — новый бой это новый скоуп, а приёмник и реестр рождаются вместе с ним.
Владелец правды: Game/CombatLifetimeScope.RegisterCoop, тесты CoopBattleWiringTests.