use azalea::blocks::{ Block as AzaleaBlock, BlockState, properties::{ChestType, Facing, LightLevel}, }; use mlua::{Function, Lua, Result, Table}; pub fn register_globals(lua: &Lua, globals: &Table) -> Result<()> { globals.set( "get_block_from_state", lua.create_function(get_block_from_state)?, )?; globals.set( "get_block_states", lua.create_async_function(get_block_states)?, )?; Ok(()) } pub fn get_block_from_state(lua: &Lua, state: u32) -> Result> { let Ok(state) = BlockState::try_from(state) else { return Ok(None); }; let block: Box = state.into(); let behavior = block.behavior(); let table = lua.create_table()?; table.set("id", block.id())?; table.set("friction", behavior.friction)?; table.set("jump_factor", behavior.jump_factor)?; table.set("destroy_time", behavior.destroy_time)?; table.set("explosion_resistance", behavior.explosion_resistance)?; table.set( "requires_correct_tool_for_drops", behavior.requires_correct_tool_for_drops, )?; Ok(Some(table)) } pub async fn get_block_states( lua: Lua, (block_names, filter_fn): (Vec, Option), ) -> Result> { let mut matched = Vec::new(); for block_name in block_names { for block in (u32::MIN..u32::MAX).map_while(|possible_id| BlockState::try_from(possible_id).ok()) { if block_name == Into::>::into(block).id() && (if let Some(filter_fn) = &filter_fn { let table = lua.create_table()?; table.set("chest_type", block.property::().map(|v| v as u8))?; table.set("facing", block.property::().map(|v| v as u8))?; table.set( "light_level", block.property::().map(|v| v as u8), )?; filter_fn.call_async::(table).await? } else { true }) { matched.push(block.id); } } } Ok(matched) }