schematic_mesher/resource_pack/
mod.rs1pub mod loader;
7pub mod blockstate;
8pub mod model;
9pub mod texture;
10
11pub use blockstate::{BlockstateDefinition, ModelVariant, MultipartCase, MultipartCondition};
12pub use model::{BlockModel, ModelElement, ModelFace};
13pub use texture::TextureData;
14
15use std::collections::HashMap;
16
17#[derive(Debug, Default, Clone)]
19pub struct ResourcePack {
20 pub blockstates: HashMap<String, HashMap<String, BlockstateDefinition>>,
23
24 pub models: HashMap<String, HashMap<String, BlockModel>>,
27
28 pub textures: HashMap<String, HashMap<String, TextureData>>,
31}
32
33impl ResourcePack {
34 pub fn new() -> Self {
35 Self::default()
36 }
37
38 pub fn get_blockstate(&self, resource_location: &str) -> Option<&BlockstateDefinition> {
40 let (namespace, path) = parse_resource_location(resource_location);
41 self.blockstates
42 .get(namespace)
43 .and_then(|ns| ns.get(path))
44 }
45
46 pub fn get_model(&self, resource_location: &str) -> Option<&BlockModel> {
48 let (namespace, path) = parse_resource_location(resource_location);
49 self.models.get(namespace).and_then(|ns| ns.get(path))
50 }
51
52 pub fn get_texture(&self, resource_location: &str) -> Option<&TextureData> {
54 let (namespace, path) = parse_resource_location(resource_location);
55 self.textures.get(namespace).and_then(|ns| ns.get(path))
56 }
57
58 pub fn add_blockstate(
60 &mut self,
61 namespace: &str,
62 block_id: &str,
63 definition: BlockstateDefinition,
64 ) {
65 self.blockstates
66 .entry(namespace.to_string())
67 .or_default()
68 .insert(block_id.to_string(), definition);
69 }
70
71 pub fn add_model(&mut self, namespace: &str, model_path: &str, model: BlockModel) {
73 self.models
74 .entry(namespace.to_string())
75 .or_default()
76 .insert(model_path.to_string(), model);
77 }
78
79 pub fn add_texture(&mut self, namespace: &str, texture_path: &str, texture: TextureData) {
81 self.textures
82 .entry(namespace.to_string())
83 .or_default()
84 .insert(texture_path.to_string(), texture);
85 }
86
87 pub fn blockstate_count(&self) -> usize {
89 self.blockstates.values().map(|m| m.len()).sum()
90 }
91
92 pub fn model_count(&self) -> usize {
94 self.models.values().map(|m| m.len()).sum()
95 }
96
97 pub fn texture_count(&self) -> usize {
99 self.textures.values().map(|m| m.len()).sum()
100 }
101
102 pub fn namespaces(&self) -> Vec<&str> {
104 let mut namespaces: Vec<_> = self.blockstates.keys()
105 .chain(self.models.keys())
106 .chain(self.textures.keys())
107 .map(|s| s.as_str())
108 .collect();
109 namespaces.sort();
110 namespaces.dedup();
111 namespaces
112 }
113}
114
115fn parse_resource_location(resource_location: &str) -> (&str, &str) {
119 if let Some((namespace, path)) = resource_location.split_once(':') {
120 (namespace, path)
121 } else {
122 ("minecraft", resource_location)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn test_parse_resource_location() {
132 assert_eq!(
133 parse_resource_location("minecraft:block/stone"),
134 ("minecraft", "block/stone")
135 );
136 assert_eq!(
137 parse_resource_location("mymod:block/custom"),
138 ("mymod", "block/custom")
139 );
140 assert_eq!(
141 parse_resource_location("block/stone"),
142 ("minecraft", "block/stone")
143 );
144 }
145}