valence_server/layer.rs
1//! Defines chunk layers and entity layers. Chunk layers contain the chunks and
2//! dimension data of a world, while entity layers contain all the Minecraft
3//! entities.
4//!
5//! These two together are analogous to Minecraft "levels" or "worlds".
6
7pub mod bvh;
8pub mod chunk;
9pub mod entity;
10pub mod message;
11
12use bevy_app::prelude::*;
13use bevy_ecs::prelude::*;
14pub use chunk::ChunkLayer;
15pub use entity::EntityLayer;
16use valence_entity::{InitEntitiesSet, UpdateTrackedDataSet};
17use valence_protocol::encode::WritePacket;
18use valence_protocol::{BlockPos, ChunkPos, Ident};
19use valence_registry::{BiomeRegistry, DimensionTypeRegistry};
20use valence_server_common::Server;
21
22pub struct LayerPlugin;
23
24/// When entity and chunk changes are written to layers. Systems that modify
25/// chunks and entities should run _before_ this. Systems that need to read
26/// layer messages should run _after_ this.
27#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
28pub struct UpdateLayersPreClientSet;
29
30/// When layers are cleared and messages from this tick are lost. Systems that
31/// read layer messages should run _before_ this.
32#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
33pub struct UpdateLayersPostClientSet;
34
35impl Plugin for LayerPlugin {
36 fn build(&self, app: &mut App) {
37 app.configure_sets(
38 PostUpdate,
39 (
40 UpdateLayersPreClientSet
41 .after(InitEntitiesSet)
42 .after(UpdateTrackedDataSet),
43 UpdateLayersPostClientSet.after(UpdateLayersPreClientSet),
44 ),
45 );
46
47 chunk::build(app);
48 entity::build(app);
49 }
50}
51
52/// Common functionality for layers. Notable implementors are [`ChunkLayer`] and
53/// [`EntityLayer`].
54///
55/// Layers support sending packets to viewers of the layer under various
56/// conditions. These are the "packet writers" exposed by this trait.
57///
58/// Layers themselves implement the [`WritePacket`] trait. Writing directly to a
59/// layer will send packets to all viewers unconditionally.
60pub trait Layer: WritePacket {
61 /// Packet writer returned by [`except_writer`](Self::except_writer).
62 type ExceptWriter<'a>: WritePacket
63 where
64 Self: 'a;
65
66 /// Packet writer returned by [`view_writer`](Self::ViewWriter).
67 type ViewWriter<'a>: WritePacket
68 where
69 Self: 'a;
70
71 /// Packet writer returned by
72 /// [`view_except_writer`](Self::ViewExceptWriter).
73 type ViewExceptWriter<'a>: WritePacket
74 where
75 Self: 'a;
76
77 /// Packet writer returned by [`radius_writer`](Self::radius_writer).
78 type RadiusWriter<'a>: WritePacket
79 where
80 Self: 'a;
81
82 /// Packet writer returned by
83 /// [`radius_except_writer`](Self::radius_except_writer).
84 type RadiusExceptWriter<'a>: WritePacket
85 where
86 Self: 'a;
87
88 /// Returns a packet writer which sends packets to all viewers not
89 /// identified by `except`.
90 fn except_writer(&mut self, except: Entity) -> Self::ExceptWriter<'_>;
91
92 /// Returns a packet writer which sends packets to viewers in view of
93 /// the chunk position `pos`.
94 fn view_writer(&mut self, pos: impl Into<ChunkPos>) -> Self::ViewWriter<'_>;
95
96 /// Returns a packet writer which sends packets to viewers in
97 /// view of the chunk position `pos` and not identified by `except`.
98 fn view_except_writer(
99 &mut self,
100 pos: impl Into<ChunkPos>,
101 except: Entity,
102 ) -> Self::ViewExceptWriter<'_>;
103
104 /// Returns a packet writer which sends packets to viewers within `radius`
105 /// blocks of the block position `pos`.
106 fn radius_writer(&mut self, pos: impl Into<BlockPos>, radius: u32) -> Self::RadiusWriter<'_>;
107
108 /// Returns a packet writer which sends packets to viewers within `radius`
109 /// blocks of the block position `pos` and not identified by `except`.
110 fn radius_except_writer(
111 &mut self,
112 pos: impl Into<BlockPos>,
113 radius: u32,
114 except: Entity,
115 ) -> Self::RadiusExceptWriter<'_>;
116}
117
118/// Convenience [`Bundle`] for spawning a layer entity with both [`ChunkLayer`]
119/// and [`EntityLayer`] components.
120#[derive(Bundle)]
121pub struct LayerBundle {
122 pub chunk: ChunkLayer,
123 pub entity: EntityLayer,
124}
125
126impl LayerBundle {
127 /// Returns a new layer bundle.
128 pub fn new<N: Into<Ident<String>>>(
129 dimension_type_name: N,
130 dimensions: &DimensionTypeRegistry,
131 biomes: &BiomeRegistry,
132 server: &Server,
133 ) -> Self {
134 Self {
135 chunk: ChunkLayer::new(dimension_type_name, dimensions, biomes, server),
136 entity: EntityLayer::new(server),
137 }
138 }
139}