chunkedge_registry/
codec.rs1use std::collections::BTreeMap;
2
3use bevy_app::prelude::*;
4use bevy_ecs::prelude::*;
5use chunkedge_ident::Ident;
6use chunkedge_nbt::{compound, Compound, List, Value};
7use tracing::error;
8
9use crate::RegistrySet;
10
11pub(super) fn build(app: &mut App) {
12 app.init_resource::<RegistryCodec>()
13 .add_systems(PostUpdate, cache_registry_codec.in_set(RegistrySet));
14}
15
16#[derive(Resource, Debug)]
22pub struct RegistryCodec {
23 pub registries: BTreeMap<Ident<String>, Vec<RegistryValue>>,
24 cached_codec: Compound,
26}
27
28#[derive(Clone, Debug)]
29pub struct RegistryValue {
30 pub name: Ident<String>,
31 pub element: Compound,
32}
33
34impl RegistryCodec {
35 pub fn cached_codec(&self) -> &Compound {
36 &self.cached_codec
37 }
38
39 pub fn registry(&self, registry_key: Ident<&str>) -> &Vec<RegistryValue> {
40 self.registries
41 .get(registry_key.as_str())
42 .unwrap_or_else(|| panic!("missing registry for {registry_key}"))
43 }
44
45 pub fn registry_mut(&mut self, registry_key: Ident<&str>) -> &mut Vec<RegistryValue> {
46 self.registries
47 .get_mut(registry_key.as_str())
48 .unwrap_or_else(|| panic!("missing registry for {registry_key}"))
49 }
50}
51
52impl Default for RegistryCodec {
53 fn default() -> Self {
54 let codec = include_bytes!("../extracted/registry_codec.json");
59 let compound = serde_json::from_slice::<Compound>(codec)
60 .expect("failed to decode vanilla registry codec");
61
62 let mut registries = BTreeMap::new();
63
64 for (k, v) in compound {
65 let reg_name: Ident<String> = Ident::new(k).expect("invalid registry name").into();
66 let mut reg_values = vec![];
67
68 let Value::Compound(inner) = v else {
69 error!("registry {reg_name} is not a compound");
70 continue;
71 };
72
73 for (k, v) in inner {
74 let name = match Ident::new(k) {
75 Ok(n) => n.into(),
76 Err(e) => {
77 error!("invalid registry value name \"{}\"", e.0);
78 continue;
79 }
80 };
81
82 let Value::Compound(value) = v else {
83 error!("registry value {name} is not a compound");
84 continue;
85 };
86
87 reg_values.push(RegistryValue {
88 name,
89 element: value,
90 });
91 }
92
93 registries.insert(reg_name, reg_values);
94 }
95
96 Self {
97 registries,
98 cached_codec: Compound::new(),
100 }
101 }
102}
103
104fn cache_registry_codec(codec: ResMut<RegistryCodec>) {
105 if codec.is_changed() {
106 let codec = codec.into_inner();
107
108 codec.cached_codec.clear();
109
110 for (reg_name, reg) in &codec.registries {
111 let mut value = vec![];
112
113 for (id, v) in reg.iter().enumerate() {
114 value.push(compound! {
115 "id" => id as i32,
116 "name" => v.name.as_str(),
117 "element" => v.element.clone(),
118 });
119 }
120
121 let registry = compound! {
122 "type" => reg_name.as_str(),
123 "value" => List::Compound(value),
124 };
125
126 codec.cached_codec.insert(reg_name.as_str(), registry);
127 }
128 }
129}