1pub use generated::*;
2
3pub use crate::demo::message::bspdecal::*;
4pub use crate::demo::message::classinfo::*;
5pub use crate::demo::message::gameevent::*;
6pub use crate::demo::message::packetentities::*;
7pub use crate::demo::message::prefetch::*;
8pub use crate::demo::message::serverinfo::*;
9pub use crate::demo::message::setconvar::*;
10pub use crate::demo::message::stringtable::*;
11pub use crate::demo::message::tempentities::*;
12pub use crate::demo::message::usermessage::*;
13pub use crate::demo::message::voice::*;
14use crate::demo::parser::{Encode, ParseBitSkip};
15use crate::{Parse, ParserState, Result, Stream};
16use bitbuffer::{BitRead, BitWrite, BitWriteStream, LittleEndian};
17use serde::{Deserialize, Serialize};
18use serde_repr::{Deserialize_repr, Serialize_repr};
19
20pub mod bspdecal;
21pub mod classinfo;
22pub mod gameevent;
23pub mod generated;
24pub mod packetentities;
25pub mod prefetch;
26mod serverinfo;
27pub mod setconvar;
28pub mod stringtable;
29pub mod tempentities;
30pub mod usermessage;
31pub mod voice;
32
33#[cfg_attr(feature = "schema", derive(schemars::JsonSchema_repr))]
34#[derive(
35 BitRead, BitWrite, Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr,
36)]
37#[repr(u8)]
38#[discriminant_bits = 6]
39pub enum MessageType {
40 Empty = 0,
41 File = 2,
42 NetTick = 3,
43 StringCmd = 4,
44 SetConVar = 5,
45 SignOnState = 6,
46 Print = 7,
47 ServerInfo = 8,
48 ClassInfo = 10,
49 SetPause = 11,
50 CreateStringTable = 12,
51 UpdateStringTable = 13,
52 VoiceInit = 14,
53 VoiceData = 15,
54 ParseSounds = 17,
55 SetView = 18,
56 FixAngle = 19,
57 BspDecal = 21,
58 UserMessage = 23,
59 EntityMessage = 24,
60 GameEvent = 25,
61 PacketEntities = 26,
62 TempEntities = 27,
63 PreFetch = 28,
64 Menu = 29,
65 GameEventList = 30,
66 GetCvarValue = 31,
67 CmdKeyValues = 32,
68}
69
70#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
71#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
72#[serde(bound(deserialize = "'a: 'static"))]
73#[serde(tag = "type")]
74pub enum Message<'a> {
75 Empty,
76 File(FileMessage),
77 NetTick(NetTickMessage),
78 StringCmd(StringCmdMessage),
79 SetConVar(SetConVarMessage),
80 SignOnState(SignOnStateMessage),
81 Print(PrintMessage),
82 ServerInfo(Box<ServerInfoMessage>),
83 ClassInfo(ClassInfoMessage),
84 SetPause(SetPauseMessage),
85 CreateStringTable(CreateStringTableMessage<'a>),
86 UpdateStringTable(UpdateStringTableMessage<'a>),
87 VoiceInit(VoiceInitMessage),
88 VoiceData(VoiceDataMessage<'a>),
89 ParseSounds(ParseSoundsMessage<'a>),
90 SetView(SetViewMessage),
91 FixAngle(FixAngleMessage),
92 BspDecal(BSPDecalMessage),
93 UserMessage(UserMessage<'a>),
94 EntityMessage(EntityMessage<'a>),
95 GameEvent(GameEventMessage),
96 PacketEntities(PacketEntitiesMessage),
97 TempEntities(TempEntitiesMessage),
98 PreFetch(PreFetchMessage),
99 Menu(MenuMessage<'a>),
100 GameEventList(GameEventListMessage),
101 GetCvarValue(GetCvarValueMessage),
102 CmdKeyValues(CmdKeyValuesMessage<'a>),
103}
104
105impl<'a> Parse<'a> for Message<'a> {
106 fn parse(stream: &mut Stream<'a>, state: &ParserState) -> Result<Self> {
107 let message_type = MessageType::parse(stream, state)?;
108 Self::from_type(message_type, stream, state)
109 }
110}
111
112impl<'a> Message<'a> {
113 pub fn get_message_type(&self) -> MessageType {
114 match self {
115 Message::Empty => MessageType::Empty,
116 Message::File(_) => MessageType::File,
117 Message::NetTick(_) => MessageType::NetTick,
118 Message::StringCmd(_) => MessageType::StringCmd,
119 Message::SetConVar(_) => MessageType::SetConVar,
120 Message::SignOnState(_) => MessageType::SignOnState,
121 Message::Print(_) => MessageType::Print,
122 Message::ServerInfo(_) => MessageType::ServerInfo,
123 Message::ClassInfo(_) => MessageType::ClassInfo,
124 Message::SetPause(_) => MessageType::SetPause,
125 Message::CreateStringTable(_) => MessageType::CreateStringTable,
126 Message::UpdateStringTable(_) => MessageType::UpdateStringTable,
127 Message::VoiceInit(_) => MessageType::VoiceInit,
128 Message::VoiceData(_) => MessageType::VoiceData,
129 Message::ParseSounds(_) => MessageType::ParseSounds,
130 Message::SetView(_) => MessageType::SetView,
131 Message::FixAngle(_) => MessageType::FixAngle,
132 Message::BspDecal(_) => MessageType::BspDecal,
133 Message::UserMessage(_) => MessageType::UserMessage,
134 Message::EntityMessage(_) => MessageType::EntityMessage,
135 Message::GameEvent(_) => MessageType::GameEvent,
136 Message::PacketEntities(_) => MessageType::PacketEntities,
137 Message::TempEntities(_) => MessageType::TempEntities,
138 Message::PreFetch(_) => MessageType::PreFetch,
139 Message::Menu(_) => MessageType::Menu,
140 Message::GameEventList(_) => MessageType::GameEventList,
141 Message::GetCvarValue(_) => MessageType::GetCvarValue,
142 Message::CmdKeyValues(_) => MessageType::CmdKeyValues,
143 }
144 }
145
146 pub fn from_type(
147 message_type: MessageType,
148 stream: &mut Stream<'a>,
149 state: &ParserState,
150 ) -> Result<Self> {
151 Ok(match message_type {
152 MessageType::Empty => Message::Empty,
153 MessageType::File => Message::File(FileMessage::parse(stream, state)?),
154 MessageType::NetTick => Message::NetTick(NetTickMessage::parse(stream, state)?),
155 MessageType::StringCmd => Message::StringCmd(StringCmdMessage::parse(stream, state)?),
156 MessageType::SetConVar => Message::SetConVar(SetConVarMessage::parse(stream, state)?),
157 MessageType::SignOnState => {
158 Message::SignOnState(SignOnStateMessage::parse(stream, state)?)
159 }
160 MessageType::Print => Message::Print(PrintMessage::parse(stream, state)?),
161 MessageType::ServerInfo => {
162 Message::ServerInfo(Box::new(ServerInfoMessage::parse(stream, state)?))
163 }
164 MessageType::ClassInfo => Message::ClassInfo(ClassInfoMessage::parse(stream, state)?),
165 MessageType::SetPause => Message::SetPause(SetPauseMessage::parse(stream, state)?),
166 MessageType::CreateStringTable => {
167 Message::CreateStringTable(CreateStringTableMessage::parse(stream, state)?)
168 }
169 MessageType::UpdateStringTable => {
170 Message::UpdateStringTable(UpdateStringTableMessage::parse(stream, state)?)
171 }
172 MessageType::VoiceInit => Message::VoiceInit(VoiceInitMessage::parse(stream, state)?),
173 MessageType::VoiceData => Message::VoiceData(VoiceDataMessage::parse(stream, state)?),
174 MessageType::ParseSounds => {
175 Message::ParseSounds(ParseSoundsMessage::parse(stream, state)?)
176 }
177 MessageType::SetView => Message::SetView(SetViewMessage::parse(stream, state)?),
178 MessageType::FixAngle => Message::FixAngle(FixAngleMessage::parse(stream, state)?),
179 MessageType::BspDecal => Message::BspDecal(BSPDecalMessage::parse(stream, state)?),
180 MessageType::UserMessage => Message::UserMessage(UserMessage::parse(stream, state)?),
181 MessageType::EntityMessage => {
182 Message::EntityMessage(EntityMessage::parse(stream, state)?)
183 }
184 MessageType::GameEvent => Message::GameEvent(GameEventMessage::parse(stream, state)?),
185 MessageType::PacketEntities => {
186 Message::PacketEntities(PacketEntitiesMessage::parse(stream, state)?)
187 }
188 MessageType::TempEntities => {
189 Message::TempEntities(TempEntitiesMessage::parse(stream, state)?)
190 }
191 MessageType::PreFetch => Message::PreFetch(PreFetchMessage::parse(stream, state)?),
192 MessageType::Menu => Message::Menu(MenuMessage::parse(stream, state)?),
193 MessageType::GameEventList => {
194 Message::GameEventList(GameEventListMessage::parse(stream, state)?)
195 }
196 MessageType::GetCvarValue => {
197 Message::GetCvarValue(GetCvarValueMessage::parse(stream, state)?)
198 }
199 MessageType::CmdKeyValues => {
200 Message::CmdKeyValues(CmdKeyValuesMessage::parse(stream, state)?)
201 }
202 })
203 }
204
205 pub fn skip_type(
206 message_type: MessageType,
207 stream: &mut Stream,
208 state: &ParserState,
209 ) -> Result<()> {
210 match message_type {
211 MessageType::Empty => Ok(()),
212 MessageType::File => FileMessage::parse_skip(stream, state),
213 MessageType::NetTick => NetTickMessage::parse_skip(stream, state),
214 MessageType::StringCmd => StringCmdMessage::parse_skip(stream, state),
215 MessageType::SetConVar => SetConVarMessage::parse_skip(stream, state),
216 MessageType::SignOnState => SignOnStateMessage::parse_skip(stream, state),
217 MessageType::Print => PrintMessage::parse_skip(stream, state),
218 MessageType::ServerInfo => ServerInfoMessage::parse_skip(stream, state),
219 MessageType::ClassInfo => ClassInfoMessage::parse_skip(stream, state),
220 MessageType::SetPause => SetPauseMessage::parse_skip(stream, state),
221 MessageType::CreateStringTable => CreateStringTableMessage::parse_skip(stream, state),
222 MessageType::UpdateStringTable => UpdateStringTableMessage::parse_skip(stream, state),
223 MessageType::VoiceInit => VoiceInitMessage::parse_skip(stream, state),
224 MessageType::VoiceData => VoiceDataMessage::parse_skip(stream, state),
225 MessageType::ParseSounds => ParseSoundsMessage::parse_skip(stream, state),
226 MessageType::SetView => SetViewMessage::parse_skip(stream, state),
227 MessageType::FixAngle => FixAngleMessage::parse_skip(stream, state),
228 MessageType::BspDecal => BSPDecalMessage::parse_skip(stream, state),
229 MessageType::UserMessage => UserMessage::parse_skip(stream, state),
230 MessageType::EntityMessage => EntityMessage::parse_skip(stream, state),
231 MessageType::GameEvent => GameEventMessage::parse_skip(stream, state),
232 MessageType::PacketEntities => PacketEntitiesMessage::parse_skip(stream, state),
233 MessageType::TempEntities => TempEntitiesMessage::parse_skip(stream, state),
234 MessageType::PreFetch => PreFetchMessage::parse_skip(stream, state),
235 MessageType::Menu => MenuMessage::parse_skip(stream, state),
236 MessageType::GameEventList => GameEventListMessage::parse_skip(stream, state),
237 MessageType::GetCvarValue => GetCvarValueMessage::parse_skip(stream, state),
238 MessageType::CmdKeyValues => CmdKeyValuesMessage::parse_skip(stream, state),
239 }
240 }
241}
242
243impl Encode for Message<'_> {
244 fn encode(&self, stream: &mut BitWriteStream<LittleEndian>, state: &ParserState) -> Result<()> {
245 match self {
246 Message::Empty => Ok(()),
247 Message::File(message) => message.encode(stream, state),
248 Message::NetTick(message) => message.encode(stream, state),
249 Message::StringCmd(message) => message.encode(stream, state),
250 Message::SetConVar(message) => message.encode(stream, state),
251 Message::SignOnState(message) => message.encode(stream, state),
252 Message::Print(message) => message.encode(stream, state),
253 Message::ServerInfo(message) => message.encode(stream, state),
254 Message::ClassInfo(message) => message.encode(stream, state),
255 Message::SetPause(message) => message.encode(stream, state),
256 Message::CreateStringTable(message) => message.encode(stream, state),
257 Message::UpdateStringTable(message) => message.encode(stream, state),
258 Message::VoiceInit(message) => message.encode(stream, state),
259 Message::VoiceData(message) => message.encode(stream, state),
260 Message::ParseSounds(message) => message.encode(stream, state),
261 Message::SetView(message) => message.encode(stream, state),
262 Message::FixAngle(message) => message.encode(stream, state),
263 Message::BspDecal(message) => message.encode(stream, state),
264 Message::UserMessage(message) => message.encode(stream, state),
265 Message::EntityMessage(message) => message.encode(stream, state),
266 Message::GameEvent(message) => message.encode(stream, state),
267 Message::PacketEntities(message) => message.encode(stream, state),
268 Message::TempEntities(message) => message.encode(stream, state),
269 Message::PreFetch(message) => message.encode(stream, state),
270 Message::Menu(message) => message.encode(stream, state),
271 Message::GameEventList(message) => message.encode(stream, state),
272 Message::GetCvarValue(message) => message.encode(stream, state),
273 Message::CmdKeyValues(message) => message.encode(stream, state),
274 }
275 }
276}