Skip to main content

classicube_relay/packet/
scope.rs

1use std::io::Read;
2
3use byteorder::{ReadBytesExt, WriteBytesExt};
4
5#[derive(Debug, thiserror::Error)]
6pub enum ScopeError {
7    #[error("invalid scope {:?} with extra {:?}", kind, extra)]
8    InvalidScope { kind: u8, extra: u8 },
9
10    #[error(transparent)]
11    Io(#[from] std::io::Error),
12}
13type Result<T> = std::result::Result<T, ScopeError>;
14
15// u16
16// byte 0: scope_id: u8,
17// byte 1: scope_extra: u8,
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum Scope {
20    /// a single player
21    Player(PlayerScope),
22
23    /// all players in my map
24    Map(MapScope),
25
26    // all players in my server
27    Server(ServerScope),
28}
29impl Scope {
30    pub fn kind(&self) -> u8 {
31        match self {
32            Scope::Player { .. } => 0,
33            Scope::Map { .. } => 1,
34            Scope::Server { .. } => 2,
35        }
36    }
37
38    pub fn encode(&self) -> Result<Vec<u8>> {
39        let mut data = Vec::with_capacity(2);
40
41        data.write_u8(self.kind())?;
42
43        match self {
44            Scope::Player(PlayerScope { player_id }) => {
45                data.write_u8(*player_id)?;
46            }
47
48            Scope::Map(MapScope { have_plugin }) => {
49                data.write_u8(if *have_plugin { 0b1000_0000 } else { 0 })?;
50            }
51            Scope::Server(ServerScope { have_plugin }) => {
52                data.write_u8(if *have_plugin { 0b1000_0000 } else { 0 })?;
53            }
54        }
55
56        Ok(data)
57    }
58
59    pub(crate) fn decode(data_stream: &mut impl Read) -> Result<Self> {
60        let kind = data_stream.read_u8()?;
61        let extra = data_stream.read_u8()?;
62
63        let scope = match kind {
64            0 => Scope::Player(PlayerScope { player_id: extra }),
65
66            1 => {
67                let have_plugin = (extra & 0b1000_0000) != 0;
68                Scope::Map(MapScope { have_plugin })
69            }
70
71            2 => {
72                let have_plugin = (extra & 0b1000_0000) != 0;
73                Scope::Server(ServerScope { have_plugin })
74            }
75
76            _ => {
77                return Err(ScopeError::InvalidScope { kind, extra });
78            }
79        };
80
81        Ok(scope)
82    }
83}
84impl From<PlayerScope> for Scope {
85    fn from(scope: PlayerScope) -> Self {
86        Self::Player(scope)
87    }
88}
89impl From<MapScope> for Scope {
90    fn from(scope: MapScope) -> Self {
91        Self::Map(scope)
92    }
93}
94impl From<ServerScope> for Scope {
95    fn from(scope: ServerScope) -> Self {
96        Self::Server(scope)
97    }
98}
99
100/// a single player
101#[derive(Debug, Clone, PartialEq, Eq)]
102pub struct PlayerScope {
103    /// target player id if from client
104    ///
105    /// sender player id if from server
106    pub player_id: u8,
107}
108impl PlayerScope {
109    pub fn new(player_id: u8) -> Self {
110        Self { player_id }
111    }
112}
113
114/// all players in my map
115#[derive(Debug, Default, Clone, PartialEq, Eq)]
116pub struct MapScope {
117    // mask 1000_0000
118    /// only send to those that have the same plugin that uses the same channel
119    /// this was sent from
120    pub have_plugin: bool,
121}
122
123// all players in my server
124#[derive(Debug, Default, Clone, PartialEq, Eq)]
125pub struct ServerScope {
126    // mask 1000_0000
127    /// only send to those that have the same plugin that uses the same channel
128    /// this was sent from
129    pub have_plugin: bool,
130}