1#[cfg(feature = "chumsky")]
4use chumsky::{IterParser as _, Parser, text::digits};
5
6#[derive(
8 Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize,
9)]
10#[expect(
11 clippy::module_name_repetitions,
12 reason = "this type is used outside of this module"
13)]
14pub struct ChatChannel(pub i32);
15
16#[cfg(feature = "chumsky")]
22#[must_use]
23#[expect(
24 clippy::module_name_repetitions,
25 reason = "this parser is used outside of this module"
26)]
27pub fn chat_channel_parser<'src>()
28-> impl Parser<'src, &'src str, ChatChannel, chumsky::extra::Err<chumsky::error::Rich<'src, char>>>
29{
30 digits(10).collect::<String>().try_map(|d, span| {
31 let d: i32 = d
32 .parse()
33 .map_err(|e| chumsky::error::Rich::custom(span, format!("{e:?}")))?;
34 Ok(ChatChannel(d))
35 })
36}
37
38impl std::fmt::Display for ChatChannel {
39 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{}", self.0)
41 }
42}
43
44impl std::str::FromStr for ChatChannel {
45 type Err = <i32 as std::str::FromStr>::Err;
46
47 fn from_str(s: &str) -> Result<Self, Self::Err> {
48 <i32 as std::str::FromStr>::from_str(s).map(ChatChannel)
49 }
50}
51
52pub const PUBLIC_CHANNEL: ChatChannel = ChatChannel(0);
54
55pub const COMBAT_CHANNEL: ChatChannel = ChatChannel(0x7FFF_FFFE);
57
58pub const DEBUG_CHANNEL: ChatChannel = ChatChannel(0x7FFF_FFFF);
60
61#[derive(
63 Debug,
64 Clone,
65 Copy,
66 PartialEq,
67 Eq,
68 PartialOrd,
69 Ord,
70 strum::EnumIs,
71 serde::Serialize,
72 serde::Deserialize,
73)]
74#[expect(
75 clippy::module_name_repetitions,
76 reason = "this type is used outside of this module"
77)]
78pub enum ChatVolume {
79 Whisper,
81 Say,
83 Shout,
85 RegionSay,
87}
88
89impl ChatVolume {
90 #[must_use]
92 pub fn volume_and_message(s: String) -> (Self, String) {
93 if let Some(whisper_message) = s.strip_prefix("whispers: ") {
94 (Self::Whisper, whisper_message.to_string())
95 } else if let Some(shout_message) = s.strip_prefix("shouts: ") {
96 (Self::Shout, shout_message.to_string())
97 } else {
98 (Self::Say, s)
99 }
100 }
101}