Skip to main content

Observer

Trait Observer 

Source
pub trait Observer {
    // Provided methods
    fn interests(&self) -> Interests { ... }
    fn on_demo_command(
        &mut self,
        ctx: &Context,
        msg_type: EDemoCommands,
        msg: &[u8],
    ) -> ObserverResult { ... }
    fn on_net_message(
        &mut self,
        ctx: &Context,
        msg_type: NetMessages,
        msg: &[u8],
    ) -> ObserverResult { ... }
    fn on_svc_message(
        &mut self,
        ctx: &Context,
        msg_type: SvcMessages,
        msg: &[u8],
    ) -> ObserverResult { ... }
    fn on_base_user_message(
        &mut self,
        ctx: &Context,
        msg_type: EBaseUserMessages,
        msg: &[u8],
    ) -> ObserverResult { ... }
    fn on_base_game_event(
        &mut self,
        ctx: &Context,
        msg_type: EBaseGameEvents,
        msg: &[u8],
    ) -> ObserverResult { ... }
    fn on_tick_start(&mut self, ctx: &Context) -> ObserverResult { ... }
    fn on_tick_end(&mut self, ctx: &Context) -> ObserverResult { ... }
    fn on_entity(
        &mut self,
        ctx: &Context,
        event: EntityEvents,
        entity: &Entity,
    ) -> ObserverResult { ... }
    fn on_game_event(
        &mut self,
        ctx: &Context,
        ge: &GameEvent<'_>,
    ) -> ObserverResult { ... }
    fn on_string_table(
        &mut self,
        ctx: &Context,
        st: &StringTable,
        modified: &[i32],
    ) -> ObserverResult { ... }
    fn on_stop(&mut self, ctx: &Context) -> ObserverResult { ... }
}
Expand description

Observer trait for handling demo file events.

Implement this trait to receive callbacks as the parser processes the demo file. You can either implement it manually or use the #[observer] attribute macro for a more convenient approach.

§Interest-based Filtering

The interests method allows you to declare which events your observer wants to receive. This is crucial for performance as it allows the parser to skip processing events that no observer cares about.

§Examples

use source2_demo::prelude::*;
use source2_demo_protobufs::CDotaUserMsgChatMessage;

#[derive(Default)]
struct GameStats {
    combat_logs: u32,
    messages: u32,
}

#[observer]
impl GameStats {
    #[on_message]
    fn on_chat_msg(&mut self, ctx: &Context, msg: CDotaUserMsgChatMessage) -> ObserverResult {
        self.messages += 1;
        Ok(())
    }

    #[on_combat_log]
    fn on_combat_log(&mut self, ctx: &Context, entry: &CombatLogEntry) -> ObserverResult {
        self.combat_logs += 1;
        Ok(())
    }
}

§Manual implementation

use source2_demo::prelude::*;

#[derive(Default)]
struct EntityCounter {
    count: usize,
}

impl Observer for EntityCounter {
    fn interests(&self) -> Interests {
        Interests::ENABLE_ENTITY | Interests::TRACK_ENTITY
    }

    fn on_entity(&mut self, ctx: &Context, event: EntityEvents, entity: &Entity) -> ObserverResult {
        if event == EntityEvents::Created {
            self.count += 1;
        }
        Ok(())
    }
}

§Combining multiple interests

use source2_demo::prelude::*;

#[derive(Default)]
struct MultiObserver;

impl Observer for MultiObserver {
    fn interests(&self) -> Interests {
        Interests::TICK_START
            | Interests::TICK_END
            | Interests::ENABLE_ENTITY
            | Interests::TRACK_ENTITY
    }

    fn on_tick_start(&mut self, ctx: &Context) -> ObserverResult {
        println!("Tick {}", ctx.tick());
        Ok(())
    }

    fn on_entity(&mut self, ctx: &Context, event: EntityEvents, entity: &Entity) -> ObserverResult {
        // Process entities
        Ok(())
    }
}

Provided Methods§

Source

fn interests(&self) -> Interests

Declares which events this observer is interested in.

Return an empty Interests to receive no events, or combine flags using the | operator. This method is called once when the observer is registered.

§Default

Returns Interests::empty() by default (no events).

Source

fn on_demo_command( &mut self, ctx: &Context, msg_type: EDemoCommands, msg: &[u8], ) -> ObserverResult

Called when a demo command is received.

Requires Interests::DEMO to be set.

Source

fn on_net_message( &mut self, ctx: &Context, msg_type: NetMessages, msg: &[u8], ) -> ObserverResult

Called when a net message is received.

Requires Interests::NET to be set.

Source

fn on_svc_message( &mut self, ctx: &Context, msg_type: SvcMessages, msg: &[u8], ) -> ObserverResult

Called when an SVC (server-to-client) message is received.

Requires Interests::SVC to be set.

Source

fn on_base_user_message( &mut self, ctx: &Context, msg_type: EBaseUserMessages, msg: &[u8], ) -> ObserverResult

Called when a base user message is received.

Requires Interests::BASE_UM to be set.

Source

fn on_base_game_event( &mut self, ctx: &Context, msg_type: EBaseGameEvents, msg: &[u8], ) -> ObserverResult

Called when a base game event is received.

Requires Interests::BASE_GE to be set.

Source

fn on_tick_start(&mut self, ctx: &Context) -> ObserverResult

Called at the start of each tick.

Requires Interests::TICK_START to be set.

Source

fn on_tick_end(&mut self, ctx: &Context) -> ObserverResult

Called at the end of each tick.

Requires Interests::TICK_END to be set.

Source

fn on_entity( &mut self, ctx: &Context, event: EntityEvents, entity: &Entity, ) -> ObserverResult

Called when an entity is created, updated, or deleted.

Requires Interests::TRACK_ENTITY and Interests::ENABLE_ENTITY to be set.

Source

fn on_game_event(&mut self, ctx: &Context, ge: &GameEvent<'_>) -> ObserverResult

Called when a game event occurs.

Requires Interests::BASE_GE to be set.

Source

fn on_string_table( &mut self, ctx: &Context, st: &StringTable, modified: &[i32], ) -> ObserverResult

Called when a string table is updated.

Requires Interests::TRACK_STRINGTAB and Interests::ENABLE_STRINGTAB to be set.

Source

fn on_stop(&mut self, ctx: &Context) -> ObserverResult

Called when the replay ends.

Requires Interests::STOP to be set. This is the last callback before parsing completes.

§Arguments
  • ctx - Current replay context

Implementors§