mirror of
https://github.com/Pumpkin-MC/Pumpkin.git
synced 2026-08-30 20:14:23 +00:00
Improve damage type
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
use heck::{ToPascalCase, ToShoutySnakeCase};
|
||||
use heck::ToShoutySnakeCase;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use syn::LitInt;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DamageTypeEntry {
|
||||
@@ -30,9 +31,8 @@ pub(crate) fn build() -> TokenStream {
|
||||
|
||||
for (name, entry) in damage_types {
|
||||
let const_ident = format_ident!("{}", name.to_shouty_snake_case());
|
||||
let enum_ident = format_ident!("{}", name.to_pascal_case());
|
||||
|
||||
enum_variants.push(enum_ident.clone());
|
||||
enum_variants.push(const_ident.clone());
|
||||
|
||||
let data = &entry.components;
|
||||
let death_message_type = match &data.death_message_type {
|
||||
@@ -43,27 +43,19 @@ pub(crate) fn build() -> TokenStream {
|
||||
let exhaustion = data.exhaustion;
|
||||
let message_id = &data.message_id;
|
||||
let scaling = &data.scaling;
|
||||
let id = entry.id;
|
||||
let id_lit = LitInt::new(&entry.id.to_string(), proc_macro2::Span::call_site());
|
||||
|
||||
constants.push(quote! {
|
||||
pub const #const_ident: DamageTypeData = DamageTypeData {
|
||||
pub const #const_ident: DamageType = DamageType {
|
||||
death_message_type: #death_message_type,
|
||||
exhaustion: #exhaustion,
|
||||
message_id: #message_id,
|
||||
scaling: #scaling,
|
||||
id: #id,
|
||||
id: #id_lit,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
let enum_arms = enum_variants.iter().map(|variant| {
|
||||
let const_name = variant.to_string().to_shouty_snake_case();
|
||||
let const_ident = format_ident!("{}", &const_name);
|
||||
quote! {
|
||||
DamageType::#variant => &#const_ident,
|
||||
}
|
||||
});
|
||||
|
||||
let type_name_pairs = enum_variants.iter().map(|variant| {
|
||||
let name = variant.to_string();
|
||||
let name_lowercase = name.to_lowercase();
|
||||
@@ -73,25 +65,9 @@ pub(crate) fn build() -> TokenStream {
|
||||
}
|
||||
});
|
||||
|
||||
let type_to_name_pairs = enum_variants.iter().map(|variant| {
|
||||
let name = variant.to_string();
|
||||
let name_lowercase = name.to_lowercase();
|
||||
let resource_name = format!("minecraft:{}", name_lowercase);
|
||||
quote! {
|
||||
Self::#variant => #resource_name
|
||||
}
|
||||
});
|
||||
|
||||
// Create array of all variants for values() method
|
||||
let variant_array = enum_variants.iter().map(|variant| {
|
||||
quote! {
|
||||
DamageType::#variant
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DamageTypeData {
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct DamageType {
|
||||
pub death_message_type: Option<&'static str>,
|
||||
pub exhaustion: f32,
|
||||
pub message_id: &'static str,
|
||||
@@ -99,27 +75,8 @@ pub(crate) fn build() -> TokenStream {
|
||||
pub id: u32,
|
||||
}
|
||||
|
||||
#(#constants)*
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum DamageType {
|
||||
#(#enum_variants,)*
|
||||
}
|
||||
|
||||
impl DamageType {
|
||||
pub const fn data(&self) -> &'static DamageTypeData {
|
||||
match self {
|
||||
#(#enum_arms)*
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Get all possible damage types"]
|
||||
pub fn values() -> &'static [DamageType] {
|
||||
static VALUES: &[DamageType] = &[
|
||||
#(#variant_array,)*
|
||||
];
|
||||
VALUES
|
||||
}
|
||||
#(#constants)*
|
||||
|
||||
#[doc = r" Try to parse a damage type from a resource location string"]
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
@@ -129,12 +86,6 @@ pub(crate) fn build() -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = r" Get the resource location string for this damage type"]
|
||||
pub const fn to_name(&self) -> &'static str {
|
||||
match self {
|
||||
#(#type_to_name_pairs,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,13 @@ pub struct DamageTypeArgumentConsumer;
|
||||
|
||||
impl GetClientSideArgParser for DamageTypeArgumentConsumer {
|
||||
fn get_client_side_parser(&self) -> ArgumentType {
|
||||
ArgumentType::ResourceLocation
|
||||
ArgumentType::Resource {
|
||||
identifier: "damage_type",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_client_side_suggestion_type_override(&self) -> Option<SuggestionProviders> {
|
||||
Some(SuggestionProviders::AskServer)
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,15 +32,12 @@ impl ArgumentConsumer for DamageTypeArgumentConsumer {
|
||||
_server: &'a Server,
|
||||
args: &mut RawArgs<'a>,
|
||||
) -> Option<Arg<'a>> {
|
||||
let s = args.pop()?;
|
||||
let name = args.pop()?;
|
||||
|
||||
// Create a static damage type first
|
||||
let damage_type = DamageType::from_name(s)?;
|
||||
let damage_type = DamageType::from_name(name)?;
|
||||
// Find matching static damage type from values array
|
||||
DamageType::values()
|
||||
.iter()
|
||||
.find(|&&dt| std::mem::discriminant(&dt) == std::mem::discriminant(&damage_type))
|
||||
.map(Arg::DamageType)
|
||||
Some(Arg::DamageType(damage_type))
|
||||
}
|
||||
|
||||
async fn suggest<'a>(
|
||||
@@ -47,18 +46,13 @@ impl ArgumentConsumer for DamageTypeArgumentConsumer {
|
||||
_server: &'a Server,
|
||||
_input: &'a str,
|
||||
) -> Result<Option<Vec<CommandSuggestion>>, CommandError> {
|
||||
// Get all available damage types
|
||||
let suggestions = DamageType::values()
|
||||
.iter()
|
||||
.map(|dt| CommandSuggestion::new(dt.to_name().to_string(), None))
|
||||
.collect();
|
||||
Ok(Some(suggestions))
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl DefaultNameArgConsumer for DamageTypeArgumentConsumer {
|
||||
fn default_name(&self) -> &'static str {
|
||||
"damageType"
|
||||
"damage_type"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ pub enum Arg<'a> {
|
||||
#[allow(unused)]
|
||||
Simple(&'a str),
|
||||
SoundCategory(SoundCategory),
|
||||
DamageType(&'a DamageType),
|
||||
DamageType(DamageType),
|
||||
}
|
||||
|
||||
/// see [`crate::commands::tree::builder::argument`] and [`CommandTree::execute`]/[`crate::commands::tree::builder::NonLeafNodeBuilder::execute`]
|
||||
|
||||
@@ -82,9 +82,9 @@ impl CommandExecutor for DamageLocationExecutor {
|
||||
|
||||
let damage_type = args
|
||||
.get(ARG_DAMAGE_TYPE)
|
||||
.map_or(DamageType::Generic, |arg| match arg {
|
||||
Arg::DamageType(dt) => **dt,
|
||||
_ => DamageType::Generic,
|
||||
.map_or(DamageType::GENERIC, |arg| match arg {
|
||||
Arg::DamageType(dt) => *dt,
|
||||
_ => DamageType::GENERIC,
|
||||
});
|
||||
|
||||
let location = Position3DArgumentConsumer::find_arg(args, ARG_LOCATION)?;
|
||||
@@ -122,9 +122,9 @@ impl CommandExecutor for DamageEntityExecutor {
|
||||
|
||||
let damage_type = args
|
||||
.get(ARG_DAMAGE_TYPE)
|
||||
.map_or(DamageType::Generic, |arg| match arg {
|
||||
Arg::DamageType(dt) => **dt,
|
||||
_ => DamageType::Generic,
|
||||
.map_or(DamageType::GENERIC, |arg| match arg {
|
||||
Arg::DamageType(dt) => *dt,
|
||||
_ => DamageType::GENERIC,
|
||||
});
|
||||
|
||||
let source = EntityArgumentConsumer::find_arg(args, ARG_ENTITY).ok();
|
||||
|
||||
@@ -50,7 +50,7 @@ impl HungerManager {
|
||||
} else if level == 0 {
|
||||
self.tick_timer.fetch_add(1);
|
||||
if self.tick_timer.load() >= 80 {
|
||||
player.living_entity.damage(1.0, DamageType::Starve).await;
|
||||
player.living_entity.damage(1.0, DamageType::STARVE).await;
|
||||
self.tick_timer.store(0);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -81,7 +81,7 @@ impl LivingEntity {
|
||||
cause: Option<&Entity>,
|
||||
) -> bool {
|
||||
// Check invulnerability before applying damage
|
||||
if self.entity.is_invulnerable_to(damage_type) {
|
||||
if self.entity.is_invulnerable_to(&damage_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ impl LivingEntity {
|
||||
.world
|
||||
.broadcast_packet_all(&CDamageEvent::new(
|
||||
self.entity.entity_id.into(),
|
||||
damage_type.data().id.into(),
|
||||
damage_type.id.into(),
|
||||
source.map(|e| e.entity_id.into()),
|
||||
cause.map(|e| e.entity_id.into()),
|
||||
position,
|
||||
@@ -156,7 +156,7 @@ impl LivingEntity {
|
||||
.play_sound(Self::get_fall_sound(fall_distance as i32))
|
||||
.await;
|
||||
// TODO: Play block fall sound
|
||||
self.damage(damage, DamageType::Fall).await; // Fall
|
||||
self.damage(damage, DamageType::FALL).await; // Fall
|
||||
} else if height_difference < 0.0 {
|
||||
let distance = self.fall_distance.load();
|
||||
self.fall_distance
|
||||
|
||||
@@ -357,9 +357,9 @@ impl Entity {
|
||||
.await;
|
||||
}
|
||||
|
||||
pub fn is_invulnerable_to(&self, damage_type: DamageType) -> bool {
|
||||
pub fn is_invulnerable_to(&self, damage_type: &DamageType) -> bool {
|
||||
self.invulnerable.load(std::sync::atomic::Ordering::Relaxed)
|
||||
|| self.damage_immunities.contains(&damage_type)
|
||||
|| self.damage_immunities.contains(damage_type)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ impl Player {
|
||||
|
||||
victim
|
||||
.living_entity
|
||||
.damage(damage as f32, DamageType::PlayerAttack) // PlayerAttack
|
||||
.damage(damage as f32, DamageType::PLAYER_ATTACK)
|
||||
.await;
|
||||
|
||||
let mut knockback_strength = 1.0;
|
||||
|
||||
Reference in New Issue
Block a user