Pumpkin/pumpkin-data/build/enchantments.rs
2025-07-03 16:41:57 +02:00

120 lines
3.6 KiB
Rust

use std::{collections::HashMap, fs};
use heck::ToShoutySnakeCase;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use serde::Deserialize;
#[derive(Deserialize)]
struct Enchantment {
anvil_cost: u32,
supported_items: String,
max_level: i32,
slots: Vec<AttributeModifierSlot>, // TODO: add more
}
#[derive(Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum AttributeModifierSlot {
Any,
MainHand,
OffHand,
Hand,
Feet,
Legs,
Chest,
Head,
Armor,
Body,
Saddle,
}
impl AttributeModifierSlot {
fn to_tokens(&self) -> TokenStream {
match self {
AttributeModifierSlot::Any => quote! { AttributeModifierSlot::Any },
AttributeModifierSlot::MainHand => quote! { AttributeModifierSlot::MainHand },
AttributeModifierSlot::OffHand => quote! { AttributeModifierSlot::OffHand },
AttributeModifierSlot::Hand => quote! { AttributeModifierSlot::Hand },
AttributeModifierSlot::Feet => quote! { AttributeModifierSlot::Feet },
AttributeModifierSlot::Legs => quote! { AttributeModifierSlot::Legs },
AttributeModifierSlot::Chest => quote! { AttributeModifierSlot::Chest },
AttributeModifierSlot::Head => quote! { AttributeModifierSlot::Head },
AttributeModifierSlot::Armor => quote! { AttributeModifierSlot::Armor },
AttributeModifierSlot::Body => quote! { AttributeModifierSlot::Body },
AttributeModifierSlot::Saddle => quote! { AttributeModifierSlot::Saddle },
}
}
}
pub(crate) fn build() -> TokenStream {
println!("cargo:rerun-if-changed=../assets/enchantments.json");
let enchantments: HashMap<String, Enchantment> =
serde_json::from_str(&fs::read_to_string("../assets/enchantments.json").unwrap())
.expect("Failed to parse biome.json");
let mut variants = TokenStream::new();
let mut name_to_type = TokenStream::new();
for (name, enchantment) in enchantments.iter() {
let raw_name = name.strip_prefix("minecraft:").unwrap();
let format_name = format_ident!("{}", raw_name.to_shouty_snake_case());
let anvil_cost = enchantment.anvil_cost;
let supported_items = enchantment.supported_items.clone();
let max_level = enchantment.max_level;
let slots = enchantment.slots.clone();
let slots = slots.iter().map(|slot| slot.to_tokens());
variants.extend([quote! {
pub const #format_name: Enchantment = Enchantment {
name: #name,
anvil_cost: #anvil_cost,
supported_items: #supported_items,
max_level: #max_level,
slots: &[#(#slots),*]
};
}]);
name_to_type.extend(quote! { #name => Some(Self::#format_name), });
}
quote! {
#[derive(Debug, Clone)]
pub struct Enchantment {
pub name: &'static str,
pub anvil_cost: u32,
pub supported_items: &'static str,
pub max_level: i32,
pub slots: &'static [AttributeModifierSlot]
// TODO: add more
}
#[derive(Debug, Clone)]
pub enum AttributeModifierSlot {
Any,
MainHand,
OffHand,
Hand,
Feet,
Legs,
Chest,
Head,
Armor,
Body,
Saddle,
}
impl Enchantment {
#variants
pub fn from_name(name: &str) -> Option<Self> {
match name {
#name_to_type
_ => None
}
}
}
}
}