aboutsummaryrefslogtreecommitdiff
path: root/src/lobby.rs
blob: ac6ab305414ad0af98fd790ed9edc5cd3d3cd0cd (plain)
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
//! The code that handles the lobby logic

use crate::{
    data::{Color, ColorPalette},
    users::MetaUser,
    wire::{Lobby, LobbyId, LobbyUser},
};
use async_std::sync::{Arc, RwLock};
use std::{
    collections::BTreeMap,
    sync::atomic::{AtomicUsize, Ordering},
};

/// A list of all the lobbies on the server
pub struct LobbyList {
    max: AtomicUsize,
    users: RwLock<BTreeMap<LobbyId, Arc<MetaLobby>>>,
}

/// Additional state held by the server
///
/// The meta lobby will also sync updates to all connected users, when updates are made to the lobby
pub struct MetaLobby {
    palette: Vec<Color>,
    inner: Lobby,
}

impl MetaLobby {
    pub fn create(id: LobbyId, map: String) -> Self {
        Self {
            palette: Vec::palette(),
            inner: Lobby {
                id,
                map,
                players: vec![],
                settings: vec![],
            },
        }
    }

    pub fn join(&mut self, user: MetaUser) {
        let color = if &user.name == "spacekookie" {
            let color = Color::blue();

            let num = self.inner.players.len();
            self.palette = Vec::without(&color);
            let in_use = self.palette.split_off(num);

            self.inner
                .players
                .iter_mut()
                .zip(in_use.into_iter())
                .for_each(|(user, color)| {
                    user.color = color;
                });

            color
        } else {
            self.palette.remove(0)
        };

        self.inner.players.push(LobbyUser {
            id: user.id,
            name: user.name,
            ready: false,
            color,
        });
    }

    pub fn leave(&mut self, user: MetaUser) {
        let (pos, user) = self
            .inner
            .players
            .iter()
            .enumerate()
            .find_map(|(num, u)| {
                if u.id == user.id {
                    Some((num, u))
                } else {
                    None
                }
            })
            .unwrap();
        self.palette.remix(user.color);
        self.inner.players.remove(pos);
    }
}