1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
use crate::{
    lobby::{self, events::LobbyEvent, Lobby, LobbyId},
    user::UserId,
};
use parking_lot::RwLock;

#[derive(Debug)]
pub struct LobbyState {
    pub lobby: Lobby,
    pub messages: Vec<lobby::LobbyMessage>,
}

pub struct LobbyStates {
    pub lobbies: RwLock<Vec<LobbyState>>,
}

impl LobbyStates {
    pub fn new() -> Self {
        Self {
            lobbies: RwLock::new(Vec::new()),
        }
    }

    #[inline]
    fn mut_member(&self, lid: LobbyId, mid: UserId, code: impl FnOnce(&mut lobby::LobbyMember)) {
        let mut lobbies = self.lobbies.write();
        if let Some(l) = lobbies.iter_mut().find(|l| l.lobby.id == lid) {
            if let Some(member) = l.lobby.members.iter_mut().find(|mem| mem.user.id == mid) {
                code(member);
            }
        }
    }

    pub fn on_event(&self, le: LobbyEvent) {
        match le {
            LobbyEvent::Create(lobby) | LobbyEvent::Connect(lobby) => {
                let mut lobbies = self.lobbies.write();
                lobbies.push(LobbyState {
                    lobby,
                    messages: Vec::new(),
                });
            }
            LobbyEvent::Delete { id } => {
                let mut lobbies = self.lobbies.write();
                if let Some(index) = lobbies.iter().position(|l| l.lobby.id == id) {
                    lobbies.swap_remove(index);
                }
            }
            LobbyEvent::Update(lobby) => {
                let mut lobbies = self.lobbies.write();
                if let Some(l) = lobbies.iter_mut().find(|l| l.lobby.id == lobby.id) {
                    l.lobby.capacity = lobby.capacity;
                    l.lobby.kind = lobby.kind;
                    l.lobby.locked = lobby.locked;
                    l.lobby.metadata = lobby.metadata;
                    l.lobby.owner_id = lobby.owner_id;
                }
            }
            LobbyEvent::MemberConnect(me) => {
                let mut lobbies = self.lobbies.write();
                if let Some(l) = lobbies.iter_mut().find(|l| l.lobby.id == me.lobby_id) {
                    l.lobby.members.push(me.member);
                }
            }
            LobbyEvent::MemberDisconnect(me) => {
                let mut lobbies = self.lobbies.write();
                if let Some(l) = lobbies.iter_mut().find(|l| l.lobby.id == me.lobby_id) {
                    if let Some(index) = l
                        .lobby
                        .members
                        .iter()
                        .position(|mem| mem.user.id == me.member.user.id)
                    {
                        l.lobby.members.remove(index);
                    }
                }
            }
            LobbyEvent::MemberUpdate(me) => {
                self.mut_member(me.lobby_id, me.member.user.id, |member| {
                    let speaking = member.speaking;
                    *member = me.member;
                    member.speaking = speaking;
                });
            }
            LobbyEvent::Message(msg) => {
                let mut lobbies = self.lobbies.write();
                if let Some(l) = lobbies.iter_mut().find(|l| l.lobby.id == msg.lobby_id) {
                    l.messages.push(msg.data);
                }
            }
            LobbyEvent::SpeakingStart(se) => {
                self.mut_member(se.lobby_id, se.user_id, |member| {
                    member.speaking = true;
                });
            }
            LobbyEvent::SpeakingStop(se) => {
                self.mut_member(se.lobby_id, se.user_id, |member| {
                    member.speaking = false;
                });
            }
        }
    }
}

impl Default for LobbyStates {
    fn default() -> Self {
        Self::new()
    }
}