Skip to main content

spru_util/player_map/
mod.rs

1mod error;
2pub use error::Error;
3
4use std::marker::PhantomData;
5
6use derive_where::derive_where;
7use spru::{common::error::AnyResult, player};
8use tagset::tagset;
9use telety::telety;
10
11use crate::cloned;
12
13/// Stores some state per player
14#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
15pub struct PlayerMap<PlayerState> {
16    map: Vec<Option<(player::Id, PlayerState)>>,
17}
18
19impl<PlayerState> PlayerMap<PlayerState> {
20    pub fn count(&self) -> usize {
21        self.map.iter().flatten().count()
22    }
23
24    pub fn get(&self, id: player::Id) -> Result<&PlayerState, Error> {
25        self.map
26            .get(id.into_u32() as usize)
27            .and_then(Option::as_ref)
28            .map(|(_, state)| state)
29            .ok_or(Error::PlayerDoesNotExist(id))
30    }
31
32    pub fn iter(&self) -> impl Iterator<Item = (player::Id, &PlayerState)> {
33        self.map.iter().flatten().map(|(id, state)| (*id, state))
34    }
35
36    pub fn expect_player(&self, id: player::Id) -> &PlayerState {
37        self.get(id).unwrap()
38    }
39}
40
41pub fn create<PlayerState>() -> Create<PlayerState> {
42    cloned::create(PlayerMap { map: vec![] })
43}
44
45pub fn add_player<PlayerState>(
46    id: player::Id,
47    player_state: PlayerState,
48) -> AddPlayer<PlayerState> {
49    AddPlayer { id, player_state }
50}
51
52pub fn remove_player<PlayerState>(id: player::Id) -> RemovePlayer<PlayerState> {
53    RemovePlayer {
54        id,
55        _p: PhantomData,
56    }
57}
58
59pub fn destroy<PlayerState>() -> Destroy<PlayerState> {
60    cloned::destroy()
61}
62
63pub type Create<PlayerState> = cloned::Create<PlayerMap<PlayerState>>;
64
65pub type Destroy<PlayerState> = cloned::Destroy<PlayerMap<PlayerState>>;
66
67#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, spru::action::Update)]
68pub struct AddPlayer<PlayerState> {
69    id: player::Id,
70    player_state: PlayerState,
71}
72
73impl<PlayerState: Clone> spru::action::Update for AddPlayer<PlayerState> {
74    type T = PlayerMap<PlayerState>;
75    type Undo = RemovePlayer<PlayerState>;
76
77    #[allow(refining_impl_trait)]
78    fn update(&self, value: &mut Self::T) -> AnyResult<Self::Undo> {
79        let index = self.id.into_u32() as usize;
80        while value.map.len() <= index {
81            value.map.push(None);
82        }
83
84        match &mut value.map[index] {
85            Some(_) => Err(Error::PlayerAlreadyExists(self.id).into()),
86            option @ None => {
87                *option = Some((self.id, self.player_state.clone()));
88                Ok(remove_player(self.id))
89            }
90        }
91    }
92}
93
94#[derive_where(Debug, Clone, Serialize, Deserialize)]
95#[derive(spru::action::Update)]
96pub struct RemovePlayer<PlayerState> {
97    id: player::Id,
98    _p: PhantomData<PlayerState>,
99}
100
101impl<PlayerState> spru::action::Update for RemovePlayer<PlayerState> {
102    type T = PlayerMap<PlayerState>;
103    type Undo = AddPlayer<PlayerState>;
104
105    #[allow(refining_impl_trait)]
106    fn update(&self, value: &mut Self::T) -> AnyResult<Self::Undo> {
107        let index = self.id.into_u32() as usize;
108        if let Some(player_state) = value.map.get_mut(index)
109            && let Some((_, player_state)) = player_state.take()
110        {
111            return Ok(add_player(self.id, player_state));
112        }
113
114        Err(Error::PlayerDoesNotExist(self.id).into())
115    }
116}
117
118#[telety(crate::player_map)]
119#[tagset(Create<PlayerState>)]
120#[tagset(Destroy<PlayerState>)]
121#[tagset(AddPlayer<PlayerState>)]
122#[tagset(RemovePlayer<PlayerState>)]
123#[tagset(reserved(..8))]
124pub struct Actions<PlayerState>;