Pumpkin/pumpkin-world/src/block/registry.rs
Alexander Medvedev 3d1e0bf35c Check for correct tool when breaking blocks
Also rewrite how we handle tags. Now we can use tags everywhere we want!. I also decided to make the json assets pretty printed which is so much easier to debug, The decision was made because of the reason that we are moving to compile time assets, so pretty printing does not affect performance
2025-02-14 22:47:09 +01:00

148 lines
4.1 KiB
Rust

use std::collections::HashMap;
use std::sync::LazyLock;
use serde::Deserialize;
use crate::loot::LootTable;
pub static BLOCKS: LazyLock<TopLevel> = LazyLock::new(|| {
serde_json::from_str(include_str!("../../../assets/blocks.json"))
.expect("Could not parse blocks.json registry.")
});
pub static BLOCKS_BY_ID: LazyLock<HashMap<u16, Block>> = LazyLock::new(|| {
let mut map = HashMap::new();
for block in &BLOCKS.blocks {
map.insert(block.id, block.clone());
}
map
});
pub static BLOCK_ID_BY_REGISTRY_ID: LazyLock<HashMap<String, u16>> = LazyLock::new(|| {
let mut map = HashMap::new();
for block in &BLOCKS.blocks {
map.insert(block.name.clone(), block.id);
}
map
});
pub static BLOCK_ID_TO_REGISTRY_ID: LazyLock<HashMap<u16, String>> = LazyLock::new(|| {
let mut map = HashMap::new();
for block in &*BLOCKS.blocks {
map.insert(block.default_state_id, block.name.clone());
}
map
});
pub static BLOCK_ID_BY_STATE_ID: LazyLock<HashMap<u16, u16>> = LazyLock::new(|| {
let mut map = HashMap::new();
for block in &BLOCKS.blocks {
for state in &block.states {
map.insert(state.id, block.id);
}
}
map
});
pub static STATE_INDEX_BY_STATE_ID: LazyLock<HashMap<u16, u16>> = LazyLock::new(|| {
let mut map = HashMap::new();
for block in &BLOCKS.blocks {
for (index, state) in block.states.iter().enumerate() {
map.insert(state.id, index as u16);
}
}
map
});
pub static BLOCK_ID_BY_ITEM_ID: LazyLock<HashMap<u16, u16>> = LazyLock::new(|| {
let mut map = HashMap::new();
for block in &BLOCKS.blocks {
map.insert(block.item_id, block.id);
}
map
});
pub fn get_block(registry_id: &str) -> Option<&Block> {
let id = BLOCK_ID_BY_REGISTRY_ID.get(&registry_id.replace("minecraft:", ""))?;
BLOCKS_BY_ID.get(id)
}
pub fn get_block_by_id<'a>(id: u16) -> Option<&'a Block> {
BLOCKS_BY_ID.get(&id)
}
pub fn get_state_by_state_id<'a>(id: u16) -> Option<&'a State> {
get_block_and_state_by_state_id(id).map(|(_, state)| state)
}
pub fn get_block_by_state_id<'a>(id: u16) -> Option<&'a Block> {
let block_id = BLOCK_ID_BY_STATE_ID.get(&id)?;
BLOCKS_BY_ID.get(block_id)
}
pub fn get_block_and_state_by_state_id<'a>(id: u16) -> Option<(&'a Block, &'a State)> {
let block_id = BLOCK_ID_BY_STATE_ID.get(&id)?;
let block = BLOCKS_BY_ID.get(block_id)?;
let state_index = STATE_INDEX_BY_STATE_ID.get(&id)?;
let state = block.states.get(*state_index as usize)?;
Some((block, state))
}
pub fn get_block_by_item<'a>(item_id: u16) -> Option<&'a Block> {
let block_id = BLOCK_ID_BY_ITEM_ID.get(&item_id)?;
BLOCKS_BY_ID.get(block_id)
}
pub fn get_block_collision_shapes(block_id: u16) -> Option<Vec<Shape>> {
let block = BLOCKS_BY_ID.get(&BLOCK_ID_BY_STATE_ID[&block_id])?;
let state = &block.states[STATE_INDEX_BY_STATE_ID[&block_id] as usize];
let mut shapes: Vec<Shape> = vec![];
for i in 0..state.collision_shapes.len() {
let shape = &BLOCKS.shapes[state.collision_shapes[i] as usize];
shapes.push(shape.clone());
}
Some(shapes)
}
#[derive(Deserialize, Clone)]
pub struct TopLevel {
pub block_entity_types: Vec<String>,
shapes: Vec<Shape>,
pub blocks: Vec<Block>,
}
#[derive(Deserialize, Clone)]
pub struct Block {
pub id: u16,
pub item_id: u16,
pub hardness: f32,
pub wall_variant_id: Option<u16>,
pub translation_key: String,
pub name: String,
pub loot_table: Option<LootTable>,
pub properties: Vec<Property>,
pub default_state_id: u16,
pub states: Vec<State>,
}
#[derive(Deserialize, Clone, Debug)]
pub struct Property {
pub name: String,
pub values: Vec<String>,
}
#[derive(Deserialize, Clone, Debug)]
pub struct State {
pub id: u16,
pub air: bool,
pub luminance: u8,
pub burnable: bool,
pub tool_required: bool,
pub opacity: Option<u32>,
pub replaceable: bool,
pub collision_shapes: Vec<u16>,
pub block_entity_type: Option<u32>,
}
#[derive(Deserialize, Clone, Debug)]
pub struct Shape {
pub min: [f64; 3],
pub max: [f64; 3],
}