-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathentities.rs
More file actions
98 lines (86 loc) · 2.79 KB
/
entities.rs
File metadata and controls
98 lines (86 loc) · 2.79 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use ahash::AHashMap;
use base::{ChunkPosition, Position};
use ecs::{Entity, SysResult, SystemExecutor};
use quill_common::events::{EntityCreateEvent, EntityRemoveEvent};
use utils::vec_remove_item;
use crate::{events::ChunkCrossEvent, Game};
pub fn register(systems: &mut SystemExecutor<Game>) {
systems.add_system(update_chunk_entities);
}
/// A spatial index to look up entities within a given chunk.
#[derive(Default)]
pub struct ChunkEntities {
entities: AHashMap<ChunkPosition, Vec<Entity>>,
}
impl ChunkEntities {
/// Returns the entities in the given chunk.
pub fn entities_in_chunk(&self, chunk: ChunkPosition) -> &[Entity] {
self.entities
.get(&chunk)
.map(Vec::as_slice)
.unwrap_or_default()
}
fn update(
&mut self,
entity: Entity,
old_chunk: Option<ChunkPosition>,
new_chunk: ChunkPosition,
) {
if let Some(old_chunk) = old_chunk {
if let Some(vec) = self.entities.get_mut(&old_chunk) {
vec_remove_item(vec, &entity);
}
}
self.entities.entry(new_chunk).or_default().push(entity);
}
fn remove_entity(&mut self, entity: Entity, chunk: ChunkPosition) {
if let Some(vec) = self.entities.get_mut(&chunk) {
vec_remove_item(vec, &entity);
}
}
}
fn update_chunk_entities(game: &mut Game) -> SysResult {
// Entities that have crossed chunks
let mut events = Vec::new();
for (entity, (old_chunk, &position)) in
game.ecs.query::<(&mut ChunkPosition, &Position)>().iter()
{
let new_chunk = position.chunk();
if position.chunk() != *old_chunk {
game.chunk_entities
.update(entity, Some(*old_chunk), new_chunk);
events.push((
entity,
ChunkCrossEvent {
old_chunk: *old_chunk,
new_chunk,
},
));
*old_chunk = new_chunk;
}
}
for (entity, event) in events {
game.ecs.insert_entity_event(entity, event)?;
}
// Entities that have been created
let mut insertions = Vec::new();
for (entity, (_event, &position)) in game.ecs.query::<(&EntityCreateEvent, &Position)>().iter()
{
let chunk = position.chunk();
game.chunk_entities.update(entity, None, chunk);
insertions.push((entity, chunk));
}
// Add ChunkPosition component to new entities
for (entity, chunk) in insertions {
game.ecs.insert(entity, chunk)?;
}
// Entities that have been destroyed
for (entity, (_event, &chunk)) in game
.ecs
.query::<(&EntityRemoveEvent, &ChunkPosition)>()
.iter()
{
game.chunk_entities.remove_entity(entity, chunk);
}
Ok(())
}