network-wiredОсновы сетевого взаимодействия

All Out — прежде всего многопользовательская игра, но CSL устроен так, что вы можете писать игровой процесс почти так, будто это одиночная игра.

Основная идея такова:

circle-info

Всё состояние игрового процесса автоматически синхронизируется с сервера к клиентам. Вам не нужно писать RPC или заниматься «сетевым спавном» объектов.

Авторитет (кто что решает?)

Как правило:

  • Сервер: определяет состояние игрового процесса (урон, награды, спавны, победа/поражение, столкновения через запросы и т. д.)

  • Клиент: отображает и проигрывает косметические эффекты (UI, частицы, тряска экрана, звук)

На практике большая часть вашего кода будет выполняться и на сервере, и на клиентах — вам просто нужно ограждать какая работа выполняется где.

Проверки: локальная против серверной

Две проверки, которые вы будете использовать постоянно:

  • is_local_or_server(): для игрового UI и обработки ввода (выполняется на сервере + локальном клиенте)

  • is_local(): для чисто косметических эффектов (выполняется только на локальном клиенте)

Пример:

Player :: class : Player_Base {
    ao_late_update :: method(dt: float) {
        // Используйте для игрового UI и ввода (выполняется на сервере + локальном клиенте)
        if is_local_or_server() {
            // draw_ability_button(this, Shoot_Ability, 0);
            // Обработка ввода, влияющего на состояние игры
            // Движение обрабатывается автоматически
        }

        // Используйте для чисто косметических эффектов (выполняется только на локальном клиенте)
        if is_local() {
            // UI.text(..., "Ожидание, пока хост начнёт игру...");
            // Эффекты частиц, косметический UI и т. д.
        }
    }
}
circle-exclamation

Состояние, специфичное для клиента

Иногда вам нужно локальное состояние, которое не должно влиять на игровой процесс и не требует репликации:

  • переключатели открытия/закрытия UI

  • таймеры тряски камеры

  • «последний наведённый предмет» в UI инвентаря

Храните это как поля, но читайте и записывайте их только за is_local() проверками.

Правила безопасности в многопользовательском режиме

  • Не используйте глобальные переменные для состояния игрока. Если каждому игроку нужно своё значение, храните его в Player.

  • Осторожнее с «синглтонами». Если вам действительно нужен глобальный менеджер, убедитесь, что он случайно не хранит данные, относящиеся к конкретным игрокам.

  • Предпочитайте детерминированное серверное состояние. Клиент должен реагировать на состояние сервера, а не выдумывать его.

Отладка проблем с сетью

  • Добавьте log_info(...) на серверных путях (не только локально), чтобы вы могли видеть решения, принимаемые авторитетной стороной.

  • Если что-то «работает локально», но не работает для других игроков, обычно это:

    • код, защищённый is_local() который должен быть под серверным авторитетом, или

    • глобальная переменная, перезаписываемая несколькими игроками.

Связанная документация

Последнее обновление