classicube_relay/packet/
scope.rs

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