mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Expose enchantments to Rust (#99)
* Expose extracted enchantments to Rust. * Give enchantments a `level: i16` field. * Update enchantment derive impls * Restructure how enchants are exposed to Rust through C-like enums * Update build/enchant.rs Co-authored-by: Ryan Johnson <ryanj00a@gmail.com> * Update build/enchant.rs Co-authored-by: Ryan Johnson <ryanj00a@gmail.com> * Move enchantment sources to their own struct. * make id() function return it's discriminant instead of matching Co-authored-by: Ryan Johnson <ryanj00a@gmail.com>
This commit is contained in:
parent
cf5b9136df
commit
b83b9f76ed
223
build/enchant.rs
Normal file
223
build/enchant.rs
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
use heck::ToPascalCase;
|
||||||
|
use proc_macro2::TokenStream;
|
||||||
|
use quote::quote;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
use crate::ident;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
struct TopLevel {
|
||||||
|
enchants: Vec<ParsedEnchantment>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct ParsedEnchantment {
|
||||||
|
#[allow(unused)]
|
||||||
|
id: u16,
|
||||||
|
name: String,
|
||||||
|
translation_key: String,
|
||||||
|
min_level: i16,
|
||||||
|
max_level: i16,
|
||||||
|
#[serde(alias = "cursed")]
|
||||||
|
is_curse: bool,
|
||||||
|
rarity_weight: i32,
|
||||||
|
#[serde(alias = "sources")]
|
||||||
|
source: ParsedEnchantmentSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct ParsedEnchantmentSource {
|
||||||
|
treasure: bool,
|
||||||
|
enchantment_table: bool,
|
||||||
|
random_selection: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build() -> anyhow::Result<TokenStream> {
|
||||||
|
let TopLevel { enchants } = serde_json::from_str(include_str!("../extracted/enchants.json"))?;
|
||||||
|
|
||||||
|
let enchantmentkind_definitions = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let id = enchant.id as isize;
|
||||||
|
quote! {
|
||||||
|
#rustified_name = #id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_id_to_variant_lookup = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let id = &enchant.id;
|
||||||
|
quote! {
|
||||||
|
#id => Some(Self::#rustified_name),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_names = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let name = &enchant.name;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => #name,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_translations = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let translation_key = &enchant.translation_key;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => #translation_key,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_min_level = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let min_level = &enchant.min_level;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => #min_level,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_max_level = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let max_level = &enchant.max_level;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => #max_level,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_is_curse = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let is_curse = &enchant.is_curse;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => #is_curse,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_rarity_weight = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let rarity_weight = &enchant.rarity_weight;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => #rarity_weight,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
let enchantmentkind_sources = enchants
|
||||||
|
.iter()
|
||||||
|
.map(|enchant| {
|
||||||
|
let rustified_name = ident(enchant.name.to_pascal_case());
|
||||||
|
let treasure = &enchant.source.treasure;
|
||||||
|
let enchantment_table = &enchant.source.enchantment_table;
|
||||||
|
let random_selection = &enchant.source.random_selection;
|
||||||
|
quote! {
|
||||||
|
Self::#rustified_name => EnchantmentSources {
|
||||||
|
treasure: #treasure,
|
||||||
|
enchantment_table: #enchantment_table,
|
||||||
|
random_selection: #random_selection,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<TokenStream>();
|
||||||
|
|
||||||
|
Ok(quote! {
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct EnchantmentSources {
|
||||||
|
pub treasure: bool,
|
||||||
|
pub enchantment_table: bool,
|
||||||
|
pub random_selection: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum EnchantmentKind {
|
||||||
|
#enchantmentkind_definitions
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnchantmentKind {
|
||||||
|
/// Constructs an `EnchantmentKind` from a raw enchantment ID.
|
||||||
|
///
|
||||||
|
/// If the given ID is invalid, `None` is returned.
|
||||||
|
pub const fn from_raw(id: u16) -> Option<Self> {
|
||||||
|
match id{
|
||||||
|
#enchantmentkind_id_to_variant_lookup
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the enchantment ID.
|
||||||
|
pub const fn id(self) -> u16 {
|
||||||
|
self as u16
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the translation key.
|
||||||
|
pub const fn translation_key(self) -> &'static str {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_translations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the enchantment name the game uses.
|
||||||
|
pub const fn name(self) -> &'static str {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_names
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum enchantment level officially supported by Minecraft.
|
||||||
|
pub const fn min_level(self) -> i16 {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_min_level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the maximum enchantment level officially supported by Minecraft.
|
||||||
|
pub const fn max_level(self) -> i16 {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_max_level
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if the enchantment is of the curse type.
|
||||||
|
pub const fn is_curse(self) -> bool {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_is_curse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the rarity of the enchant. Lower means more rare.
|
||||||
|
pub const fn rarity_weight(self) -> i32 {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_rarity_weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the different sources this enchantment has.
|
||||||
|
pub const fn sources(self) -> EnchantmentSources {
|
||||||
|
match self{
|
||||||
|
#enchantmentkind_sources
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ use anyhow::Context;
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
|
|
||||||
mod block;
|
mod block;
|
||||||
|
mod enchant;
|
||||||
mod entity;
|
mod entity;
|
||||||
mod entity_event;
|
mod entity_event;
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ pub fn main() -> anyhow::Result<()> {
|
||||||
(entity::build as fn() -> _, "entity.rs"),
|
(entity::build as fn() -> _, "entity.rs"),
|
||||||
(entity_event::build, "entity_event.rs"),
|
(entity_event::build, "entity_event.rs"),
|
||||||
(block::build, "block.rs"),
|
(block::build, "block.rs"),
|
||||||
|
(enchant::build, "enchant.rs"),
|
||||||
];
|
];
|
||||||
|
|
||||||
let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?;
|
let out_dir = env::var_os("OUT_DIR").context("can't get OUT_DIR env var")?;
|
||||||
|
|
5
src/enchant.rs
Normal file
5
src/enchant.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// enchant.rs exposes constant values provided by the build script.
|
||||||
|
// All enchantment variants are located in `EnchantmentKind`. You can use the
|
||||||
|
// associated const fn functions of `EnchantmentKind` to access details about an
|
||||||
|
// enchantment type. enchantment specific functions
|
||||||
|
include!(concat!(env!("OUT_DIR"), "/enchant.rs"));
|
|
@ -107,6 +107,7 @@ mod chunk_pos;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod dimension;
|
pub mod dimension;
|
||||||
|
pub mod enchant;
|
||||||
pub mod entity;
|
pub mod entity;
|
||||||
pub mod ident;
|
pub mod ident;
|
||||||
pub mod itemstack;
|
pub mod itemstack;
|
||||||
|
|
Loading…
Reference in a new issue