Skip to content

Commit 975014e

Browse files
authored
tag registry (#350)
- add Tags extractor - add tags.json to extracted - send `SynchronizeTagsS2c` packet on join - fix encode ## Description Adds a `TagsRegistry` resource that contains all the information needed to build and send `SynchronizeTagsS2c` on join. closes #349
1 parent c5557e7 commit 975014e

File tree

10 files changed

+7445
-30
lines changed

10 files changed

+7445
-30
lines changed

crates/valence_client/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ use valence_instance::packet::{
6767
ChunkLoadDistanceS2c, ChunkRenderDistanceCenterS2c, UnloadChunkS2c,
6868
};
6969
use valence_instance::{ClearInstanceChangesSet, Instance, WriteUpdatePacketsToInstancesSet};
70-
use valence_registry::{RegistryCodec, RegistryCodecSet};
70+
use valence_registry::{RegistryCodec, RegistryCodecSet, TagsRegistry};
7171

7272
pub mod action;
7373
pub mod chat;
@@ -678,6 +678,7 @@ struct ClientJoinQuery {
678678

679679
fn initial_join(
680680
codec: Res<RegistryCodec>,
681+
tags: Res<TagsRegistry>,
681682
mut clients: Query<ClientJoinQuery, Added<Client>>,
682683
instances: Query<&Instance>,
683684
mut commands: Commands,
@@ -724,6 +725,8 @@ fn initial_join(
724725
last_death_location,
725726
});
726727

728+
q.client.enc.append_bytes(tags.sync_tags_packet());
729+
727730
/*
728731
// TODO: enable all the features?
729732
q.client.write_packet(&FeatureFlags {

crates/valence_core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl Default for CoreSettings {
142142
}
143143

144144
/// Contains global server state accessible as a [`Resource`].
145-
#[derive(Resource)]
145+
#[derive(Resource, Default)]
146146
pub struct Server {
147147
/// Incremented on every tick.
148148
current_tick: i64,

crates/valence_core/src/protocol/packet.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,26 +1372,3 @@ pub mod map {
13721372
}
13731373
}
13741374
}
1375-
1376-
// TODO: Move this to valence_registry?
1377-
pub mod synchronize_tags {
1378-
use super::*;
1379-
1380-
#[derive(Clone, Debug, Encode, Decode, Packet)]
1381-
#[packet(id = packet_id::SYNCHRONIZE_TAGS_S2C)]
1382-
pub struct SynchronizeTagsS2c<'a> {
1383-
pub tags: Vec<TagGroup<'a>>,
1384-
}
1385-
1386-
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
1387-
pub struct TagGroup<'a> {
1388-
pub kind: Ident<Cow<'a, str>>,
1389-
pub tags: Vec<Tag<'a>>,
1390-
}
1391-
1392-
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
1393-
pub struct Tag<'a> {
1394-
pub name: Ident<Cow<'a, str>>,
1395-
pub entries: Vec<VarInt>,
1396-
}
1397-
}

crates/valence_core/src/protocol/var_int.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use std::io::{Read, Write};
22

33
use anyhow::bail;
44
use byteorder::ReadBytesExt;
5+
use serde::Deserialize;
56
use thiserror::Error;
67

78
use crate::protocol::{Decode, Encode};
89

910
/// An `i32` encoded with variable length.
10-
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
11+
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Deserialize)]
1112
#[repr(transparent)]
1213
pub struct VarInt(pub i32);
1314

crates/valence_registry/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ tracing.workspace = true
88
valence_core.workspace = true
99
valence_nbt.workspace = true
1010
bevy_ecs.workspace = true
11-
bevy_app.workspace = true
11+
bevy_app.workspace = true
12+
serde.workspace = true
13+
serde_json.workspace = true

crates/valence_registry/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ use tracing::error;
2525
use valence_core::ident::Ident;
2626
use valence_nbt::{compound, Compound, List, Value};
2727

28+
mod tags;
29+
30+
pub use tags::*;
31+
2832
pub struct RegistryPlugin;
2933

3034
/// The [`SystemSet`] where the [`RegistryCodec`] cache is rebuilt. Systems that
@@ -35,8 +39,11 @@ pub struct RegistryCodecSet;
3539
impl Plugin for RegistryPlugin {
3640
fn build(&self, app: &mut bevy_app::App) {
3741
app.init_resource::<RegistryCodec>()
42+
.init_resource::<TagsRegistry>()
3843
.configure_set(RegistryCodecSet.in_base_set(CoreSet::PostUpdate))
39-
.add_system(cache_registry_codec.in_set(RegistryCodecSet));
44+
.add_startup_system(init_tags_registry.in_set(RegistryCodecSet))
45+
.add_system(cache_registry_codec.in_set(RegistryCodecSet))
46+
.add_system(cache_tags_packet.in_set(RegistryCodecSet));
4047
}
4148
}
4249

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use std::borrow::Cow;
2+
3+
use bevy_ecs::prelude::*;
4+
use serde::Deserialize;
5+
use valence_core::ident::Ident;
6+
use valence_core::protocol::encode::{PacketWriter, WritePacket};
7+
use valence_core::protocol::var_int::VarInt;
8+
use valence_core::protocol::{packet_id, Decode, Encode, Packet};
9+
use valence_core::Server;
10+
11+
#[derive(Clone, Debug, Encode, Decode, Packet)]
12+
#[packet(id = packet_id::SYNCHRONIZE_TAGS_S2C)]
13+
pub struct SynchronizeTagsS2c<'a> {
14+
pub registries: Cow<'a, [Registry]>,
15+
}
16+
17+
#[derive(Debug, Resource, Default)]
18+
pub struct TagsRegistry {
19+
pub registries: Vec<Registry>,
20+
cached_packet: Vec<u8>,
21+
}
22+
23+
#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Encode, Decode)]
24+
pub struct Registry {
25+
pub registry: Ident<String>,
26+
pub tags: Vec<TagEntry>,
27+
}
28+
29+
#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Encode, Decode)]
30+
pub struct TagEntry {
31+
pub name: Ident<String>,
32+
pub entries: Vec<VarInt>,
33+
}
34+
35+
impl<'a> TagsRegistry {
36+
pub(crate) fn build_synchronize_tags(&'a self) -> SynchronizeTagsS2c<'a> {
37+
SynchronizeTagsS2c {
38+
registries: Cow::Borrowed(&self.registries),
39+
}
40+
}
41+
42+
pub fn sync_tags_packet(&self) -> &Vec<u8> {
43+
&self.cached_packet
44+
}
45+
}
46+
47+
pub(crate) fn init_tags_registry(mut tags: ResMut<TagsRegistry>) {
48+
let registries =
49+
serde_json::from_str::<Vec<Registry>>(include_str!("../../../extracted/tags.json"))
50+
.expect("tags.json is invalid");
51+
tags.registries = registries;
52+
}
53+
54+
pub(crate) fn cache_tags_packet(server: Res<Server>, tags: ResMut<TagsRegistry>) {
55+
if tags.is_changed() {
56+
let tags = tags.into_inner();
57+
let packet = tags.build_synchronize_tags();
58+
let mut bytes = vec![];
59+
let mut scratch = vec![];
60+
let mut writer =
61+
PacketWriter::new(&mut bytes, server.compression_threshold(), &mut scratch);
62+
writer.write_packet(&packet);
63+
tags.cached_packet = bytes;
64+
}
65+
}
66+
67+
#[cfg(test)]
68+
mod tests {
69+
use super::*;
70+
use crate::RegistryPlugin;
71+
72+
#[test]
73+
fn smoke_test() {
74+
let mut app = bevy_app::App::new();
75+
app.add_plugin(RegistryPlugin);
76+
app.insert_resource(Server::default());
77+
app.update();
78+
79+
let tags_registry = app.world.get_resource::<TagsRegistry>().unwrap();
80+
let packet = tags_registry.build_synchronize_tags();
81+
assert!(!packet.registries.is_empty());
82+
assert!(!tags_registry.cached_packet.is_empty());
83+
}
84+
}

0 commit comments

Comments
 (0)