zero-trust-rps 0.0.5

Online Multiplayer Rock Paper Scissors
Documentation
use std::fmt::Display;

use crate::common::connection::{WriteMessageError, Writer};
use crate::common::message::ServerMessage;
use crate::common::message::{RoomId, RoomState};

use super::types::{ArcMut, Connections, RoomData};

#[derive(thiserror::Error, Debug)]
pub enum SendRoomUpdateError {
    #[error("{}", .0)]
    WriteMessageError(#[from] WriteMessageError),
    #[error("{}", .0)]
    Other(String),
}
impl From<String> for SendRoomUpdateError {
    fn from(value: String) -> Self {
        SendRoomUpdateError::Other(value)
    }
}

pub async fn send_room_update<P: Display + std::hash::Hash + Clone + Eq, W: Writer>(
    room_id: RoomId,
    room: &ArcMut<RoomData<P>>,
    streams: &Connections<P, W>,
) -> Result<(), SendRoomUpdateError> {
    let room = room.lock().await;

    let new_state = RoomState {
        id: room_id,
        users: {
            let mut users: Box<[_]> = room.users.values().copied().collect();
            users.sort_by_key(|u| u.id);
            users
        },
        round: room.round.clone(),
    };
    let users = room.users.clone();
    drop(room);

    for (peer, user) in users {
        let mut guard = streams.lock().await;
        let stream = if let Some(stream) = guard.get_mut(&peer) {
            stream
        } else {
            continue;
        };

        log::info!(
            "Calling room_update for {peer} ({}) in room {room_id}",
            user.id
        );
        stream
            .write_message(ServerMessage::RoomUpdate {
                new_state: new_state.clone(),
            })
            .await?;
    }

    Ok(())
}