dreamwell-runtime 1.0.0

Dreamwell Runtime — cross-platform GPU-accelerated game client
Documentation
//! Authority protocol — trait contract for local and remote authority backends.
//!
//! Both LocalAuthority and RemoteAuthorityClient implement AuthorityClient.
//! The runtime holds `Box<dyn AuthorityClient>` and calls it at phase boundaries,
//! never in hot inner loops.

use dreamwell_fabric::packets::ClientIntent;

/// Connection state for the authority backend.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionState {
    /// No connection attempt.
    Disconnected,
    /// Connection in progress.
    Connecting,
    /// Connected and synchronized.
    Connected,
    /// Connected but state diverged — needs resync.
    Desynced,
}

/// Event received from the authority backend.
#[derive(Debug, Clone)]
pub enum AuthorityEvent {
    /// Acknowledgment of a submitted intent.
    Ack { seq: u64 },
    /// Rejection of a submitted intent.
    Reject { seq: u64, reason: String },
    /// Canonical event from the authority.
    CanonEvent {
        tick: u64,
        event_type: String,
        payload: Vec<u8>,
    },
    /// Snapshot chunk for initial or re-sync.
    SnapshotChunk {
        chunk_id: u32,
        total_chunks: u32,
        data: Vec<u8>,
    },
}

/// Authority client contract. Implemented by LocalAuthority and RemoteAuthorityClient.
/// Called at phase boundaries (PollAuthority, StageAuthorityEvents), never in hot loops.
pub trait AuthorityClient: Send {
    /// Submit client intents to the authority for processing.
    fn submit_intents(&mut self, intents: &[ClientIntent]);

    /// Poll for authority events (non-blocking).
    fn poll_events(&mut self, out: &mut Vec<AuthorityEvent>);

    /// Request a full state snapshot for initial sync or resync.
    fn request_snapshot(&mut self);

    /// Current connection state.
    fn connection_state(&self) -> ConnectionState;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn connection_state_variants() {
        let states = [
            ConnectionState::Disconnected,
            ConnectionState::Connecting,
            ConnectionState::Connected,
            ConnectionState::Desynced,
        ];
        assert_eq!(states.len(), 4);
    }

    #[test]
    fn authority_event_variants() {
        let _ack = AuthorityEvent::Ack { seq: 1 };
        let _reject = AuthorityEvent::Reject {
            seq: 2,
            reason: "test".into(),
        };
        let _canon = AuthorityEvent::CanonEvent {
            tick: 100,
            event_type: "move".into(),
            payload: vec![],
        };
        let _snapshot = AuthorityEvent::SnapshotChunk {
            chunk_id: 0,
            total_chunks: 1,
            data: vec![],
        };
    }
}