From baeb6b94aa18c76a69c224de7df1cba7876470ee Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Wed, 23 Mar 2016 21:07:49 +0000 Subject: [PATCH] Rework block system --- src/chunk_builder.rs | 14 +- src/main.rs | 2 +- src/protocol/mojang.rs | 2 +- src/server.rs | 4 +- src/world/block/mod.rs | 579 ++++++++++++++++---------------------- src/world/block/simple.rs | 39 --- src/world/block/stone.rs | 76 ----- src/world/mod.rs | 57 ++-- 8 files changed, 274 insertions(+), 499 deletions(-) delete mode 100644 src/world/block/simple.rs delete mode 100644 src/world/block/stone.rs diff --git a/src/chunk_builder.rs b/src/chunk_builder.rs index 5efc6ad..4915f2d 100644 --- a/src/chunk_builder.rs +++ b/src/chunk_builder.rs @@ -127,16 +127,16 @@ fn build_func(id: usize, textures: Arc>, work_rec for y in 0 .. 16 { for x in 0 .. 16 { for z in 0 .. 16 { - let block = snapshot.get_block(x, y, z); - if !block.renderable() { + let block = snapshot.get_block(x, y, z).get_material(); + if !block.renderable { continue; } for dir in Direction::all() { let offset = dir.get_offset(); - let other = snapshot.get_block(x + offset.0, y + offset.1, z + offset.2); - if other.renderable() { + let other = snapshot.get_block(x + offset.0, y + offset.1, z + offset.2).get_material(); + if other.renderable { continue; } @@ -147,7 +147,7 @@ fn build_func(id: usize, textures: Arc>, work_rec cb = ((cb as f64) * 0.8) as u8; } - let stone = render::Renderer::get_texture(&textures, &format!("minecraft:blocks/{}", "dirt")); + let stone = render::Renderer::get_texture(&textures, &format!("minecraft:blocks/{}", block.texture)); solid_count += 6; for vert in dir.get_verts() { let mut vert = vert.clone(); @@ -203,7 +203,7 @@ fn calculate_light(snapshot: &world::Snapshot, orig_x: i32, orig_y: i32, orig_z: x: f64, y: f64, z: f64, face: Direction, smooth: bool, force: bool) -> (u16, u16) { use std::cmp::max; use world::block; - let (ox, oy, oz) = if !snapshot.get_block(orig_x, orig_y, orig_z).renderable() { // TODO: cull check + let (ox, oy, oz) = if !snapshot.get_block(orig_x, orig_y, orig_z).get_material().renderable { // TODO: cull check (0, 0, 0) } else { face.get_offset() @@ -234,7 +234,7 @@ fn calculate_light(snapshot: &world::Snapshot, orig_x: i32, orig_y: i32, orig_z: let lz = (z + oz + dz).round() as i32; let mut bl = snapshot.get_block_light(lx, ly, lz); let mut sl = snapshot.get_sky_light(lx, ly, lz); - if (force && !snapshot.get_block(lx, ly, lz).in_set(&*block::AIR)) + if (force && match snapshot.get_block(lx, ly, lz) { block::Air{} => false, _ => true }) || (sl == 0 && bl == 0){ bl = s_block_light; sl = s_sky_light; diff --git a/src/main.rs b/src/main.rs index 65fc4aa..b002d2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ extern crate collision; #[macro_use] pub mod macros; + pub mod ecs; pub mod protocol; pub mod format; @@ -135,7 +136,6 @@ impl Game { } fn main() { - world::block::force_init(); let con = Arc::new(Mutex::new(console::Console::new())); { let mut con = con.lock().unwrap(); diff --git a/src/protocol/mojang.rs b/src/protocol/mojang.rs index 83bea16..0d9b195 100644 --- a/src/protocol/mojang.rs +++ b/src/protocol/mojang.rs @@ -152,7 +152,7 @@ fn twos_compliment(data: &mut Vec) { data[i] = !data[i]; if carry { carry = data[i] == 0xFF; - data[i] += 1; + data[i].wrapping_add(1); } } } diff --git a/src/server.rs b/src/server.rs index 4bfa592..093d7bf 100644 --- a/src/server.rs +++ b/src/server.rs @@ -14,7 +14,7 @@ use protocol::{self, mojang, packet}; use world; -use world::block::{self, BlockSet}; +use world::block; use rand::{self, Rng}; use std::sync::{Arc, RwLock, Mutex}; use std::sync::mpsc; @@ -168,7 +168,7 @@ impl Server { for z in -7*16 .. 7*16 { let h = rng.gen_range(3, 10); for y in 0 .. h { - world.set_block(x, y, z, block::MISSING.base()); + world.set_block(x, y, z, block::Dirt{}); } } } diff --git a/src/world/block/mod.rs b/src/world/block/mod.rs index 8240132..2586c29 100644 --- a/src/world/block/mod.rs +++ b/src/world/block/mod.rs @@ -1,373 +1,264 @@ -use std::collections::HashMap; -use std::cell::UnsafeCell; +use std::fmt::{Display, Formatter, Error}; -pub trait BlockSet { - fn plugin(&self) -> &'static str { - "minecraft" - } +pub use self::Block::*; - fn name(&self) -> &'static str; - fn blocks(&'static self) -> Vec<&'static Block>; +macro_rules! consume_token { ($i:tt) => (0) } - fn base(&'static self) -> &'static Block { - self.blocks()[0] - } -} - -pub trait Block: Sync + ::std::fmt::Debug { - fn steven_id(&'static self) -> usize; - fn vanilla_id(&'static self) -> Option; - fn set_steven_id(&'static self, id: usize); - fn set_vanilla_id(&'static self, id: usize); - fn plugin(&self) -> &'static str; - fn name(&self) -> &'static str; - - fn equals(&'static self, other: &'static Block) -> bool { - self.steven_id() == other.steven_id() - } - - fn in_set(&'static self, set: &'static BlockSet) -> bool { - // TODO: Make faster - for block in set.blocks() { - if self.equals(block) { - return true - } - } - false - } - - fn renderable(&'static self) -> bool { - true - } - - fn data(&'static self) -> Option { - Some(0) - } -} - -pub struct BlockManager { - vanilla_id: Vec>, - steven_id: Vec<&'static Block>, - next_id: usize, +macro_rules! offsets { + ($first:ident, $($other:ident),*) => ( + #[allow(non_upper_case_globals)] + pub const $first: usize = 0; + offsets!(prev($first), $($other),*); + ); + (prev($prev:ident), $first:ident, $($other:ident),*) => ( + #[allow(non_upper_case_globals)] + pub const $first: usize = $prev + internal_sizes::$prev; + offsets!(prev($first), $($other),*); + ); + (prev($prev:ident), $first:ident) => ( + #[allow(non_upper_case_globals)] + pub const $first: usize = $prev + internal_sizes::$prev; + ) } macro_rules! define_blocks { ( $( - $internal_name:ident $ty:ty = $bl:expr; - )* + $name:ident { + props { + $( + $fname:ident : $ftype:ty = [$($val:expr),+], + )* + }, + data $datafunc:expr, + material $mat:expr, + } + )+ ) => ( - lazy_static! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub enum Block { $( - pub static ref $internal_name: $ty = $bl; - )* - static ref MANAGER: BlockManager = { - let mut manager = BlockManager { - vanilla_id: vec![None; 0xFFFF], - steven_id: vec![], - next_id: 0, - }; - $( - manager.register_set(&*$internal_name); - )* - manager + $name { + $( + $fname : $ftype, + )* + }, + )+ + } + mod internal_ids { + create_ids!(usize, $($name),+); + } + mod internal_sizes { + $( + #[allow(non_upper_case_globals)] + pub const $name : usize = $(($(1 + consume_token!($val) + )+ 0) * )* 1; + )+ + } + mod internal_offsets { + use super::internal_sizes; + offsets!($($name),+); + } + mod internal_offset_max { + use super::internal_sizes; + use super::internal_offsets; + $( + #[allow(non_upper_case_globals)] + pub const $name: usize = internal_offsets::$name + internal_sizes::$name - 1; + )+ + } + + impl Block { + #[allow(unused_variables, unused_mut, unused_assignments)] + pub fn get_steven_id(&self) -> usize { + match *self { + $( + Block::$name { + $($fname,)* + } => { + let mut offset = internal_offsets::$name; + let mut mul = 1; + $( + offset += [$($val),+].into_iter().position(|v| *v == $fname).unwrap() * mul; + mul *= $(1 + consume_token!($val) + )+ 0; + )* + offset + }, + )+ + } + } + + #[allow(unused_variables, unused_assignments)] + pub fn by_steven_id(id: usize) -> Block { + match id { + $( + mut data @ internal_offsets::$name ... internal_offset_max::$name=> { + data -= internal_offsets::$name; + $( + let vals = [$($val),+]; + let $fname = vals[data % vals.len()]; + data /= vals.len(); + )* + Block::$name { + $( + $fname: $fname, + )* + } + }, + )* + _ => Block::Missing {} + } + } + + pub fn get_vanilla_id(&self) -> Option { + match *self { + $( + Block::$name { + $($fname,)* + } => { + ($datafunc).map(|v| v + (internal_ids::$name << 4)) + } + )+ + } + } + + pub fn by_vanilla_id(id: usize) -> Block { + VANILLA_ID_MAP.get(id).and_then(|v| *v).unwrap_or(Block::Missing{}) + } + + pub fn get_material(&self) -> Material { + match *self { + $( + Block::$name { + $($fname,)* + } => { + $mat + } + )+ + } + } + } + + lazy_static! { + static ref VANILLA_ID_MAP: Vec> = { + let mut blocks = vec![]; + for i in 0 .. internal_offsets::Missing { + let block = Block::by_steven_id(i); + if let Some(id) = block.get_vanilla_id() { + if blocks.len() <= id { + blocks.resize(id + 1, None); + } + blocks[id] = Some(block); + } + } + blocks }; } - ) -} - -// TODO: Replace this with trait fields when supported by rust -macro_rules! block_impl { - () => ( - fn steven_id(&'static self) -> usize { - unsafe { *self.steven_id_storage.get() } - } - fn vanilla_id(&'static self) -> Option { - unsafe { *self.vanilla_id_storage.get() } - } - fn set_steven_id(&'static self, id: usize) { - unsafe { *self.steven_id_storage.get() = id; } - } - fn set_vanilla_id(&'static self, id: usize) { - unsafe { *self.vanilla_id_storage.get() = Some(id); } - } - - fn plugin(&self) -> &'static str { - self.plugin - } - - fn name(&self) -> &'static str { - self.name - } - ) -} - -macro_rules! block_combos { - ( - $set:ty, params($($pname:ident : $pty:ty),*), - $bty:ident { - $( - $fname:ident : $fval:expr, - )* - } - ) => ( - struct $bty { - steven_id_storage: UnsafeCell, - vanilla_id_storage: UnsafeCell>, - plugin: &'static str, - name: &'static str, - $( - $fname: $fty, - )* - } - unsafe impl Sync for $bty {} - - impl ::std::fmt::Debug for $bty { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - write!(f, "{}:{}", self.plugin(), self.name()) - } - } - - impl $set { - fn gen_combos(&mut self, $($pname: $pty),*) { - let val = $bty { - steven_id_storage: UnsafeCell::new(0), - vanilla_id_storage: UnsafeCell::new(None), - name: self.name(), - plugin: self.plugin(), - $( - $fname: $fval, - )* - }; - self.sub_blocks.push(val); - } - } ); - ( - $set:ty, params($($pname:ident : $pty:ty),*), - types ( - $( - $tname:ident : $tty:ty = [$($val:expr),+] - ),+ - ), - $bty:ident { - $( - $fname:ident : $fty:ty = $fval:expr, - )* - } - ) => ( - struct $bty { - steven_id_storage: UnsafeCell, - vanilla_id_storage: UnsafeCell>, - plugin: &'static str, - name: &'static str, - $( - $fname: $fty, - )* - } - unsafe impl Sync for $bty {} - - impl ::std::fmt::Debug for $bty { - fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - try!(write!(f, "{}:{}[", self.plugin(), self.name())); - let mut s = String::new(); - $( - s.push_str(&format!("{}={},", stringify!($tname), self.$tname)); - )+ - s.pop(); - write!(f, "{}]", s) - } - } - - impl $set { - fn gen_combos(&mut self, $($pname: $pty),*) { - use std::iter::Iterator; - #[allow(dead_code)] - #[allow(non_camel_case_types)] - struct CombinationIter<$($tname),+> { - $( - $tname: $tname, - )+ - orig: CombinationIterOrig<$($tname),+> , - last: Option, - done: bool, - } - #[allow(non_camel_case_types)] - struct CombinationIterOrig<$($tname),+> { - $( - $tname: $tname, - )+ - } - - #[derive(Clone)] - struct Wrapper { - $( - $tname: $tty, - )+ - } - - #[allow(non_camel_case_types)] - impl <$($tname: Iterator + Clone),+> CombinationIter<$($tname),+> { - fn new($($tname: $tname),+) -> CombinationIter<$($tname),+> { - let orig = CombinationIterOrig { - $( - $tname: $tname - ),+ - }; - CombinationIter { - $( - $tname: orig.$tname.clone(), - )+ - orig: orig, - last: None, - done: false, - } - } - } - - #[allow(non_camel_case_types)] - impl <$($tname: Iterator + Clone),+> Iterator for CombinationIter<$($tname),+> { - type Item = Wrapper; - - fn next(&mut self) -> Option { - if self.done { - return None - } - if self.last.is_none() { - let wrapper = Wrapper { - $( - $tname: self.$tname.next().unwrap() // Shouldn't ever fail the first iter - ),+ - }; - self.last = Some(wrapper.clone()); - return Some(wrapper); - } - let mut ret = self.last.take().unwrap(); - $( - if let Some(val) = self.$tname.next() { - ret.$tname = val; - self.last = Some(ret.clone()); - return Some(ret) - } - self.$tname = self.orig.$tname.clone(); - )+ - self.done = true; - None - } - } - - let iter = CombinationIter::new($(vec![$($val),+].into_iter()),+); - for val in iter { - $( - let $tname = val.$tname; - )+ - let val = $bty { - steven_id_storage: UnsafeCell::new(0), - vanilla_id_storage: UnsafeCell::new(None), - name: self.name(), - plugin: self.plugin(), - $( - $fname: $fval, - )* - }; - self.sub_blocks.push(val); - } - } - } - ) } -#[test] -fn temp_test() { - force_init(); - - println!("{:?}", STONE.blocks()); - unimplemented!() +pub struct Material { + pub renderable: bool, + // TEMP + pub texture: &'static str, } -impl BlockManager { - fn force_init(&self) {} - fn register_set(&mut self, set: &'static BlockSet) { - for block in set.blocks() { - if let Some(data) = block.data() { - let id = (self.next_id<<4) | (data as usize); - self.vanilla_id[id] = Some(block); - block.set_vanilla_id(id); - } - block.set_steven_id(self.steven_id.len()); - self.steven_id.push(block); - } - self.next_id += 1; - } - - fn get_block_by_steven_id(&self, id: usize) -> &'static Block { - self.steven_id[id] - } - - fn get_block_by_vanilla_id(&self, id: usize) -> &'static Block { - self.vanilla_id.get(id).and_then(|v| *v).unwrap_or(MISSING.base()) - } -} - -pub fn force_init() { - MANAGER.force_init(); -} - -pub fn get_block_by_steven_id(id: usize) -> &'static Block { - MANAGER.get_block_by_steven_id(id) -} - -pub fn get_block_by_vanilla_id(id: usize) -> &'static Block { - MANAGER.get_block_by_vanilla_id(id) -} - -pub mod simple; -pub mod stone; - define_blocks! { - AIR InvisibleBlockSet = InvisibleBlockSet::new("air"); - STONE stone::StoneBlockSet = stone::StoneBlockSet::new("stone"); - GRASS simple::SimpleBlockSet = simple::SimpleBlockSet::new("grass"); - DIRT simple::SimpleBlockSet = simple::SimpleBlockSet::new("dirt"); - MISSING simple::SimpleBlockSet = simple::SimpleBlockSet::new("missing"); -} - -/// A block set that contains blocks which cannot be rendered. -pub struct InvisibleBlockSet { - name: &'static str, - sub_blocks: Vec, -} - -block_combos!(InvisibleBlockSet, params(), - InvisibleBlock { + Air { + props {}, + data { Some(0) }, + material Material { + renderable: false, + texture: "none", + }, } -); - -impl InvisibleBlockSet { - fn new(name: &'static str) -> InvisibleBlockSet { - let mut set = InvisibleBlockSet { - name: name, - sub_blocks: vec![], - }; - set.gen_combos(); - set + Stone { + props { + variant: StoneVariant = [ + StoneVariant::Normal, + StoneVariant::Granite, StoneVariant::SmoothGranite, + StoneVariant::Diorite, StoneVariant::SmoothDiorite, + StoneVariant::Andesite, StoneVariant::SmoothAndesite + ], + }, + data { Some(variant.data()) }, + material Material { + renderable: true, + texture: match variant { + StoneVariant::Normal => "stone", + StoneVariant::Granite => "stone_granite", + StoneVariant::SmoothGranite => "stone_granite_smooth", + StoneVariant::Diorite => "stone_diorite", + StoneVariant::SmoothDiorite => "stone_diorite_smooth", + StoneVariant::Andesite => "stone_andesite", + StoneVariant::SmoothAndesite => "stone_andesite_smooth", + }, + }, + } + Grass { + props { + }, + data { Some(0) }, + material Material { + renderable: true, + texture: "grass_path_top", + }, + } + Dirt { + props { + }, + data { Some(0) }, + material Material { + renderable: true, + texture: "dirt", + }, + } + Missing { + props {}, + data { None:: }, + material Material { + renderable: true, + texture: "missing_texture", + }, } } -impl BlockSet for InvisibleBlockSet { - fn name(&self) -> &'static str { - self.name - } - fn blocks(&'static self) -> Vec<&'static Block> { - self.sub_blocks.iter().map(|v| v as &Block).collect() +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum StoneVariant { + Normal, + Granite, + SmoothGranite, + Diorite, + SmoothDiorite, + Andesite, + SmoothAndesite, +} + +impl Display for StoneVariant { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + write!(f, "{}", match *self { + StoneVariant::Normal => "stone", + StoneVariant::Granite => "granite", + StoneVariant::SmoothGranite => "smooth_granite", + StoneVariant::Diorite => "diorite", + StoneVariant::SmoothDiorite => "smooth_diorite", + StoneVariant::Andesite => "andesite", + StoneVariant::SmoothAndesite => "smooth_andesite", + }) } } -impl Block for InvisibleBlock { - block_impl!(); - fn renderable(&'static self) -> bool { - false +impl StoneVariant { + fn data(&self) -> usize { + match *self { + StoneVariant::Normal => 0, + StoneVariant::Granite => 1, + StoneVariant::SmoothGranite => 2, + StoneVariant::Diorite => 3, + StoneVariant::SmoothDiorite => 4, + StoneVariant::Andesite => 5, + StoneVariant::SmoothAndesite => 6, + } } } diff --git a/src/world/block/simple.rs b/src/world/block/simple.rs deleted file mode 100644 index 41fff20..0000000 --- a/src/world/block/simple.rs +++ /dev/null @@ -1,39 +0,0 @@ - -use super::{Block, BlockSet}; -use std::cell::UnsafeCell; - -/// A block set for blocks which don't have any special features about them. -pub struct SimpleBlockSet { - name: &'static str, - sub_blocks: Vec, -} - -block_combos!(SimpleBlockSet, params(), - SimpleBlock { - } -); - -impl SimpleBlockSet { - pub fn new(name: &'static str) -> SimpleBlockSet { - let mut set = SimpleBlockSet { - name: name, - sub_blocks: vec![], - }; - set.gen_combos(); - set - } -} - -impl BlockSet for SimpleBlockSet { - fn name(&self) -> &'static str { - self.name - } - - fn blocks(&'static self) -> Vec<&'static Block> { - self.sub_blocks.iter().map(|v| v as &Block).collect() - } -} - -impl Block for SimpleBlock { - block_impl!(); -} diff --git a/src/world/block/stone.rs b/src/world/block/stone.rs deleted file mode 100644 index 6c71d2a..0000000 --- a/src/world/block/stone.rs +++ /dev/null @@ -1,76 +0,0 @@ - -use super::{Block, BlockSet}; -use std::cell::UnsafeCell; -use std::fmt::{Display, Formatter, Error}; - -/// A block set for stone blocks. -pub struct StoneBlockSet { - name: &'static str, - sub_blocks: Vec, -} - -block_combos!(StoneBlockSet, params(), - types ( - variant: Variant = [ - Variant::Normal, - Variant::Granite, Variant::SmoothGranite, - Variant::Diorite, Variant::SmoothDiorite, - Variant::Andesite, Variant::SmoothAndesite - ], - test_num: u32 = [0, 1, 2, 3, 4, 5, 6] - ), - StoneBlock { - variant: Variant = variant, - test_num: u32 = test_num, - } -); - -#[derive(Clone, Copy, Debug)] -pub enum Variant { - Normal, - Granite, - SmoothGranite, - Diorite, - SmoothDiorite, - Andesite, - SmoothAndesite, -} - -impl Display for Variant { - fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { - write!(f, "{}", match *self { - Variant::Normal => "stone", - Variant::Granite => "granite", - Variant::SmoothGranite => "smooth_granite", - Variant::Diorite => "diorite", - Variant::SmoothDiorite => "smooth_diorite", - Variant::Andesite => "andesite", - Variant::SmoothAndesite => "smooth_andesite", - }) - } -} - -impl StoneBlockSet { - pub fn new(name: &'static str) -> StoneBlockSet { - let mut set = StoneBlockSet { - name: name, - sub_blocks: vec![], - }; - set.gen_combos(); - set - } -} - -impl BlockSet for StoneBlockSet { - fn name(&self) -> &'static str { - self.name - } - - fn blocks(&'static self) -> Vec<&'static Block> { - self.sub_blocks.iter().map(|v| v as &Block).collect() - } -} - -impl Block for StoneBlock { - block_impl!(); -} diff --git a/src/world/mod.rs b/src/world/mod.rs index 73b0d42..08e9de7 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -13,7 +13,6 @@ // limitations under the License. pub mod block; -use self::block::BlockSet; use std::sync::Arc; use std::collections::HashMap; @@ -37,7 +36,7 @@ impl World { self.chunks.contains_key(&CPos(x, z)) } - pub fn set_block(&mut self, x: i32, y: i32, z: i32, b: &'static block::Block) { + pub fn set_block(&mut self, x: i32, y: i32, z: i32, b: block::Block) { let cpos = CPos(x >> 4, z >> 4); if !self.chunks.contains_key(&cpos) { self.chunks.insert(cpos, Chunk::new(cpos)); @@ -46,10 +45,10 @@ impl World { chunk.set_block(x & 0xF, y, z & 0xF, b); } - pub fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block { + pub fn get_block(&self, x: i32, y: i32, z: i32) -> block::Block { match self.chunks.get(&CPos(x >> 4, z >> 4)) { Some(ref chunk) => chunk.get_block(x & 0xF, y, z & 0xF), - None => block::MISSING.base(), + None => block::Missing{}, } } @@ -107,7 +106,7 @@ impl World { }; for i in 0 .. (w * h * d) as usize { snapshot.sky_light.set(i, 0xF); - snapshot.blocks[i] = block::MISSING.base().steven_id() as u16; + snapshot.blocks[i] = block::Missing{}.get_steven_id() as u16; } let cx1 = x >> 4; @@ -150,7 +149,7 @@ impl World { snapshot.set_sky_light(ox, oy, oz, sec.get_sky_light(xx, yy, zz)); }, None => { - snapshot.set_block(ox, oy, oz, block::AIR.base()); + snapshot.set_block(ox, oy, oz, block::Air{}); }, } } @@ -213,7 +212,7 @@ impl World { for i in 0 .. 4096 { let val = m.get(i); let block_id = block_map.get(&val).map(|v| *v as usize).unwrap_or(val); - let block = block::get_block_by_vanilla_id(block_id); + let block = block::Block::by_vanilla_id(block_id); let i = i as i32; section.set_block( i & 0xF, @@ -276,13 +275,13 @@ impl Snapshot { self.z = z; } - pub fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block { - block::get_block_by_steven_id(self.blocks[self.index(x, y, z)] as usize) + pub fn get_block(&self, x: i32, y: i32, z: i32) -> block::Block { + block::Block::by_steven_id(self.blocks[self.index(x, y, z)] as usize) } - pub fn set_block(&mut self, x: i32, y: i32, z: i32, b: &'static block::Block) { + pub fn set_block(&mut self, x: i32, y: i32, z: i32, b: block::Block) { let idx = self.index(x, y, z); - self.blocks[idx] = b.steven_id() as u16; + self.blocks[idx] = b.get_steven_id() as u16; } pub fn get_block_light(&self, x: i32, y: i32, z: i32) -> u8 { @@ -333,13 +332,13 @@ impl Chunk { } } - fn set_block(&mut self, x: i32, y: i32, z: i32, b: &'static block::Block) { + fn set_block(&mut self, x: i32, y: i32, z: i32, b: block::Block) { let s_idx = y >> 4; if s_idx < 0 || s_idx > 15 { return; } if self.sections[s_idx as usize].is_none() { - if b.in_set(&*block::AIR) { + if let block::Air {} = b { return; } self.sections[s_idx as usize] = Some(Section::new(self.position.0, s_idx as u8, self.position.1)); @@ -348,14 +347,14 @@ impl Chunk { section.set_block(x, y & 0xF, z, b); } - fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block { + fn get_block(&self, x: i32, y: i32, z: i32) -> block::Block { let s_idx = y >> 4; if s_idx < 0 || s_idx > 15 { - return block::MISSING.base(); + return block::Missing{}; } match self.sections[s_idx as usize].as_ref() { Some(sec) => sec.get_block(x, y & 0xF, z), - None => block::AIR.base(), + None => block::Air{}, } } } @@ -391,8 +390,8 @@ struct Section { y: u8, blocks: bit::Map, - block_map: Vec<(&'static block::Block, u32)>, - rev_block_map: HashMap>, + block_map: Vec<(block::Block, u32)>, + rev_block_map: HashMap>, block_light: nibble::Array, sky_light: nibble::Array, @@ -411,7 +410,7 @@ impl Section { blocks: bit::Map::new(4096, 4), block_map: vec![ - (block::AIR.base(), 0xFFFFFFFF) + (block::Air{}, 0xFFFFFFFF) ], rev_block_map: HashMap::with_hasher(BuildHasherDefault::default()), @@ -424,36 +423,36 @@ impl Section { for i in 0 .. 16*16*16 { section.sky_light.set(i, 0xF); } - section.rev_block_map.insert(block::AIR.base().steven_id(), 0); + section.rev_block_map.insert(block::Air{}, 0); section } - fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block { + fn get_block(&self, x: i32, y: i32, z: i32) -> block::Block { let idx = self.blocks.get(((y << 8) | (z << 4) | x) as usize); self.block_map[idx].0 } - fn set_block(&mut self, x: i32, y: i32, z: i32, b: &'static block::Block) { + fn set_block(&mut self, x: i32, y: i32, z: i32, b: block::Block) { let old = self.get_block(x, y, z); - if old.equals(b) { + if old == b { return; } // Clean up old block { - let idx = self.rev_block_map[&old.steven_id()]; + let idx = self.rev_block_map[&old]; let info = &mut self.block_map[idx]; info.1 -= 1; if info.1 == 0 { // None left of this type - self.rev_block_map.remove(&old.steven_id()); + self.rev_block_map.remove(&old); } } - if !self.rev_block_map.contains_key(&b.steven_id()) { + if !self.rev_block_map.contains_key(&b) { let mut found = false; for (i, ref mut info) in self.block_map.iter_mut().enumerate() { if info.1 == 0 { info.0 = b; - self.rev_block_map.insert(b.steven_id(), i); + self.rev_block_map.insert(b, i); found = true; break; } @@ -464,12 +463,12 @@ impl Section { let new_blocks = self.blocks.resize(new_size); self.blocks = new_blocks; } - self.rev_block_map.insert(b.steven_id(), self.block_map.len()); + self.rev_block_map.insert(b, self.block_map.len()); self.block_map.push((b, 0)); } } - let idx = self.rev_block_map[&b.steven_id()]; + let idx = self.rev_block_map[&b]; let info = &mut self.block_map[idx]; info.1 += 1; self.blocks.set(((y << 8) | (z << 4) | x) as usize, idx);