Skip to main content

yog_registry/
entities.rs

1//! Entities: what a mod declares an entity type as.
2
3/// What kind of entity a type is.
4#[derive(yog_data::Schema, Debug, Clone, Copy, PartialEq, Eq, Default)]
5pub enum EntityKind {
6    /// Not alive: a thing in the world (a scroll on a wall, a vehicle, a
7    /// display) — no health, no AI.
8    #[default]
9    Object,
10    /// Alive: health, attributes, hurt and death, but no AI of its own.
11    Living,
12    /// A creature with AI: `goals`, and walking about.
13    Mob,
14    /// Hangs on a block's side, as a painting: `width`×`height` whole
15    /// blocks of wall (the item it's placed from may say another size —
16    /// [`ItemDef::hangs`]); it stays while the blocks behind hold it, and
17    /// breaking it, or losing its wall, drops the item it was placed from.
18    Hanging,
19}
20
21/// An entity type to register (`.yentity`). Its look is a body model
22/// (`model`, `.ymodel`) with clips by state; what it does beyond `goals` is
23/// the mod's code (entity events, a tick of its own).
24#[derive(yog_data::Schema, Debug, Clone)]
25pub struct EntityDef {
26    /// Its id; a source may leave it out: the file's name, the build fills it in.
27    #[data(default)]
28    pub id: String,
29    /// Its name (a text or a `@Set.key` resource); default: the id's lang key.
30    pub name: Option<String>,
31    #[data(default)]
32    pub kind: EntityKind,
33    /// Its spawn group (`MobCategory`): `misc`, `monster`, `creature`,
34    /// `ambient`, `water_creature`, `water_ambient`, `underground_water_creature`.
35    #[data(default = "misc")]
36    pub category: String,
37    /// Hitbox, blocks.
38    pub width: f32,
39    pub height: f32,
40    /// Eye height, blocks; default 85% of the height.
41    pub eye_height: Option<f32>,
42    /// Lava and fire don't hurt it.
43    #[data(default)]
44    pub fire_immune: bool,
45    /// It doesn't fall.
46    #[data(default)]
47    pub no_gravity: bool,
48    /// Others push it (living things by default).
49    pub pushable: Option<bool>,
50    /// Others stand on and bump into it as into a block (a boat).
51    #[data(default)]
52    pub solid: bool,
53    /// How far players see it, chunks.
54    #[data(default = "eight")]
55    pub tracking_range: u32,
56    /// How often its movement is sent, ticks.
57    #[data(default = "three")]
58    pub update_interval: u32,
59    /// Living and mob attributes by id: `max_health`, `movement_speed`,
60    /// `attack_damage`, `follow_range`, `armor`, `knockback_resistance`… (the
61    /// game's, `minecraft:` optional, or a mod's).
62    #[data(default)]
63    pub attributes: yog_data::Ordered<f64>,
64    /// Its body model (`.ymodel` id); none: the mod draws it (`on_body`).
65    pub model: Option<String>,
66    /// Its clips (`.yanim` id).
67    pub animations: Option<String>,
68    /// Clip by state: `idle`, `walk`, `attack`, `hurt`, `death`, or the mod's
69    /// own states (entity data `yog:state`).
70    #[data(default)]
71    pub clips: yog_data::Ordered<String>,
72    /// Spawn egg colors `[base, spots]` (`0xRRGGBB`); none: no egg.
73    pub spawn_egg: Option<[u32; 2]>,
74    /// Mobs' AI goals, in priority order — the game's by name: `float`,
75    /// `panic`, `melee_attack`, `wander`, `look_at_player`,
76    /// `look_around`, `target_player`, `avoid_player`.
77    #[data(default)]
78    pub goals: Vec<String>,
79    /// The mod handles each tick of every entity of this type
80    /// (`yog_event::entity::game::Tick`, keyed by the type).
81    #[data(default)]
82    pub ticks: bool,
83    /// A hanging thing's sound events when it's placed and when it breaks;
84    /// default: a painting's.
85    pub place_sound: Option<String>,
86    pub break_sound: Option<String>,
87}
88
89/// A hanging thing's sounds when it names none: a painting's.
90pub const HANGING_PLACE_SOUND: &str = yog_ids::id!(yog_ids::ns::MINECRAFT, "entity.painting.place");
91pub const HANGING_BREAK_SOUND: &str = yog_ids::id!(yog_ids::ns::MINECRAFT, "entity.painting.break");
92
93fn eight() -> u32 {
94    8
95}
96
97fn three() -> u32 {
98    3
99}
100
101fn misc() -> String {
102    "misc".into()
103}
104
105impl EntityDef {
106    pub fn new(id: impl Into<String>, kind: EntityKind, width: f32, height: f32) -> Self {
107        Self {
108            id: id.into(),
109            name: None,
110            kind,
111            category: misc(),
112            width,
113            height,
114            eye_height: None,
115            fire_immune: false,
116            no_gravity: false,
117            pushable: None,
118            solid: false,
119            tracking_range: eight(),
120            update_interval: three(),
121            attributes: yog_data::Ordered::default(),
122            model: None,
123            animations: None,
124            clips: yog_data::Ordered::default(),
125            spawn_egg: None,
126            goals: Vec::new(),
127            ticks: false,
128            place_sound: None,
129            break_sound: None,
130        }
131    }
132
133    /// Itself with the sounds it doesn't name: a painting's.
134    pub fn with_default_sounds(mut self) -> Self {
135        self.place_sound
136            .get_or_insert_with(|| HANGING_PLACE_SOUND.into());
137        self.break_sound
138            .get_or_insert_with(|| HANGING_BREAK_SOUND.into());
139        self
140    }
141}