diff options
Diffstat (limited to 'src/sim/cell_sim')
| -rw-r--r-- | src/sim/cell_sim/sim.rs | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/src/sim/cell_sim/sim.rs b/src/sim/cell_sim/sim.rs index 92a263e..fbaf2f0 100644 --- a/src/sim/cell_sim/sim.rs +++ b/src/sim/cell_sim/sim.rs @@ -5,7 +5,7 @@ use rand::{Rng, SeedableRng, rngs::SmallRng}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use crate::{ - config::CHUNK_SIZE, + config::{CHUNK_SIZE, SETTLED_THRESOHLD}, sim::{ cell::{cell::Cell, materials::MaterialDef}, cell_sim::{chunk::Chunk, world::World}, @@ -127,7 +127,7 @@ fn adjacent_chunks(x: u8, y: u8) -> Vec<usize> { } } -pub fn set_cell(chunks: &mut [Option<&mut Chunk>; 9], x: i32, y: i32, cell: Cell) { +fn internal_set_cell(chunks: &mut [Option<&mut Chunk>; 9], x: i32, y: i32, cell: Cell) { let cx = x.div_euclid(CHUNK_SIZE); let cy = y.div_euclid(CHUNK_SIZE); let lx = x.rem_euclid(CHUNK_SIZE) as u8; @@ -160,6 +160,18 @@ pub fn set_cell(chunks: &mut [Option<&mut Chunk>; 9], x: i32, y: i32, cell: Cell } } +#[derive(PartialEq, Eq, Clone, Copy)] +// the action that the cell's update fn took +pub enum PostUpdateAction { + // the cell managed its own lifecycle, the updater will take no action + None, + // the updater should rewrite this cell, settling it, and let the chunk sleep if it's fully settled + // this cell's parity should be flipped if it is not yet settled + Settle, + // the cell changed itself, the updater should unconditionally rewrite it and not settle the cell or sleep + Apply, +} + pub struct UpdateCtx<'a, 'b, 'c> { pub chunks: &'a mut [Option<&'b mut Chunk>; 9], pub seqno: u64, @@ -171,7 +183,6 @@ pub struct UpdateCtx<'a, 'b, 'c> { pub material: &'c MaterialDef, pub rng: &'c mut dyn Rng, - pub do_rewrite: bool, } impl UpdateCtx<'_, '_, '_> { @@ -188,10 +199,10 @@ impl UpdateCtx<'_, '_, '_> { debug_assert!(dy > -CHUNK_SIZE + 1 && dy < CHUNK_SIZE - 1); let x = self.x + dx; let y = self.y + dy; - set_cell(self.chunks, x, y, cell); + internal_set_cell(self.chunks, x, y, cell); } - pub fn candidates_swap(&mut self, candidates: &[(i32, i32)]) -> bool { + pub fn swap_or_settle(&mut self, candidates: &[(i32, i32)]) -> PostUpdateAction { for &(dx, dy) in candidates { if let Some(mut candidate_cell) = self.get_cell(dx, dy) && candidate_cell.material.def().density < self.material.density @@ -202,11 +213,10 @@ impl UpdateCtx<'_, '_, '_> { self.set_cell(0, 0, candidate_cell); self.set_cell(dx, dy, *self.cell); - self.do_rewrite = false; - return true; + return PostUpdateAction::None; } } - false + PostUpdateAction::Settle } } @@ -245,16 +255,24 @@ pub fn sim_tick_chunk(chunks: &mut [Option<&mut Chunk>; 9], seqno: u64) { // TODO this is platform-dependent, will break for multiplayer rng: &mut rng, - do_rewrite: true, }; - update(&mut update_ctx); + let action = update(&mut update_ctx); - if update_ctx.do_rewrite { - // the cell didn't move, so it's more settled, and we also need to update its state for parity - cell.match_parity(seqno + 1); - cell.increment_settled(); - set_cell(chunks, x, y, cell); + match action { + PostUpdateAction::None => {} + PostUpdateAction::Settle => { + // the cell didn't move, so it's more settled, and we also need to update its state for parity + if cell.settled() < SETTLED_THRESOHLD { + cell.match_parity(seqno + 1); + cell.increment_settled(); + internal_set_cell(chunks, x, y, cell); + } + } + PostUpdateAction::Apply => { + cell.match_parity(seqno + 1); + internal_set_cell(chunks, x, y, cell); + } } } } |
