pub struct Entity { /* private fields */ }Expand description
Represents a game entity with its properties and state.
Entities are the fundamental objects in Source 2 games, representing everything from players and heroes to items and buildings. Each entity has:
- An index (position in the entity list)
- A serial number (for handle-based lookups)
- A class (defines what type of entity it is)
- A state (contains all property values)
§Property Access
Entity properties can be accessed in multiple ways:
- Using
get_property_by_nameand converting manually - Using the
property!macro - Using the
try_property!macro for optional properties
§Examples
§Basic property access
use source2_demo::prelude::*;
// Get a property and convert it
let health: i32 = entity.get_property_by_name("m_iHealth")?.try_into()?;
// Using the property! macro (simpler)
let max_health: i32 = property!(entity, "m_iHealth");
// With type annotation
let position = property!(entity, i32, "m_iHealth.m_vecPosition");§Working with arrays (formatted property names)
use source2_demo::prelude::*;
// Access array element using formatting
let player_id = 3;
let name: String = property!(
entity,
"m_vecPlayerData.{:04}.m_iszPlayerName",
player_id
);§Optional properties
use source2_demo::prelude::*;
// Returns None if property doesn't exist or can't be converted
if let Some(health) = try_property!(entity, i32, "m_iHealth") {
println!("Health: {}", health);
}Implementations§
Source§impl Entity
impl Entity
Sourcepub fn index(&self) -> u32
pub fn index(&self) -> u32
Returns the entity’s index in the entity list.
The index is the position of this entity in the internal entity array. Valid entities have indices in the range 0..8192.
Sourcepub fn serial(&self) -> u32
pub fn serial(&self) -> u32
Returns the entity’s serial number.
The serial number is used for handle-based entity lookups and is incremented each time an entity slot is reused.
Sourcepub fn handle(&self) -> u32
pub fn handle(&self) -> u32
Returns the entity’s handle.
The handle combines the serial number and index into a single value
that uniquely identifies this entity. It’s calculated as:
(serial << 14) | index
Sourcepub fn class(&self) -> &Class
pub fn class(&self) -> &Class
Returns a reference to the entity’s class.
The class defines what type of entity this is (e.g., “CDOTA_Unit_Hero_Axe”). It also contains the serializer that defines what properties the entity has.
§Examples
use source2_demo::prelude::*;
let class = entity.class();
println!("Class name: {}", class.name());
println!("Class ID: {}", class.id());
// Check if entity is a hero
if class.name().starts_with("CDOTA_Unit_Hero_") {
println!("This is a hero!");
}Sourcepub fn get_property_by_name(
&self,
name: &str,
) -> Result<&FieldValue, EntityError>
pub fn get_property_by_name( &self, name: &str, ) -> Result<&FieldValue, EntityError>
Gets the value of an entity property by its name.
This method looks up a property by its string name (e.g., “m_iHealth”)
and returns a reference to its FieldValue. The value can then be
converted to the desired Rust type using TryInto.
§Property Names
Property names use dot notation for nested properties:
- Simple:
"m_iHealth","m_flMana" - Nested:
"CBodyComponent.m_cellX" - Arrays:
"m_vecPlayerData.0000.m_iszPlayerName"(use formatting for indices)
§Recommended Alternatives
For most use cases, prefer the property! or try_property! macros
which provide a more ergonomic interface with automatic type conversion:
// Instead of:
let health: i32 = entity.get_property_by_name("m_iHealth")?.try_into()?;
// Use:
let health: i32 = property!(entity, "m_iHealth");§Arguments
name- The property name in dot notation (e.g., “CBodyComponent.m_cellX”)
§Returns
Returns Ok(&FieldValue) if the property exists, or an error if:
- The property name is invalid or doesn’t exist
- The entity class doesn’t have this property
§Errors
Returns EntityError::PropertyNameNotFound if the property doesn’t exist
on this entity or if the name is invalid.
§Examples
§Basic usage with manual conversion
use source2_demo::prelude::*;
// Get property and convert to i32
let health: i32 = entity.get_property_by_name("m_iHealth")?.try_into()?;
// Get nested property
let cell_x: u8 = entity
.get_property_by_name("CBodyComponent.m_cellX")?
.try_into()?;
// Get vector property
let position: i32 = entity
.get_property_by_name("m_iHealth")?
.try_into()?;§Using in an observer
use source2_demo::prelude::*;
#[derive(Default)]
struct HealthTracker;
#[observer]
#[uses_entities]
impl HealthTracker {
fn on_entity(
&mut self,
ctx: &Context,
event: EntityEvents,
entity: &Entity,
) -> ObserverResult {
// Manual conversion with get_property_by_name
let health: i32 = entity
.get_property_by_name("m_iHealth")?
.try_into()?;
// Recommended: using property! macro instead
let max_health: i32 = property!(entity, "m_iMaxHealth");
println!("Health: {}/{}", health, max_health);
Ok(())
}
}§Comparison with macros
use source2_demo::prelude::*;
// Method 1: get_property_by_name (verbose)
let health: i32 = entity.get_property_by_name("m_iHealth")?.try_into()?;
// Method 2: property! macro (recommended)
let health: i32 = property!(entity, "m_iHealth");
// Method 3: try_property! macro (for optional properties)
let health: Option<i32> = try_property!(entity, i32, "m_iHealth");§See Also
property!- Macro for concise property access with automatic conversiontry_property!- Macro for optional property access (returnsOption)FieldValue- The type returned by this method