use fxhash::FxHashMap; use crate::{ config::CHUNK_SIZE, sim::{cell::cell::Cell, cell_sim::chunk::Chunk}, }; pub struct World { pub chunks: Vec, // TODO FxFxHashMap? pub chunk_position_to_chunk_idx: FxHashMap<(i32, i32), usize>, } impl World { #[inline] pub fn split_game_position(x: i32, y: i32) -> ((i32, i32), (u8, u8)) { ( ( // TODO is this cast expensive? x.div_euclid(CHUNK_SIZE), y.div_euclid(CHUNK_SIZE), ), ( x.rem_euclid(CHUNK_SIZE) as u8, y.rem_euclid(CHUNK_SIZE) as u8, ), ) } // VERY EXPENSIVE pub fn get_cell_from_game_position(&self, x: i32, y: i32) -> Option { let ((cx, cy), (dx, dy)) = World::split_game_position(x, y); self.chunk_position_to_chunk_idx .get(&(cx, cy)) .map(|&idx| self.chunks[idx].get_cell_at_local_position(dx, dy)) } // VERY EXPENSIVE pub fn set_cell_from_game_position(&mut self, x: i32, y: i32, cell: Cell, sleeping: bool) { let ((cx, cy), (dx, dy)) = World::split_game_position(x, y); if let Some(&idx) = self.chunk_position_to_chunk_idx.get(&(cx, cy)) { self.chunks[idx].set_cell_at_local_position(dx, dy, cell); // this is a temporary hack self.chunks[idx].sleeping = sleeping; self.chunks[idx].needs_texture_update = true; } } pub fn insert(&mut self, x: i32, y: i32, chunk: Chunk) { self.chunk_position_to_chunk_idx .insert((x, y), self.chunks.len()); self.chunks.push(chunk); } pub fn from_default_size() -> Self { let mut world = World { chunks: Vec::new(), chunk_position_to_chunk_idx: FxHashMap::default(), }; for y in -10..1 { for x in -100..100 { world.insert(x, y, Chunk::void()); } } world } }