World & Networking

aether-multiplayer

Server-authoritative multiplayer with QUIC transport and avatar sync

The aether-multiplayer crate integrates aether-network (QUIC transport) with aether-world-runtime (tick scheduling, input buffering, state sync) into a working server-authoritative multiplayer system with avatar synchronization.

Overview

This crate provides the concrete multiplayer implementation that ties together Aether's networking and world runtime subsystems:

  • Server-authoritative simulation where the server validates all state changes.
  • QUIC transport for reliable and unreliable channels with low latency.
  • Avatar state synchronization for position, rotation, and animation across clients.
  • Client-server protocol with typed messages for join, leave, input, and state updates.
  • World state management tracking all entities and their replicated state.

Key Types

MultiplayerServer

The authoritative game server that processes client inputs and broadcasts world state.

use aether_multiplayer::{MultiplayerServer, MultiplayerConfig};

let config = MultiplayerConfig {
    listen_port: 7777,
    max_players: 32,
    tick_rate: 30,
};
let server = MultiplayerServer::new(config)?;

MultiplayerClient

Connects to a multiplayer server, sends inputs, and receives world state updates.

use aether_multiplayer::{MultiplayerClient, MultiplayerConfig, RemoteWorldState};

let config = MultiplayerConfig {
    server_address: "127.0.0.1:7777".into(),
    ..Default::default()
};
let mut client = MultiplayerClient::connect(config)?;

// Each frame, send local input and receive remote state
let world_state: RemoteWorldState = client.poll()?;

AvatarState

Represents the synchronized state of a player's avatar across the network.

use aether_multiplayer::{AvatarState, PlayerId};

let avatar = AvatarState {
    player_id: PlayerId(1),
    position: [0.0, 1.0, 0.0],
    rotation: [0.0, 0.0, 0.0, 1.0],
    animation_state: "idle".into(),
};

WorldState

The server-side world state containing all active entities and player avatars.

use aether_multiplayer::WorldState;

let mut world = WorldState::new();
// Entities are managed by the server simulation

Protocol Messages

Typed messages for client-server communication.

use aether_multiplayer::{ClientMessage, ServerMessage, PlayerId};

// Client sends input to server
let msg = ClientMessage::Input {
    tick: 42,
    actions: vec![/* player actions */],
};

// Server broadcasts state to all clients
let msg = ServerMessage::WorldUpdate {
    tick: 42,
    avatars: vec![/* avatar states */],
};

MultiplayerConfig

Configuration shared between server and client.

use aether_multiplayer::MultiplayerConfig;

let config = MultiplayerConfig {
    listen_port: 7777,
    server_address: "0.0.0.0:7777".into(),
    max_players: 64,
    tick_rate: 30,
};

Usage Examples

Running a Server

use aether_multiplayer::{MultiplayerServer, MultiplayerConfig};

let config = MultiplayerConfig {
    listen_port: 7777,
    max_players: 32,
    tick_rate: 30,
    ..Default::default()
};
let mut server = MultiplayerServer::new(config)?;

// Main server loop
loop {
    server.tick()?;
}

Connecting a Client

use aether_multiplayer::{MultiplayerClient, MultiplayerConfig, AvatarState};

let config = MultiplayerConfig {
    server_address: "127.0.0.1:7777".into(),
    ..Default::default()
};
let mut client = MultiplayerClient::connect(config)?;

// Game loop
loop {
    client.send_input(local_input)?;
    let state = client.poll()?;
    for avatar in &state.avatars {
        render_avatar(avatar);
    }
}