summaryrefslogtreecommitdiff
path: root/src/resources/ground.rs
blob: 7868be9c5c72a2164ad725a0d0c5da02c70b3c77 (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
75
76

use std::collections::{HashMap, HashSet};

use specs::{
	ReadStorage,
	Component,
	Entity
};

use crate::{
	components::{Visible, Flags, Flag},
	Pos,
	controls::Direction
};

#[derive(Default)]
pub struct Ground {
	pub cells: HashMap<Pos, HashSet<Entity>>,
	pub changes: HashSet<Pos>
}

impl Ground {
	
	pub fn insert(&mut self, pos: Pos, ent: Entity){
		self.cells.entry(pos).or_insert_with(HashSet::new).insert(ent);
		self.changes.insert(pos);
	}
	
	pub fn remove(&mut self, pos: &Pos, ent: Entity) -> bool{
		if let Some(cell) = self.cells.get_mut(pos) {
			self.changes.insert(*pos);
			cell.remove(&ent)
		} else {
			false
		}
	}
	
	pub fn components_on<'a, C: Component>(&self, pos: Pos, component_type: &'a ReadStorage<C>) -> Vec<&'a C> {
		self.cells
			.get(&pos)
			.unwrap_or(&HashSet::new())
			.iter()
			.filter_map(|e| component_type.get(*e))
			.collect()
	}
	
	pub fn components_near<'a, C: Component>(&self, pos: Pos, directions: &[Direction], component_type: &'a ReadStorage<C>) -> Vec<(Entity, &'a C)> {
		let mut nearby_components: Vec<(Entity, &'a C)> = Vec::new();
		for direction in directions {
			let pos = pos + direction.to_position();
			for ent in self.cells.get(&pos).unwrap_or(&HashSet::new()) {
				if let Some(comp) = component_type.get(*ent) {
					nearby_components.push((*ent, comp));
				}
			}
		}
		nearby_components
	}
	
	pub fn by_height(&self, pos: &Pos, visibles: &ReadStorage<Visible>, ignore: &Entity) -> Vec<Entity> {
		let mut entities: Vec<Entity> = self.cells
			.get(&pos).unwrap_or(&HashSet::new())
			.iter()
			.cloned()
			.filter(|e| e != ignore && visibles.contains(*e))
			.collect();
		entities.sort_by(|a, b|
			visibles.get(*b).unwrap().height.partial_cmp(&visibles.get(*a).unwrap().height).unwrap()
		);
		entities
	}
	
	pub fn flags_on<'a>(&self, pos: Pos, flags: &'a ReadStorage<Flags>) -> HashSet<Flag> {
		self.components_on::<Flags>(pos, flags).into_iter().fold(HashSet::new(), |a, b| &a | &b.0)
	}
}