From bdad89910dcf3a56790dba60ed1f0db679432323 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Sat, 22 Aug 2026 16:49:56 -0700 Subject: refactor entities --- src/sim/sim_manager/mod.rs | 125 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 105 insertions(+), 20 deletions(-) (limited to 'src/sim/sim_manager/mod.rs') diff --git a/src/sim/sim_manager/mod.rs b/src/sim/sim_manager/mod.rs index a98f3b2..b6d2528 100644 --- a/src/sim/sim_manager/mod.rs +++ b/src/sim/sim_manager/mod.rs @@ -1,14 +1,18 @@ use std::time::Instant; +use fxhash::FxHashMap; +use glam::IVec2; + use crate::{ Config, config::{PHYSICS_DELTA_TIME, PHYSICS_FPS, SIM_FPS}, sim::{ cell::{cell::Cell, materials::MaterialId}, cell_manager::manager::CellManager, + entity::{Entity, EntityDef}, particle_manager::ParticleManager, rb_manager::RbManager, - sim_manager::utils::write_rb_entity_to_world, + sim_manager::utils::write_entity_to_world, }, }; @@ -27,53 +31,116 @@ pub struct SimManager { pub cell_manager: CellManager, pub rb_manager: RbManager, pub particle_manager: ParticleManager, + + // entities + // TODO entity manager? + next_entity_id: u32, + pub entities: FxHashMap, } impl SimManager { - pub fn new() -> Self { - SimManager { - paused: false, - ignore_pause_next_tick: false, - last_cell_update: Instant::now(), - cell_updates_due: 0.0, - last_physics_update: Instant::now(), - physics_updates_due: 0.0, - cell_manager: CellManager::from_default_size(), - rb_manager: RbManager::new(), - particle_manager: ParticleManager::new(), + pub fn create_entity(&mut self, def: EntityDef) -> u32 { + let (rb_h, collider_h) = if let Some(rb) = def.rb { + let rb_h = self.rb_manager.physics_manager.rigid_body_set.insert(rb); + + if let Some(collider) = def.collider { + let collider_h = self + .rb_manager + .physics_manager + .collider_set + .insert_with_parent( + collider, + rb_h, + &mut self.rb_manager.physics_manager.rigid_body_set, + ); + (Some(rb_h), Some(collider_h)) + } else { + (Some(rb_h), None) + } + } else if let Some(collider) = def.collider { + let collider_h = self + .rb_manager + .physics_manager + .collider_set + .insert(collider); + (None, Some(collider_h)) + } else { + (None, None) + }; + + let entity = Entity::new( + self.next_entity_id, + rb_h, + collider_h, + def.cells, + def.behaviour, + ); + + let id = self.next_entity_id; + self.entities.insert(id, entity); + self.next_entity_id += 1; + id + } + + pub fn destroy_entity(&mut self, id: u32) { + if let Some(entity) = self.entities.get(&id) { + if let Some(rb_h) = entity.rb_h { + self.rb_manager.physics_manager.rigid_body_set.remove( + rb_h, + &mut self.rb_manager.physics_manager.island_manager, + &mut self.rb_manager.physics_manager.collider_set, + &mut self.rb_manager.physics_manager.impulse_joint_set, + &mut self.rb_manager.physics_manager.multibody_joint_set, + true, + ); + } else if let Some(collider_h) = entity.collider_h { + self.rb_manager.physics_manager.collider_set.remove( + collider_h, + &mut self.rb_manager.physics_manager.island_manager, + &mut self.rb_manager.physics_manager.rigid_body_set, + true, + ); + } + + self.entities.remove(&id); } } fn cell_update(&mut self, config: &Config) { - // before we tick, write all the rb entities into the sim world + // before we tick, write all the entities into the sim world // TODO optimize - let entity_ids: Vec = self.rb_manager.rb_entities.keys().copied().collect(); + let entity_ids: Vec = self.entities.keys().copied().collect(); let mut cells_written_by_entity: Vec<(u32, Vec<(u8, u8, i32, i32)>)> = Vec::new(); for entity_id in entity_ids { - let cells_written = write_rb_entity_to_world(self, entity_id, self.cell_manager.seqno); + let cells_written = write_entity_to_world(self, entity_id, self.cell_manager.seqno); cells_written_by_entity.push((entity_id, cells_written)); } self.cell_manager.tick(config.use_threading); - // after we tick, remove the written rb cells and update the entities + // after we tick, remove the written entity cells and update the entities // TODO optimize for (entity_id, cells_written) in cells_written_by_entity { - let rb_entity = self.rb_manager.rb_entities.get_mut(&entity_id).unwrap(); + let entity = self.entities.get_mut(&entity_id).unwrap(); for (lx, ly, x, y) in cells_written { // update the entity // TODO we should skip cells that weren't changed? // TODO optimize let new_local_cell = self.cell_manager.get_cell_from_game_position(x, y).unwrap(); - if new_local_cell.material != MaterialId::Void && !new_local_cell.rb() { + if new_local_cell.material != MaterialId::Void && !new_local_cell.entity() { panic!( - "Someone swapped into this rb's cell! ({x}, {y}, {m:#?}, {f})", + "Someone swapped into this entity's cell! ({x}, {y}, {m:#?}, {f})", m = new_local_cell.material, f = new_local_cell.flags ); } - rb_entity.set_cell_at_local_position(lx, ly, new_local_cell); + if let Some(cells) = &mut entity.cells { + cells.set_cell_at_local_position( + IVec2::new(lx as i32, ly as i32), + new_local_cell, + ); + } // update the world self.cell_manager .set_cell_from_game_position(x, y, Cell::void(), false); @@ -149,4 +216,22 @@ impl SimManager { self.ignore_pause_next_tick = false; } + + pub fn new() -> Self { + SimManager { + paused: false, + ignore_pause_next_tick: false, + last_cell_update: Instant::now(), + cell_updates_due: 0.0, + last_physics_update: Instant::now(), + physics_updates_due: 0.0, + + cell_manager: CellManager::from_default_size(), + rb_manager: RbManager::new(), + particle_manager: ParticleManager::new(), + + next_entity_id: 0, + entities: FxHashMap::default(), + } + } } -- cgit v1.3.1