summaryrefslogtreecommitdiff
path: root/src/sim/world.rs
blob: 6645d4e8748ac8c9916451653dd02843247dfb28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use fxhash::FxHashMap;

use crate::{
    config::CHUNK_SIZE,
    sim::{cell::Cell, chunk::Chunk},
};

pub struct World {
    pub chunks: Vec<Chunk>,
    // 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<Cell> {
        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;
        }
    }

    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..10 {
            for x in -10..10 {
                world.insert(x, y, Chunk::void());
            }
        }

        world
    }
}