Rework block system
This commit is contained in:
parent
2969dfe799
commit
baeb6b94aa
|
@ -127,16 +127,16 @@ fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, 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<RwLock<render::TextureManager>>, 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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -152,7 +152,7 @@ fn twos_compliment(data: &mut Vec<u8>) {
|
|||
data[i] = !data[i];
|
||||
if carry {
|
||||
carry = data[i] == 0xFF;
|
||||
data[i] += 1;
|
||||
data[i].wrapping_add(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<usize>;
|
||||
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<u8> {
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockManager {
|
||||
vanilla_id: Vec<Option<&'static Block>>,
|
||||
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<usize> {
|
||||
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<Option<Block>> = {
|
||||
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<usize> {
|
||||
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<usize>,
|
||||
vanilla_id_storage: UnsafeCell<Option<usize>>,
|
||||
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<usize>,
|
||||
vanilla_id_storage: UnsafeCell<Option<usize>>,
|
||||
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<Wrapper>,
|
||||
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<Item=$tty> + 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<Item=$tty> + Clone),+> Iterator for CombinationIter<$($tname),+> {
|
||||
type Item = Wrapper;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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<InvisibleBlock>,
|
||||
}
|
||||
|
||||
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::<usize> },
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<SimpleBlock>,
|
||||
}
|
||||
|
||||
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!();
|
||||
}
|
|
@ -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<StoneBlock>,
|
||||
}
|
||||
|
||||
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!();
|
||||
}
|
|
@ -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<usize, usize, BuildHasherDefault<FNVHash>>,
|
||||
block_map: Vec<(block::Block, u32)>,
|
||||
rev_block_map: HashMap<block::Block, usize, BuildHasherDefault<FNVHash>>,
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue