diff --git a/blocks/src/lib.rs b/blocks/src/lib.rs index bdbc9cc..1231b5c 100644 --- a/blocks/src/lib.rs +++ b/blocks/src/lib.rs @@ -7,6 +7,7 @@ use crate::shared::{Axis, Direction, Position}; use collision::Aabb3; use cgmath::Point3; use lazy_static::lazy_static; +use std::collections::HashMap; pub mod material; pub use self::material::Material; @@ -44,12 +45,14 @@ macro_rules! create_ids { struct VanillaIDMap { flat: Vec>, hier: Vec>, + modded: HashMap; 16]>, } macro_rules! define_blocks { ( $( $name:ident { + $(modid $modid:expr,)* props { $( $fname:ident : $ftype:ty = [$($val:expr),+], @@ -133,11 +136,43 @@ macro_rules! define_blocks { } } - pub fn by_vanilla_id(id: usize, protocol_version: i32) -> Block { + #[allow(unused_variables, unreachable_code)] + pub fn get_modid(&self) -> Option<&str> { + match *self { + $( + Block::$name { + $($fname,)* + } => { + $( + return Some($modid); + )* + None + } + )+ + } + } + + pub fn by_vanilla_id(id: usize, protocol_version: i32, modded_block_ids: &HashMap) -> Block { if protocol_version >= 404 { VANILLA_ID_MAP.flat.get(id).and_then(|v| *v).unwrap_or(Block::Missing{}) + // TODO: support modded 1.13.2+ blocks after https://github.com/iceiix/stevenarella/pull/145 } else { - VANILLA_ID_MAP.hier.get(id).and_then(|v| *v).unwrap_or(Block::Missing{}) + if let Some(block) = VANILLA_ID_MAP.hier.get(id).and_then(|v| *v) { + block + } else { + let data = id & 0xf; + + if let Some(name) = modded_block_ids.get(&(id >> 4)) { + if let Some(blocks_by_data) = VANILLA_ID_MAP.modded.get(name) { + blocks_by_data[data].unwrap_or(Block::Missing{}) + } else { + //println!("Modded block not supported yet: {}:{} -> {}", id >> 4, data, name); + Block::Missing{} + } + } else { + Block::Missing{} + } + } } } @@ -257,6 +292,7 @@ macro_rules! define_blocks { static ref VANILLA_ID_MAP: VanillaIDMap = { let mut blocks_flat = vec![]; let mut blocks_hier = vec![]; + let mut blocks_modded: HashMap; 16]> = HashMap::new(); let mut flat_id = 0; let mut last_internal_id = 0; let mut hier_block_id = 0; @@ -353,6 +389,16 @@ macro_rules! define_blocks { for block in iter { let internal_id = block.get_internal_id(); let hier_data: Option = block.get_hierarchical_data(); + if let Some(modid) = block.get_modid() { + let hier_data = hier_data.unwrap(); + if !blocks_modded.contains_key(modid) { + blocks_modded.insert(modid.to_string(), [None; 16]); + } + let block_from_data = blocks_modded.get_mut(modid).unwrap(); + block_from_data[hier_data] = Some(block); + continue + } + let vanilla_id = if let Some(hier_data) = hier_data { if internal_id != last_internal_id { @@ -422,7 +468,7 @@ macro_rules! define_blocks { } })+ - VanillaIDMap { flat: blocks_flat, hier: blocks_hier } + VanillaIDMap { flat: blocks_flat, hier: blocks_hier, modded: blocks_modded } }; } ); @@ -1014,6 +1060,56 @@ define_blocks! { data Some(color.data()), model { ("minecraft", format!("{}_wool", color.as_string()) ) }, } + ThermalExpansionRockwool { + modid "ThermalExpansion:Rockwool", + props { + color: ColoredVariant = [ + ColoredVariant::White, + ColoredVariant::Orange, + ColoredVariant::Magenta, + ColoredVariant::LightBlue, + ColoredVariant::Yellow, + ColoredVariant::Lime, + ColoredVariant::Pink, + ColoredVariant::Gray, + ColoredVariant::Silver, + ColoredVariant::Cyan, + ColoredVariant::Purple, + ColoredVariant::Blue, + ColoredVariant::Brown, + ColoredVariant::Green, + ColoredVariant::Red, + ColoredVariant::Black + ], + }, + data Some(color.data()), + model { ("minecraft", format!("{}_wool", color.as_string()) ) }, + } + ThermalFoundationRockwool { + modid "thermalfoundation:rockwool", + props { + color: ColoredVariant = [ + ColoredVariant::White, + ColoredVariant::Orange, + ColoredVariant::Magenta, + ColoredVariant::LightBlue, + ColoredVariant::Yellow, + ColoredVariant::Lime, + ColoredVariant::Pink, + ColoredVariant::Gray, + ColoredVariant::Silver, + ColoredVariant::Cyan, + ColoredVariant::Purple, + ColoredVariant::Blue, + ColoredVariant::Brown, + ColoredVariant::Green, + ColoredVariant::Red, + ColoredVariant::Black + ], + }, + data Some(color.data()), + model { ("minecraft", format!("{}_wool", color.as_string()) ) }, + } PistonExtension { props { facing: Direction = [ diff --git a/src/protocol/forge.rs b/src/protocol/forge.rs index 841df92..005a887 100644 --- a/src/protocol/forge.rs +++ b/src/protocol/forge.rs @@ -85,6 +85,9 @@ impl Serializable for ModIdMapping { } } +pub static BLOCK_NAMESPACE: &'static str = "\u{1}"; +pub static ITEM_NAMESPACE: &'static str = "\u{2}"; + #[derive(Debug)] pub enum FmlHs { ServerHello { diff --git a/src/server/mod.rs b/src/server/mod.rs index 9be139a..dcc623a 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -711,17 +711,26 @@ impl Server { self.write_fmlhs_plugin_message(&HandshakeAck { phase: WaitingServerData }); }, - ModIdData { mappings: _, block_substitutions: _, item_substitutions: _ } => { + ModIdData { mappings, block_substitutions: _, item_substitutions: _ } => { println!("Received FML|HS ModIdData"); + for m in mappings.data { + let (namespace, name) = m.name.split_at(1); + if namespace == protocol::forge::BLOCK_NAMESPACE { + self.world.modded_block_ids.insert(m.id.0 as usize, name.to_string()); + } + } self.write_fmlhs_plugin_message(&HandshakeAck { phase: WaitingServerComplete }); - // TODO: dynamically register mod blocks }, - RegistryData { has_more, name, ids: _, substitutions: _, dummies: _ } => { + RegistryData { has_more, name, ids, substitutions: _, dummies: _ } => { println!("Received FML|HS RegistryData for {}", name); + if name == "minecraft:blocks" { + for m in ids.data { + self.world.modded_block_ids.insert(m.id.0 as usize, m.name); + } + } if !has_more { self.write_fmlhs_plugin_message(&HandshakeAck { phase: WaitingServerComplete }); } - // TODO: dynamically register mod blocks }, HandshakeAck { phase } => { match phase { @@ -1285,7 +1294,7 @@ impl Server { } fn on_block_change(&mut self, location: Position, id: i32) { - self.world.set_block(location, block::Block::by_vanilla_id(id as usize, self.protocol_version)) + self.world.set_block(location, block::Block::by_vanilla_id(id as usize, self.protocol_version, &self.world.modded_block_ids)) } fn on_block_change_varint(&mut self, block_change: packet::play::clientbound::BlockChange_VarInt) { @@ -1309,7 +1318,7 @@ impl Server { record.y as i32, oz + (record.xz & 0xF) as i32 ), - block::Block::by_vanilla_id(record.block_id.0 as usize, self.protocol_version) + block::Block::by_vanilla_id(record.block_id.0 as usize, self.protocol_version, &self.world.modded_block_ids) ); } } @@ -1332,7 +1341,7 @@ impl Server { self.world.set_block( Position::new(x, y, z), - block::Block::by_vanilla_id(id as usize, self.protocol_version) + block::Block::by_vanilla_id(id as usize, self.protocol_version, &self.world.modded_block_ids) ); } } diff --git a/src/world/mod.rs b/src/world/mod.rs index 87f4c28..6087d16 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -45,6 +45,7 @@ pub struct World { block_entity_actions: VecDeque, protocol_version: i32, + pub modded_block_ids: HashMap, } #[derive(Clone, Debug)] @@ -619,7 +620,7 @@ impl World { for bi in 0 .. 4096 { let id = data.read_u16::()?; - section.blocks.set(bi, block::Block::by_vanilla_id(id as usize, self.protocol_version)); + section.blocks.set(bi, block::Block::by_vanilla_id(id as usize, self.protocol_version, &self.modded_block_ids)); // Spawn block entities let b = section.blocks.get(bi); @@ -805,7 +806,7 @@ impl World { for bi in 0 .. 4096 { let id = ((block_add[i].get(bi) as u16) << 12) | ((block_types[i][bi] as u16) << 4) | (block_meta[i].get(bi) as u16); - section.blocks.set(bi, block::Block::by_vanilla_id(id as usize, self.protocol_version)); + section.blocks.set(bi, block::Block::by_vanilla_id(id as usize, self.protocol_version, &self.modded_block_ids)); // Spawn block entities let b = section.blocks.get(bi); @@ -882,7 +883,7 @@ impl World { let count = VarInt::read_from(&mut data)?.0; for i in 0 .. count { let id = VarInt::read_from(&mut data)?.0; - let bl = block::Block::by_vanilla_id(id as usize, self.protocol_version); + let bl = block::Block::by_vanilla_id(id as usize, self.protocol_version, &self.modded_block_ids); mappings.insert(i as usize, bl); } } @@ -892,7 +893,7 @@ impl World { for bi in 0 .. 4096 { let id = m.get(bi); - section.blocks.set(bi, mappings.get(&id).cloned().unwrap_or(block::Block::by_vanilla_id(id, self.protocol_version))); + section.blocks.set(bi, mappings.get(&id).cloned().unwrap_or(block::Block::by_vanilla_id(id, self.protocol_version, &self.modded_block_ids))); // Spawn block entities let b = section.blocks.get(bi); if block_entity::BlockEntityType::get_block_entity(b).is_some() {