feat: Entities drop exp now
This commit is contained in:
parent
d33484d057
commit
501fd0ced5
File diff suppressed because one or more lines are too long
@ -15,6 +15,7 @@ pub struct EntityType {
|
||||
/// Numeric registry ID for this entity type.
|
||||
pub id: u16,
|
||||
pub attributes: Option<Vec<BTreeMap<String, f64>>>,
|
||||
pub experience_reward: Option<u32>,
|
||||
/// Static hurt sound event name when it is safely derivable from extracted entity data.
|
||||
pub hurt_sound: Option<String>,
|
||||
/// Whether this entity can be attacked by players or other entities.
|
||||
@ -180,10 +181,13 @@ impl ToTokens for NamedEntityType<'_> {
|
||||
quote! { None }
|
||||
};
|
||||
|
||||
let experience_reward = entity.experience_reward.unwrap_or(0);
|
||||
|
||||
tokens.extend(quote! {
|
||||
EntityType {
|
||||
id: #id,
|
||||
attributes: #attributes_field,
|
||||
experience_reward: #experience_reward,
|
||||
hurt_sound: #hurt_sound,
|
||||
attackable: #attackable,
|
||||
mob: #mob,
|
||||
@ -247,6 +251,7 @@ pub fn build() -> TokenStream {
|
||||
pub struct EntityType {
|
||||
pub id: u16,
|
||||
pub attributes: &'static [(Attributes, f64)],
|
||||
pub experience_reward: u32,
|
||||
pub hurt_sound: Option<Sound>,
|
||||
pub attackable: Option<bool>,
|
||||
pub mob: bool,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@ use std::sync::atomic::{
|
||||
use std::{collections::HashMap, sync::atomic::AtomicI32};
|
||||
use tracing::warn;
|
||||
|
||||
use super::experience_orb::ExperienceOrbEntity;
|
||||
use super::{Entity, NBTStorage};
|
||||
use super::{EntityBase, NBTStorageInit};
|
||||
use crate::block::OnLandedUponArgs;
|
||||
@ -1301,6 +1302,16 @@ impl LivingEntity {
|
||||
|
||||
// Drop loot
|
||||
self.drop_loot(params).await;
|
||||
|
||||
// Award experience
|
||||
if params.killed_by_player.unwrap_or(false)
|
||||
&& world.level_info.load().game_rules.mob_drops
|
||||
{
|
||||
let amount = dyn_self.get_experience_reward(cause);
|
||||
if amount > 0 {
|
||||
ExperienceOrbEntity::spawn(&world, self.entity.pos.load(), amount).await;
|
||||
}
|
||||
}
|
||||
self.entity.pose.store(EntityPose::Dying);
|
||||
|
||||
let block_pos = self.entity.block_pos.load();
|
||||
|
||||
@ -335,6 +335,10 @@ pub trait Mob: EntityBase + Send + Sync {
|
||||
fn is_sitting(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn get_base_experience_reward(&self) -> u32 {
|
||||
self.get_entity().entity_type.experience_reward
|
||||
}
|
||||
}
|
||||
impl<T: Mob + Send + 'static> EntityBase for T {
|
||||
fn tick<'a>(
|
||||
@ -511,6 +515,23 @@ impl<T: Mob + Send + 'static> EntityBase for T {
|
||||
fn get_y_velocity_drag(&self) -> Option<f64> {
|
||||
self.get_mob_y_velocity_drag()
|
||||
}
|
||||
|
||||
fn get_experience_reward(&self, _killer: Option<&dyn EntityBase>) -> u32 {
|
||||
if self
|
||||
.get_entity()
|
||||
.age
|
||||
.load(std::sync::atomic::Ordering::Relaxed)
|
||||
< 0
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// TODO: apply enchantment processing like in vanilla
|
||||
Mob::get_base_experience_reward(self)
|
||||
}
|
||||
|
||||
fn get_base_experience_reward(&self) -> u32 {
|
||||
Mob::get_base_experience_reward(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
|
||||
@ -363,6 +363,14 @@ pub trait EntityBase: Send + Sync + NBTStorage + std::any::Any {
|
||||
|
||||
/// Returns itself as the nbt storage for saving and loading data.
|
||||
fn as_nbt_storage(&self) -> &dyn NBTStorage;
|
||||
|
||||
fn get_experience_reward(&self, _killer: Option<&dyn EntityBase>) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn get_base_experience_reward(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
|
||||
@ -3842,6 +3842,12 @@ impl EntityBase for Player {
|
||||
self
|
||||
}
|
||||
|
||||
fn get_experience_reward(&self, _killer: Option<&dyn EntityBase>) -> u32 {
|
||||
// vanilla: min(level * 7, 100)
|
||||
let level = self.experience_level.load(Ordering::Relaxed);
|
||||
(level * 7).min(100) as u32
|
||||
}
|
||||
|
||||
fn tick_in_void<'a>(&'a self, dyn_self: &'a dyn EntityBase) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
self.living_entity.tick_in_void(dyn_self).await;
|
||||
|
||||
@ -10,7 +10,7 @@ use pumpkin_util::{
|
||||
};
|
||||
use rand::RngExt;
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Copy, Clone)]
|
||||
pub struct LootContextParameters {
|
||||
pub explosion_radius: Option<f32>,
|
||||
pub block_state: Option<&'static BlockState>,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user