140 lines
4.0 KiB
Rust
140 lines
4.0 KiB
Rust
use std::{collections::HashMap, fs, io::Cursor};
|
|
|
|
use proc_macro2::TokenStream;
|
|
use quote::quote;
|
|
use serde::Deserialize;
|
|
use serde_repr::Deserialize_repr;
|
|
|
|
#[derive(Deserialize_repr, Debug)]
|
|
#[repr(i32)]
|
|
enum BedrockItemVersion {
|
|
Legacy = 0,
|
|
DataDriven = 1,
|
|
None = 2,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
#[serde(deny_unknown_fields, rename_all = "camelCase")]
|
|
struct BedrockRuntimeItemState {
|
|
name: String,
|
|
id: i16,
|
|
version: BedrockItemVersion,
|
|
component_based: bool,
|
|
}
|
|
|
|
pub fn build() -> TokenStream {
|
|
let be_runtime_item_states: Vec<BedrockRuntimeItemState> = serde_json::from_str(
|
|
&fs::read_to_string("../assets/bedrock/runtime_item_states.json").unwrap(),
|
|
)
|
|
.expect("Failed to parse bedrock/runtime_item_states.json");
|
|
|
|
let bedrock_items_map: HashMap<String, i16> = be_runtime_item_states
|
|
.into_iter()
|
|
.map(|item| (item.name, item.id))
|
|
.collect();
|
|
|
|
let nbt_path = "../assets/bedrock/creative_items.nbt";
|
|
if !std::path::Path::new(nbt_path).exists() {
|
|
let generated_path = "../pumpkin-data/src/generated/bedrock_creative.rs";
|
|
if let Ok(content) = fs::read_to_string(generated_path) {
|
|
return content.parse().unwrap_or_else(|_| TokenStream::new());
|
|
}
|
|
return TokenStream::new();
|
|
}
|
|
|
|
let nbt_bytes = fs::read(nbt_path).expect("Failed to read bedrock/creative_items.nbt");
|
|
let mut cursor = Cursor::new(nbt_bytes);
|
|
|
|
#[derive(serde::Deserialize)]
|
|
struct CreativeGroupEntry {
|
|
category: i32,
|
|
name: String,
|
|
icon: Option<CreativeItemEntry>,
|
|
}
|
|
|
|
#[derive(serde::Deserialize)]
|
|
struct CreativeItemEntry {
|
|
name: String,
|
|
meta: Option<i16>,
|
|
group_index: Option<i32>,
|
|
}
|
|
|
|
#[derive(serde::Deserialize)]
|
|
struct CreativeData {
|
|
groups: Vec<CreativeGroupEntry>,
|
|
items: Vec<CreativeItemEntry>,
|
|
}
|
|
|
|
let data: CreativeData = pumpkin_nbt::deserializer::from_bytes_bedrock(&mut cursor)
|
|
.expect("Failed to deserialize creative_items.nbt");
|
|
|
|
let mut group_tokens = Vec::new();
|
|
for g in &data.groups {
|
|
let category = g.category;
|
|
let name = &g.name;
|
|
let mut icon_item_id = 0i16;
|
|
let mut icon_item_aux_value = 0u32;
|
|
|
|
if let Some(ref icon) = g.icon
|
|
&& let Some(&id) = bedrock_items_map.get(icon.name.as_str())
|
|
{
|
|
icon_item_id = id;
|
|
icon_item_aux_value = icon.meta.unwrap_or(0) as u32;
|
|
}
|
|
|
|
group_tokens.push(quote! {
|
|
CreativeGroup {
|
|
category: #category,
|
|
name: #name,
|
|
icon_item_id: #icon_item_id,
|
|
icon_item_aux_value: #icon_item_aux_value,
|
|
}
|
|
});
|
|
}
|
|
|
|
// 4. Build entry definitions TokenStream
|
|
let mut entry_tokens = Vec::new();
|
|
for item in &data.items {
|
|
if let Some(&id) = bedrock_items_map.get(item.name.as_str()) {
|
|
let item_aux_value = item.meta.unwrap_or(0) as u32;
|
|
let group_index = item.group_index.unwrap_or(0) as u32;
|
|
|
|
entry_tokens.push(quote! {
|
|
CreativeEntry {
|
|
item_id: #id,
|
|
item_aux_value: #item_aux_value,
|
|
group_index: #group_index,
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
let groups_len = group_tokens.len();
|
|
let entries_len = entry_tokens.len();
|
|
|
|
quote! {
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct CreativeGroup {
|
|
pub category: i32,
|
|
pub name: &'static str,
|
|
pub icon_item_id: i16,
|
|
pub icon_item_aux_value: u32,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct CreativeEntry {
|
|
pub item_id: i16,
|
|
pub item_aux_value: u32,
|
|
pub group_index: u32,
|
|
}
|
|
|
|
pub const CREATIVE_GROUPS: &[CreativeGroup; #groups_len] = &[
|
|
#(#group_tokens),*
|
|
];
|
|
|
|
pub const CREATIVE_ENTRIES: &[CreativeEntry; #entries_len] = &[
|
|
#(#entry_tokens),*
|
|
];
|
|
}
|
|
}
|