Решили: гость получает состояние забега снимком, а команды только отправляет хосту. Своего держателя, лога команд и обработчика у него нет вовсе.
Почему: очевидной альтернативой было «гость применяет тот же лог команд у себя» — красиво на
бумаге и ровно так описан реконнект («снимок плюс хвост»). Но сегодня четыре транзакции идут мимо
шины (TrySpendGold, TryAddRelic, TrySpendRestart, IncreaseCapacity — они отвечают «вышло
ли» синхронно, и их переезд это отложенный шаг транзакций, ТЗ кооп-вертикали §10). Применяющий лог
гость потерял бы ровно эти изменения — и узнал бы об этом не сразу, а через час игры, разъехавшимся
золотом. Снимок же несёт состояние целиком и мимо шины проехать не может по устройству.
Вторая причина — это уже принятая у нас модель: гость не тикает симуляцию, а смотрит ленту. Забег устроен так же, и одинаковость тут дороже экономии трафика.
Цена названа честно: снимок уезжает целиком на каждое изменение, это несколько килобайт. Дельта имела бы смысл при десятках снимков в секунду, а их единицы за узел.
Снимок уходит там же, где пишется сейв. Точки совпадают намеренно: гость получает ровно то, что
легло бы на диск, поэтому «у нас разные состояния» и «состояние разошлось с сейвом» — один баг, а не
два. Отсюда же общий владелец правил сериализации SaveJson: вторая копия настроек Newtonsoft
разошлась бы молча, а без конвертера Vector2 сериализатор вообще уходит в рекурсию — то есть
вешал бы отправку на первой позиции слота.
Грабли: роль выбирает состав — значит наружу из сеанса торчат два контракта, и оба пришлось
назвать отдельно (ISessionRunCommands, ISessionRunState). Причина не в красоте: под теми же
интерфейсами в корне стоят вечные роутеры, и спроси роутер свой же интерфейс — резолв ушёл бы вверх
по контейнеру и вернулся к нему самому.
Вторые грабли, стоившие прогона: Enum.IsDefined для байтового перечисления бросает на int —
приведение к (int) в проверке вида команды роняло разбор целиком.
Владелец правды: Game/Session/Net/ (GuestRunState, RemoteRunCommands, RunStateBroadcast,
кодеки), тест GuestRunSyncTests.