feat: implement all missing entities

This commit is contained in:
Alexander Medvedev 2026-04-28 21:29:27 +02:00
parent a36240dd40
commit 6f2c3cd5e3
76 changed files with 3838 additions and 131 deletions

View File

@ -113,38 +113,43 @@ impl ChunkData {
position.x, position.y, chunk_data.x_pos, chunk_data.z_pos,
)));
}
let section_count = chunk_data.sections.len();
let mut block_lights = Vec::with_capacity(section_count);
let mut sky_lights = Vec::with_capacity(section_count);
let mut block_palettes = Vec::with_capacity(section_count);
let mut biome_palettes = Vec::with_capacity(section_count);
let min_y_section = chunk_data.min_y_section;
let max_y_section = chunk_data
.sections
.iter()
.map(|s| s.y)
.max()
.unwrap_or(min_y_section as i8);
let section_count = (max_y_section as i32 - min_y_section + 1).max(0) as usize;
let mut block_lights = vec![LightContainer::Empty(0); section_count];
let mut sky_lights = vec![LightContainer::Empty(0); section_count];
let mut block_palettes = vec![BlockPalette::default(); section_count];
let mut biome_palettes = vec![BiomePalette::default(); section_count];
for section in chunk_data.sections {
let index = (section.y as i32 - min_y_section) as usize;
if index >= section_count {
continue;
}
// When loading light data, missing data should default to 0 (no light)
block_lights.push(
section
block_lights[index] = section
.block_light
.map_or(LightContainer::Empty(0), LightContainer::Full),
);
sky_lights.push(
section
.map_or(LightContainer::Empty(0), LightContainer::Full);
sky_lights[index] = section
.sky_light
.map_or(LightContainer::Empty(0), LightContainer::Full),
);
.map_or(LightContainer::Empty(0), LightContainer::Full);
// Convert NBT to Palettes
block_palettes.push(
section
block_palettes[index] = section
.block_states
.map(BlockPalette::from_disk_nbt)
.unwrap_or_default(),
);
biome_palettes.push(
section
.unwrap_or_default();
biome_palettes[index] = section
.biomes
.map(BiomePalette::from_disk_nbt)
.unwrap_or_default(),
);
.unwrap_or_default();
}
// Assemble the LightEngine

View File

@ -6,7 +6,8 @@ use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
@ -28,12 +29,16 @@ impl BlazeEntity {
let mut goal_selector = mob_arc.entity.goals_selector.lock().await;
let mut target_selector = mob_arc.entity.target_selector.lock().await;
// TODO
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
// TODO: BlazeShootFireballGoal
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, false)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
8,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.entity, &EntityType::PLAYER, true),

View File

@ -0,0 +1,56 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct BreezeEntity {
pub mob_entity: MobEntity,
}
impl BreezeEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let breeze = Self { mob_entity };
let mob_arc = Arc::new(breeze);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for BreezeEntity {}
impl Mob for BreezeEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,26 @@
use std::sync::Arc;
use crate::entity::{
Entity, NBTStorage,
mob::{Mob, MobEntity, spider::SpiderEntity},
};
pub struct CaveSpiderEntity {
pub spider: Arc<SpiderEntity>,
}
impl CaveSpiderEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let spider = SpiderEntity::new(entity).await;
Arc::new(Self { spider })
}
}
impl NBTStorage for CaveSpiderEntity {}
impl Mob for CaveSpiderEntity {
fn get_mob_entity(&self) -> &MobEntity {
self.spider.get_mob_entity()
}
// TODO: Poison effect on attack
}

View File

@ -0,0 +1,58 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct CreakingEntity {
pub mob_entity: MobEntity,
}
impl CreakingEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let creaking = Self { mob_entity };
let mob_arc = Arc::new(creaking);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for CreakingEntity {}
impl Mob for CreakingEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,56 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct ElderGuardianEntity {
pub mob_entity: MobEntity,
}
impl ElderGuardianEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let guardian = Self { mob_entity };
let mob_arc = Arc::new(guardian);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
5,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for ElderGuardianEntity {}
impl Mob for ElderGuardianEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,58 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct EndermiteEntity {
pub mob_entity: MobEntity,
}
impl EndermiteEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let endermite = Self { mob_entity };
let mob_arc = Arc::new(endermite);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for EndermiteEntity {}
impl Mob for EndermiteEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,65 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct EvokerEntity {
pub mob_entity: MobEntity,
}
impl EvokerEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let evoker = Self { mob_entity };
let mob_arc = Arc::new(evoker);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
// Evokers have complex spell AI, but for now basic movement
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::VILLAGER, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::IRON_GOLEM, true),
);
};
mob_arc
}
}
impl NBTStorage for EvokerEntity {}
impl Mob for EvokerEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal},
mob::{Mob, MobEntity},
};
pub struct GhastEntity {
pub mob_entity: MobEntity,
}
impl GhastEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let ghast = Self { mob_entity };
let mob_arc = Arc::new(ghast);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
// TODO: GhastFlyGoal, GhastLookGoal, GhastAttackGoal
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for GhastEntity {}
impl Mob for GhastEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
fn get_mob_gravity(&self) -> f64 {
0.0
}
}

View File

@ -0,0 +1,49 @@
use std::sync::Arc;
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
melee_attack::MeleeAttackGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct GiantEntity {
pub mob_entity: MobEntity,
}
impl GiantEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let giant = Self { mob_entity };
let mob_arc = Arc::new(giant);
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for GiantEntity {}
impl Mob for GiantEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,68 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct GuardianEntity {
pub mob_entity: MobEntity,
}
impl GuardianEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let guardian = Self { mob_entity };
let mob_arc = Arc::new(guardian);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
5,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::SQUID, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::GLOW_SQUID, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::AXOLOTL, true),
);
};
mob_arc
}
}
impl NBTStorage for GuardianEntity {}
impl Mob for GuardianEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,58 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct HoglinEntity {
pub mob_entity: MobEntity,
}
impl HoglinEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let hoglin = Self { mob_entity };
let mob_arc = Arc::new(hoglin);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for HoglinEntity {}
impl Mob for HoglinEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,64 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct IllusionerEntity {
pub mob_entity: MobEntity,
}
impl IllusionerEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let illusioner = Self { mob_entity };
let mob_arc = Arc::new(illusioner);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::VILLAGER, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::IRON_GOLEM, true),
);
};
mob_arc
}
}
impl NBTStorage for IllusionerEntity {}
impl Mob for IllusionerEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,25 @@
use std::sync::Arc;
use crate::entity::{
Entity, NBTStorage,
mob::{Mob, MobEntity, slime::SlimeEntity},
};
pub struct MagmaCubeEntity {
pub slime: Arc<SlimeEntity>,
}
impl MagmaCubeEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let slime = SlimeEntity::new(entity).await;
Arc::new(Self { slime })
}
}
impl NBTStorage for MagmaCubeEntity {}
impl Mob for MagmaCubeEntity {
fn get_mob_entity(&self) -> &MobEntity {
self.slime.get_mob_entity()
}
}

View File

@ -27,13 +27,37 @@ use uuid::Uuid;
pub mod bat;
pub mod blaze;
pub mod breeze;
pub mod cave_spider;
pub mod creaking;
pub mod creeper;
pub mod elder_guardian;
pub mod enderman;
pub mod endermite;
pub mod evoker;
pub mod ghast;
pub mod giant;
pub mod guardian;
pub mod hoglin;
pub mod illusioner;
pub mod magma_cube;
pub mod phantom;
pub mod piglin;
pub mod piglin_brute;
pub mod pillager;
pub mod ravager;
pub mod shulker;
pub mod silverfish;
pub mod skeleton;
pub mod slime;
pub mod spider;
pub mod vex;
pub mod vindicator;
pub mod warden;
pub mod witch;
pub mod zoglin;
pub mod zombie;
pub mod zombified_piglin;
pub struct MobEntity {
pub living_entity: LivingEntity,
@ -78,6 +102,7 @@ impl MobEntity {
last_sent_head_yaw: AtomicU8::new(0),
}
}
pub fn is_in_position_target_range(&self) -> bool {
self.is_in_position_target_range_pos(&self.living_entity.entity.block_pos.load())
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal},
mob::{Mob, MobEntity},
};
pub struct PhantomEntity {
pub mob_entity: MobEntity,
}
impl PhantomEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let phantom = Self { mob_entity };
let mob_arc = Arc::new(phantom);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
// TODO: PhantomCircleAroundAnchorGoal, PhantomSweepAttackGoal
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for PhantomEntity {}
impl Mob for PhantomEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
fn get_mob_gravity(&self) -> f64 {
0.0
}
}

View File

@ -0,0 +1,71 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct PiglinEntity {
pub mob_entity: MobEntity,
}
impl PiglinEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let piglin = Self { mob_entity };
let mob_arc = Arc::new(piglin);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
// Piglins use crossbows or swords, but for now we give them melee
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(
&mob_arc.mob_entity,
&EntityType::WITHER_SKELETON,
true,
),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::WITHER, true),
);
};
mob_arc
}
}
impl NBTStorage for PiglinEntity {}
impl Mob for PiglinEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,70 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct PiglinBruteEntity {
pub mob_entity: MobEntity,
}
impl PiglinBruteEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let piglin = Self { mob_entity };
let mob_arc = Arc::new(piglin);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(
&mob_arc.mob_entity,
&EntityType::WITHER_SKELETON,
true,
),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::WITHER, true),
);
};
mob_arc
}
}
impl NBTStorage for PiglinBruteEntity {}
impl Mob for PiglinBruteEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,67 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct PillagerEntity {
pub mob_entity: MobEntity,
}
impl PillagerEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let pillager = Self { mob_entity };
let mob_arc = Arc::new(pillager);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
// Pillagers use crossbows, but for now we give them melee
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::VILLAGER, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::IRON_GOLEM, true),
);
};
mob_arc
}
}
impl NBTStorage for PillagerEntity {}
impl Mob for PillagerEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,66 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct RavagerEntity {
pub mob_entity: MobEntity,
}
impl RavagerEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let ravager = Self { mob_entity };
let mob_arc = Arc::new(ravager);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::VILLAGER, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::IRON_GOLEM, true),
);
};
mob_arc
}
}
impl NBTStorage for RavagerEntity {}
impl Mob for RavagerEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -1,10 +1,14 @@
use std::sync::Arc;
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::active_target::ActiveTargetGoal,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
@ -15,13 +19,26 @@ pub struct SilverfishEntity {
impl SilverfishEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let entity = Arc::new(MobEntity::new(entity));
let zombie = Self { entity };
let mob_arc = Arc::new(zombie);
let silverfish = Self { entity };
let mob_arc = Arc::new(silverfish);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.entity.goals_selector.lock().await;
let mut target_selector = mob_arc.entity.target_selector.lock().await;
// TODO
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, false)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
8,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.entity, &EntityType::PLAYER, true),

View File

@ -6,7 +6,8 @@ use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, revenge::RevengeGoal,
swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
@ -35,12 +36,16 @@ impl SkeletonEntityBase {
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.2, false)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
8,
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(1, Box::new(RevengeGoal::new(true)));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),

View File

@ -1,10 +1,15 @@
use std::sync::Arc;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use pumpkin_data::sound::Sound;
use crate::entity::{
Entity, NBTStorage, NbtFuture,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
@ -13,10 +18,36 @@ pub struct SlimeEntity {
}
impl SlimeEntity {
pub fn new(entity: Entity) -> Arc<Self> {
Arc::new(Self {
entity: Arc::new(MobEntity::new(entity)),
})
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let slime = Self {
entity: Arc::new(mob_entity),
};
let mob_arc = Arc::new(slime);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.entity.goals_selector.lock().await;
let mut target_selector = mob_arc.entity.target_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
pub(crate) const fn hurt_sound_for_size(size: i32) -> Sound {

View File

@ -0,0 +1,64 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, revenge::RevengeGoal,
swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct SpiderEntity {
pub mob_entity: MobEntity,
}
impl SpiderEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let spider = Self { mob_entity };
let mob_arc = Arc::new(spider);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
goal_selector.add_goal(1, Box::new(SwimGoal::default()));
// TODO: SpiderAttackGoal for jumping
goal_selector.add_goal(3, Box::new(MeleeAttackGoal::new(1.0, false)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(0.8)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(1, Box::new(RevengeGoal::new(true)));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::IRON_GOLEM, true),
);
};
mob_arc
}
}
impl NBTStorage for SpiderEntity {}
impl Mob for SpiderEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,58 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct VexEntity {
pub mob_entity: MobEntity,
}
impl VexEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let vex = Self { mob_entity };
let mob_arc = Arc::new(vex);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for VexEntity {}
impl Mob for VexEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,66 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct VindicatorEntity {
pub mob_entity: MobEntity,
}
impl VindicatorEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let vindicator = Self { mob_entity };
let mob_arc = Arc::new(vindicator);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::VILLAGER, true),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::IRON_GOLEM, true),
);
};
mob_arc
}
}
impl NBTStorage for VindicatorEntity {}
impl Mob for VindicatorEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,58 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct WardenEntity {
pub mob_entity: MobEntity,
}
impl WardenEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let warden = Self { mob_entity };
let mob_arc = Arc::new(warden);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(0.5)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for WardenEntity {}
impl Mob for WardenEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,59 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, revenge::RevengeGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct WitchEntity {
pub mob_entity: MobEntity,
}
impl WitchEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let witch = Self { mob_entity };
let mob_arc = Arc::new(witch);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
goal_selector.add_goal(1, Box::new(SwimGoal::default()));
// TODO: WitchAttackGoal (potions)
goal_selector.add_goal(2, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
3,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(1, Box::new(RevengeGoal::new(true)));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for WitchEntity {}
impl Mob for WitchEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,58 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct ZoglinEntity {
pub mob_entity: MobEntity,
}
impl ZoglinEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let zoglin = Self { mob_entity };
let mob_arc = Arc::new(zoglin);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(4, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),
);
};
mob_arc
}
}
impl NBTStorage for ZoglinEntity {}
impl Mob for ZoglinEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -1,11 +1,8 @@
use std::sync::Arc;
use pumpkin_data::entity::EntityType;
use crate::entity::mob::zombie::ZombieEntityBase;
use crate::entity::{
Entity, NBTStorage,
ai::goal::active_target::ActiveTargetGoal,
mob::{Mob, MobEntity},
};
@ -17,23 +14,7 @@ impl HuskEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let entity = ZombieEntityBase::new(entity).await;
let zombie = Self { entity };
let mob_arc = Arc::new(zombie);
{
let mut target_selector = mob_arc.entity.mob_entity.target_selector.lock().await;
// TODO
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(
&mob_arc.entity.mob_entity,
&EntityType::PLAYER,
true,
),
);
};
mob_arc
Arc::new(zombie)
}
}

View File

@ -1,6 +1,9 @@
use super::{Mob, MobEntity};
use crate::entity::ai::goal::destroy_egg::DestroyEggGoal;
use crate::entity::ai::goal::look_around::RandomLookAroundGoal;
use crate::entity::ai::goal::revenge::RevengeGoal;
use crate::entity::ai::goal::swim::SwimGoal;
use crate::entity::ai::goal::wander_around::WanderAroundGoal;
use crate::entity::ai::goal::zombie_attack::ZombieAttackGoal;
use crate::entity::{
Entity, NBTStorage,
@ -33,14 +36,17 @@ impl ZombieEntityBase {
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, ZombieAttackGoal::new(1.0, false));
goal_selector.add_goal(4, DestroyEggGoal::new(1.0, 3));
goal_selector.add_goal(7, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
8,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
goal_selector.add_goal(3, ZombieAttackGoal::new(1.0, false));
target_selector.add_goal(1, Box::new(RevengeGoal::new(true)));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, true),

View File

@ -0,0 +1,57 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal,
melee_attack::MeleeAttackGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct ZombifiedPiglinEntity {
pub mob_entity: MobEntity,
}
impl ZombifiedPiglinEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let piglin = Self { mob_entity };
let mob_arc = Arc::new(piglin);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
let _target_selector = mob_arc.mob_entity.target_selector.lock().await;
// Zombified piglins are neutral by default (only attack if hit),
// but for now we give it ActiveTargetGoal for players to make them hostile
// (or we can leave it empty for neutral behavior).
// Let's make them neutral for now (no ActiveTargetGoal).
};
mob_arc
}
}
impl NBTStorage for ZombifiedPiglinEntity {}
impl Mob for ZombifiedPiglinEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents an Allay, a passive, flying entity that can collect items for the player.
///
/// Wiki: <https://minecraft.wiki/w/Allay>
pub struct AllayEntity {
pub mob_entity: MobEntity,
}
impl AllayEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let allay = Self { mob_entity };
let mob_arc = Arc::new(allay);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for AllayEntity {}
impl Mob for AllayEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents an Armadillo, a passive entity that can roll into a ball when threatened.
///
/// Wiki: <https://minecraft.wiki/w/Armadillo>
pub struct ArmadilloEntity {
pub mob_entity: MobEntity,
}
impl ArmadilloEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let armadillo = Self { mob_entity };
let mob_arc = Arc::new(armadillo);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for ArmadilloEntity {}
impl Mob for ArmadilloEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents an Axolotl, a passive aquatic mob that can play dead to regenerate health.
///
/// Wiki: <https://minecraft.wiki/w/Axolotl>
pub struct AxolotlEntity {
pub mob_entity: MobEntity,
}
impl AxolotlEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let axolotl = Self { mob_entity };
let mob_arc = Arc::new(axolotl);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for AxolotlEntity {}
impl Mob for AxolotlEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Bee, a neutral flying mob that can pollinate crops and sting attackers.
///
/// Wiki: <https://minecraft.wiki/w/Bee>
pub struct BeeEntity {
pub mob_entity: MobEntity,
}
impl BeeEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let bee = Self { mob_entity };
let mob_arc = Arc::new(bee);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for BeeEntity {}
impl Mob for BeeEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Camel, a passive mount that can carry two players and dash.
///
/// Wiki: <https://minecraft.wiki/w/Camel>
pub struct CamelEntity {
pub mob_entity: MobEntity,
}
impl CamelEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let camel = Self { mob_entity };
let mob_arc = Arc::new(camel);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for CamelEntity {}
impl Mob for CamelEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -5,7 +5,8 @@ use pumpkin_data::{entity::EntityType, item::Item};
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
escape_danger::EscapeDangerGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
breed::BreedGoal, escape_danger::EscapeDangerGoal, follow_parent::FollowParentGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
@ -13,6 +14,9 @@ use crate::entity::{
const TEMPT_ITEMS: &[&Item] = &[&Item::COD, &Item::SALMON];
/// Represents a Cat, a passive mob that can be tamed and scares away creepers.
///
/// Wiki: <https://minecraft.wiki/w/Cat>
pub struct CatEntity {
pub mob_entity: MobEntity,
}
@ -32,12 +36,17 @@ impl CatEntity {
goal_selector.add_goal(1, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(1.5));
// goal_selector.add_goal(2, SitGoal::new(mob_arc.clone()));
goal_selector.add_goal(4, Box::new(TemptGoal::new(0.6, TEMPT_ITEMS)));
goal_selector.add_goal(5, BreedGoal::new(0.8));
// goal_selector.add_goal(7, FollowOwnerGoal::new(1.0, 10.0, 5.0, false));
goal_selector.add_goal(9, Box::new(FollowParentGoal::new(0.8)));
goal_selector.add_goal(11, Box::new(WanderAroundGoal::new(0.8)));
goal_selector.add_goal(
12,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 10.0),
);
goal_selector.add_goal(12, Box::new(RandomLookAroundGoal::default()));
};
mob_arc

View File

@ -4,17 +4,21 @@ use std::sync::{
};
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::{entity::EntityType, item::Item};
use pumpkin_util::math::vector3::Vector3;
use rand::RngExt;
use crate::entity::{
Entity, EntityBase, EntityBaseFuture, NBTStorage,
ai::goal::{
escape_danger::EscapeDangerGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, tempt::TemptGoal,
wander_around::WanderAroundGoal,
breed::BreedGoal, escape_danger::EscapeDangerGoal, follow_parent::FollowParentGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
player::Player,
};
const TEMPT_ITEMS: &[&Item] = &[
@ -26,6 +30,9 @@ const TEMPT_ITEMS: &[&Item] = &[
&Item::PITCHER_POD,
];
/// Represents a Chicken, a passive mob that lays eggs and is immune to fall damage.
///
/// Wiki: <https://minecraft.wiki/w/Chicken>
pub struct ChickenEntity {
pub mob_entity: MobEntity,
egg_lay_time: AtomicI32,
@ -50,7 +57,9 @@ impl ChickenEntity {
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(1.4));
goal_selector.add_goal(2, BreedGoal::new(1.0));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.0, TEMPT_ITEMS)));
goal_selector.add_goal(4, Box::new(FollowParentGoal::new(1.1)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
@ -85,4 +94,41 @@ impl Mob for ChickenEntity {
}
})
}
fn mob_interact<'a>(
&'a self,
player: &'a Player,
item_stack: &'a mut ItemStack,
) -> EntityBaseFuture<'a, bool> {
Box::pin(async move {
let is_food = TEMPT_ITEMS.iter().any(|i| i.id == item_stack.item.id);
if is_food && self.is_breeding_ready() && !self.is_in_love() {
item_stack.decrement_unless_creative(player.gamemode.load(), 1);
self.mob_entity.set_love_ticks(600);
let entity = &self.mob_entity.living_entity.entity;
let world = entity.world.load();
let pos = entity.pos.load();
world
.spawn_particle(
pos + Vector3::new(0.0, f64::from(entity.height()), 0.0),
Vector3::new(0.5, 0.5, 0.5),
1.0,
7,
Particle::Heart,
)
.await;
world
.play_sound(
Sound::EntityChickenAmbient,
SoundCategory::Neutral,
&entity.pos.load(),
)
.await;
return true;
}
false
})
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Cod, a common passive aquatic mob.
///
/// Wiki: <https://minecraft.wiki/w/Cod>
pub struct CodEntity {
pub mob_entity: MobEntity,
}
impl CodEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let cod = Self { mob_entity };
let mob_arc = Arc::new(cod);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for CodEntity {}
impl Mob for CodEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -1,19 +1,27 @@
use std::sync::{Arc, Weak};
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::{entity::EntityType, item::Item};
use pumpkin_util::math::vector3::Vector3;
use crate::entity::{
Entity, NBTStorage,
Entity, EntityBase, EntityBaseFuture, NBTStorage,
ai::goal::{
escape_danger::EscapeDangerGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, tempt::TemptGoal,
wander_around::WanderAroundGoal,
breed::BreedGoal, escape_danger::EscapeDangerGoal, follow_parent::FollowParentGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
player::Player,
};
const TEMPT_ITEMS: &[&Item] = &[&Item::WHEAT];
/// Represents a Cow, a common passive mob that provides milk, leather, and beef.
///
/// Wiki: <https://minecraft.wiki/w/Cow>
pub struct CowEntity {
pub mob_entity: MobEntity,
}
@ -33,7 +41,9 @@ impl CowEntity {
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(2.0));
goal_selector.add_goal(2, BreedGoal::new(1.0));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.25, TEMPT_ITEMS)));
goal_selector.add_goal(4, Box::new(FollowParentGoal::new(1.25)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
@ -52,4 +62,41 @@ impl Mob for CowEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
fn mob_interact<'a>(
&'a self,
player: &'a Player,
item_stack: &'a mut ItemStack,
) -> EntityBaseFuture<'a, bool> {
Box::pin(async move {
let is_food = TEMPT_ITEMS.iter().any(|i| i.id == item_stack.item.id);
if is_food && self.is_breeding_ready() && !self.is_in_love() {
item_stack.decrement_unless_creative(player.gamemode.load(), 1);
self.mob_entity.set_love_ticks(600);
let entity = &self.mob_entity.living_entity.entity;
let world = entity.world.load();
let pos = entity.pos.load();
world
.spawn_particle(
pos + Vector3::new(0.0, f64::from(entity.height()), 0.0),
Vector3::new(0.5, 0.5, 0.5),
1.0,
7,
Particle::Heart,
)
.await;
world
.play_sound(
Sound::EntityCowAmbient,
SoundCategory::Neutral,
&entity.pos.load(),
)
.await;
return true;
}
false
})
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Dolphin, a neutral aquatic mob that can give players the Dolphin's Grace effect.
///
/// Wiki: <https://minecraft.wiki/w/Dolphin>
pub struct DolphinEntity {
pub mob_entity: MobEntity,
}
impl DolphinEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let dolphin = Self { mob_entity };
let mob_arc = Arc::new(dolphin);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for DolphinEntity {}
impl Mob for DolphinEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Donkey, a passive mob that can be tamed and equipped with chests.
///
/// Wiki: <https://minecraft.wiki/w/Donkey>
pub struct DonkeyEntity {
pub mob_entity: MobEntity,
}
impl DonkeyEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let donkey = Self { mob_entity };
let mob_arc = Arc::new(donkey);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for DonkeyEntity {}
impl Mob for DonkeyEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,60 @@
use std::sync::{Arc, Weak};
use pumpkin_data::{entity::EntityType, item::Item};
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
breed::BreedGoal, escape_danger::EscapeDangerGoal, follow_parent::FollowParentGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
const TEMPT_ITEMS: &[&Item] = &[&Item::SWEET_BERRIES, &Item::GLOW_BERRIES];
/// Represents a Fox, a passive nocturnal mob.
///
/// Wiki: <https://minecraft.wiki/w/Fox>
pub struct FoxEntity {
pub mob_entity: MobEntity,
}
impl FoxEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let fox = Self { mob_entity };
let mob_arc = Arc::new(fox);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(1.5));
goal_selector.add_goal(2, BreedGoal::new(1.0));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.2, TEMPT_ITEMS)));
goal_selector.add_goal(4, Box::new(FollowParentGoal::new(1.1)));
goal_selector.add_goal(6, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
7,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for FoxEntity {}
impl Mob for FoxEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Frog, a passive mob that can eat small slimes and magma cubes.
///
/// Wiki: <https://minecraft.wiki/w/Frog>
pub struct FrogEntity {
pub mob_entity: MobEntity,
}
impl FrogEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let frog = Self { mob_entity };
let mob_arc = Arc::new(frog);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for FrogEntity {}
impl Mob for FrogEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Glow Squid, a passive aquatic mob that emits a glowing particle effect.
///
/// Wiki: <https://minecraft.wiki/w/Glow_Squid>
pub struct GlowSquidEntity {
pub mob_entity: MobEntity,
}
impl GlowSquidEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let glow_squid = Self { mob_entity };
let mob_arc = Arc::new(glow_squid);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for GlowSquidEntity {}
impl Mob for GlowSquidEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Goat, a neutral mob that can jump high and ram players or other mobs.
///
/// Wiki: <https://minecraft.wiki/w/Goat>
pub struct GoatEntity {
pub mob_entity: MobEntity,
}
impl GoatEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let goat = Self { mob_entity };
let mob_arc = Arc::new(goat);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for GoatEntity {}
impl Mob for GoatEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Horse, a passive mob that can be tamed and ridden.
///
/// Wiki: <https://minecraft.wiki/w/Horse>
pub struct HorseEntity {
pub mob_entity: MobEntity,
}
impl HorseEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let horse = Self { mob_entity };
let mob_arc = Arc::new(horse);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for HorseEntity {}
impl Mob for HorseEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -4,10 +4,17 @@ use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal},
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, melee_attack::MeleeAttackGoal, revenge::RevengeGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents an Iron Golem, a powerful neutral mob that protects villagers and players.
///
/// Wiki: <https://minecraft.wiki/w/Iron_Golem>
pub struct IronGolemEntity {
pub mob_entity: MobEntity,
}
@ -24,13 +31,25 @@ impl IronGolemEntity {
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
// TODO
goal_selector.add_goal(1, Box::new(MeleeAttackGoal::new(1.0, true)));
goal_selector.add_goal(6, Box::new(WanderAroundGoal::new(0.6)));
goal_selector.add_goal(
8,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
7,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(1, Box::new(RevengeGoal::new(true)));
target_selector.add_goal(
2,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::PLAYER, false),
);
target_selector.add_goal(
3,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::ZOMBIE, true),
);
};
mob_arc

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Llama, a neutral mob that can be used for carrying items and spits at enemies.
///
/// Wiki: <https://minecraft.wiki/w/Llama>
pub struct LlamaEntity {
pub mob_entity: MobEntity,
}
impl LlamaEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let llama = Self { mob_entity };
let mob_arc = Arc::new(llama);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for LlamaEntity {}
impl Mob for LlamaEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -1,8 +1,42 @@
pub mod allay;
pub mod armadillo;
pub mod axolotl;
pub mod bee;
pub mod camel;
pub mod cat;
pub mod chicken;
pub mod cod;
pub mod cow;
pub mod dolphin;
pub mod donkey;
pub mod fox;
pub mod frog;
pub mod glow_squid;
pub mod goat;
pub mod horse;
pub mod iron_golem;
pub mod llama;
pub mod mooshroom;
pub mod mule;
pub mod ocelot;
pub mod panda;
pub mod parrot;
pub mod pig;
pub mod polar_bear;
pub mod pufferfish;
pub mod rabbit;
pub mod salmon;
pub mod sheep;
pub mod skeleton_horse;
pub mod sniffer;
pub mod snow_golem;
pub mod squid;
pub mod strider;
pub mod tadpole;
pub mod trader_llama;
pub mod tropical_fish;
pub mod turtle;
pub mod villager;
pub mod wandering_trader;
pub mod wolf;
pub mod zombie_horse;

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Mooshroom, a fungal variant of cows that can be milked for mushroom stew.
///
/// Wiki: <https://minecraft.wiki/w/Mooshroom>
pub struct MooshroomEntity {
pub mob_entity: MobEntity,
}
impl MooshroomEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let mooshroom = Self { mob_entity };
let mob_arc = Arc::new(mooshroom);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for MooshroomEntity {}
impl Mob for MooshroomEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Mule, a passive mob created by breeding a horse and a donkey.
///
/// Wiki: <https://minecraft.wiki/w/Mule>
pub struct MuleEntity {
pub mob_entity: MobEntity,
}
impl MuleEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let mule = Self { mob_entity };
let mob_arc = Arc::new(mule);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for MuleEntity {}
impl Mob for MuleEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents an Ocelot, a shy passive mob found in jungles.
///
/// Wiki: <https://minecraft.wiki/w/Ocelot>
pub struct OcelotEntity {
pub mob_entity: MobEntity,
}
impl OcelotEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let ocelot = Self { mob_entity };
let mob_arc = Arc::new(ocelot);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for OcelotEntity {}
impl Mob for OcelotEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Panda, a rare passive mob with various personalities.
///
/// Wiki: <https://minecraft.wiki/w/Panda>
pub struct PandaEntity {
pub mob_entity: MobEntity,
}
impl PandaEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let panda = Self { mob_entity };
let mob_arc = Arc::new(panda);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for PandaEntity {}
impl Mob for PandaEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Parrot, a passive flying mob that can mimic nearby mob sounds.
///
/// Wiki: <https://minecraft.wiki/w/Parrot>
pub struct ParrotEntity {
pub mob_entity: MobEntity,
}
impl ParrotEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let parrot = Self { mob_entity };
let mob_arc = Arc::new(parrot);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for ParrotEntity {}
impl Mob for ParrotEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -1,16 +1,20 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_data::{entity::EntityType, item::Item};
use pumpkin_util::math::vector3::Vector3;
use crate::entity::{
Entity, NBTStorage,
Entity, EntityBase, EntityBaseFuture, NBTStorage,
ai::goal::{
escape_danger::EscapeDangerGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, tempt::TemptGoal,
wander_around::WanderAroundGoal,
breed::BreedGoal, escape_danger::EscapeDangerGoal, follow_parent::FollowParentGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
player::Player,
};
const PIG_FOOD: &[&Item] = &[
@ -20,6 +24,9 @@ const PIG_FOOD: &[&Item] = &[
&Item::CARROT_ON_A_STICK,
];
/// Represents a Pig, a common passive mob that provides porkchops.
///
/// Wiki: <https://minecraft.wiki/w/Pig>
pub struct PigEntity {
pub mob_entity: MobEntity,
}
@ -39,13 +46,15 @@ impl PigEntity {
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(1.25));
goal_selector.add_goal(4, Box::new(TemptGoal::new(1.2, PIG_FOOD)));
goal_selector.add_goal(6, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(2, BreedGoal::new(1.0));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.2, PIG_FOOD)));
goal_selector.add_goal(4, Box::new(FollowParentGoal::new(1.1)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
7,
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
@ -58,4 +67,41 @@ impl Mob for PigEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
fn mob_interact<'a>(
&'a self,
player: &'a Player,
item_stack: &'a mut ItemStack,
) -> EntityBaseFuture<'a, bool> {
Box::pin(async move {
let is_food = PIG_FOOD.iter().any(|i| i.id == item_stack.item.id);
if is_food && self.is_breeding_ready() && !self.is_in_love() {
item_stack.decrement_unless_creative(player.gamemode.load(), 1);
self.mob_entity.set_love_ticks(600);
let entity = &self.mob_entity.living_entity.entity;
let world = entity.world.load();
let pos = entity.pos.load();
world
.spawn_particle(
pos + Vector3::new(0.0, f64::from(entity.height()), 0.0),
Vector3::new(0.5, 0.5, 0.5),
1.0,
7,
Particle::Heart,
)
.await;
world
.play_sound(
Sound::EntityPigAmbient,
SoundCategory::Neutral,
&entity.pos.load(),
)
.await;
return true;
}
false
})
}
}

View File

@ -0,0 +1,60 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Polar Bear, a neutral mob found in cold biomes.
///
/// Wiki: <https://minecraft.wiki/w/Polar_Bear>
pub struct PolarBearEntity {
pub mob_entity: MobEntity,
}
impl PolarBearEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let polar_bear = Self { mob_entity };
let mob_arc = Arc::new(polar_bear);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
// Polar bears are neutral but aggressive towards foxes
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::FOX, true),
);
};
mob_arc
}
}
impl NBTStorage for PolarBearEntity {}
impl Mob for PolarBearEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,53 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
/// Represents a Pufferfish, a passive aquatic mob that can inflate when threatened.
///
/// Wiki: <https://minecraft.wiki/w/Pufferfish>
pub struct PufferfishEntity {
pub mob_entity: MobEntity,
}
impl PufferfishEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let pufferfish = Self { mob_entity };
let mob_arc = Arc::new(pufferfish);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for PufferfishEntity {}
impl Mob for PufferfishEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,57 @@
use std::sync::{Arc, Weak};
use pumpkin_data::{entity::EntityType, item::Item};
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
breed::BreedGoal, escape_danger::EscapeDangerGoal, follow_parent::FollowParentGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
const TEMPT_ITEMS: &[&Item] = &[&Item::CARROT, &Item::GOLDEN_CARROT, &Item::DANDELION];
pub struct RabbitEntity {
pub mob_entity: MobEntity,
}
impl RabbitEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let rabbit = Self { mob_entity };
let mob_arc = Arc::new(rabbit);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(1, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(2.2));
goal_selector.add_goal(2, BreedGoal::new(0.8));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.0, TEMPT_ITEMS)));
goal_selector.add_goal(4, Box::new(FollowParentGoal::new(0.8)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(0.6)));
goal_selector.add_goal(
11,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 10.0),
);
goal_selector.add_goal(11, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for RabbitEntity {}
impl Mob for RabbitEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct SalmonEntity {
pub mob_entity: MobEntity,
}
impl SalmonEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let salmon = Self { mob_entity };
let mob_arc = Arc::new(salmon);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for SalmonEntity {}
impl Mob for SalmonEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -9,15 +9,22 @@ use pumpkin_data::{
use pumpkin_protocol::java::client::play::Metadata;
use crate::entity::{
Entity, EntityBaseFuture, NBTStorage, NbtFuture,
Entity, EntityBase, EntityBaseFuture, NBTStorage, NbtFuture,
ai::goal::{
eat_grass::EatGrassGoal, escape_danger::EscapeDangerGoal,
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
tempt::TemptGoal, wander_around::WanderAroundGoal,
breed::BreedGoal, eat_grass::EatGrassGoal, escape_danger::EscapeDangerGoal,
follow_parent::FollowParentGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, tempt::TemptGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
player::Player,
};
use pumpkin_data::item_stack::ItemStack;
use pumpkin_data::particle::Particle;
use pumpkin_data::sound::{Sound, SoundCategory};
use pumpkin_util::math::vector3::Vector3;
const TEMPT_ITEMS: &[&Item] = &[&Item::WHEAT];
pub struct SheepEntity {
@ -43,7 +50,9 @@ impl SheepEntity {
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, EscapeDangerGoal::new(1.25));
goal_selector.add_goal(2, BreedGoal::new(1.0));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.1, TEMPT_ITEMS)));
goal_selector.add_goal(4, Box::new(FollowParentGoal::new(1.1)));
goal_selector.add_goal(5, Box::new(EatGrassGoal::default()));
goal_selector.add_goal(6, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
@ -132,4 +141,41 @@ impl Mob for SheepEntity {
self.set_sheared(false).await;
})
}
fn mob_interact<'a>(
&'a self,
player: &'a Player,
item_stack: &'a mut ItemStack,
) -> EntityBaseFuture<'a, bool> {
Box::pin(async move {
let is_food = TEMPT_ITEMS.iter().any(|i| i.id == item_stack.item.id);
if is_food && self.is_breeding_ready() && !self.is_in_love() {
item_stack.decrement_unless_creative(player.gamemode.load(), 1);
self.mob_entity.set_love_ticks(600);
let entity = &self.mob_entity.living_entity.entity;
let world = entity.world.load();
let pos = entity.pos.load();
world
.spawn_particle(
pos + Vector3::new(0.0, f64::from(entity.height()), 0.0),
Vector3::new(0.5, 0.5, 0.5),
1.0,
7,
Particle::Heart,
)
.await;
world
.play_sound(
Sound::EntitySheepAmbient,
SoundCategory::Neutral,
&entity.pos.load(),
)
.await;
return true;
}
false
})
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct SkeletonHorseEntity {
pub mob_entity: MobEntity,
}
impl SkeletonHorseEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let horse = Self { mob_entity };
let mob_arc = Arc::new(horse);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for SkeletonHorseEntity {}
impl Mob for SkeletonHorseEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct SnifferEntity {
pub mob_entity: MobEntity,
}
impl SnifferEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let sniffer = Self { mob_entity };
let mob_arc = Arc::new(sniffer);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for SnifferEntity {}
impl Mob for SnifferEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -4,7 +4,10 @@ use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal},
ai::goal::{
active_target::ActiveTargetGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
@ -15,8 +18,8 @@ pub struct SnowGolemEntity {
impl SnowGolemEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let wolf = Self { mob_entity };
let mob_arc = Arc::new(wolf);
let snow_golem = Self { mob_entity };
let mob_arc = Arc::new(snow_golem);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
@ -24,13 +27,20 @@ impl SnowGolemEntity {
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
let mut target_selector = mob_arc.mob_entity.target_selector.lock().await;
// TODO
// TODO: SnowballAttackGoal
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
8,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(6, Box::new(RandomLookAroundGoal::default()));
target_selector.add_goal(
1,
ActiveTargetGoal::with_default(&mob_arc.mob_entity, &EntityType::ZOMBIE, true),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
};
mob_arc

View File

@ -0,0 +1,52 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct SquidEntity {
pub mob_entity: MobEntity,
}
impl SquidEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let squid = Self { mob_entity };
let mob_arc = Arc::new(squid);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
// Squids don't have WanderAroundGoal in vanilla (they use custom movement),
// but for now we give it to them.
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.6)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for SquidEntity {}
impl Mob for SquidEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct StriderEntity {
pub mob_entity: MobEntity,
}
impl StriderEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let strider = Self { mob_entity };
let mob_arc = Arc::new(strider);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for StriderEntity {}
impl Mob for StriderEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct TadpoleEntity {
pub mob_entity: MobEntity,
}
impl TadpoleEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let tadpole = Self { mob_entity };
let mob_arc = Arc::new(tadpole);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for TadpoleEntity {}
impl Mob for TadpoleEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct TraderLlamaEntity {
pub mob_entity: MobEntity,
}
impl TraderLlamaEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let llama = Self { mob_entity };
let mob_arc = Arc::new(llama);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for TraderLlamaEntity {}
impl Mob for TraderLlamaEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct TropicalFishEntity {
pub mob_entity: MobEntity,
}
impl TropicalFishEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let tropical_fish = Self { mob_entity };
let mob_arc = Arc::new(tropical_fish);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for TropicalFishEntity {}
impl Mob for TropicalFishEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,54 @@
use std::sync::{Arc, Weak};
use pumpkin_data::{entity::EntityType, item::Item};
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
breed::BreedGoal, look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal,
swim::SwimGoal, tempt::TemptGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
const TEMPT_ITEMS: &[&Item] = &[&Item::SEAGRASS];
pub struct TurtleEntity {
pub mob_entity: MobEntity,
}
impl TurtleEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let turtle = Self { mob_entity };
let mob_arc = Arc::new(turtle);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(1, Box::new(SwimGoal::default()));
goal_selector.add_goal(2, BreedGoal::new(1.0));
goal_selector.add_goal(3, Box::new(TemptGoal::new(1.1, TEMPT_ITEMS)));
goal_selector.add_goal(5, Box::new(WanderAroundGoal::new(1.0)));
goal_selector.add_goal(
6,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(7, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for TurtleEntity {}
impl Mob for TurtleEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,55 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct VillagerEntity {
pub mob_entity: MobEntity,
}
impl VillagerEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let villager = Self { mob_entity };
let mob_arc = Arc::new(villager);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
// Villagers have complex AI, but for now we give them basic movement
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.6)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak.clone(), &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(
3,
LookAtEntityGoal::with_default(mob_weak, &EntityType::VILLAGER, 8.0),
);
goal_selector.add_goal(4, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for VillagerEntity {}
impl Mob for VillagerEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct WanderingTraderEntity {
pub mob_entity: MobEntity,
}
impl WanderingTraderEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let trader = Self { mob_entity };
let mob_arc = Arc::new(trader);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.6)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for WanderingTraderEntity {}
impl Mob for WanderingTraderEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -5,7 +5,11 @@ use pumpkin_data::item::Item;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{beg::BegGoal, look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal},
ai::goal::{
beg::BegGoal, breed::BreedGoal, escape_danger::EscapeDangerGoal,
follow_parent::FollowParentGoal, look_around::RandomLookAroundGoal,
look_at_entity::LookAtEntityGoal, swim::SwimGoal, wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
@ -26,12 +30,19 @@ impl WolfEntity {
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(1, Box::new(SwimGoal::default()));
// goal_selector.add_goal(2, SitGoal::new(mob_arc.clone()));
goal_selector.add_goal(4, EscapeDangerGoal::new(1.5));
goal_selector.add_goal(5, BreedGoal::new(1.0));
// goal_selector.add_goal(6, FollowOwnerGoal::new(1.0, 10.0, 2.0, false));
goal_selector.add_goal(8, Box::new(FollowParentGoal::new(1.1)));
goal_selector.add_goal(9, BegGoal::new(8.0, &[&Item::BONE]));
goal_selector.add_goal(
8,
10,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 8.0),
);
goal_selector.add_goal(8, Box::new(RandomLookAroundGoal::default()));
goal_selector.add_goal(9, BegGoal::new(8.0, &[&Item::BONE]));
goal_selector.add_goal(10, Box::new(RandomLookAroundGoal::default()));
goal_selector.add_goal(12, Box::new(WanderAroundGoal::new(1.0)));
};
mob_arc

View File

@ -0,0 +1,50 @@
use std::sync::{Arc, Weak};
use pumpkin_data::entity::EntityType;
use crate::entity::{
Entity, NBTStorage,
ai::goal::{
look_around::RandomLookAroundGoal, look_at_entity::LookAtEntityGoal, swim::SwimGoal,
wander_around::WanderAroundGoal,
},
mob::{Mob, MobEntity},
};
pub struct ZombieHorseEntity {
pub mob_entity: MobEntity,
}
impl ZombieHorseEntity {
pub async fn new(entity: Entity) -> Arc<Self> {
let mob_entity = MobEntity::new(entity);
let horse = Self { mob_entity };
let mob_arc = Arc::new(horse);
let mob_weak: Weak<dyn Mob> = {
let mob_arc: Arc<dyn Mob> = mob_arc.clone();
Arc::downgrade(&mob_arc)
};
{
let mut goal_selector = mob_arc.mob_entity.goals_selector.lock().await;
goal_selector.add_goal(0, Box::new(SwimGoal::default()));
goal_selector.add_goal(1, Box::new(WanderAroundGoal::new(0.7)));
goal_selector.add_goal(
2,
LookAtEntityGoal::with_default(mob_weak, &EntityType::PLAYER, 6.0),
);
goal_selector.add_goal(3, Box::new(RandomLookAroundGoal::default()));
};
mob_arc
}
}
impl NBTStorage for ZombieHorseEntity {}
impl Mob for ZombieHorseEntity {
fn get_mob_entity(&self) -> &MobEntity {
&self.mob_entity
}
}

View File

@ -5,41 +5,114 @@ use pumpkin_util::math::vector3::Vector3;
use uuid::Uuid;
use crate::entity::boss::ender_dragon::EnderDragonEntity;
use crate::entity::boss::wither::WitherEntity;
use crate::entity::decoration::{
armor_stand::ArmorStandEntity, end_crystal::EndCrystalEntity, painting::PaintingEntity,
};
use crate::entity::experience_orb::ExperienceOrbEntity;
use crate::entity::falling::FallingEntity;
use crate::entity::item::ItemEntity;
use crate::entity::living::LivingEntity;
use crate::entity::mob::bat::BatEntity;
use crate::entity::mob::blaze::BlazeEntity;
use crate::entity::mob::breeze::BreezeEntity;
use crate::entity::mob::cave_spider::CaveSpiderEntity;
use crate::entity::mob::creaking::CreakingEntity;
use crate::entity::mob::creeper::CreeperEntity;
use crate::entity::mob::elder_guardian::ElderGuardianEntity;
use crate::entity::mob::enderman::EndermanEntity;
use crate::entity::mob::endermite::EndermiteEntity;
use crate::entity::mob::evoker::EvokerEntity;
use crate::entity::mob::ghast::GhastEntity;
use crate::entity::mob::giant::GiantEntity;
use crate::entity::mob::guardian::GuardianEntity;
use crate::entity::mob::hoglin::HoglinEntity;
use crate::entity::mob::illusioner::IllusionerEntity;
use crate::entity::mob::magma_cube::MagmaCubeEntity;
use crate::entity::mob::phantom::PhantomEntity;
use crate::entity::mob::piglin::PiglinEntity;
use crate::entity::mob::piglin_brute::PiglinBruteEntity;
use crate::entity::mob::pillager::PillagerEntity;
use crate::entity::mob::ravager::RavagerEntity;
use crate::entity::mob::shulker::ShulkerEntity;
use crate::entity::mob::silverfish::SilverfishEntity;
use crate::entity::mob::skeleton::{
bogged::BoggedSkeletonEntity, parched::ParchedSkeletonEntity, skeleton::SkeletonEntity,
stray::StraySkeletonEntity, wither::WitherSkeletonEntity,
};
use crate::entity::mob::slime::SlimeEntity;
use crate::entity::mob::spider::SpiderEntity;
use crate::entity::mob::vex::VexEntity;
use crate::entity::mob::vindicator::VindicatorEntity;
use crate::entity::mob::warden::WardenEntity;
use crate::entity::mob::witch::WitchEntity;
use crate::entity::mob::zoglin::ZoglinEntity;
use crate::entity::mob::zombie::zombie_villager::ZombieVillagerEntity;
use crate::entity::mob::zombie::{drowned::DrownedEntity, husk::HuskEntity, zombie::ZombieEntity};
use crate::entity::mob::zombified_piglin::ZombifiedPiglinEntity;
use crate::entity::passive::allay::AllayEntity;
use crate::entity::passive::armadillo::ArmadilloEntity;
use crate::entity::passive::axolotl::AxolotlEntity;
use crate::entity::passive::bee::BeeEntity;
use crate::entity::passive::camel::CamelEntity;
use crate::entity::passive::cat::CatEntity;
use crate::entity::passive::chicken::ChickenEntity;
use crate::entity::passive::cod::CodEntity;
use crate::entity::passive::cow::CowEntity;
use crate::entity::passive::dolphin::DolphinEntity;
use crate::entity::passive::donkey::DonkeyEntity;
use crate::entity::passive::fox::FoxEntity;
use crate::entity::passive::frog::FrogEntity;
use crate::entity::passive::glow_squid::GlowSquidEntity;
use crate::entity::passive::goat::GoatEntity;
use crate::entity::passive::horse::HorseEntity;
use crate::entity::passive::iron_golem::IronGolemEntity;
use crate::entity::passive::llama::LlamaEntity;
use crate::entity::passive::mooshroom::MooshroomEntity;
use crate::entity::passive::mule::MuleEntity;
use crate::entity::passive::ocelot::OcelotEntity;
use crate::entity::passive::panda::PandaEntity;
use crate::entity::passive::parrot::ParrotEntity;
use crate::entity::passive::pig::PigEntity;
use crate::entity::passive::polar_bear::PolarBearEntity;
use crate::entity::passive::pufferfish::PufferfishEntity;
use crate::entity::passive::rabbit::RabbitEntity;
use crate::entity::passive::salmon::SalmonEntity;
use crate::entity::passive::sheep::SheepEntity;
use crate::entity::passive::skeleton_horse::SkeletonHorseEntity;
use crate::entity::passive::sniffer::SnifferEntity;
use crate::entity::passive::snow_golem::SnowGolemEntity;
use crate::entity::passive::squid::SquidEntity;
use crate::entity::passive::strider::StriderEntity;
use crate::entity::passive::tadpole::TadpoleEntity;
use crate::entity::passive::trader_llama::TraderLlamaEntity;
use crate::entity::passive::tropical_fish::TropicalFishEntity;
use crate::entity::passive::turtle::TurtleEntity;
use crate::entity::passive::villager::VillagerEntity;
use crate::entity::passive::wandering_trader::WanderingTraderEntity;
use crate::entity::passive::wolf::WolfEntity;
use crate::entity::passive::zombie_horse::ZombieHorseEntity;
use crate::entity::projectile::ThrownItemEntity;
use crate::entity::projectile::arrow::ArrowEntity;
use crate::entity::projectile::egg::EggEntity;
use crate::entity::projectile::ender_pearl::EnderPearlEntity;
use crate::entity::projectile::eye_of_ender::EyeOfEnder;
use crate::entity::projectile::firework_rocket::FireworkRocketEntity;
use crate::entity::projectile::lingering_potion::LingeringPotionEntity;
use crate::entity::projectile::shulker_bullet::ShulkerBulletEntity;
use crate::entity::projectile::snowball::SnowballEntity;
use crate::{
entity::{
Entity, EntityBase,
boss::wither::WitherEntity,
decoration::{
armor_stand::ArmorStandEntity, end_crystal::EndCrystalEntity, painting::PaintingEntity,
},
living::LivingEntity,
mob::{
bat::BatEntity,
creeper::CreeperEntity,
enderman::EndermanEntity,
silverfish::SilverfishEntity,
skeleton::{
bogged::BoggedSkeletonEntity, parched::ParchedSkeletonEntity,
skeleton::SkeletonEntity, stray::StraySkeletonEntity, wither::WitherSkeletonEntity,
},
slime::SlimeEntity,
zombie::{drowned::DrownedEntity, husk::HuskEntity, zombie::ZombieEntity},
},
passive::{
cat::CatEntity, chicken::ChickenEntity, cow::CowEntity, iron_golem::IronGolemEntity,
pig::PigEntity, sheep::SheepEntity, snow_golem::SnowGolemEntity, wolf::WolfEntity,
},
},
world::World,
};
use crate::entity::projectile::splash_potion::SplashPotionEntity;
use crate::entity::projectile::wind_charge::WindChargeEntity;
use crate::entity::tnt::TNTEntity;
use crate::entity::vehicle::boat::BoatEntity;
use crate::entity::{Entity, EntityBase};
use crate::world::World;
use pumpkin_data::Block;
use pumpkin_data::item::Item;
use pumpkin_data::item_stack::ItemStack;
use std::sync::atomic::AtomicBool;
#[expect(clippy::too_many_lines)]
pub async fn from_type(
entity_type: &'static EntityType,
position: Vector3<f64>,
@ -54,8 +127,9 @@ pub async fn from_type(
id if id == EntityType::DROWNED.id => DrownedEntity::new(entity).await,
id if id == EntityType::HUSK.id => HuskEntity::new(entity).await,
id if id == EntityType::ZOMBIE_VILLAGER.id => ZombieVillagerEntity::new(entity).await,
id if id == EntityType::ZOMBIFIED_PIGLIN.id => ZombifiedPiglinEntity::new(entity).await,
// Sekelton
// Skeleton
id if id == EntityType::SKELETON.id => SkeletonEntity::new(entity).await,
id if id == EntityType::BOGGED.id => BoggedSkeletonEntity::new(entity).await,
id if id == EntityType::PARCHED.id => ParchedSkeletonEntity::new(entity).await,
@ -67,14 +141,73 @@ pub async fn from_type(
id if id == EntityType::ENDERMAN.id => EndermanEntity::new(entity).await,
id if id == EntityType::BLAZE.id => BlazeEntity::new(entity).await,
id if id == EntityType::SPIDER.id => SpiderEntity::new(entity).await,
id if id == EntityType::CAVE_SPIDER.id => CaveSpiderEntity::new(entity).await,
id if id == EntityType::GHAST.id => GhastEntity::new(entity).await,
id if id == EntityType::MAGMA_CUBE.id => MagmaCubeEntity::new(entity).await,
id if id == EntityType::PHANTOM.id => PhantomEntity::new(entity).await,
id if id == EntityType::WITCH.id => WitchEntity::new(entity).await,
id if id == EntityType::PIGLIN.id => PiglinEntity::new(entity).await,
id if id == EntityType::PIGLIN_BRUTE.id => PiglinBruteEntity::new(entity).await,
id if id == EntityType::PILLAGER.id => PillagerEntity::new(entity).await,
id if id == EntityType::VINDICATOR.id => VindicatorEntity::new(entity).await,
id if id == EntityType::EVOKER.id => EvokerEntity::new(entity).await,
id if id == EntityType::RAVAGER.id => RavagerEntity::new(entity).await,
id if id == EntityType::GUARDIAN.id => GuardianEntity::new(entity).await,
id if id == EntityType::ELDER_GUARDIAN.id => ElderGuardianEntity::new(entity).await,
id if id == EntityType::WARDEN.id => WardenEntity::new(entity).await,
id if id == EntityType::HOGLIN.id => HoglinEntity::new(entity).await,
id if id == EntityType::ZOGLIN.id => ZoglinEntity::new(entity).await,
id if id == EntityType::BREEZE.id => BreezeEntity::new(entity).await,
id if id == EntityType::CREAKING.id => CreakingEntity::new(entity).await,
id if id == EntityType::ILLUSIONER.id => IllusionerEntity::new(entity).await,
id if id == EntityType::VEX.id => VexEntity::new(entity).await,
id if id == EntityType::ENDERMITE.id => EndermiteEntity::new(entity).await,
id if id == EntityType::GIANT.id => GiantEntity::new(entity).await,
id if id == EntityType::CAT.id => CatEntity::new(entity).await,
id if id == EntityType::CHICKEN.id => ChickenEntity::new(entity).await,
id if id == EntityType::COW.id => CowEntity::new(entity).await,
id if id == EntityType::PIG.id => PigEntity::new(entity).await,
id if id == EntityType::SNOW_GOLEM.id => SnowGolemEntity::new(entity).await,
id if id == EntityType::IRON_GOLEM.id => IronGolemEntity::new(entity).await,
id if id == EntityType::SHEEP.id => SheepEntity::new(entity).await,
id if id == EntityType::WOLF.id => WolfEntity::new(entity).await,
id if id == EntityType::FOX.id => FoxEntity::new(entity).await,
id if id == EntityType::RABBIT.id => RabbitEntity::new(entity).await,
id if id == EntityType::TURTLE.id => TurtleEntity::new(entity).await,
id if id == EntityType::VILLAGER.id => VillagerEntity::new(entity).await,
id if id == EntityType::SQUID.id => SquidEntity::new(entity).await,
id if id == EntityType::HORSE.id => HorseEntity::new(entity).await,
id if id == EntityType::DONKEY.id => DonkeyEntity::new(entity).await,
id if id == EntityType::MULE.id => MuleEntity::new(entity).await,
id if id == EntityType::ZOMBIE_HORSE.id => ZombieHorseEntity::new(entity).await,
id if id == EntityType::SKELETON_HORSE.id => SkeletonHorseEntity::new(entity).await,
id if id == EntityType::LLAMA.id => LlamaEntity::new(entity).await,
id if id == EntityType::TRADER_LLAMA.id => TraderLlamaEntity::new(entity).await,
id if id == EntityType::WANDERING_TRADER.id => WanderingTraderEntity::new(entity).await,
id if id == EntityType::ALLAY.id => AllayEntity::new(entity).await,
id if id == EntityType::ARMADILLO.id => ArmadilloEntity::new(entity).await,
id if id == EntityType::AXOLOTL.id => AxolotlEntity::new(entity).await,
id if id == EntityType::BEE.id => BeeEntity::new(entity).await,
id if id == EntityType::CAMEL.id => CamelEntity::new(entity).await,
id if id == EntityType::FROG.id => FrogEntity::new(entity).await,
id if id == EntityType::GOAT.id => GoatEntity::new(entity).await,
id if id == EntityType::MOOSHROOM.id => MooshroomEntity::new(entity).await,
id if id == EntityType::OCELOT.id => OcelotEntity::new(entity).await,
id if id == EntityType::PANDA.id => PandaEntity::new(entity).await,
id if id == EntityType::PARROT.id => ParrotEntity::new(entity).await,
id if id == EntityType::POLAR_BEAR.id => PolarBearEntity::new(entity).await,
id if id == EntityType::SNIFFER.id => SnifferEntity::new(entity).await,
id if id == EntityType::STRIDER.id => StriderEntity::new(entity).await,
id if id == EntityType::GLOW_SQUID.id => GlowSquidEntity::new(entity).await,
id if id == EntityType::COD.id => CodEntity::new(entity).await,
id if id == EntityType::SALMON.id => SalmonEntity::new(entity).await,
id if id == EntityType::PUFFERFISH.id => PufferfishEntity::new(entity).await,
id if id == EntityType::TROPICAL_FISH.id => TropicalFishEntity::new(entity).await,
id if id == EntityType::TADPOLE.id => TadpoleEntity::new(entity).await,
id if id == EntityType::DOLPHIN.id => DolphinEntity::new(entity).await,
id if id == EntityType::SNOW_GOLEM.id => SnowGolemEntity::new(entity).await,
id if id == EntityType::IRON_GOLEM.id => IronGolemEntity::new(entity).await,
id if id == EntityType::WITHER.id => WitherEntity::new(entity).await,
id if id == EntityType::ENDER_DRAGON.id => EnderDragonEntity::new(entity).await,
@ -89,13 +222,72 @@ pub async fn from_type(
id if id == EntityType::SNOWBALL.id => Arc::new(SnowballEntity::new(entity).await),
id if id == EntityType::EGG.id => Arc::new(EggEntity::new(entity).await),
id if id == EntityType::SILVERFISH.id => SilverfishEntity::new(entity).await,
id if id == EntityType::SLIME.id => SlimeEntity::new(entity),
id if id == EntityType::SLIME.id => SlimeEntity::new(entity).await,
id if id == EntityType::SHULKER.id => ShulkerEntity::new(entity).await,
id if id == EntityType::SHULKER_BULLET.id => {
// Shulker bullets are normally spawned by ShulkerEntity directly;
// when loaded from the world we create a no-target bullet at the given position.
Arc::new(ShulkerBulletEntity::orphan(entity))
}
id if id == EntityType::FALLING_BLOCK.id => {
Arc::new(FallingEntity::new(entity, Block::SAND.default_state.id))
}
id if id == EntityType::EXPERIENCE_ORB.id => Arc::new(ExperienceOrbEntity::new(entity, 1)),
id if id == EntityType::TNT.id => Arc::new(TNTEntity::new(entity, 4.0, 80)),
id if id == EntityType::ITEM.id => {
Arc::new(ItemEntity::new(entity, ItemStack::new(1, &Item::AIR)).await)
}
id if id == EntityType::ARROW.id => Arc::new(ArrowEntity::new(entity, None)),
id if id == EntityType::SPECTRAL_ARROW.id => Arc::new(ArrowEntity::new(entity, None)),
id if id == EntityType::WIND_CHARGE.id => {
let thrown = ThrownItemEntity {
entity,
owner_id: None,
collides_with_projectiles: false,
has_hit: AtomicBool::new(false),
};
Arc::new(WindChargeEntity::new(thrown))
}
id if id == EntityType::BREEZE_WIND_CHARGE.id => {
let thrown = ThrownItemEntity {
entity,
owner_id: None,
collides_with_projectiles: false,
has_hit: AtomicBool::new(false),
};
Arc::new(WindChargeEntity::new(thrown))
}
id if id == EntityType::FIREWORK_ROCKET.id => {
Arc::new(FireworkRocketEntity::new(entity).await)
}
id if id == EntityType::SPLASH_POTION.id => Arc::new(SplashPotionEntity::new(entity).await),
id if id == EntityType::LINGERING_POTION.id => {
Arc::new(LingeringPotionEntity::new(entity).await)
}
id if id == EntityType::EYE_OF_ENDER.id => Arc::new(EyeOfEnder::new(entity)),
id if id == EntityType::ACACIA_BOAT.id
|| id == EntityType::ACACIA_CHEST_BOAT.id
|| id == EntityType::BIRCH_BOAT.id
|| id == EntityType::BIRCH_CHEST_BOAT.id
|| id == EntityType::DARK_OAK_BOAT.id
|| id == EntityType::DARK_OAK_CHEST_BOAT.id
|| id == EntityType::JUNGLE_BOAT.id
|| id == EntityType::JUNGLE_CHEST_BOAT.id
|| id == EntityType::MANGROVE_BOAT.id
|| id == EntityType::MANGROVE_CHEST_BOAT.id
|| id == EntityType::OAK_BOAT.id
|| id == EntityType::OAK_CHEST_BOAT.id
|| id == EntityType::PALE_OAK_BOAT.id
|| id == EntityType::PALE_OAK_CHEST_BOAT.id
|| id == EntityType::SPRUCE_BOAT.id
|| id == EntityType::SPRUCE_CHEST_BOAT.id
|| id == EntityType::BAMBOO_RAFT.id
|| id == EntityType::BAMBOO_CHEST_RAFT.id
|| id == EntityType::CHERRY_BOAT.id
|| id == EntityType::CHERRY_CHEST_BOAT.id =>
{
Arc::new(BoatEntity::new(entity))
}
// Fallback Entity
_ => {
if entity_type.attributes.is_empty() {