pub mod loader;
pub mod blockstate;
pub mod model;
pub mod texture;
pub use blockstate::{BlockstateDefinition, ModelVariant, MultipartCase, MultipartCondition};
pub use model::{BlockModel, ModelElement, ModelFace};
pub use texture::TextureData;
use std::collections::HashMap;
#[derive(Debug, Default, Clone)]
pub struct ResourcePack {
pub blockstates: HashMap<String, HashMap<String, BlockstateDefinition>>,
pub models: HashMap<String, HashMap<String, BlockModel>>,
pub textures: HashMap<String, HashMap<String, TextureData>>,
}
impl ResourcePack {
pub fn new() -> Self {
Self::default()
}
pub fn get_blockstate(&self, resource_location: &str) -> Option<&BlockstateDefinition> {
let (namespace, path) = parse_resource_location(resource_location);
self.blockstates
.get(namespace)
.and_then(|ns| ns.get(path))
}
pub fn get_model(&self, resource_location: &str) -> Option<&BlockModel> {
let (namespace, path) = parse_resource_location(resource_location);
self.models.get(namespace).and_then(|ns| ns.get(path))
}
pub fn get_texture(&self, resource_location: &str) -> Option<&TextureData> {
let (namespace, path) = parse_resource_location(resource_location);
self.textures.get(namespace).and_then(|ns| ns.get(path))
}
pub fn add_blockstate(
&mut self,
namespace: &str,
block_id: &str,
definition: BlockstateDefinition,
) {
self.blockstates
.entry(namespace.to_string())
.or_default()
.insert(block_id.to_string(), definition);
}
pub fn add_model(&mut self, namespace: &str, model_path: &str, model: BlockModel) {
self.models
.entry(namespace.to_string())
.or_default()
.insert(model_path.to_string(), model);
}
pub fn add_texture(&mut self, namespace: &str, texture_path: &str, texture: TextureData) {
self.textures
.entry(namespace.to_string())
.or_default()
.insert(texture_path.to_string(), texture);
}
pub fn blockstate_count(&self) -> usize {
self.blockstates.values().map(|m| m.len()).sum()
}
pub fn model_count(&self) -> usize {
self.models.values().map(|m| m.len()).sum()
}
pub fn texture_count(&self) -> usize {
self.textures.values().map(|m| m.len()).sum()
}
pub fn namespaces(&self) -> Vec<&str> {
let mut namespaces: Vec<_> = self.blockstates.keys()
.chain(self.models.keys())
.chain(self.textures.keys())
.map(|s| s.as_str())
.collect();
namespaces.sort();
namespaces.dedup();
namespaces
}
}
fn parse_resource_location(resource_location: &str) -> (&str, &str) {
if let Some((namespace, path)) = resource_location.split_once(':') {
(namespace, path)
} else {
("minecraft", resource_location)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_resource_location() {
assert_eq!(
parse_resource_location("minecraft:block/stone"),
("minecraft", "block/stone")
);
assert_eq!(
parse_resource_location("mymod:block/custom"),
("mymod", "block/custom")
);
assert_eq!(
parse_resource_location("block/stone"),
("minecraft", "block/stone")
);
}
}