For the complete documentation index, see llms.txt. This page is also available as Markdown.

Начало работы с CSL

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

CSL — это собственный скриптовый язык All Out. Он статически типизирован и больше всего похож на Go/Odin — за исключением состояние игрового процесса автоматически синхронизируется с сервера на клиентов.

Вам не нужно писать RPC, SyncVar или собственную репликацию. Мы делаем это за вас!

Ваш первый скрипт (main.csl)

Когда вы создаёте новый проект, All Out создаёт main.csl в папке вашего проекта scripts/ папке.

import "core:ao"

// ============================================================================
// Глобальный жизненный цикл
// ============================================================================

ao_before_scene_load :: proc() {
    // Зарегистрировать определения предметов, валют и т. д.
    // Выполняется после создания пустой Scene, до загрузки содержимого сцены.
}

ao_start :: proc() {
    // Вызывается один раз при запуске сцены.
}

ao_update :: proc(dt: float) {
    // Вызывается каждый кадр.
}

ao_late_update :: proc(dt: float) {
    // Вызывается каждый кадр после ao_update.
}

// ============================================================================
// Жизненный цикл игрока
// ============================================================================

Player :: class : Player_Base {
    ao_start :: method() {
    }

    ao_update :: method(dt: float) {
    }

    ao_late_update :: method(dt: float) {
    }

    ao_end :: method() {
    }
}

Например, выводите сообщение в лог при подключении каждого игрока:

Если вам нужно более глубокое объяснение того, когда выполняются эти функции, см. Жизненный цикл игры/кадра.

Импорты

Ваш main.csl должен импортировать core:ao и любые созданные вами папки (например ui/, abilities/, и т. д).

Импорты указывают на папки, а не на отдельные файлы. Импорт папки включает .csl файлы в этой папке. Импорты внутри этой папки разрешаются относительно неё:

Объявления (переменные и константы)

Объявления связывают имя со значением.

Переменные

Можно опустить либо <type> или <expression> следующее:

Константы

Константы используют :: и должны быть константами времени компиляции. Они могут быть скалярами, строками, типами, значениями процедур, массивами или составными литералами:

Это недопустимо (потому что a не является константой времени компиляции):

Инициализаторы глобальных переменных тоже должны быть константами времени компиляции. Используйте ao_before_scene_load или ao_start для инициализации во время выполнения.

Глобальные переменные

Глобальные переменные используют тот же синтаксис объявления, что и локальные. Их можно оставить с нулевой инициализацией или инициализировать константами времени компиляции, включая структуры, массивы, значения процедур и typeid значения:

Глобальные переменные изменяемы и сохраняются в течение жизни экземпляра скрипта. Не используйте их для состояния игрового процесса отдельного игрока.

Типы

Примитивные типы

  • Знаковые целые числа: s8, s16, s32, s64

  • Беззнаковые целые числа: u8, u16, u32, u64

  • Булевы значения: bool

  • Числа с плавающей точкой: f32, f64

  • Псевдонимы:

    • int == s64

    • uint == u64

    • float == f32

  • Векторы: v2, v3, v4

  • string

  • typeid

  • любой

Векторные типы

v2 имеют .x, .y; v3 добавляют .z; v4 добавляют .w — все поля float:

Структуры и классы

Структуры — это типы значений (копируются при присваивании). Классы — это ссылочные типы (их выделяют с помощью new).

Структуры (типы-значения)

Классы (ссылочные типы)

Поля класса могут иметь значения по умолчанию. Производный класс может переопределять унаследованные значения по умолчанию без повторного объявления поля:

Наследование

Структуры/классы могут наследоваться от других структур/классов:

Процедуры и методы

Процедуры (proc)

Процедуры — это обычные значения, и их можно присваивать/хранить как любые другие значения:

Методы (method)

Используйте method() внутри структуры/класса. Методы имеют неявный this параметр по ссылке.

Доступ к полям и вызовы методов

Используйте . для полей и методов:

Любую процедуру можно вызвать как «метод», если её первый параметр совпадает с типом получателя. Настоящие методы и поля типа, содержащие значение процедуры, имеют приоритет, прежде чем CSL перейдёт к подходящей свободной процедуре.

Массивы

В CSL есть несколько «похожих на массивы» типов, которые вы будете использовать постоянно:

  • Фиксированные массивы: [4]int

  • Срезы / управляемые массивы: []T (часто используется как «только для чтения» представление массива)

  • Динамические массивы: [..]T (изменяемый по размеру список)

  • Неуправляемые массивы: [^]T (используется в сигнатурах встроенного API, например format_string, log_info, и т. д. — передавайте значения как {a, b, c})

Динамические массивы предоставляют .data, .count, а .capacity, а для операций используют синтаксис вызова методов:

Полное руководство (включая шаблоны удаления) см. Массивы и коллекции.

Управление потоком

Если / иначе

Оператор switch

Используйте default: для ветки default. Варианты поддерживают несколько значений (через запятую) и диапазоны. Нет проваливания, как в C.

.. включает обе границы. ..< исключает верхнюю границу.

Пока / for

Циклы на основе пользовательских итераторов for требуют next :: method() -> bool и current поля.

Приведение типов

Используйте expr.(T) или cast(T)expr для преобразования типа:

Когда целевой тип уже известен, вы можете позволить CSL вывести его:

Передача по ссылке: ref (предпочтительно)

Когда вам нужно изменить параметр, предпочитайте ref ссылки вместо сырых указателей.

Колбэки: указатели на функции + userdata (без замыканий)

В CSL нет замыканий. Встроенный proc(...) { ... } не может захватывать окружающие переменные.

Чтобы передавать контекст, сочетайте колбэки с полем userdata: Object полем:

Информация о типах (типы как значения)

typeid значения можно передавать полиморфным процедурам:

Лучшие практики (CSL в All Out)

  • Избегайте глобального состояния игрового процесса. Подключаются несколько игроков — храните состояние каждого игрока в Player вместо этого.

  • Стройте весь UI игрока из Player.ao_late_update. Оберните это в is_local_or_server().

  • Используйте is_local() только для визуальных переопределений, специфичных для игрока. Не изменяйте внутри него состояние игрового процесса или UI.

  • По умолчанию — сначала мобильные устройства. Не полагайтесь на ввод с клавиатуры/мыши, если только ваша игра явно не ориентирована на ПК.

  • Если вы не уверены в синтаксисе или API, откройте соответствующий .csl_engine файл в api_references/ вашем проекте.

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