valence_registry/
tags.rs

1use std::borrow::Cow;
2
3use bevy_app::prelude::*;
4use bevy_ecs::prelude::*;
5use valence_protocol::encode::{PacketWriter, WritePacket};
6pub use valence_protocol::packets::play::synchronize_tags_s2c::RegistryMap;
7use valence_protocol::packets::play::SynchronizeTagsS2c;
8use valence_server_common::Server;
9
10use crate::RegistrySet;
11
12#[derive(Debug, Resource, Default)]
13pub struct TagsRegistry {
14    pub registries: RegistryMap,
15    cached_packet: Vec<u8>,
16}
17
18pub(super) fn build(app: &mut App) {
19    app.init_resource::<TagsRegistry>()
20        .add_systems(PreStartup, init_tags_registry)
21        .add_systems(PostUpdate, cache_tags_packet.in_set(RegistrySet));
22}
23
24impl TagsRegistry {
25    fn build_synchronize_tags(&self) -> SynchronizeTagsS2c {
26        SynchronizeTagsS2c {
27            groups: Cow::Borrowed(&self.registries),
28        }
29    }
30
31    /// Returns bytes of the cached [`SynchronizeTagsS2c`] packet.
32    pub fn sync_tags_packet(&self) -> &[u8] {
33        &self.cached_packet
34    }
35}
36
37fn init_tags_registry(mut tags: ResMut<TagsRegistry>) {
38    let registries = serde_json::from_str::<RegistryMap>(include_str!("../extracted/tags.json"))
39        .expect("tags.json must have expected structure");
40
41    tags.registries = registries;
42}
43
44pub(crate) fn cache_tags_packet(server: Res<Server>, tags: ResMut<TagsRegistry>) {
45    if tags.is_changed() {
46        let tags = tags.into_inner();
47        let packet = tags.build_synchronize_tags();
48        let mut bytes = vec![];
49        let mut writer = PacketWriter::new(&mut bytes, server.compression_threshold());
50
51        writer.write_packet(&packet);
52        tags.cached_packet = bytes;
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    /* TODO: move this to src/tests/
59    #[test]
60    fn smoke_test() {
61        let mut app = bevy_app::App::new();
62        app.add_plugins(RegistryPlugin);
63        // app.insert_resource(Server::default());
64        app.update();
65
66        let tags_registry = app.world.get_resource::<TagsRegistry>().unwrap();
67        let packet = tags_registry.build_synchronize_tags();
68        assert!(!packet.registries.is_empty());
69        assert!(!tags_registry.cached_packet.is_empty());
70    }
71    */
72}