forked from feather-rs/feather
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchunk_subscriptions.rs
More file actions
70 lines (61 loc) · 2.02 KB
/
chunk_subscriptions.rs
File metadata and controls
70 lines (61 loc) · 2.02 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
use ahash::AHashMap;
use base::ChunkPosition;
use common::{events::ViewUpdateEvent, view::View, Game};
use ecs::{SysResult, SystemExecutor};
use quill_common::events::EntityRemoveEvent;
use utils::vec_remove_item;
use crate::{ClientId, Server};
/// Data structure to query which clients should
/// receive updates from a given chunk, fast.
#[derive(Default)]
pub struct ChunkSubscriptions {
chunks: AHashMap<ChunkPosition, Vec<ClientId>>,
}
impl ChunkSubscriptions {
pub fn subscriptions_for(&self, chunk: ChunkPosition) -> &[ClientId] {
self.chunks
.get(&chunk)
.map(Vec::as_slice)
.unwrap_or_default()
}
}
pub fn register(systems: &mut SystemExecutor<Game>) {
systems
.group::<Server>()
.add_system(update_chunk_subscriptions);
}
fn update_chunk_subscriptions(game: &mut Game, server: &mut Server) -> SysResult {
// Update players whose views have changed
for (_, (event, &client_id)) in game.ecs.query::<(&ViewUpdateEvent, &ClientId)>().iter() {
for new_chunk in event.new_view.difference(event.old_view) {
server
.chunk_subscriptions
.chunks
.entry(new_chunk)
.or_default()
.push(client_id);
}
for old_chunk in event.old_view.difference(event.new_view) {
remove_subscription(server, old_chunk, client_id);
}
}
// Update players that have left
for (_, (_event, &client_id, &view)) in game
.ecs
.query::<(&EntityRemoveEvent, &ClientId, &View)>()
.iter()
{
for chunk in view.iter() {
remove_subscription(server, chunk, client_id);
}
}
Ok(())
}
fn remove_subscription(server: &mut Server, chunk: ChunkPosition, client_id: ClientId) {
if let Some(vec) = server.chunk_subscriptions.chunks.get_mut(&chunk) {
vec_remove_item(vec, &client_id);
if vec.is_empty() {
server.chunk_subscriptions.chunks.remove(&chunk);
}
}
}