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 pumpkin_data::attributes::Attributes;
|
||||
use pumpkin_data::damage::DamageType;
|
||||
use pumpkin_data::data_component_impl::EquipmentSlot;
|
||||
use pumpkin_data::item_stack::ItemStack;
|
||||
use pumpkin_data::meta_data_type::MetaDataType;
|
||||
use pumpkin_data::tag::{self, Taggable};
|
||||
use pumpkin_data::tracked_data::TrackedData;
|
||||
use pumpkin_protocol::java::client::play::{CHeadRot, CUpdateEntityRot, Metadata};
|
||||
use pumpkin_util::math::boundingbox::BoundingBox;
|
||||
@ -240,6 +240,68 @@ impl MobEntity {
|
||||
|
||||
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 {
|
||||
@ -348,6 +410,7 @@ impl<T: Mob + Send + 'static> EntityBase for T {
|
||||
) -> EntityBaseFuture<'a, ()> {
|
||||
Box::pin(async move {
|
||||
let mob_entity = self.get_mob_entity();
|
||||
mob_entity.tick_sun_burn().await;
|
||||
|
||||
if mob_entity.breeding_cooldown.load(Relaxed) > 0 {
|
||||
mob_entity.breeding_cooldown.fetch_sub(1, Relaxed);
|
||||
@ -578,66 +641,3 @@ pub trait PathAwareEntity: Mob + Send + Sync {
|
||||
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::{
|
||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
||||
Entity, NBTStorage,
|
||||
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
@ -23,10 +22,4 @@ impl Mob for BoggedSkeletonEntity {
|
||||
fn get_mob_entity(&self) -> &MobEntity {
|
||||
&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 crate::entity::mob::SunSensitive;
|
||||
use crate::entity::{
|
||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
||||
Entity, NBTStorage,
|
||||
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
||||
};
|
||||
|
||||
@ -24,10 +23,4 @@ impl Mob for SkeletonEntity {
|
||||
fn get_mob_entity(&self) -> &MobEntity {
|
||||
&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 crate::entity::mob::SunSensitive;
|
||||
use crate::entity::{
|
||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
||||
Entity, NBTStorage,
|
||||
mob::{Mob, MobEntity, skeleton::SkeletonEntityBase},
|
||||
};
|
||||
|
||||
@ -24,10 +23,4 @@ impl Mob for StraySkeletonEntity {
|
||||
fn get_mob_entity(&self) -> &MobEntity {
|
||||
&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 crate::entity::mob::SunSensitive;
|
||||
use crate::entity::mob::zombie::ZombieEntityBase;
|
||||
use crate::entity::{
|
||||
Entity, EntityBase, EntityBaseFuture, NBTStorage,
|
||||
Entity, NBTStorage,
|
||||
mob::{Mob, MobEntity},
|
||||
};
|
||||
|
||||
@ -41,10 +40,4 @@ impl Mob for DrownedEntity {
|
||||
fn get_mob_entity(&self) -> &MobEntity {
|
||||
&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::{Mob, MobEntity, SunSensitive};
|
||||
use crate::entity::{EntityBase, EntityBaseFuture, NBTStorage};
|
||||
use crate::entity::mob::{Mob, MobEntity};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct ZombieEntity {
|
||||
@ -21,10 +21,4 @@ impl Mob for ZombieEntity {
|
||||
fn get_mob_entity(&self) -> &MobEntity {
|
||||
&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::{Mob, MobEntity, SunSensitive};
|
||||
use crate::entity::{Entity, EntityBase, EntityBaseFuture, NBTStorage};
|
||||
use crate::entity::mob::{Mob, MobEntity};
|
||||
use crate::entity::{Entity, NBTStorage};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct ZombieVillagerEntity {
|
||||
@ -21,10 +21,4 @@ impl Mob for ZombieVillagerEntity {
|
||||
fn get_mob_entity(&self) -> &MobEntity {
|
||||
&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