Snapshot System API Reference

This document provides a comprehensive reference for the Snapshot System API in Rummage.

Core Types

GameSnapshot

The primary data structure for storing game state:

#![allow(unused)]
fn main() {
/// A serializable snapshot of the game state
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct GameSnapshot {
    /// Unique identifier for the snapshot
    pub id: Uuid,
    /// The game turn the snapshot was taken on
    pub turn: u32,
    /// The phase within the turn
    pub phase: Phase,
    /// Active player when snapshot was taken
    pub active_player: usize,
    /// Serialized game data
    pub game_data: HashMap<String, Vec<u8>>,
    /// Timestamp when the snapshot was created
    pub timestamp: f64,
}

impl GameSnapshot {
    /// Creates a new empty snapshot
    pub fn new(turn: u32, phase: Phase, active_player: usize) -> Self;
    
    /// Returns the size of the snapshot in bytes
    pub fn size_bytes(&self) -> usize;
    
    /// Checks if the snapshot contains a specific entity
    pub fn contains_entity(&self, entity: Entity) -> bool;
    
    /// Gets the serialized data for a specific entity
    pub fn get_entity_data(&self, entity: Entity) -> Option<&Vec<u8>>;
}
}

SnapshotRegistry

Resource for managing snapshots:

#![allow(unused)]
fn main() {
/// Manages snapshots in memory
#[derive(Resource, Default)]
pub struct SnapshotRegistry {
    /// All available snapshots indexed by ID
    pub snapshots: HashMap<Uuid, GameSnapshot>,
}

impl SnapshotRegistry {
    /// Returns the most recent snapshot
    pub fn most_recent(&self) -> Option<&GameSnapshot>;
    
    /// Returns a snapshot by ID
    pub fn get(&self, id: Uuid) -> Option<&GameSnapshot>;
    
    /// Adds a snapshot to the registry
    pub fn add(&mut self, snapshot: GameSnapshot);
    
    /// Removes a snapshot from the registry
    pub fn remove(&mut self, id: Uuid) -> Option<GameSnapshot>;
    
    /// Clears all snapshots
    pub fn clear(&mut self);
    
    /// Returns all snapshots sorted by timestamp
    pub fn all_sorted_by_time(&self) -> Vec<&GameSnapshot>;
    
    /// Finds snapshots for a specific turn
    pub fn find_by_turn(&self, turn: u32) -> Vec<&GameSnapshot>;
}
}

PendingSnapshots

Resource for tracking snapshot operations:

#![allow(unused)]
fn main() {
/// Tracks pending snapshot operations
#[derive(Resource, Default)]
pub struct PendingSnapshots {
    /// Snapshots waiting to be processed
    pub queue: VecDeque<GameSnapshot>,
    /// Whether snapshot processing is paused
    pub paused: bool,
}

impl PendingSnapshots {
    /// Adds a snapshot to the queue
    pub fn enqueue(&mut self, snapshot: GameSnapshot);
    
    /// Gets the next snapshot from the queue
    pub fn dequeue(&mut self) -> Option<GameSnapshot>;
    
    /// Pauses snapshot processing
    pub fn pause(&mut self);
    
    /// Resumes snapshot processing
    pub fn resume(&mut self);
    
    /// Clears the queue
    pub fn clear(&mut self);
}
}

SnapshotConfig

Configuration for the snapshot system:

#![allow(unused)]
fn main() {
/// Configuration for the snapshot system
#[derive(Resource)]
pub struct SnapshotConfig {
    /// Whether to automatically create snapshots on turn changes
    pub auto_snapshot_on_turn: bool,
    /// Whether to automatically create snapshots on phase changes
    pub auto_snapshot_on_phase: bool,
    /// Maximum number of snapshots to process per frame
    pub max_snapshots_per_frame: usize,
    /// Maximum number of snapshots to keep in history
    pub max_history_size: usize,
    /// Whether to compress snapshots
    pub use_compression: bool,
}

impl Default for SnapshotConfig {
    fn default() -> Self {
        Self {
            auto_snapshot_on_turn: true,
            auto_snapshot_on_phase: false,
            max_snapshots_per_frame: 1,
            max_history_size: 100,
            use_compression: true,
        }
    }
}
}

Components

Snapshotable

Marker component for entities that should be included in snapshots:

#![allow(unused)]
fn main() {
/// Marker for entities that should be included in snapshots
#[derive(Component)]
pub struct Snapshotable;
}

SnapshotExcluded

Marker component for components that should not be included in snapshots:

#![allow(unused)]
fn main() {
/// Marker for components that should be excluded from snapshots
#[derive(Component)]
pub struct SnapshotExcluded;
}

Events

SnapshotEvent

Events for controlling snapshot operations:

#![allow(unused)]
fn main() {
/// Events for snapshot operations
#[derive(Event)]
pub enum SnapshotEvent {
    /// Take a new snapshot of the current state
    Take,
    /// Apply a specific snapshot
    Apply(Uuid),
    /// Save the current snapshot to disk
    Save(String),
    /// Load a snapshot from disk
    Load(String),
}
}

SnapshotProcessedEvent

Event for snapshot processing completion:

#![allow(unused)]
fn main() {
/// Event fired when a snapshot has been processed
#[derive(Event)]
pub struct SnapshotProcessedEvent {
    /// The ID of the processed snapshot
    pub id: Uuid,
    /// Whether processing succeeded
    pub success: bool,
    /// Error message if processing failed
    pub error: Option<String>,
}
}

Plugin

SnapshotPlugin

Main plugin for the snapshot system:

#![allow(unused)]
fn main() {
pub struct SnapshotPlugin;

impl Plugin for SnapshotPlugin {
    fn build(&self, app: &mut App) {
        app
            // Register resources
            .init_resource::<PendingSnapshots>()
            .init_resource::<SnapshotConfig>()
            .init_resource::<SnapshotRegistry>()
            
            // Register snapshot events
            .add_event::<SnapshotEvent>()
            .add_event::<SnapshotProcessedEvent>()
            
            // Add snapshot systems to the appropriate schedule
            .add_systems(Update, (
                handle_snapshot_events,
                process_pending_snapshots,
                trigger_snapshot_on_turn_change,
                trigger_snapshot_on_phase_change,
                cleanup_old_snapshots,
            ).chain());
    }
}
}

Systems

Handle Snapshot Events

#![allow(unused)]
fn main() {
/// Handles snapshot events
pub fn handle_snapshot_events(
    mut commands: Commands,
    mut snapshot_events: EventReader<SnapshotEvent>,
    mut pending: ResMut<PendingSnapshots>,
    mut snapshot_registry: ResMut<SnapshotRegistry>,
    mut processed_events: EventWriter<SnapshotProcessedEvent>,
    game_state: Res<GameState>,
    time: Res<Time>,
    world: &World,
) {
    // Implementation details...
}
}

Process Pending Snapshots

#![allow(unused)]
fn main() {
/// Process any pending snapshots in the queue
pub fn process_pending_snapshots(
    mut commands: Commands,
    mut pending: ResMut<PendingSnapshots>,
    mut processed_events: EventWriter<SnapshotProcessedEvent>,
    config: Res<SnapshotConfig>,
) {
    // Implementation details...
}
}

Automatic Snapshot Triggers

#![allow(unused)]
fn main() {
/// Triggers a snapshot when the turn changes
pub fn trigger_snapshot_on_turn_change(
    mut turn_events: EventReader<TurnChangeEvent>,
    mut snapshot_events: EventWriter<SnapshotEvent>,
    config: Res<SnapshotConfig>,
) {
    // Implementation details...
}

/// Triggers a snapshot when the phase changes
pub fn trigger_snapshot_on_phase_change(
    mut phase_events: EventReader<PhaseChangeEvent>,
    mut snapshot_events: EventWriter<SnapshotEvent>,
    config: Res<SnapshotConfig>,
) {
    // Implementation details...
}
}

Cleanup System

#![allow(unused)]
fn main() {
/// Cleans up old snapshots to maintain the history size limit
pub fn cleanup_old_snapshots(
    mut snapshot_registry: ResMut<SnapshotRegistry>,
    config: Res<SnapshotConfig>,
) {
    // Implementation details...
}
}

Functions

Create Snapshot

#![allow(unused)]
fn main() {
/// Creates a complete snapshot of the current game state
pub fn create_game_snapshot(
    world: &World,
    game_state: &GameState,
) -> GameSnapshot {
    // Implementation details...
}
}

Serialize Entity

#![allow(unused)]
fn main() {
/// Serializes an entity to a snapshot
pub fn serialize_entity_to_snapshot(
    world: &World,
    entity: Entity,
    snapshot: &mut GameSnapshot,
) {
    // Implementation details...
}
}

Apply Snapshot

#![allow(unused)]
fn main() {
/// Applies a snapshot to restore game state
pub fn apply_snapshot(
    commands: &mut Commands,
    snapshot: &GameSnapshot,
) {
    // Implementation details...
}
}

Save and Load

#![allow(unused)]
fn main() {
/// Saves a snapshot to disk
pub fn save_snapshot_to_disk(
    snapshot: &GameSnapshot,
    path: &str,
) -> Result<(), std::io::Error> {
    // Implementation details...
}

/// Loads a snapshot from disk
pub fn load_snapshot_from_disk(
    path: &str,
) -> Result<GameSnapshot, std::io::Error> {
    // Implementation details...
}
}

Networking Integration

NetworkSnapshotPlugin

#![allow(unused)]
fn main() {
/// Plugin that integrates the snapshot system with networking
pub struct NetworkSnapshotPlugin;

impl Plugin for NetworkSnapshotPlugin {
    fn build(&self, app: &mut App) {
        // Implementation details...
    }
}
}

NetworkSnapshotConfig

#![allow(unused)]
fn main() {
/// Resource that tracks network-specific snapshot configuration
#[derive(Resource)]
pub struct NetworkSnapshotConfig {
    /// Frequency of network snapshot updates (in seconds)
    pub sync_frequency: f32,
    /// Maximum size of a snapshot packet (in bytes)
    pub max_packet_size: usize,
    /// Whether to compress network snapshots
    pub compress_network_snapshots: bool,
    /// Number of snapshots to keep for rollback purposes
    pub rollback_history_size: usize,
}
}

NetworkSnapshotable

#![allow(unused)]
fn main() {
/// Component marking entities with network-specific snapshot requirements
#[derive(Component)]
pub struct NetworkSnapshotable {
    /// Which player IDs can see this entity
    pub visible_to: Vec<u64>,
    /// Priority for synchronization (higher values sync first)
    pub sync_priority: u8,
}
}

Usage Examples

Basic Usage

#![allow(unused)]
fn main() {
// Add the snapshot plugin to your app
app.add_plugins(SnapshotPlugin);

// Configure the snapshot system
let mut config = SnapshotConfig::default();
config.auto_snapshot_on_turn = true;
config.max_history_size = 50;
app.insert_resource(config);

// Mark entities for snapshot inclusion
commands.spawn((
    Snapshotable,
    MyComponent { value: 42 },
));

// Manually create a snapshot
app.world.send_event(SnapshotEvent::Take);

// Apply a snapshot
let snapshot_id = app.world.resource::<SnapshotRegistry>()
                         .most_recent().unwrap().id;
app.world.send_event(SnapshotEvent::Apply(snapshot_id));

// Save a snapshot to disk
app.world.send_event(SnapshotEvent::Save("save_game_1.snapshot".to_string()));

// Load a snapshot from disk
app.world.send_event(SnapshotEvent::Load("save_game_1.snapshot".to_string()));
}

Network Integration

#![allow(unused)]
fn main() {
// Add the network snapshot plugin
app.add_plugins((
    SnapshotPlugin,
    NetworkSnapshotPlugin,
));

// Configure network snapshot settings
let mut network_config = NetworkSnapshotConfig::default();
network_config.sync_frequency = 0.1; // 10 updates per second
network_config.compress_network_snapshots = true;
app.insert_resource(network_config);

// Mark entities for network visibility
commands.spawn((
    Snapshotable,
    NetworkSnapshotable {
        visible_to: vec![1, 2], // Only visible to players 1 and 2
        sync_priority: 10,      // High priority
    },
    MyComponent { value: 42 },
));
}

Rollback Usage

#![allow(unused)]
fn main() {
// Add rollback plugin
app.add_plugins((
    SnapshotPlugin,
    NetworkSnapshotPlugin,
    RollbackPlugin,
));

// Trigger a rollback to a specific turn
app.world.send_event(RollbackEvent {
    turn: 5,
    phase: Some(Phase::Combat),
});
}

Common Patterns

Snapshot Listener

#![allow(unused)]
fn main() {
fn my_snapshot_listener(
    mut snapshot_events: EventReader<SnapshotProcessedEvent>,
) {
    for event in snapshot_events.iter() {
        println!("Snapshot processed: {}", event.id);
        if !event.success {
            if let Some(error) = &event.error {
                println!("Error: {}", error);
            }
        }
    }
}
}

Custom Snapshot Trigger

#![allow(unused)]
fn main() {
fn trigger_snapshot_on_critical_event(
    mut critical_events: EventReader<CriticalGameEvent>,
    mut snapshot_events: EventWriter<SnapshotEvent>,
) {
    for event in critical_events.iter() {
        // Create a snapshot when critical events occur
        snapshot_events.send(SnapshotEvent::Take);
    }
}
}

Snapshot Analysis

#![allow(unused)]
fn main() {
fn analyze_snapshots(
    snapshot_registry: Res<SnapshotRegistry>,
) {
    let snapshots = snapshot_registry.all_sorted_by_time();
    for snapshot in snapshots {
        println!("Snapshot {} - Turn {}, Phase {:?}", 
                 snapshot.id, snapshot.turn, snapshot.phase);
    }
}
}