summaryrefslogtreecommitdiff
path: root/src/sim/sim_manager
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-23 12:57:20 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-23 12:57:20 -0700
commitc2d6115403b244f05ccd45ba9edc16b050cf3772 (patch)
tree046ebf581d9c237423565190c4e063ef2aba96c6 /src/sim/sim_manager
parent35f1bc48629456ee66cfb4643ca69b0811f02167 (diff)
refactor writing entities
Diffstat (limited to 'src/sim/sim_manager')
-rw-r--r--src/sim/sim_manager/mod.rs64
-rw-r--r--src/sim/sim_manager/utils.rs78
2 files changed, 75 insertions, 67 deletions
diff --git a/src/sim/sim_manager/mod.rs b/src/sim/sim_manager/mod.rs
index 97f542b..74c21fa 100644
--- a/src/sim/sim_manager/mod.rs
+++ b/src/sim/sim_manager/mod.rs
@@ -1,18 +1,16 @@
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_manager::manager::CellManager,
entity::{Entity, EntityDef, EntityId},
particle_manager::ParticleManager,
rb_manager::RbManager,
- sim_manager::utils::write_entity_to_world,
+ sim_manager::utils::{read_back_entities_from_world, write_entities_to_world},
},
};
@@ -95,17 +93,12 @@ impl SimManager {
fn cell_update(&mut self, config: &Config, delta_time: f32) {
// before we tick, write all the entities into the sim world
- // TODO optimize
- let entity_ids: Vec<EntityId> = self.entities.keys().copied().collect();
- let mut cells_written_by_entity: Vec<(EntityId, Vec<(u8, u8, i32, i32)>)> = Vec::new();
-
- for entity_id in entity_ids {
- let cells_written = write_entity_to_world(self, entity_id, self.cell_manager.seqno);
- cells_written_by_entity.push((entity_id, cells_written));
- }
+ let cells_written_by_entity = write_entities_to_world(self);
+ // tick
self.cell_manager.tick(config.use_threading);
+ // update entities
let entity_ids: Vec<EntityId> = self.entities.keys().cloned().collect();
for id in entity_ids {
let entity = self.entities.get_mut(&id);
@@ -117,6 +110,7 @@ impl SimManager {
if let Some(entity) = entity
&& let Some(result) = entity.update(&mut ctx, delta_time)
{
+ // process entity update results
for d in result.deferred_destructions {
self.destroy_entity(d);
}
@@ -124,53 +118,7 @@ impl SimManager {
}
// after we tick, remove the written entity cells and update the entities
- // TODO optimize
- for (entity_id, cells_written) in cells_written_by_entity {
- if let Some(entity) = self.entities.get_mut(&entity_id) {
- let entity_cells = entity.data.cells.as_mut().unwrap();
- let mut should_update_entity = false;
-
- for (lx, ly, x, y) in cells_written {
- // update the entity
- // TODO optimize
- let new_local_cell =
- self.cell_manager.get_cell_from_game_position(x, y).unwrap();
- if !new_local_cell.entity_integrated() {
- // this means that the entity changed in some way, so we should recompute its shape
- // TODO wait N frames to debounce this
- should_update_entity = true;
- }
- // we do this unconditionally because it's cheaper than checking if it actually needs to be updated
- // and because we don't have a good way to track changes to cell state
- entity_cells.set_cell_at_local_position(
- IVec2::new(lx as i32, ly as i32),
- new_local_cell,
- );
-
- // update the world
- // TODO optimize
- self.cell_manager
- .set_cell_from_game_position(x, y, Cell::void(), false);
- }
-
- if should_update_entity {
- if let Some(new_collider) = entity.compute_collider() {
- self.rb_manager
- .physics_manager
- .world
- .remove_collider(entity.data.collider_h.unwrap());
-
- let new_handle = self
- .rb_manager
- .physics_manager
- .world
- .insert_collider(new_collider, Some(entity.data.rb_h.unwrap()));
-
- entity.data.collider_h = Some(new_handle);
- }
- }
- }
- }
+ read_back_entities_from_world(self, cells_written_by_entity);
}
fn physics_update(&mut self, delta_time: f32) {
diff --git a/src/sim/sim_manager/utils.rs b/src/sim/sim_manager/utils.rs
index 13d7891..413e709 100644
--- a/src/sim/sim_manager/utils.rs
+++ b/src/sim/sim_manager/utils.rs
@@ -2,16 +2,10 @@ use glam::IVec2;
use crate::{
content::materials::MaterialId,
- sim::{entity::EntityId, sim_manager::SimManager},
+ sim::{cell::Cell, entity::EntityId, sim_manager::SimManager},
};
-pub fn write_entity_to_world(
- sim: &mut SimManager,
- entity_id: EntityId,
- // make sure these cells will be simulated
- seqno: u64,
- // (entity_x, entity_y, cell_x, cell_y)
-) -> Vec<(u8, u8, i32, i32)> {
+fn write_entity_to_world(sim: &mut SimManager, entity_id: EntityId) -> Vec<(u8, u8, i32, i32)> {
let mut cells_written: Vec<(u8, u8, i32, i32)> = Vec::new();
if let Some(entity) = sim.entities.get(&entity_id)
&& let Some(cells) = &entity.data.cells
@@ -57,7 +51,7 @@ pub fn write_entity_to_world(
continue;
}
- cell.match_parity(seqno);
+ cell.match_parity(sim.cell_manager.seqno);
// TODO: OPTIMIZE!!
sim.cell_manager
@@ -69,3 +63,69 @@ pub fn write_entity_to_world(
}
cells_written
}
+
+pub fn write_entities_to_world(
+ sim: &mut SimManager,
+ // (entity_x, entity_y, cell_x, cell_y)
+) -> Vec<(EntityId, Vec<(u8, u8, i32, i32)>)> {
+ // TODO optimize
+ let entity_ids: Vec<EntityId> = sim.entities.keys().copied().collect();
+ let mut cells_written_by_entity: Vec<(EntityId, Vec<(u8, u8, i32, i32)>)> = Vec::new();
+
+ for entity_id in entity_ids {
+ let cells_written = write_entity_to_world(sim, entity_id);
+ cells_written_by_entity.push((entity_id, cells_written));
+ }
+
+ cells_written_by_entity
+}
+
+// TODO optimize
+pub fn read_back_entities_from_world(
+ sim: &mut SimManager,
+ cells_written_by_entity: Vec<(EntityId, Vec<(u8, u8, i32, i32)>)>,
+) {
+ for (entity_id, cells_written) in cells_written_by_entity {
+ if let Some(entity) = sim.entities.get_mut(&entity_id) {
+ let entity_cells = entity.data.cells.as_mut().unwrap();
+ let mut should_update_entity = false;
+
+ for (lx, ly, x, y) in cells_written {
+ // update the entity
+ // TODO optimize
+ let new_local_cell = sim.cell_manager.get_cell_from_game_position(x, y).unwrap();
+ if !new_local_cell.entity_integrated() {
+ // this means that the entity changed in some way, so we should recompute its shape
+ // TODO wait N frames to debounce this
+ should_update_entity = true;
+ }
+ // we do this unconditionally because it's cheaper than checking if it actually needs to be updated
+ // and because we don't have a good way to track changes to cell state
+ entity_cells
+ .set_cell_at_local_position(IVec2::new(lx as i32, ly as i32), new_local_cell);
+
+ // update the world
+ // TODO optimize
+ sim.cell_manager
+ .set_cell_from_game_position(x, y, Cell::void(), false);
+ }
+
+ if should_update_entity {
+ if let Some(new_collider) = entity.compute_collider() {
+ sim.rb_manager
+ .physics_manager
+ .world
+ .remove_collider(entity.data.collider_h.unwrap());
+
+ let new_handle = sim
+ .rb_manager
+ .physics_manager
+ .world
+ .insert_collider(new_collider, Some(entity.data.rb_h.unwrap()));
+
+ entity.data.collider_h = Some(new_handle);
+ }
+ }
+ }
+ }
+}