2016-04-20 14:25:51 -04:00
|
|
|
|
2018-11-04 14:48:03 -05:00
|
|
|
use crate::types::bit;
|
|
|
|
use crate::types::hash::FNVHash;
|
|
|
|
use crate::world::block;
|
2016-04-20 14:25:51 -04:00
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::hash::BuildHasherDefault;
|
|
|
|
|
|
|
|
pub struct BlockStorage {
|
|
|
|
blocks: bit::Map,
|
|
|
|
block_map: Vec<(block::Block, u32)>,
|
|
|
|
rev_block_map: HashMap<block::Block, usize, BuildHasherDefault<FNVHash>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BlockStorage {
|
|
|
|
pub fn new(size: usize) -> BlockStorage {
|
2016-04-20 15:07:39 -04:00
|
|
|
Self::new_default(size, block::Air{})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_default(size: usize, def: block::Block) -> BlockStorage {
|
2016-04-20 14:25:51 -04:00
|
|
|
let mut storage = BlockStorage {
|
|
|
|
blocks: bit::Map::new(size, 4),
|
|
|
|
block_map: vec![
|
2016-04-20 15:07:39 -04:00
|
|
|
(def, size as u32)
|
2016-04-20 14:25:51 -04:00
|
|
|
],
|
|
|
|
rev_block_map: HashMap::with_hasher(BuildHasherDefault::default()),
|
|
|
|
};
|
2016-04-20 15:07:39 -04:00
|
|
|
storage.rev_block_map.insert(def, 0);
|
2016-04-20 14:25:51 -04:00
|
|
|
storage
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(&self, idx: usize) -> block::Block {
|
|
|
|
let idx = self.blocks.get(idx);
|
2016-04-21 07:55:42 -04:00
|
|
|
self.block_map[idx].0
|
2016-04-20 14:25:51 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set(&mut self, idx: usize, b: block::Block) -> bool {
|
|
|
|
use std::collections::hash_map::Entry;
|
|
|
|
let old = self.get(idx);
|
|
|
|
if old == b {
|
|
|
|
return false;
|
|
|
|
}
|
2016-04-21 08:38:49 -04:00
|
|
|
// Clean up the old block
|
2016-04-20 14:25:51 -04:00
|
|
|
{
|
2016-04-21 16:20:28 -04:00
|
|
|
let idx = *self.rev_block_map.get(&old).unwrap();
|
|
|
|
let info = &mut self.block_map[idx];
|
|
|
|
info.1 -= 1;
|
|
|
|
if info.1 == 0 { // None left of this type
|
|
|
|
self.rev_block_map.remove(&old);
|
2016-04-20 14:25:51 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Entry::Vacant(entry) = self.rev_block_map.entry(b) {
|
|
|
|
let mut found = false;
|
|
|
|
let id = entry.insert(self.block_map.len());
|
|
|
|
for (i, ref mut info) in self.block_map.iter_mut().enumerate() {
|
|
|
|
if info.1 == 0 {
|
|
|
|
info.0 = b;
|
|
|
|
*id = i;
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
if self.block_map.len() >= 1 << self.blocks.bit_size {
|
|
|
|
let new_size = self.blocks.bit_size + 1;
|
|
|
|
self.blocks = self.blocks.resize(new_size);
|
|
|
|
}
|
|
|
|
self.block_map.push((b, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
let b_idx = self.rev_block_map[&b];
|
|
|
|
let info = &mut self.block_map[b_idx];
|
|
|
|
info.1 += 1;
|
|
|
|
self.blocks.set(idx, b_idx);
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|