1use std::collections::hash_map::Entry;
2use std::collections::BTreeSet;
3
4use bevy_app::prelude::*;
5use bevy_ecs::prelude::*;
6use rustc_hash::FxHashMap;
7use valence_entity::query::UpdateEntityQuery;
8use valence_entity::{EntityId, EntityLayerId, OldEntityLayerId, OldPosition, Position};
9use valence_protocol::encode::{PacketWriter, WritePacket};
10use valence_protocol::{BlockPos, ChunkPos, CompressionThreshold, Encode, Packet};
11use valence_server_common::{Despawned, Server};
12
13use super::bvh::GetChunkPos;
14use super::message::Messages;
15use super::{Layer, UpdateLayersPostClientSet, UpdateLayersPreClientSet};
16use crate::client::Client;
17
18#[derive(Component, Debug)]
20pub struct EntityLayer {
21 messages: EntityLayerMessages,
22 entities: FxHashMap<ChunkPos, BTreeSet<Entity>>,
23 threshold: CompressionThreshold,
24}
25
26type EntityLayerMessages = Messages<GlobalMsg, LocalMsg>;
27
28#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
29pub(crate) enum GlobalMsg {
30 Packet,
33 PacketExcept { except: Entity },
36 DespawnLayer,
39}
40
41#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
42pub(crate) enum LocalMsg {
44 DespawnEntity { pos: ChunkPos, dest_layer: Entity },
47 DespawnEntityTransition { pos: ChunkPos, dest_pos: ChunkPos },
50 SpawnEntity { pos: ChunkPos, src_layer: Entity },
53 SpawnEntityTransition { pos: ChunkPos, src_pos: ChunkPos },
56 PacketAt { pos: ChunkPos },
59 PacketAtExcept { pos: ChunkPos, except: Entity },
63 RadiusAt {
65 center: BlockPos,
66 radius_squared: u32,
67 },
68 RadiusAtExcept {
70 center: BlockPos,
71 radius_squared: u32,
72 except: Entity,
73 },
74}
75
76impl GetChunkPos for LocalMsg {
77 fn chunk_pos(&self) -> ChunkPos {
78 match *self {
79 LocalMsg::PacketAt { pos } => pos,
80 LocalMsg::PacketAtExcept { pos, .. } => pos,
81 LocalMsg::RadiusAt { center, .. } => center.into(),
82 LocalMsg::RadiusAtExcept { center, .. } => center.into(),
83 LocalMsg::SpawnEntity { pos, .. } => pos,
84 LocalMsg::SpawnEntityTransition { pos, .. } => pos,
85 LocalMsg::DespawnEntity { pos, .. } => pos,
86 LocalMsg::DespawnEntityTransition { pos, .. } => pos,
87 }
88 }
89}
90
91impl EntityLayer {
92 pub fn new(server: &Server) -> Self {
94 Self {
95 messages: Messages::new(),
96 entities: Default::default(),
97 threshold: server.compression_threshold(),
98 }
99 }
100
101 pub fn entities_at<P: Into<ChunkPos>>(
104 &self,
105 pos: P,
106 ) -> impl Iterator<Item = Entity> + Clone + '_ {
107 self.entities
108 .get(&pos.into())
109 .into_iter()
110 .flat_map(|entities| entities.iter().copied())
111 }
112
113 pub(crate) fn messages(&self) -> &EntityLayerMessages {
114 &self.messages
115 }
116}
117
118impl Layer for EntityLayer {
119 type ExceptWriter<'a> = ExceptWriter<'a>;
120
121 type ViewWriter<'a> = ViewWriter<'a>;
122
123 type ViewExceptWriter<'a> = ViewExceptWriter<'a>;
124
125 type RadiusWriter<'a> = RadiusWriter<'a>;
126
127 type RadiusExceptWriter<'a> = RadiusExceptWriter<'a>;
128
129 fn except_writer(&mut self, except: Entity) -> Self::ExceptWriter<'_> {
130 ExceptWriter {
131 layer: self,
132 except,
133 }
134 }
135
136 fn view_writer(&mut self, pos: impl Into<ChunkPos>) -> Self::ViewWriter<'_> {
137 ViewWriter {
138 layer: self,
139 pos: pos.into(),
140 }
141 }
142
143 fn view_except_writer(
144 &mut self,
145 pos: impl Into<ChunkPos>,
146 except: Entity,
147 ) -> Self::ViewExceptWriter<'_> {
148 ViewExceptWriter {
149 layer: self,
150 pos: pos.into(),
151 except,
152 }
153 }
154
155 fn radius_writer(
156 &mut self,
157 center: impl Into<BlockPos>,
158 radius: u32,
159 ) -> Self::RadiusWriter<'_> {
160 RadiusWriter {
161 layer: self,
162 center: center.into(),
163 radius_squared: radius.saturating_mul(radius),
164 }
165 }
166
167 fn radius_except_writer(
168 &mut self,
169 center: impl Into<BlockPos>,
170 radius: u32,
171 except: Entity,
172 ) -> Self::RadiusExceptWriter<'_> {
173 RadiusExceptWriter {
174 layer: self,
175 center: center.into(),
176 radius_squared: radius.saturating_mul(radius),
177 except,
178 }
179 }
180}
181
182impl WritePacket for EntityLayer {
183 fn write_packet_fallible<P>(&mut self, packet: &P) -> anyhow::Result<()>
184 where
185 P: Packet + Encode,
186 {
187 self.messages.send_global(GlobalMsg::Packet, |b| {
188 PacketWriter::new(b, self.threshold).write_packet_fallible(packet)
189 })
190 }
191
192 fn write_packet_bytes(&mut self, bytes: &[u8]) {
193 self.messages
194 .send_global_infallible(GlobalMsg::Packet, |b| b.extend_from_slice(bytes));
195 }
196}
197
198pub struct ExceptWriter<'a> {
199 layer: &'a mut EntityLayer,
200 except: Entity,
201}
202
203impl WritePacket for ExceptWriter<'_> {
204 fn write_packet_fallible<P>(&mut self, packet: &P) -> anyhow::Result<()>
205 where
206 P: Packet + Encode,
207 {
208 self.layer.messages.send_global(
209 GlobalMsg::PacketExcept {
210 except: self.except,
211 },
212 |b| PacketWriter::new(b, self.layer.threshold).write_packet_fallible(packet),
213 )
214 }
215
216 fn write_packet_bytes(&mut self, bytes: &[u8]) {
217 self.layer.messages.send_global_infallible(
218 GlobalMsg::PacketExcept {
219 except: self.except,
220 },
221 |b| b.extend_from_slice(bytes),
222 )
223 }
224}
225
226pub struct ViewWriter<'a> {
227 layer: &'a mut EntityLayer,
228 pos: ChunkPos,
229}
230
231impl WritePacket for ViewWriter<'_> {
232 fn write_packet_fallible<P>(&mut self, packet: &P) -> anyhow::Result<()>
233 where
234 P: Packet + Encode,
235 {
236 self.layer
237 .messages
238 .send_local(LocalMsg::PacketAt { pos: self.pos }, |b| {
239 PacketWriter::new(b, self.layer.threshold).write_packet_fallible(packet)
240 })
241 }
242
243 fn write_packet_bytes(&mut self, bytes: &[u8]) {
244 self.layer
245 .messages
246 .send_local_infallible(LocalMsg::PacketAt { pos: self.pos }, |b| {
247 b.extend_from_slice(bytes)
248 });
249 }
250}
251
252pub struct ViewExceptWriter<'a> {
253 layer: &'a mut EntityLayer,
254 pos: ChunkPos,
255 except: Entity,
256}
257
258impl WritePacket for ViewExceptWriter<'_> {
259 fn write_packet_fallible<P>(&mut self, packet: &P) -> anyhow::Result<()>
260 where
261 P: Packet + Encode,
262 {
263 self.layer.messages.send_local(
264 LocalMsg::PacketAtExcept {
265 pos: self.pos,
266 except: self.except,
267 },
268 |b| PacketWriter::new(b, self.layer.threshold).write_packet_fallible(packet),
269 )
270 }
271
272 fn write_packet_bytes(&mut self, bytes: &[u8]) {
273 self.layer.messages.send_local_infallible(
274 LocalMsg::PacketAtExcept {
275 pos: self.pos,
276 except: self.except,
277 },
278 |b| b.extend_from_slice(bytes),
279 );
280 }
281}
282
283pub struct RadiusWriter<'a> {
284 layer: &'a mut EntityLayer,
285 center: BlockPos,
286 radius_squared: u32,
287}
288
289impl WritePacket for RadiusWriter<'_> {
290 fn write_packet_fallible<P>(&mut self, packet: &P) -> anyhow::Result<()>
291 where
292 P: Packet + Encode,
293 {
294 self.layer.messages.send_local(
295 LocalMsg::RadiusAt {
296 center: self.center,
297 radius_squared: self.radius_squared,
298 },
299 |b| PacketWriter::new(b, self.layer.threshold).write_packet_fallible(packet),
300 )
301 }
302
303 fn write_packet_bytes(&mut self, bytes: &[u8]) {
304 self.layer.messages.send_local_infallible(
305 LocalMsg::RadiusAt {
306 center: self.center,
307 radius_squared: self.radius_squared,
308 },
309 |b| b.extend_from_slice(bytes),
310 );
311 }
312}
313
314pub struct RadiusExceptWriter<'a> {
315 layer: &'a mut EntityLayer,
316 center: BlockPos,
317 radius_squared: u32,
318 except: Entity,
319}
320
321impl WritePacket for RadiusExceptWriter<'_> {
322 fn write_packet_fallible<P>(&mut self, packet: &P) -> anyhow::Result<()>
323 where
324 P: Packet + Encode,
325 {
326 self.layer.messages.send_local(
327 LocalMsg::RadiusAtExcept {
328 center: self.center,
329 radius_squared: self.radius_squared,
330 except: self.except,
331 },
332 |b| PacketWriter::new(b, self.layer.threshold).write_packet_fallible(packet),
333 )
334 }
335
336 fn write_packet_bytes(&mut self, bytes: &[u8]) {
337 self.layer.messages.send_local_infallible(
338 LocalMsg::RadiusAtExcept {
339 center: self.center,
340 radius_squared: self.radius_squared,
341 except: self.except,
342 },
343 |b| b.extend_from_slice(bytes),
344 );
345 }
346}
347
348pub(super) fn build(app: &mut App) {
349 app.add_systems(
350 PostUpdate,
351 (
352 (
353 change_entity_positions,
354 send_entity_update_messages,
355 send_layer_despawn_messages,
356 ready_entity_layers,
357 )
358 .chain()
359 .in_set(UpdateLayersPreClientSet),
360 unready_entity_layers.in_set(UpdateLayersPostClientSet),
361 ),
362 );
363}
364
365fn change_entity_positions(
366 entities: Query<
367 (
368 Entity,
369 &EntityId,
370 &Position,
371 &OldPosition,
372 &EntityLayerId,
373 &OldEntityLayerId,
374 Has<Despawned>,
375 ),
376 Or<(Changed<Position>, Changed<EntityLayerId>, With<Despawned>)>,
377 >,
378 mut layers: Query<&mut EntityLayer>,
379) {
380 for (entity, entity_id, pos, old_pos, layer_id, old_layer_id, despawned) in &entities {
381 let chunk_pos = ChunkPos::from(pos.0);
382 let old_chunk_pos = ChunkPos::from(old_pos.get());
383
384 if despawned {
385 if let Ok(old_layer) = layers.get_mut(layer_id.0) {
388 let old_layer = old_layer.into_inner();
389
390 if let Entry::Occupied(mut old_cell) = old_layer.entities.entry(old_chunk_pos) {
391 if old_cell.get_mut().remove(&entity) {
392 old_layer.messages.send_local_infallible(
393 LocalMsg::DespawnEntity {
394 pos: old_chunk_pos,
395 dest_layer: Entity::PLACEHOLDER,
396 },
397 |b| b.extend_from_slice(&entity_id.get().to_ne_bytes()),
398 );
399
400 if old_cell.get().is_empty() {
401 old_cell.remove();
402 }
403 }
404 }
405 }
406 } else if old_layer_id != layer_id {
407 if let Ok(old_layer) = layers.get_mut(old_layer_id.get()) {
411 let old_layer = old_layer.into_inner();
412
413 if let Entry::Occupied(mut old_cell) = old_layer.entities.entry(old_chunk_pos) {
414 if old_cell.get_mut().remove(&entity) {
415 old_layer.messages.send_local_infallible(
416 LocalMsg::DespawnEntity {
417 pos: old_chunk_pos,
418 dest_layer: layer_id.0,
419 },
420 |b| b.extend_from_slice(&entity_id.get().to_ne_bytes()),
421 );
422
423 if old_cell.get().is_empty() {
424 old_cell.remove();
425 }
426 }
427 }
428 }
429
430 if let Ok(mut layer) = layers.get_mut(layer_id.0) {
431 if layer.entities.entry(chunk_pos).or_default().insert(entity) {
432 layer.messages.send_local_infallible(
433 LocalMsg::SpawnEntity {
434 pos: chunk_pos,
435 src_layer: old_layer_id.get(),
436 },
437 |b| b.extend_from_slice(&entity.to_bits().to_ne_bytes()),
438 );
439 }
440 }
441 } else if chunk_pos != old_chunk_pos {
442 if let Ok(mut layer) = layers.get_mut(layer_id.0) {
446 if let Entry::Occupied(mut old_cell) = layer.entities.entry(old_chunk_pos) {
447 if old_cell.get_mut().remove(&entity) {
448 layer.messages.send_local_infallible(
449 LocalMsg::DespawnEntityTransition {
450 pos: old_chunk_pos,
451 dest_pos: chunk_pos,
452 },
453 |b| b.extend_from_slice(&entity_id.get().to_ne_bytes()),
454 );
455 }
456 }
457
458 if layer.entities.entry(chunk_pos).or_default().insert(entity) {
459 layer.messages.send_local_infallible(
460 LocalMsg::SpawnEntityTransition {
461 pos: chunk_pos,
462 src_pos: old_chunk_pos,
463 },
464 |b| b.extend_from_slice(&entity.to_bits().to_ne_bytes()),
465 );
466 }
467 }
468 }
469 }
470}
471
472fn send_entity_update_messages(
473 entities: Query<(Entity, UpdateEntityQuery, Has<Client>), Without<Despawned>>,
474 mut layers: Query<&mut EntityLayer>,
475) {
476 for layer in &mut layers {
477 let layer = layer.into_inner();
478
479 for cell in layer.entities.values_mut() {
480 for &entity in cell.iter() {
481 if let Ok((entity, update, is_client)) = entities.get(entity) {
482 let chunk_pos = ChunkPos::from(update.pos.0);
483
484 let msg = if is_client {
488 LocalMsg::PacketAtExcept {
489 pos: chunk_pos,
490 except: entity,
491 }
492 } else {
493 LocalMsg::PacketAt { pos: chunk_pos }
494 };
495
496 layer.messages.send_local_infallible(msg, |b| {
497 update.write_update_packets(PacketWriter::new(b, layer.threshold))
498 });
499 } else {
500 panic!(
501 "Entity {entity:?} was not properly removed from entity layer. Did you \
502 forget to use the `Despawned` component?"
503 );
504 }
505 }
506 }
507 }
508}
509
510fn send_layer_despawn_messages(mut layers: Query<&mut EntityLayer, With<Despawned>>) {
511 for mut layer in &mut layers {
512 layer
513 .messages
514 .send_global_infallible(GlobalMsg::DespawnLayer, |_| {});
515 }
516}
517
518fn ready_entity_layers(mut layers: Query<&mut EntityLayer>) {
519 for mut layer in &mut layers {
520 layer.messages.ready();
521 }
522}
523
524fn unready_entity_layers(mut layers: Query<&mut EntityLayer>) {
525 for mut layer in &mut layers {
526 layer.messages.unready();
527 }
528}