265 lines
7.8 KiB
Rust
265 lines
7.8 KiB
Rust
|
|
use std::fmt::{Display, Formatter, Error};
|
|
|
|
pub use self::Block::*;
|
|
|
|
macro_rules! consume_token { ($i:tt) => (0) }
|
|
|
|
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 {
|
|
(
|
|
$(
|
|
$name:ident {
|
|
props {
|
|
$(
|
|
$fname:ident : $ftype:ty = [$($val:expr),+],
|
|
)*
|
|
},
|
|
data $datafunc:expr,
|
|
material $mat:expr,
|
|
}
|
|
)+
|
|
) => (
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
pub enum Block {
|
|
$(
|
|
$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
|
|
};
|
|
}
|
|
);
|
|
}
|
|
|
|
pub struct Material {
|
|
pub renderable: bool,
|
|
// TEMP
|
|
pub texture: &'static str,
|
|
}
|
|
|
|
define_blocks! {
|
|
Air {
|
|
props {},
|
|
data { Some(0) },
|
|
material Material {
|
|
renderable: false,
|
|
texture: "none",
|
|
},
|
|
}
|
|
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",
|
|
},
|
|
}
|
|
}
|
|
|
|
|
|
#[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 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,
|
|
}
|
|
}
|
|
}
|