Skip to content

Commit

Permalink
Potions Extractor (#559)
Browse files Browse the repository at this point in the history
# Objective

We need a way to acquire (and thus extract) all potion/status effects +
their attributes

Also, #558 was getting really large.

# Solution

I made an extractor.

Also, as per [the
request](#558 (comment))
of @dyc3, I split #558's extractor code into this pr.
  • Loading branch information
SelfMadeSystem authored Oct 12, 2023
1 parent b0c4b0f commit ec01b0b
Show file tree
Hide file tree
Showing 11 changed files with 576 additions and 4 deletions.
4 changes: 2 additions & 2 deletions crates/valence_entity/extracted/entities.json
Original file line number Diff line number Diff line change
Expand Up @@ -1528,7 +1528,7 @@
"name": "health",
"index": 9,
"type": "float",
"default_value": 6.0
"default_value": 20.0
},
{
"name": "potion_swirls_color",
Expand Down Expand Up @@ -2863,7 +2863,7 @@
"type": "villager_data",
"default_value": {
"type": "plains",
"profession": "weaponsmith",
"profession": "none",
"level": 1
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/valence_generated/build/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ mod chunk_view;
mod item;
mod packet_id;
mod sound;
mod status_effects;

pub fn main() -> anyhow::Result<()> {
write_generated_file(block::build()?, "block.rs")?;
write_generated_file(item::build()?, "item.rs")?;
write_generated_file(sound::build()?, "sound.rs")?;
write_generated_file(packet_id::build()?, "packet_id.rs")?;
write_generated_file(chunk_view::build(), "chunk_view.rs")?;
write_generated_file(status_effects::build()?, "status_effects.rs")?;

Ok(())
}
226 changes: 226 additions & 0 deletions crates/valence_generated/build/status_effects.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
use heck::ToPascalCase;
use proc_macro2::TokenStream;
use quote::quote;
use serde::Deserialize;
use valence_build_utils::{ident, rerun_if_changed};

#[derive(Deserialize, Debug)]
pub enum StatusEffectCategory {
Beneficial,
Harmful,
Neutral,
}

#[derive(Deserialize, Debug)]
pub struct StatusEffect {
id: u16,
name: String,
translation_key: String,
category: StatusEffectCategory,
color: u32,
instant: bool,
}

pub fn build() -> anyhow::Result<TokenStream> {
rerun_if_changed(["extracted/effects.json"]);

let effects =
serde_json::from_str::<Vec<StatusEffect>>(include_str!("../extracted/effects.json"))?;

let effect_count = effects.len();

let effect_from_raw_id_arms = effects
.iter()
.map(|effect| {
let id = &effect.id;
let name = ident(effect.name.to_pascal_case());

quote! {
#id => Some(Self::#name),
}
})
.collect::<TokenStream>();

let effect_to_raw_id_arms = effects
.iter()
.map(|effect| {
let id = &effect.id;
let name = ident(effect.name.to_pascal_case());

quote! {
Self::#name => #id,
}
})
.collect::<TokenStream>();

let effect_from_ident_arms = effects
.iter()
.map(|effect| {
let path_name = &effect.name;
let ident_name = format!("minecraft:{}", &effect.name);

let name = ident(path_name.to_pascal_case());
quote! {
#ident_name => Some(Self::#name),
}
})
.collect::<TokenStream>();

let effect_to_ident_arms = effects
.iter()
.map(|effect| {
let str_name = &effect.name;
let name = ident(str_name.to_pascal_case());
quote! {
Self::#name => ident!(#str_name),
}
})
.collect::<TokenStream>();

let effect_to_translation_key_arms = effects
.iter()
.map(|effect| {
let str_name = &effect.translation_key;
let name = ident(effect.name.to_pascal_case());
quote! {
Self::#name => #str_name,
}
})
.collect::<TokenStream>();

let effect_to_category_arms = effects
.iter()
.map(|effect| {
let category = match &effect.category {
StatusEffectCategory::Beneficial => quote! { StatusEffectCategory::Beneficial },
StatusEffectCategory::Harmful => quote! { StatusEffectCategory::Harmful },
StatusEffectCategory::Neutral => quote! { StatusEffectCategory::Neutral },
};

let name = ident(effect.name.to_pascal_case());
quote! {
Self::#name => #category,
}
})
.collect::<TokenStream>();

let effect_to_color_arms = effects
.iter()
.map(|effect| {
let color = &effect.color;
let name = ident(effect.name.to_pascal_case());
quote! {
Self::#name => #color,
}
})
.collect::<TokenStream>();

let effect_to_instant_arms = effects
.iter()
.map(|effect| {
let instant = &effect.instant;
let name = ident(effect.name.to_pascal_case());
quote! {
Self::#name => #instant,
}
})
.collect::<TokenStream>();

let effect_variants = effects
.iter()
.map(|effect| ident(effect.name.to_pascal_case()))
.collect::<Vec<_>>();

Ok(quote! {
use valence_ident::{Ident, ident};

/// Represents a status effect category
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum StatusEffectCategory {
Beneficial,
Harmful,
Neutral,
}

/// Represents a status effect from the game
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum StatusEffect {
#(#effect_variants,)*
}

impl StatusEffect {
/// Constructs a effect from a raw item ID.
///
/// If the given ID is invalid, `None` is returned.
pub const fn from_raw(id: u16) -> Option<Self> {
match id {
#effect_from_raw_id_arms
_ => None
}
}

/// Gets the raw effect ID from the effect
pub const fn to_raw(self) -> u16 {
match self {
#effect_to_raw_id_arms
}
}

/// Construct a effect from its snake_case name.
///
/// Returns `None` if the name is invalid.
pub fn from_ident(id: Ident<&str>) -> Option<Self> {
match id.as_str() {
#effect_from_ident_arms
_ => None
}
}

/// Gets the identifier of this effect.
pub const fn to_ident(self) -> Ident<&'static str> {
match self {
#effect_to_ident_arms
}
}

/// Gets the name of this effect.
/// Same as [`StatusEffect::to_ident`], but doesn't take ownership.
pub const fn name(&self) -> Ident<&'static str> {
match self {
#effect_to_ident_arms
}
}

/// Gets the translation key of this effect.
pub const fn translation_key(&self) -> &'static str {
match self {
#effect_to_translation_key_arms
}
}

/// Gets the category of this effect.
pub const fn category(&self) -> StatusEffectCategory {
match self {
#effect_to_category_arms
}
}

/// Gets the color of this effect.
pub const fn color(&self) -> u32 {
match self {
#effect_to_color_arms
}
}

/// Gets whether this effect is instant.
pub const fn instant(&self) -> bool {
match self {
#effect_to_instant_arms
}
}

/// An array of all effects.
pub const ALL: [Self; #effect_count] = [#(Self::#effect_variants,)*];
}
})
}
Loading

0 comments on commit ec01b0b

Please sign in to comment.