network-wiredNetworking Fundamentals

All Out is multiplayer-first, but CSL is designed so you can write gameplay almost like it’s singleplayer.

The key idea is:

circle-info

All gameplay state is automatically synced from the server to clients. You do not need to write RPCs or “network spawn” things.

Authority (who decides what?)

As a rule of thumb:

  • Server: decides gameplay state (damage, rewards, spawns, win/loss, collisions-by-query, etc)

  • Client: renders and plays cosmetics (UI, particles, screen shake, sound)

In practice, most of your code will run on both server and clients — you just guard what work runs where.

Local vs server checks

Two checks you’ll use constantly:

  • is_local_or_server(): for gameplay UI and input handling (runs on server + local client)

  • is_local(): for purely cosmetic effects (runs only on the local client)

Example:

Player :: class : Player_Base {
    ao_late_update :: method(dt: float) {
        // Use for gameplay UI and inputs (runs on server + local client)
        if is_local_or_server() {
            // draw_ability_button(this, Shoot_Ability, 0);
            // Handle inputs that affect game state
            // Movement is handled automatically
        }

        // Use for purely cosmetic effects (runs only on local client)
        if is_local() {
            // UI.text(..., "Waiting for host to start the game...");
            // Particle effects, cosmetic UI, etc.
        }
    }
}
circle-exclamation

Client-specific state

Sometimes you need local state that should not affect gameplay and doesn’t need replication:

  • UI open/close toggles

  • Camera shake timers

  • “last hovered item” in an inventory UI

Keep these as fields, but only read/write them behind is_local() checks.

Multiplayer safety rules

  • Avoid global variables for player state. If each player needs their own value, store it on Player.

  • Be careful with “singletons”. If you truly need a global manager, make sure it doesn’t accidentally store per-player data.

  • Prefer deterministic server state. The client should react to the server’s state, not invent it.

Debugging networking issues

  • Add log_info(...) on the server paths (not just local) so you can see authoritative decisions.

  • If something “works locally” but not for other players, it’s usually:

    • code guarded by is_local() that should be server-authoritative, or

    • a global variable being overwritten by multiple players.

Last updated