Skip to main content

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}