Skip to main content

steel_core/entity/manager/
benchmark_support.rs

1//! Fixtures for benchmarking the world entity manager without a live world.
2
3use std::sync::{Arc, Weak};
4
5use glam::DVec3;
6use steel_registry::entity_type::EntityTypeRef;
7use steel_registry::vanilla_entities;
8use steel_utils::ChunkPos;
9use uuid::Uuid;
10
11use crate::entity::{Entity, EntityBase, SharedEntity};
12
13use super::{EntityOwnership, EntityVisibility, WorldEntityManager};
14
15const CHUNK_WIDTH: i32 = 16;
16const ENTITY_Y: f64 = 64.0;
17const BLOCK_CENTER: f64 = 0.5;
18
19struct BenchEntity {
20    base: EntityBase,
21}
22
23impl BenchEntity {
24    fn shared(id: i32, position: DVec3) -> SharedEntity {
25        Arc::new(Self {
26            base: EntityBase::with_uuid(
27                id,
28                Uuid::from_u128(u128::try_from(id).expect("positive benchmark entity id") + 1),
29                position,
30                vanilla_entities::ITEM.dimensions,
31                Weak::new(),
32            ),
33        })
34    }
35}
36
37// SAFETY: The key is unique to this benchmark-only type in the test process.
38unsafe impl steel_utils::DowncastType for BenchEntity {
39    const TYPE_KEY: steel_utils::DowncastTypeKey =
40        steel_utils::DowncastTypeKey::new("steel:bench/entity_manager/BenchEntity");
41}
42
43impl Entity for BenchEntity {
44    fn base(&self) -> &EntityBase {
45        &self.base
46    }
47
48    fn entity_type(&self) -> EntityTypeRef {
49        &vanilla_entities::ITEM
50    }
51}
52
53/// Builds a manager with `count` ticking, non-riding entities in one chunk.
54///
55/// # Panics
56///
57/// Panics if `count` exceeds `i32::MAX` or an entity fails to register.
58#[must_use]
59pub fn manager_with_entities(count: usize) -> WorldEntityManager {
60    let manager = WorldEntityManager::new();
61    let chunk = ChunkPos::new(0, 0);
62    let _ = manager.on_chunk_loaded(chunk);
63    let _ = manager.update_chunk_visibility(chunk, EntityVisibility::Ticking);
64
65    for index in 0..count {
66        let index = i32::try_from(index).expect("benchmark entity count fits in i32");
67        let entity = BenchEntity::shared(
68            index + 1,
69            DVec3::new(
70                f64::from(index % CHUNK_WIDTH) + BLOCK_CENTER,
71                ENTITY_Y,
72                f64::from((index / CHUNK_WIDTH) % CHUNK_WIDTH) + BLOCK_CENTER,
73            ),
74        );
75        manager
76            .add_live_entity(entity, EntityOwnership::ManagerOwned)
77            .expect("benchmark entity should register");
78    }
79
80    manager
81}