mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-11 02:21:38 -10:00
A server's parrot or slime sent as a baby stays grown; fix the baby flag test
AgeableMob.isBaby is canBeABaby() && getAge() < 0, so a vanilla client ignores DATA_BABY_ID on a frog, parrot, slime, magma cube, camel husk or zombie nautilus. The client now does too (drops::can_be_baby). The test gives each type a model, which MobTypes::load needs, and checks a parrot. baby_index reuses doors::is_zombie. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
868069dea7
commit
02be02992c
2 files changed
+31
-10
No files matched your search
@@ -250,10 +250,12 @@ pub(super) fn baby_index(species: Species) -> Option<u8> {
|
||||
use Species as S;
|
||||
match species {
|
||||
S::Piglin => Some(17),
|
||||
S::Zombie | S::Husk | S::Drowned | S::ZombieVillager | S::ZombifiedPiglin | S::Zoglin => {
|
||||
s if horizon_client::mobs::finalize::ageable(s)
|
||||
|| horizon_client::mobs::doors::is_zombie(s)
|
||||
|| s == S::Zoglin =>
|
||||
{
|
||||
Some(16)
|
||||
}
|
||||
s if horizon_client::mobs::finalize::ageable(s) => Some(16),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -473,7 +475,7 @@ fn mob_meta(
|
||||
meta.push((15, serializer::BYTE, Value::Byte(flags)));
|
||||
}
|
||||
defaults.push((15, serializer::BYTE, Value::Byte(0)));
|
||||
// AgeableMob.DATA_BABY_ID (and Zombie's, Piglin's).
|
||||
// AgeableMob.DATA_BABY_ID (and Zombie's, Zoglin's, Piglin's).
|
||||
if let Some(index) = baby_index(m.species()) {
|
||||
if m.is_baby() {
|
||||
meta.push((index, serializer::BOOLEAN, Value::Bool(true)));
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
use super::Game;
|
||||
use horizon_client::mobs::render::{PROFESSIONS, VILLAGER_TYPES};
|
||||
use horizon_client::mobs::{
|
||||
Mob, Species, Who, armadillo, bat, bee, camel, creaking, equine, finalize, illusioner, panda,
|
||||
phantom, sniffer, sync, tame, zombie_villager,
|
||||
Mob, Species, Who, armadillo, bat, bee, camel, creaking, drops, equine, finalize, illusioner,
|
||||
panda, phantom, sniffer, sync, tame, zombie_villager,
|
||||
};
|
||||
use horizon_client::particles::{ParticleOptions, ParticleType};
|
||||
use horizon_protocol::entity_data::{Particle, ParticleData, Value};
|
||||
@@ -82,7 +82,15 @@ fn apply(m: &mut Mob, values: &[(u8, i32, Value)], builtin: &Builtin, local_enti
|
||||
m.extra.left_handed = flags & 2 != 0;
|
||||
m.ai.aggressive = flags & 4 != 0;
|
||||
}
|
||||
(i, Value::Bool(b)) if Some(i) == baby => m.extra.age = if *b { -1 } else { 0 },
|
||||
// AgeableMob.isBaby: `canBeABaby` too, so a parrot or a slime
|
||||
// sent as one is still drawn grown.
|
||||
(i, Value::Bool(b)) if Some(i) == baby => {
|
||||
m.extra.age = if *b && drops::can_be_baby(species) {
|
||||
-1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
}
|
||||
// AgeableMob.AGE_LOCKED, the entry after DATA_BABY_ID (not
|
||||
// Zombie's or Piglin's).
|
||||
(17, Value::Bool(locked)) if baby == Some(16) && finalize::ageable(species) => {
|
||||
@@ -630,20 +638,26 @@ mod tests {
|
||||
}
|
||||
|
||||
/// #6133: a server's baby happy ghast (a hatched dried ghast) and baby
|
||||
/// nautilus come with AgeableMob.DATA_BABY_ID (16) like any other animal.
|
||||
/// nautilus come with AgeableMob.DATA_BABY_ID (16) like any other animal;
|
||||
/// a parrot never is one (`Parrot.canBeABaby`).
|
||||
#[test]
|
||||
fn a_happy_ghast_and_a_nautilus_take_their_babyhood() {
|
||||
use horizon_client::mobs::MobTypes;
|
||||
use std::{fs, sync::Arc};
|
||||
|
||||
let root = std::env::temp_dir().join(format!("horizon-baby-flag-{}", std::process::id()));
|
||||
fs::create_dir(&root).unwrap();
|
||||
fs::create_dir_all(&root).unwrap();
|
||||
fs::write(
|
||||
root.join("entity-types.json"),
|
||||
r#"{"minecraft:happy_ghast": {}, "minecraft:nautilus": {}}"#,
|
||||
r#"{"minecraft:happy_ghast": {}, "minecraft:nautilus": {}, "minecraft:parrot": {}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
root.join("entity-models.json"),
|
||||
r#"{"minecraft:happy_ghast#main": {}, "minecraft:nautilus#main": {},
|
||||
"minecraft:parrot#main": {}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(root.join("entity-models.json"), "{}").unwrap();
|
||||
let mut types = MobTypes::load(&root).unwrap();
|
||||
fs::remove_dir_all(root).unwrap();
|
||||
for kind in ["minecraft:happy_ghast", "minecraft:nautilus"] {
|
||||
@@ -656,6 +670,11 @@ mod tests {
|
||||
apply(&mut m, &[(16, s::BOOLEAN, Value::Bool(false))]);
|
||||
assert!(!m.is_baby(), "{kind}");
|
||||
}
|
||||
let t = Arc::new(types.types.remove("minecraft:parrot").unwrap());
|
||||
let mut parrot = Mob::new(1, t, horizon_core::geometry::Vec3::ZERO, 0.0);
|
||||
client_defaults(&mut parrot);
|
||||
apply(&mut parrot, &[(16, s::BOOLEAN, Value::Bool(true))]);
|
||||
assert!(!parrot.is_baby());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user