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

Primeros pasos con CSL

CSL es el lenguaje de programación personalizado de All Out, creado para que escribir juegos multijugador sea tan fácil como crear juegos para un solo jugador.

CSL es el lenguaje de scripting personalizado de All Out. Es tipado estáticamente y se parece más a Go/Odin — excepto el estado de la jugabilidad se sincroniza automáticamente del servidor a los clientes.

No necesitas escribir RPCs, SyncVars ni replicación personalizada. ¡Nosotros nos encargamos de eso por ti!

Tu primer script (main.csl)

Cuando creas un nuevo proyecto, All Out genera un main.csl en tu carpeta de proyecto scripts/ folder.

import "core:ao"

// ============================================================================
// Ciclo de vida global
// ============================================================================

ao_before_scene_load :: proc() {
    // Registrar definiciones de objetos, monedas, etc.
    // Se ejecuta después de que existe la Scene vacía, antes de que se cargue el contenido de la escena.
}

ao_start :: proc() {
    // Se llama una vez cuando comienza la escena.
}

ao_update :: proc(dt: float) {
    // Se llama en cada frame.
}

ao_late_update :: proc(dt: float) {
    // Se llama en cada frame después de ao_update.
}

// ============================================================================
// Ciclo de vida del jugador
// ============================================================================

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

    ao_update :: method(dt: float) {
    }

    ao_late_update :: method(dt: float) {
    }

    ao_end :: method() {
    }
}

Por ejemplo, registra un mensaje cuando se una cada jugador:

Si quieres una explicación más profunda de cuándo se ejecutan estas funciones, consulta Ciclo de vida del juego/fotograma.

Importaciones

Tu main.csl debe importar core:ao y cualquier carpeta que crees (como ui/, abilities/, etc.).

Las importaciones apuntan a carpetas, no a archivos individuales. Una importación de carpeta incluye los .csl archivos de esa carpeta. Las importaciones dentro de esa carpeta se resuelven de forma relativa a ella:

Declaraciones (variables y constantes)

Las declaraciones vinculan un nombre a un valor.

Variables

O bien <tipo> o <expresión> puede omitirse:

Constantes

Las constantes usan :: y deben ser constantes en tiempo de compilación. Pueden ser escalares, cadenas, tipos, valores de procedimiento, arrays o literales compuestos:

Esto no es válido (porque a no es una constante en tiempo de compilación):

Los inicializadores de variables globales también deben ser constantes en tiempo de compilación. Usa ao_before_scene_load o ao_start para la inicialización en tiempo de ejecución.

Variables globales

Las globales usan la misma sintaxis de declaración que las locales. Pueden dejarse inicializadas a cero o inicializadas con constantes en tiempo de compilación, incluidos structs, arrays, valores de procedimiento y typeid valores:

Las globales son mutables y persisten durante toda la vida útil de la instancia del script. Evita usarlas para el estado de jugabilidad por jugador.

Tipos

Tipos primitivos

  • Enteros con signo: s8, s16, s32, s64

  • Enteros sin signo: u8, u16, u32, u64

  • Booleanos: bool

  • Flotantes: f32, f64

  • Alias:

    • int == s64

    • uint == u64

    • float == f32

  • Vectores: v2, v3, v4

  • string

  • typeid

  • cualquier

Los tipos vectoriales

v2 tiene .x, .y; v3 añade .z; v4 añade .w — todos los campos float:

Structs y clases

Los structs son tipos por valor (se copian al asignarse). Las clases son tipos por referencia (las asignas con new).

Structs (tipos por valor)

Clases (tipos por referencia)

Los campos de clase pueden tener valores predeterminados. Una clase derivada puede sobrescribir los valores predeterminados heredados sin redeclarar el campo:

Herencia

Los structs/clases pueden heredar de otros structs/clases:

Procedimientos y métodos

Procedimientos (proc)

Los procedimientos son valores normales y pueden asignarse/almacenarse como cualquier otro valor:

Métodos (método)

Usa method() dentro de un struct/class. Los métodos tienen un parámetro implícito por referencia this de referencia.

Acceso a campos vs llamadas a métodos

Usa . tanto para campos como para métodos:

Cualquier procedimiento puede llamarse como un “método” si su primer parámetro coincide con el tipo del receptor. Los métodos reales y los campos de tipo valor de procedimiento tienen prioridad antes de que CSL recurra a un procedimiento libre coincidente.

Arrays

CSL tiene algunos tipos “similares a arrays” que usarás constantemente:

  • Arreglos fijos: [4]int

  • Slices / arreglos administrados: []T (a menudo usado como “vista de solo lectura” de un array)

  • Arreglos dinámicos: [..]T (lista redimensionable)

  • Arrays no gestionados: [^]T (usado en firmas de API integradas como format_string, log_info, etc. — pasa valores como {a, b, c})

Los arrays dinámicos exponen .data, .count, y .capacity, y usan sintaxis de llamada a método para las operaciones:

Para una guía completa (incluidos los patrones de eliminación), consulta Arreglos y colecciones.

Flujo de control

Si / else

Switch

Usa default: para la cláusula predeterminada. Los cases admiten múltiples valores (separados por comas) y rangos. No hay fallthrough al estilo C.

.. incluye ambos extremos. ..< excluye el extremo superior.

While / for

Basado en iterador personalizado for los bucles requieren un next :: method() -> bool y un campo .

Conversión de tipos

Usa expr.(T) o cast(T)expr Para convertir:

Cuando el tipo objetivo ya se conoce, puedes dejar que CSL lo infiera:

Pasar por referencia: ref (preferido)

Cuando necesites modificar un parámetro, prefiere ref en lugar de punteros en bruto.

Callbacks: punteros a funciones + userdata (sin cierres)

CSL no tiene cierres. En línea proc(...) { ... } no pueden capturar variables circundantes.

Para transportar contexto, combina los callbacks con un campo userdata: Object campo:

Información de tipos (tipos como valores)

typeid los valores pueden pasarse a procs polimórficos:

Buenas prácticas (CSL en All Out)

  • Evita el estado global de jugabilidad. Se conectan varios jugadores: guarda el estado por jugador en Player en su lugar.

  • Dibuja toda la UI del jugador desde Player.ao_late_update. Envuélvelo en is_local_or_server().

  • Usa is_local() solo para invalidaciones visuales específicas del jugador. No cambies el estado de jugabilidad ni de la UI dentro de él.

  • Valores predeterminados orientados a móvil. No dependas del teclado/ratón a menos que tu juego esté explícitamente enfocado en PC.

  • Si no estás seguro de la sintaxis o las API, abre el .csl_engine archivo correspondiente en api_references/ de tu proyecto.

Última actualización