chore: more entities taking sun damage
instead of hardcoding, it now uses the tag::EntityType::MINECRAFT_BURN_IN_DAYLIGHT, will definitely be more future proof as well
This commit is contained in:
parent
9c0adaa576
commit
755a1bd749
@ -8,9 +8,9 @@ use crate::world::World;
|
|||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use pumpkin_data::attributes::Attributes;
|
use pumpkin_data::attributes::Attributes;
|
||||||
use pumpkin_data::damage::DamageType;
|
use pumpkin_data::damage::DamageType;
|
||||||
use pumpkin_data::data_component_impl::EquipmentSlot;
|
|
||||||
use pumpkin_data::item_stack::ItemStack;
|
use pumpkin_data::item_stack::ItemStack;
|
||||||
use pumpkin_data::meta_data_type::MetaDataType;
|
use pumpkin_data::meta_data_type::MetaDataType;
|
||||||
|
use pumpkin_data::tag::{self, Taggable};
|
||||||
use pumpkin_data::tracked_data::TrackedData;
|
use pumpkin_data::tracked_data::TrackedData;
|
||||||
use pumpkin_protocol::java::client::play::{CHeadRot, CUpdateEntityRot, Metadata};
|
use pumpkin_protocol::java::client::play::{CHeadRot, CUpdateEntityRot, Metadata};
|
||||||
use pumpkin_util::math::boundingbox::BoundingBox;
|
use pumpkin_util::math::boundingbox::BoundingBox;
|
||||||
@ -240,6 +240,68 @@ impl MobEntity {
|
|||||||
|
|
||||||
base_box.expand(attack_range, 0.0, attack_range)
|
base_box.expand(attack_range, 0.0, attack_range)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn tick_sun_burn(&self) {
|
||||||
|
if !self
|
||||||
|
.living_entity
|
||||||
|
.entity
|
||||||
|
.entity_type
|
||||||
|
.has_tag(&tag::EntityType::MINECRAFT_BURN_IN_DAYLIGHT)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !self.is_sun_burn_tick().await {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.apply_sun_burn();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn is_sun_burn_tick(&self) -> bool {
|
||||||
|
let entity = &self.living_entity.entity;
|
||||||
|
|
||||||
|
let world_arc = entity.world.load();
|
||||||
|
let world = world_arc.as_ref();
|
||||||
|
|
||||||
|
// TODO: gate behind EnvironmentAttributes::MONSTERS_BURN once implemented.
|
||||||
|
|
||||||
|
// Vanilla: getLightLevelDependentMagicValue() — sky light at eye pos, scaled 0–1.
|
||||||
|
let eye_block_pos = entity.get_eye_pos();
|
||||||
|
let brightness = world
|
||||||
|
.level
|
||||||
|
.light_engine
|
||||||
|
.get_sky_light_level(&world.level, &eye_block_pos.to_block_pos())
|
||||||
|
.await as f32
|
||||||
|
/ 15.0;
|
||||||
|
|
||||||
|
if brightness <= 0.5 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let is_in_non_burnable = entity.touching_water.load(Relaxed)
|
||||||
|
|| world.weather.lock().await.raining
|
||||||
|
|| entity.is_in_powder_snow()
|
||||||
|
|| entity.was_in_powder_snow.load(Relaxed);
|
||||||
|
|
||||||
|
if is_in_non_burnable {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pos = entity.pos.load();
|
||||||
|
let top_y = world
|
||||||
|
.get_top_block(Vector2::new(pos.x as i32, pos.z as i32))
|
||||||
|
.await;
|
||||||
|
if (entity.get_eye_y() as i32) < top_y {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut rng = rand::rng();
|
||||||
|
rng.random::<f32>() * 30.0 < (brightness - 0.4) * 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_sun_burn(&self) {
|
||||||
|
let entity = &self.living_entity.entity;
|
||||||
|
entity.set_on_fire_for(8.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Mob: EntityBase + Send + Sync {
|
pub trait Mob: EntityBase + Send + Sync {
|
||||||
@ -348,6 +410,7 @@ impl<T: Mob + Send + 'static> EntityBase for T {
|
|||||||
) -> EntityBaseFuture<'a, ()> {
|
) -> EntityBaseFuture<'a, ()> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let mob_entity = self.get_mob_entity();
|
let mob_entity = self.get_mob_entity();
|
||||||
|
mob_entity.tick_sun_burn().await;
|
||||||
|
|
||||||
if mob_entity.breeding_cooldown.load(Relaxed) > 0 {
|
if mob_entity.breeding_cooldown.load(Relaxed) > 0 {
|
||||||
mob_entity.breeding_cooldown.fetch_sub(1, Relaxed);
|
mob_entity.breeding_cooldown.fetch_sub(1, Relaxed);
|
||||||
@ -578,66 +641,3 @@ pub trait PathAwareEntity: Mob + Send + Sync {
|
|||||||
1.0
|
1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SunSensitive: Mob + Send + Sync {
|
|
||||||
fn sun_sensitive_tick(&self) -> EntityBaseFuture<'_, ()> {
|
|
||||||
Box::pin(async {
|
|
||||||
let mob = self.get_mob_entity();
|
|
||||||
let entity = &mob.living_entity.entity;
|
|
||||||
|
|
||||||
if !entity.is_alive()
|
|
||||||
|| entity.touching_water.load(Relaxed)
|
|
||||||
|| entity.is_in_powder_snow()
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let world_arc = entity.world.load();
|
|
||||||
let world = world_arc.as_ref();
|
|
||||||
|
|
||||||
if world.level_time.lock().await.is_night() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if world.weather.lock().await.raining {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let pos = entity.pos.load();
|
|
||||||
let top_y = world
|
|
||||||
.get_top_block(Vector2::new(pos.x as i32, pos.z as i32))
|
|
||||||
.await;
|
|
||||||
if (entity.get_eye_y() as i32) < top_y {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let brightness = world
|
|
||||||
.level
|
|
||||||
.light_engine
|
|
||||||
.get_sky_light_level(&world.level, &pos.to_block_pos())
|
|
||||||
.await as f32
|
|
||||||
/ 15.0;
|
|
||||||
|
|
||||||
if brightness < 0.5 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let damage_amount = {
|
|
||||||
let mut rng = self.get_random();
|
|
||||||
if rng.random::<f32>() * 30.0 >= (brightness - 0.4) * 2.0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rng.random_range(0..=1i32)
|
|
||||||
};
|
|
||||||
|
|
||||||
let equipment = mob.living_entity.entity_equipment.lock().await;
|
|
||||||
let head_slot = equipment.get(&EquipmentSlot::HEAD);
|
|
||||||
let mut head_item = head_slot.lock().await;
|
|
||||||
if head_item.is_empty() {
|
|
||||||
entity.set_on_fire_for(8.0);
|
|
||||||
} else {
|
|
||||||
// TODO: Handle DamageResult::Broken to broadcast item break and update player slot.
|
|
||||||
let _ = head_item.damage_item(damage_amount);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
use crate::entity::mob::SunSensitive;
|
|
||||||
use crate::entity::{
|
use crate::entity::{
|
||||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
Entity, NBTStorage,
|
||||||
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
||||||
};
|
};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -23,10 +22,4 @@ impl Mob for BoggedSkeletonEntity {
|
|||||||
fn get_mob_entity(&self) -> &MobEntity {
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
&self.entity.mob_entity
|
&self.entity.mob_entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mob_tick<'a>(&'a self, _caller: &'a Arc<dyn EntityBase>) -> EntityBaseFuture<'a, ()> {
|
|
||||||
self.sun_sensitive_tick()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SunSensitive for BoggedSkeletonEntity {}
|
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::entity::mob::SunSensitive;
|
|
||||||
use crate::entity::{
|
use crate::entity::{
|
||||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
Entity, NBTStorage,
|
||||||
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,10 +23,4 @@ impl Mob for SkeletonEntity {
|
|||||||
fn get_mob_entity(&self) -> &MobEntity {
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
&self.entity.mob_entity
|
&self.entity.mob_entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mob_tick<'a>(&'a self, _caller: &'a Arc<dyn EntityBase>) -> EntityBaseFuture<'a, ()> {
|
|
||||||
self.sun_sensitive_tick()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SunSensitive for SkeletonEntity {}
|
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::entity::mob::SunSensitive;
|
|
||||||
use crate::entity::{
|
use crate::entity::{
|
||||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
Entity, NBTStorage,
|
||||||
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,10 +23,4 @@ impl Mob for StraySkeletonEntity {
|
|||||||
fn get_mob_entity(&self) -> &MobEntity {
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
&self.entity.mob_entity
|
&self.entity.mob_entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mob_tick<'a>(&'a self, _caller: &'a Arc<dyn EntityBase>) -> EntityBaseFuture<'a, ()> {
|
|
||||||
self.sun_sensitive_tick()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SunSensitive for StraySkeletonEntity {}
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::entity::mob::SunSensitive;
|
|
||||||
use crate::entity::mob::zombie::ZombieEntityBase;
|
use crate::entity::mob::zombie::ZombieEntityBase;
|
||||||
use crate::entity::{
|
use crate::entity::{
|
||||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
Entity, NBTStorage,
|
||||||
mob::{Mob, MobEntity},
|
mob::{Mob, MobEntity},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,10 +40,4 @@ impl Mob for DrownedEntity {
|
|||||||
fn get_mob_entity(&self) -> &MobEntity {
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
&self.entity.mob_entity
|
&self.entity.mob_entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mob_tick<'a>(&'a self, _caller: &'a Arc<dyn EntityBase>) -> EntityBaseFuture<'a, ()> {
|
|
||||||
self.sun_sensitive_tick()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SunSensitive for DrownedEntity {}
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
use crate::entity::NBTStorage;
|
||||||
use crate::entity::mob::zombie::ZombieEntityBase;
|
use crate::entity::mob::zombie::ZombieEntityBase;
|
||||||
use crate::entity::mob::{Mob, MobEntity, SunSensitive};
|
use crate::entity::mob::{Mob, MobEntity};
|
||||||
use crate::entity::{EntityBase, EntityBaseFuture, NBTStorage};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct ZombieEntity {
|
pub struct ZombieEntity {
|
||||||
@ -21,10 +21,4 @@ impl Mob for ZombieEntity {
|
|||||||
fn get_mob_entity(&self) -> &MobEntity {
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
&self.entity.mob_entity
|
&self.entity.mob_entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mob_tick<'a>(&'a self, _caller: &'a Arc<dyn EntityBase>) -> EntityBaseFuture<'a, ()> {
|
|
||||||
self.sun_sensitive_tick()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SunSensitive for ZombieEntity {}
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::entity::mob::zombie::ZombieEntityBase;
|
use crate::entity::mob::zombie::ZombieEntityBase;
|
||||||
use crate::entity::mob::{Mob, MobEntity, SunSensitive};
|
use crate::entity::mob::{Mob, MobEntity};
|
||||||
use crate::entity::{Entity, EntityBase, EntityBaseFuture, NBTStorage};
|
use crate::entity::{Entity, NBTStorage};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct ZombieVillagerEntity {
|
pub struct ZombieVillagerEntity {
|
||||||
@ -21,10 +21,4 @@ impl Mob for ZombieVillagerEntity {
|
|||||||
fn get_mob_entity(&self) -> &MobEntity {
|
fn get_mob_entity(&self) -> &MobEntity {
|
||||||
&self.mob_entity.mob_entity
|
&self.mob_entity.mob_entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mob_tick<'a>(&'a self, _caller: &'a Arc<dyn EntityBase>) -> EntityBaseFuture<'a, ()> {
|
|
||||||
self.sun_sensitive_tick()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl SunSensitive for ZombieVillagerEntity {}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user