fix(ai): damage endermen in rain (#2714)

This commit is contained in:
Eshan I.
2026-08-02 14:07:35 -04:00
committed by GitHub
parent f474756b16
commit 7844590958
3 changed files with 62 additions and 3 deletions

View File

@@ -67,7 +67,6 @@ impl TemperatureModifier {
/// Represents weather information for a biome, including temperature and precipitation.
#[derive(Clone, Debug)]
pub struct Weather {
#[expect(dead_code)]
has_precipitation: bool,
/// Base temperature of the biome.
temperature: f32,
@@ -136,4 +135,37 @@ impl Weather {
modified_temperature
}
}
#[must_use]
pub fn warm_enough_to_rain(&self, x: i32, y: i32, z: i32, sea_level: i32) -> bool {
self.compute_temperature(f64::from(x), y, f64::from(z), sea_level) >= 0.15
}
#[must_use]
pub fn is_rain_at(&self, x: i32, y: i32, z: i32, sea_level: i32) -> bool {
self.has_precipitation && self.warm_enough_to_rain(x, y, z, sea_level)
}
}
#[cfg(test)]
mod tests {
use super::{TemperatureModifier, Weather};
#[test]
fn precipitation_controls_rain() {
let weather = Weather::new(false, 1.0, TemperatureModifier::None, 0.0);
assert!(!weather.is_rain_at(0, 64, 0, 63));
}
#[test]
fn warm_precipitation_is_rain() {
let weather = Weather::new(true, 1.0, TemperatureModifier::None, 0.0);
assert!(weather.is_rain_at(0, 64, 0, 63));
}
#[test]
fn cold_precipitation_is_snow() {
let weather = Weather::new(true, 0.0, TemperatureModifier::None, 0.0);
assert!(!weather.is_rain_at(0, 64, 0, 63));
}
}

View File

@@ -427,8 +427,12 @@ impl Mob for EndermanEntity {
return;
}
// TODO: also check rain
if entity.touching_water.load(Ordering::SeqCst) {
let world = entity.world.load();
let raining_at_feet = world.is_raining_at(&entity.block_pos.load()).await;
let raining_at_head = world
.is_raining_at(&entity.bounding_box.load().max_block_pos())
.await;
if entity.touching_water.load(Ordering::SeqCst) || raining_at_feet || raining_at_head {
self.mob_entity
.living_entity
.damage_with_context(self, 1.0, DamageType::DROWN, None, None, None)

View File

@@ -162,6 +162,8 @@ use weather::Weather;
type FlowingFluidProperties = pumpkin_data::fluid::FlowingWaterLikeFluidProperties;
const MAX_LIGHT_LEVEL: u8 = 15;
use rustc_hash::{FxHashMap, FxHashSet};
impl PumpkinError for GetBlockError {
@@ -1730,6 +1732,20 @@ impl World {
self.weather.lock().await.raining
}
pub async fn is_raining_at(&self, pos: &BlockPos) -> bool {
if !self.is_raining().await {
return false;
}
if self.get_heightmap_height(MotionBlocking, pos.0.x, pos.0.z) + 1 > pos.0.y {
return false;
}
self.can_see_sky(pos)
&& self
.get_biome(pos)
.weather
.is_rain_at(pos.0.x, pos.0.y, pos.0.z, self.sea_level)
}
pub async fn set_raining(&self, raining: bool) {
let mut weather = self.weather.lock().await;
if weather.raining != raining {
@@ -4439,6 +4455,13 @@ impl World {
.get_sky_light_level(&self.level, position)
}
#[must_use]
pub fn can_see_sky(&self, position: &BlockPos) -> bool {
position.0.y >= self.dimension.min_y
&& position.0.y < self.dimension.min_y + self.dimension.height
&& self.get_sky_light_level(position) >= MAX_LIGHT_LEVEL
}
pub fn set_block_light_level(&self, position: &BlockPos, light_level: u8) {
let _ = self
.level