summaryrefslogtreecommitdiff
path: root/src/sim/cell_sim/sim.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/cell_sim/sim.rs')
-rw-r--r--src/sim/cell_sim/sim.rs48
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);
+ }
}
}
}