source2_demo/event/mod.rs
1//! Game event system for handling in-game events.
2//!
3//! This module provides types for working with game events - structured events
4//! that occur during gameplay like player kills, item purchases, ability uses, etc.
5//!
6//! # Overview
7//!
8//! Game events are defined by the game and contain named key-value pairs.
9//! Each event has a name (e.g., "dota_player_kill") and a set of values.
10//!
11//! # Examples
12//!
13//! ## Handling game events
14//!
15//! ```no_run
16//! use source2_demo::prelude::*;
17//!
18//! #[derive(Default)]
19//! struct EventLogger;
20//!
21//! #[observer]
22//! #[uses_game_events]
23//! impl EventLogger{
24//! #[on_game_event]
25//! fn on_game_event(&mut self, ctx: &Context, ge: &GameEvent) -> ObserverResult {
26//! println!("Event: {}", ge.name());
27//!
28//! // Iterate all key-value pairs
29//! for (key, value) in ge.iter() {
30//! println!(" {}: {:?}", key, value);
31//! }
32//!
33//! // Get specific value
34//! if let Ok(player_id) = ge.get_value("player_id") {
35//! let id: i32 = player_id.try_into()?;
36//! println!("Player ID: {}", id);
37//! }
38//!
39//! Ok(())
40//! }
41//! }
42//! ```
43
44#[cfg(feature = "dota")]
45mod combat_log;
46mod definition;
47mod list;
48mod value;
49
50#[cfg(feature = "dota")]
51pub use combat_log::*;
52use definition::*;
53pub use list::*;
54pub use value::*;
55
56use crate::error::GameEventError;
57use crate::proto::CSvcMsgGameEvent;
58
59/// Represents a game event with its name and values.
60///
61/// Game events are structured in-game occurrences. Each event has a name and a set of named values.
62///
63/// # Examples
64///
65/// ## Accessing event data
66///
67/// ```no_run
68/// use source2_demo::prelude::*;
69///
70/// # fn example(ge: &GameEvent) -> anyhow::Result<()> {
71/// // Get the event name
72/// println!("Event: {}", ge.name());
73///
74/// // Iterate all key-value pairs
75/// for (key, value) in ge.iter() {
76/// println!("{}: {:?}", key, value);
77/// }
78///
79/// // Get a specific value
80/// let player_id: i32 = ge.get_value("player_id")?.try_into()?;
81/// # Ok(())
82/// # }
83/// ```
84pub struct GameEvent<'a> {
85 id: i32,
86 list: &'a GameEventList,
87 keys: Vec<EventValue>,
88}
89
90impl<'a> GameEvent<'a> {
91 pub(crate) fn new(list: &'a GameEventList, ge: CSvcMsgGameEvent) -> Self {
92 let id = ge.eventid();
93 let keys = ge
94 .keys
95 .iter()
96 .map(|key| match key.r#type() {
97 1 => EventValue::String(key.val_string().into()),
98 2 => EventValue::Float(key.val_float()),
99 3 => EventValue::Int(key.val_long()),
100 4 => EventValue::Int(key.val_short()),
101 5 => EventValue::Byte(key.val_byte() as u8),
102 6 => EventValue::Bool(key.val_bool()),
103 7 => EventValue::U64(key.val_uint64()),
104 8 => EventValue::Int(key.val_long()),
105 9 => EventValue::Int(key.val_short()),
106 _ => unreachable!("Unknown event type: {}", key.r#type()),
107 })
108 .collect::<Vec<_>>();
109
110 Self { id, list, keys }
111 }
112
113 /// Returns the event's numeric ID.
114 pub fn id(&self) -> i32 {
115 self.id
116 }
117
118 /// Returns the event's name.
119 ///
120 /// Event names are strings
121 pub fn name(&self) -> &str {
122 &self.list.list[&self.id].name
123 }
124
125 /// Returns an iterator over all key-value pairs in the event.
126 ///
127 /// # Examples
128 ///
129 /// ```no_run
130 /// use source2_demo::prelude::*;
131 ///
132 /// # fn example(ge: &GameEvent) {
133 /// for (key, value) in ge.iter() {
134 /// println!("{}: {:?}", key, value);
135 /// }
136 /// # }
137 /// ```
138 pub fn iter(&self) -> impl Iterator<Item = (&str, &EventValue)> {
139 self.keys
140 .iter()
141 .zip(self.list.list[&self.id].keys.iter())
142 .map(|(value, key)| (key.name.as_str(), value))
143 }
144
145 /// Gets the value for a specific key.
146 ///
147 /// # Arguments
148 ///
149 /// * `key` - The name of the key to look up
150 ///
151 /// # Errors
152 ///
153 /// Returns [`GameEventError::UnknownKey`] if the key doesn't exist for this event.
154 ///
155 /// # Examples
156 ///
157 /// ```no_run
158 /// use source2_demo::prelude::*;
159 ///
160 /// # fn example(ge: &GameEvent) -> anyhow::Result<()> {
161 /// // Get a value and convert it
162 /// let player_id: i32 = ge.get_value("player_id")?.try_into()?;
163 /// let hero_name: String = ge.get_value("hero_name")?.try_into()?;
164 /// # Ok(())
165 /// # }
166 /// ```
167 pub fn get_value(&self, key: &str) -> Result<&EventValue, GameEventError> {
168 let key = self.list.list[&self.id]
169 .name_to_key
170 .get(key)
171 .ok_or_else(|| GameEventError::UnknownKey(key.to_string()))?;
172 Ok(&self.keys[key.id as usize])
173 }
174}