spru_util/player_map/
mod.rs1mod 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#[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>;