1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
use crate::comp::{body::Body, quadruped_medium};
use crossbeam_utils::atomic::AtomicCell;
use specs::Component;
use std::{num::NonZeroU64, sync::Arc};
use super::Mass;
pub type PetId = AtomicCell<Option<NonZeroU64>>;
// TODO: move to server crate
#[derive(Clone, Debug)]
pub struct Pet {
database_id: Arc<PetId>,
}
impl Pet {
/// Not to be used outside of persistence - provides mutable access to the
/// pet component's database ID which is required to save the pet's data
/// from the persistence thread.
#[doc(hidden)]
pub fn get_database_id(&self) -> Arc<PetId> { Arc::clone(&self.database_id) }
pub fn new_from_database(database_id: NonZeroU64) -> Self {
Self {
database_id: Arc::new(AtomicCell::new(Some(database_id))),
}
}
}
impl Default for Pet {
fn default() -> Self {
Self {
database_id: Arc::new(AtomicCell::new(None)),
}
}
}
/// Determines whether an entity of a particular body variant is tameable.
pub fn is_tameable(body: &Body) -> bool {
// Currently only Quadruped animals can be tamed pending further work
// on the pets feature (allowing larger animals to be tamed will
// require balance issues to be addressed).
match body {
Body::QuadrupedMedium(quad_med) =>
// NOTE: the reason we ban mammoth from being tameable even though they're
// agressive anyway, is that UncomfySilence is going to make them
// peaceful after this MR gets merged. Please, remove this note in your MR,
// UncomfySilence!
{
!matches!(
quad_med.species,
quadruped_medium::Species::Catoblepas
| quadruped_medium::Species::Mammoth
| quadruped_medium::Species::Hirdrasil
)
},
Body::QuadrupedLow(_)
| Body::QuadrupedSmall(_)
| Body::BirdMedium(_)
| Body::Crustacean(_) => true,
_ => false,
}
}
pub fn is_mountable(
mount: &Body,
mount_mass: &Mass,
rider: Option<&Body>,
rider_mass: Option<&Mass>,
) -> bool {
let is_light_enough = rider_mass.map_or(false, |r| r.0 / mount_mass.0 < 0.7);
match mount {
Body::Humanoid(_) => matches!(rider, Some(Body::BirdMedium(_))) && is_light_enough,
Body::Ship(_) => true,
Body::Object(_) => false,
Body::ItemDrop(_) => false,
_ => is_light_enough,
}
}
impl Component for Pet {
// Using `DenseVecStorage` has a u64 space overhead per entity and `Pet` just
// has an `Arc` pointer which is the same size on 64-bit platforms. So it
// isn't worth using `DenseVecStorage` here.
type Storage = specs::VecStorage<Self>;
}