module Lapis::Docs::C_GAMEPLAY_AND_DECLARATIVE_DSL::I_MULTIPLAYER_AND_NETWORKING

Overview

Multiplayer and Networking

Comprehensive guide to multiplayer networking in Lapis for Crystal, covering ENetMultiplayerPeer, declarative @[RPC] method reflection, automated property synchronizers, multi-client testing harnesses, and Wireshark-style packet auditing.

Executive Summary & Key Topics

Topic Method / Anchor Description
Multiplayer Architecture & Topology .topic_00_multiplayer_architecture Dedicated server and client network topology using ENetMultiplayerPeer and MultiplayerAPI.
Declarative @[RPC] Annotations .topic_01_rpc_annotations Declaring remote procedure calls with mode, sync, transfer_mode, and channel.
MultiplayerSpawner and Property Synchronization DSL .topic_02_synchronizers_and_spawners Automated scene replication and property tracking without manual packet packing.
Multi-Client Testing Harness and Wireshark Spy .topic_03_multiplayer_harness_and_testing Asynchronous multi-peer input pumping, frame stepping, and packet auditing.

Related Guides & Source References

Defined in:

libgodot/docs/c_gameplay_and_declarative_dsl/i_multiplayer_and_networking.cr

Class Method Summary

Class Method Detail

def self.topic_00_multiplayer_architecture : Nil #

Multiplayer Architecture & Topology: Dedicated server and client network topology using ENetMultiplayerPeer and MultiplayerAPI.

Key Topics & Information

  • ENetMultiplayerPeer socket lifecycle, channel multiplexing, and compression
  • MultiplayerAPI peer tracking and authority management
  • Declarative @[RPC] annotations registered with Godot ClassDB
  • MultiplayerSpawner and MultiplayerSynchronizer property replication
  • Lapis::Multiplayer::Harness and Wireshark-style Spy packet auditing

def self.topic_01_rpc_annotations : Nil #

Declarative @[RPC] Annotations: Declaring remote procedure calls with mode, sync, transfer_mode, and channel.

Methods annotated with @[RPC] are automatically registered in Godot's ClassDB with full metadata when the node class compiles.

node NetworkedHero < CharacterBody2D do
  property hp : Int32 = 100

  # Broadcast damage from any peer to all peers, including caller
  @[RPC(mode: :any_peer, sync: :call_local, transfer_mode: :reliable, channel: 0)]
  def apply_damage(amount : Int32) : Void
    @hp = Math.max(0, @hp - amount)
  end

  # Fast unreliable position updates from authority
  @[RPC(mode: :authority, sync: :call_remote, transfer_mode: :unreliable_ordered, channel: 1)]
  def update_position(pos : Godot::Vector2) : Void
    set_position(pos)
  end

  # Direct RPC invocation via typed method or dynamic rpc helper:
  def attack_target(target : NetworkedHero) : Void
    # Calls apply_damage on all peers
    target.rpc("apply_damage", 25)

    # Or target a specific peer ID:
    target.rpc_id(1_i64, "apply_damage", 10)
  end
end

def self.topic_02_synchronizers_and_spawners : Nil #

MultiplayerSpawner and Property Synchronization DSL: Automated scene replication and property tracking without manual packet packing.

Godot 4's MultiplayerSpawner and MultiplayerSynchronizer manage node instancing and continuous variable synchronization. Lapis provides a clean DSL for property watching that abstracts internal path formatting (.:position):

# Configure replication on synchronizer:
config = Godot::SceneReplicationConfig.new
config.watch(:position)  # Automatically formats as internal ".:position"
config.watch(:rotation)

synchronizer = Godot::MultiplayerSynchronizer.new
synchronizer.set_replication_config(config)
synchronizer.set_root_path(Godot::NodePath.new("."))
hero.add_child(synchronizer)

def self.topic_03_multiplayer_harness_and_testing : Nil #

Multi-Client Testing Harness and Wireshark Spy: Asynchronous multi-peer input pumping, frame stepping, and packet auditing.

Testing multiplayer games reliably requires running multiple simulated peers, pumping frames deterministically, and auditing network packets without physical network flakiness.

Lapis provides multiplayer_test with Lapis::Multiplayer::Harness and Lapis::Multiplayer::Spy:

multiplayer_test "client-server damage synchronization", clients: 2 do |harness|
  # 1. Spawn player on server and clients
  server_hero = harness.server.spawn(NetworkedHero, "Hero")
  client1_hero = harness.client(0).spawn(NetworkedHero, "Hero")
  client2_hero = harness.client(1).spawn(NetworkedHero, "Hero")

  # 2. Simulate client 1 sending damage RPC
  harness.client(0).rpc(client1_hero, "apply_damage", 30)

  # 3. Step physics and network frames forward
  harness.step_frames(5)

  # 4. Verify Wireshark Spy audited the packet
  harness.spy.assert_rpc_sent(from: 2, to: 0, method: "apply_damage")
  harness.spy.assert_max_bandwidth(50.0) # KB/s

  # 5. Assert game state synchronized across peers
  client1_hero.hp.should eq(70)
  server_hero.hp.should eq(70)
end