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}