CrossServerEvent¶
The CrossServerEvent table manages cluster-wide events that span multiple servers. These events — such as PvP tournaments, seasonal celebrations, raid bosses, or community challenges — are defined once in this table and broadcast to all participating servers through SpacetimeDB's subscription model.
Scope¶
🌍 Global — All servers and the admin panel can read and subscribe to the events table. Participating servers react to event state changes (scheduled → active → completed) to trigger in-game behavior.
Schema¶
| Column | Type | Constraints | Description |
|---|---|---|---|
event_id |
u64 |
Primary Key, auto-increment | Unique identifier for this event |
event_type |
String |
— | Machine-readable event type (e.g., "pvp_tournament", "seasonal", "raid_boss") |
title |
String |
— | Human-readable event title for display |
description |
String |
— | Detailed event description |
participating_servers |
Vec<String> |
— | List of server_id values for servers participating in this event |
start_at |
Timestamp |
— | Scheduled start time |
end_at |
Option<Timestamp> |
— | Scheduled end time (None for open-ended events) |
status |
String |
— | Current event state (see state machine below) |
metadata |
String |
— | Additional event-specific data (JSON format) |
Rust Definition¶
#[spacetimedb::table(public, name = cross_server_event)]
pub struct CrossServerEvent {
#[primary_key]
#[auto_inc]
pub event_id: u64,
pub event_type: String,
pub title: String,
pub description: String,
pub participating_servers: Vec<String>,
pub start_at: Timestamp,
pub end_at: Option<Timestamp>,
pub status: String,
pub metadata: String,
}
Event State Machine¶
Events progress through a lifecycle of three states:
graph LR
Scheduled["scheduled"] --> Active["active"] --> Completed["completed"]
| Status | Description |
|---|---|
scheduled |
Event is defined but has not started yet. Visible in upcoming events UI. |
active |
Event is currently running. Participating servers enable event-specific game logic. |
completed |
Event has ended. Results are finalized. Row is preserved for historical record. |
State transitions can be triggered by:
- Time-based: The gateway or a scheduled process checks start_at and end_at timestamps and updates the status accordingly.
- Manual: An administrator changes the status through the panel (e.g., to start an event early or end one prematurely).
Usage Patterns¶
Event Definition¶
Events are created through the admin panel or gateway API:
// Pseudocode — creating a cross-server PvP tournament
CrossServerEvent::insert(CrossServerEvent {
event_id: 0, // auto-incremented
event_type: "pvp_tournament".to_string(),
title: "Season 3 Championship".to_string(),
description: "Cross-server PvP tournament. Top 16 players from each server compete.".to_string(),
participating_servers: vec![
"us-east-pvp-1".to_string(),
"us-east-pvp-2".to_string(),
"eu-west-pvp-1".to_string(),
],
start_at: /* scheduled timestamp */,
end_at: Some(/* end timestamp */),
status: "scheduled".to_string(),
metadata: serde_json::to_string(&json!({
"prize_pool": 10000,
"bracket_type": "single_elimination",
"registration_deadline": "2026-04-01T00:00:00Z"
})).unwrap(),
});
Game Hook Reaction¶
Participating game servers subscribe to the events table and filter for their own server_id:
// Game hook — react to event state changes
fn on_event_update(event: &CrossServerEvent) {
if !event.participating_servers.contains(&self.server_id) {
return; // Not participating in this event
}
match event.status.as_str() {
"active" => enable_event_features(&event),
"completed" => disable_event_features(&event),
_ => {}
}
}
Metadata Field¶
The metadata column stores event-specific configuration as a JSON string. Like other JSON fields in the platform (GlobalVault, ServerTransferQueue), the platform treats this as an opaque payload. Common metadata patterns:
| Event Type | Metadata Example |
|---|---|
| PvP Tournament | { "bracket_type": "...", "prize_pool": ..., "registration_deadline": "..." } |
| Seasonal Event | { "theme": "winter", "bonus_xp_multiplier": 2.0, "special_loot_table": "..." } |
| Raid Boss | { "boss_id": "...", "health_pool": ..., "damage_contribution_tracking": true } |
| Community Challenge | { "goal": "collect_1000000_wood", "current_progress": 0, "reward": "..." } |
Participating Servers List¶
The participating_servers column is a Vec<String> containing server_id values. This allows events to target a subset of the cluster:
- All servers: Include every
server_idin the cluster. - Regional events: Include only servers in a specific region.
- Mode-specific events: Include only PvP servers, or only PvE servers.
- Single-server events: Include one
server_id(useful for server-specific promotions that still benefit from cluster-wide visibility).
Related Reducers¶
Event management is typically handled by gateway-level or admin-level operations rather than dedicated platform reducers. The gateway creates, updates, and completes events based on schedules or admin requests.
Related Subscriptions¶
| Subscriber | Query | Purpose |
|---|---|---|
| Game Hook | SELECT * FROM cross_server_event |
React to event state changes for participated events |
| Admin Panel | SELECT * FROM cross_server_event |
Event management, scheduling, status monitoring |
For full subscription architecture, see Subscriptions.
Related Pages¶
- ServerRegistry — Server directory (provides
server_idvalues forparticipating_servers) - Multi-Server Architecture — Cross-server events as a cluster capability
- Platform Overview — How CrossServerEvent fits in the 12-table platform model