Skip to content

Commit 07372c8

Browse files
committed
Generate hardness values for blocks
1 parent ff4990b commit 07372c8

File tree

7 files changed

+1977
-2
lines changed

7 files changed

+1977
-2
lines changed

core/blocks/build.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ fn main() {
1313
let kind = format!("{}/kind.rs", base);
1414
let block_fns = format!("{}/block_fns.rs", base);
1515
let table = format!("{}/table.rs", base);
16+
let metadata = format!("{}/metadata.rs", base);
1617

1718
write_to_file(&kind, &code.kind);
1819
write_to_file(&block_fns, &code.block_fns);
1920
write_to_file(&table, &code.block_table);
21+
write_to_file(&metadata, &code.metadata);
2022

21-
[kind, block_fns, table].iter().for_each(|path| {
23+
[kind, block_fns, table, metadata].iter().for_each(|path| {
2224
Command::new("rustfmt").arg(path).output().unwrap();
2325
});
2426

core/blocks/generator/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::str::FromStr;
1111
use syn::export::ToTokens;
1212

1313
mod load;
14+
mod metadata;
1415

1516
#[derive(Debug)]
1617
struct Blocks {
@@ -237,6 +238,7 @@ pub struct Output {
237238
pub kind: String,
238239
pub block_fns: String,
239240
pub block_table: String,
241+
pub metadata: String,
240242
pub block_table_serialized: Vec<u8>,
241243
pub vanilla_ids_serialized: Vec<u8>,
242244
}
@@ -255,6 +257,7 @@ pub fn generate() -> anyhow::Result<Output> {
255257

256258
output.block_table_serialized = serialize_block_table(&blocks);
257259
output.vanilla_ids_serialized = serialized_vanilla_ids(&blocks);
260+
output.metadata = metadata::generate()?;
258261

259262
Ok(output)
260263
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//! Handles loading and output of block metadata,
2+
//! taking from PrismarineJS/minecraft-data.
3+
//!
4+
//! This includes useful information such as drops,
5+
//! light emission, hardness, bounding boxes, ...
6+
7+
use heck::CamelCase;
8+
use proc_macro2::{Ident, Span, TokenStream};
9+
use quote::quote;
10+
use serde::{Deserialize, Serialize};
11+
12+
#[derive(Debug, Serialize, Deserialize)]
13+
struct BlockData<'a>(#[serde(borrow)] Vec<DataEntry<'a>>);
14+
15+
#[derive(Debug, Serialize, Deserialize)]
16+
#[serde(rename_all = "camelCase")]
17+
struct DataEntry<'a> {
18+
id: i32,
19+
display_name: &'a str,
20+
name: &'a str,
21+
hardness: Option<f64>,
22+
min_state_id: i32,
23+
max_state_id: u32,
24+
drops: Vec<usize>,
25+
diggable: bool,
26+
transparent: bool,
27+
filter_light: u8,
28+
emit_light: u8,
29+
bounding_box: BoundingBox,
30+
stack_size: u32,
31+
}
32+
33+
#[derive(Debug, Serialize, Deserialize)]
34+
#[serde(rename_all = "lowercase")]
35+
enum BoundingBox {
36+
Empty,
37+
Block,
38+
}
39+
40+
/// Generates block metadata file.
41+
pub fn generate() -> anyhow::Result<String> {
42+
let data = parse_data()?;
43+
44+
let result = generate_tokens(&data);
45+
Ok(result.to_string())
46+
}
47+
48+
fn parse_data() -> anyhow::Result<BlockData<'static>> {
49+
const DATA: &[u8] = feather_data::minecraft_data::BLOCKS;
50+
51+
serde_json::from_slice(DATA).map_err(anyhow::Error::from)
52+
}
53+
54+
fn generate_tokens(data: &BlockData) -> TokenStream {
55+
let hardness = generate_hardness(data);
56+
let diggable = generate_diggable(data);
57+
let transparent = generate_transparent(data);
58+
59+
quote! {
60+
impl crate::BlockId {
61+
#hardness
62+
#diggable
63+
#transparent
64+
}
65+
}
66+
}
67+
68+
fn generate_hardness(data: &BlockData) -> TokenStream {
69+
let body = match_arms(data, |entry| {
70+
let hardness = entry.hardness.unwrap_or_default();
71+
quote! { #hardness }
72+
});
73+
74+
quote! {
75+
#[doc = "Returns the hardness value of this block."]
76+
pub fn hardness(self) -> f64 {
77+
#body
78+
}
79+
}
80+
}
81+
82+
fn generate_diggable(data: &BlockData) -> TokenStream {
83+
let body = match_arms(data, |entry| {
84+
let diggable = entry.diggable;
85+
quote! { #diggable }
86+
});
87+
88+
quote! {
89+
#[doc = "Returns whether this block is diggable."]
90+
pub fn is_diggable(self) -> bool {
91+
#body
92+
}
93+
}
94+
}
95+
96+
fn generate_transparent(data: &BlockData) -> TokenStream {
97+
let body = match_arms(data, |entry| {
98+
let opaque = !entry.transparent;
99+
quote! { #opaque }
100+
});
101+
102+
quote! {
103+
#[doc = "Returns whether this block is opaque."]
104+
pub fn is_opaque(self) -> bool {
105+
#body
106+
}
107+
}
108+
}
109+
110+
fn match_arms(data: &BlockData, mut f: impl FnMut(&DataEntry) -> TokenStream) -> TokenStream {
111+
let arms: Vec<_> = data
112+
.0
113+
.iter()
114+
.map(|entry| {
115+
let ident = kind_ident(entry.name);
116+
let block = f(entry);
117+
118+
quote! {
119+
crate::BlockKind::#ident => { #block }
120+
}
121+
})
122+
.collect();
123+
124+
quote! {
125+
match self.kind() {
126+
#(#arms,)*
127+
}
128+
}
129+
}
130+
131+
fn kind_ident(name: &str) -> Ident {
132+
Ident::new(&name.to_camel_case(), Span::call_site())
133+
}

0 commit comments

Comments
 (0)