use crate::entity::mob::Mob; use std::{any::TypeId, ops::BitOr, ptr}; pub mod active_target; pub mod ambient_stand; pub mod avoid_entity; pub mod beg; pub mod blaze_attack; pub mod bow_attack; pub mod break_door; pub mod breed; pub mod chase_player; pub mod creeper_ignite; pub mod destroy_egg; pub mod door_interact; pub mod eat_grass; pub mod escape_danger; pub mod flee_sun; pub mod follow_mob; pub mod follow_owner; pub mod follow_parent; pub mod goal_selector; pub mod interact; pub mod leap_at_target; pub mod look_around; pub mod look_at_entity; pub mod melee_attack; pub mod move_to_target_pos; pub mod move_towards_restriction; pub mod move_towards_target; pub mod ocelot_attack; pub mod offer_flower; pub mod open_door; pub mod owner_hurt_by_target; pub mod owner_hurt_target; pub mod pathfind_to_raid; pub mod pick_up_block; pub mod place_block; pub mod ranged_attack; pub mod ranged_crossbow_attack; pub mod restrict_sun; pub mod revenge; pub mod run_around_like_crazy; pub mod sit_when_ordered_to; pub mod step_and_destroy_block; pub mod swim; pub mod teleport_towards_player; pub mod tempt; pub(crate) mod track_target; pub mod trade_with_player; pub mod try_find_water; pub mod use_item; pub mod wander_around; pub mod water_avoiding_random_flying; pub mod work_at_job_site; pub mod zombie_attack; #[must_use] pub const fn to_goal_ticks(server_ticks: i32) -> i32 { -(-server_ticks).div_euclid(2) } pub trait Goal: Send + Sync { /// How should the `Goal` initially start? fn can_start(&mut self, _mob: &dyn Mob) -> bool { false } /// When it's started, how should it continue to run? fn should_continue(&self, _mob: &dyn Mob) -> bool { false } /// Call when goal start fn start(&mut self, _mob: &dyn Mob) {} /// Call when goal stop fn stop(&mut self, _mob: &dyn Mob) {} /// If the `Goal` is running, this gets called every tick. fn tick(&mut self, _mob: &dyn Mob) {} fn should_run_every_tick(&self) -> bool { false } fn can_stop(&self) -> bool { true } fn get_tick_count(&self, ticks: i32) -> i32 { if self.should_run_every_tick() { ticks } else { to_goal_ticks(ticks) } } fn controls(&self) -> Controls { Controls::empty() } } #[derive(Clone, Copy, Default, PartialEq, Eq, Debug)] // We actually only use the first 4 bits ;) pub struct Controls(u8); impl Controls { pub const MOVE: Self = Self(1); pub const LOOK: Self = Self(2); pub const JUMP: Self = Self(4); pub const TARGET: Self = Self(8); pub const ITER: [Self; 4] = [Self::MOVE, Self::LOOK, Self::JUMP, Self::TARGET]; #[must_use] pub const fn empty() -> Self { Self(0) } #[must_use] pub const fn contains(&self, other: Self) -> bool { (self.0 & other.0) == other.0 } pub const fn insert(&mut self, other: Self) { self.0 |= other.0; } pub const fn remove(&mut self, other: Self) { self.0 &= !other.0; } pub const fn set(&mut self, control: Self, value: bool) { if value { self.insert(control); } else { self.remove(control); } } #[must_use] pub const fn is_empty(&self) -> bool { self.0 == 0 } #[must_use] pub const fn get(&self, control: Self) -> bool { (self.0 & control.0) != 0 } #[must_use] pub const fn union(self, other: Self) -> Self { Self(self.0 | other.0) } #[must_use] pub const fn idx(&self) -> usize { self.0.trailing_zeros() as usize } } impl BitOr for Controls { type Output = Self; fn bitor(self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) } } pub struct PrioritizedGoal { pub goal: Box, pub running: bool, pub priority: u8, /// Used to compare goals of the same type. /// Always set to `TypeId::of::()` where `G: Goal`. type_id: TypeId, } impl PrioritizedGoal { #[must_use] pub fn new(type_id: TypeId, priority: u8, goal: Box) -> Self { Self { goal, running: false, priority, type_id, } } fn can_be_replaced_by(&self, goal: &Self) -> bool { self.can_stop() && goal.priority < self.priority } } impl Goal for PrioritizedGoal { fn can_start(&mut self, mob: &dyn Mob) -> bool { self.goal.can_start(mob) } fn should_continue(&self, mob: &dyn Mob) -> bool { self.goal.should_continue(mob) } fn start(&mut self, mob: &dyn Mob) { if !self.running { self.running = true; self.goal.start(mob); } } fn stop(&mut self, mob: &dyn Mob) { if self.running { self.running = false; self.goal.stop(mob); } } fn tick(&mut self, mob: &dyn Mob) { self.goal.tick(mob); } fn should_run_every_tick(&self) -> bool { self.goal.should_run_every_tick() } fn get_tick_count(&self, ticks: i32) -> i32 { self.goal.get_tick_count(ticks) } fn controls(&self) -> Controls { self.goal.controls() } } #[derive(Clone)] pub struct ParentHandle

{ ptr: *const P, } impl

ParentHandle

{ /// This wrapper allows a child struct to hold a reference to its parent /// without making the code overly verbose. /// /// # Safety /// - The parent must outlive this handle. /// - The parent must be inside a smart pointer; otherwise it /// will move in memory and cause undefined behavior! /// /// # Example /// ``` /// use pumpkin::entity::ai::goal::ParentHandle; /// /// struct Parent { /// child: Child, /// value: i32 /// } /// /// struct Child { /// parent: ParentHandle, /// } /// /// impl Child { /// fn value(&self) -> i32 { /// self.parent.get().unwrap().value /// } /// } /// /// let mut parent = Box::new(Parent { /// child: Child {parent: ParentHandle::none()}, /// value: 7, /// }); /// parent.child.parent = unsafe { ParentHandle::new(&parent) }; /// /// assert_eq!(parent.child.value(), 7); /// ``` pub const unsafe fn new(parent: &P) -> Self { Self { ptr: ptr::from_ref(parent), } } #[must_use] /// Creates an empty handle (equivalent to `Option::None`). // We can use null as None because we handle it in get. pub const fn none() -> Self { Self { ptr: ptr::null() } } #[must_use] /// Returns a reference to the parent if available. /// This will cause undefined behavior if #Safety rules in new aren't followed pub const fn get(&self) -> Option<&P> { if self.ptr.is_null() { None } else { // SAFETY: `self.ptr` was initialized from a valid reference in `ParentHandle::new` and outlives `ParentHandle`. unsafe { Some(&*self.ptr) } } } } impl

Default for ParentHandle

{ fn default() -> Self { Self::none() } } // SAFETY: ParentHandle stores a raw pointer `*const P` to parent goal structures managed within the same AI engine instance. unsafe impl

Sync for ParentHandle

{} // SAFETY: ParentHandle stores a raw pointer `*const P` to parent goal structures managed within the same AI engine instance. unsafe impl

Send for ParentHandle

{}