gled-protocol 2.30.1

What gled's user interfaces and its engine send each other
Documentation
//! What a remote interface knows of the engine, rebuilt from the server's
//! messages.

use gled_model::collection::Collections;

use crate::{assets::collections_from, message::ServerMessage, state::EngineState};

#[derive(Debug, Clone, Default)]
pub struct StateReplica {
    pub state: EngineState,
    /// The number of the newest action of this interface the engine applied.
    pub applied_sequence: u64,
    /// Whether a full state has arrived; updates before it are ignored.
    pub complete: bool,
    /// The engine's assets.
    pub assets: Collections,
    /// Whether all assets have arrived; changes before them are ignored.
    pub(crate) assets_complete: bool,
}

impl StateReplica {
    /// Takes a message. Returns whether the state changed.
    pub fn apply(&mut self, message: &ServerMessage) -> bool {
        match message {
            ServerMessage::State {
                state,
                applied_sequence,
            } => {
                self.state = EngineState::clone(state);
                self.applied_sequence = *applied_sequence;
                self.complete = true;
                true
            }
            ServerMessage::Update {
                state,
                project,
                applied_sequence,
            } if self.complete => {
                let mut replica_project = self.state.project.take();
                project.clone().apply_to(&mut replica_project);
                self.state = EngineState {
                    project: replica_project,
                    ..EngineState::clone(state)
                };
                self.applied_sequence = *applied_sequence;
                true
            }
            ServerMessage::Assets(assets) => {
                self.assets = collections_from(assets.clone());
                self.assets_complete = true;
                true
            }
            ServerMessage::AssetsChanged(changes) if self.assets_complete => {
                changes.clone().apply_to(&mut self.assets);
                true
            }
            ServerMessage::Timing { beat, render } if self.complete => {
                self.state.beat = *beat;
                self.state.render = *render;
                true
            }
            _ => false,
        }
    }
}