use std::collections::HashMap;
use std::sync::Mutex;
use crate::world::block;
use crate::world::block_entity::BlockEntity;
use crate::world::collision::{self, Aabb, RayHit};
use crate::world::handle::WorldHandle;
pub struct MockWorld {
blocks: Mutex<HashMap<(i32, i32, i32), u16>>,
block_entities: Mutex<HashMap<(i32, i32, i32), BlockEntity>>,
dirty: Mutex<std::collections::HashSet<(i32, i32)>>,
flat: bool,
}
impl MockWorld {
pub fn flat() -> Self {
Self {
blocks: Mutex::new(HashMap::new()),
block_entities: Mutex::new(HashMap::new()),
dirty: Mutex::new(std::collections::HashSet::new()),
flat: true,
}
}
pub fn empty() -> Self {
Self {
blocks: Mutex::new(HashMap::new()),
block_entities: Mutex::new(HashMap::new()),
dirty: Mutex::new(std::collections::HashSet::new()),
flat: false,
}
}
fn block_at(&self, x: i32, y: i32, z: i32) -> u16 {
let map = self.blocks.lock().unwrap();
if let Some(&state) = map.get(&(x, y, z)) {
return state;
}
if self.flat {
return match y {
-64 => block::BEDROCK,
-63 | -62 => block::DIRT,
-61 => block::GRASS_BLOCK,
_ => block::AIR,
};
}
block::AIR
}
}
impl WorldHandle for MockWorld {
fn get_block(&self, x: i32, y: i32, z: i32) -> u16 {
self.block_at(x, y, z)
}
fn set_block(&self, x: i32, y: i32, z: i32, state: u16) {
self.blocks.lock().unwrap().insert((x, y, z), state);
let cx = x >> 4;
let cz = z >> 4;
self.dirty.lock().unwrap().insert((cx, cz));
}
fn get_block_entity(&self, x: i32, y: i32, z: i32) -> Option<BlockEntity> {
self.block_entities.lock().unwrap().get(&(x, y, z)).cloned()
}
fn set_block_entity(&self, x: i32, y: i32, z: i32, entity: BlockEntity) {
self.block_entities
.lock()
.unwrap()
.insert((x, y, z), entity);
}
fn mark_chunk_dirty(&self, cx: i32, cz: i32) {
self.dirty.lock().unwrap().insert((cx, cz));
}
fn persist_chunk(&self, _cx: i32, _cz: i32) {
}
fn dirty_chunks(&self) -> Vec<(i32, i32)> {
self.dirty.lock().unwrap().iter().copied().collect()
}
fn check_overlap(&self, aabb: &Aabb) -> bool {
collision::check_overlap(self, aabb)
}
fn ray_cast(
&self,
origin: (f64, f64, f64),
direction: (f64, f64, f64),
max_distance: f64,
) -> Option<RayHit> {
collision::ray_cast(self, origin, direction, max_distance)
}
fn resolve_movement(&self, aabb: &Aabb, dx: f64, dy: f64, dz: f64) -> (f64, f64, f64) {
collision::resolve_movement(self, aabb, dx, dy, dz)
}
}