A golem's or a fox's lead hangs where vanilla puts it

`IronGolem`, `SnowGolem`, `CopperGolem` and `Fox.getLeashOffset` use their
own height, not the default: 0.875, 0.75, 0.75 and 0.55 of the eye height,
and the copper golem's rope hangs on the centre rather than `bbWidth / 2`
in front. `leash::leash_offset` knew the llama, wolf, allay, camel and bee
and gave these four the default, so their leads were drawn too high.

Corrects the four ledger rows in game-012.tsv.
This commit is contained in:
MSedgeMC committed 2026-11-02 05:10:44 +00:00
1 parent e7275ddee3
commit f8741e7eee
2 files changed
+56 -4

No files matched your search

+52
View File
@@ -467,6 +467,31 @@ pub fn leash_offset(m: &Mob) -> [f64; 3] {
} else if m.species() == super::Species::Bee {
// Bee.getLeashOffset: half the eye height, a fifth of the width ahead.
[0.0, 0.5 * m.eye_height(), f64::from(m.width() * 0.2)]
} else if m.species() == super::Species::IronGolem {
// IronGolem.getLeashOffset: 0.875 of the eye height.
[
0.0,
f64::from(0.875_f32 * m.eye_height() as f32),
f64::from(m.width() * 0.4),
]
} else if m.species() == super::Species::SnowGolem {
// SnowGolem.getLeashOffset: 0.75 of the eye height.
[
0.0,
f64::from(0.75_f32 * m.eye_height() as f32),
f64::from(m.width() * 0.4),
]
} else if m.species() == super::Species::CopperGolem {
// CopperGolem.getLeashOffset: 0.75 of the eye height, on the centre
// rather than the default `bbWidth / 2` in front.
[0.0, f64::from(0.75_f32 * m.eye_height() as f32), 0.0]
} else if m.species() == super::Species::Fox {
// Fox.getLeashOffset: 0.55 of the eye height.
[
0.0,
f64::from(0.55_f32 * m.eye_height() as f32),
f64::from(m.width() * 0.4),
]
} else {
[0.0, m.eye_height(), f64::from(m.width() * 0.4)]
}
@@ -579,6 +604,33 @@ mod tests {
assert!(near(p[2], [lr, y, -fb + f]));
assert!(near(p[3], [lr, y, fb + f]));
}
/// `IronGolem`, `SnowGolem`, `CopperGolem` and `Fox.getLeashOffset`: the
/// rope hangs at a share of the eye height, and the copper golem's on the
/// centre instead of the default `bbWidth / 2` in front.
#[test]
fn a_golem_or_a_fox_hangs_its_lead_where_vanilla_does() {
let _ = crate::mobs::world::with_test_world(&[], |_, types| {
for (kind, factor, forwards) in [
("minecraft:iron_golem", 0.875, 0.4),
("minecraft:snow_golem", 0.75, 0.4),
("minecraft:copper_golem", 0.75, 0.0),
("minecraft:fox", 0.55, 0.4),
] {
let m = Mob::new(
1,
std::sync::Arc::new(types.types[kind].clone()),
Vec3::ZERO,
0.0,
);
let o = leash_offset(&m);
let h = f64::from(factor * m.eye_height() as f32);
let z = f64::from(m.width() * forwards as f32);
assert!((o[1] - h).abs() < 1e-9, "{kind}: height {} vs {h}", o[1]);
assert!((o[2] - z).abs() < 1e-9, "{kind}: forward {} vs {z}", o[2]);
assert_eq!(o[0], 0.0, "{kind}: centred");
}
});
}
/// `Nautilus.canBeLeashed` and `ZombieNautilus.canBeLeashed`: an
/// aggravated nautilus, one holding an `ANGRY_AT` or an `ATTACK_TARGET`
/// memory, cannot be put on a lead.
+4 -4
View File
@@ -21,7 +21,7 @@ Fox.getHeadRollAngle port crates/horizon-client/src/mobs/fox.rs::pose head_roll_
Fox.setTarget missing minor: only clears the defending flag, which is never set
Fox.playAmbientSound port crates/horizon-client/src/mobs/ai.rs::play_ambient ticked in #3512; `Fox.playAmbientSound` is cited at crates/horizon-client/src/mobs/ai.rs:1095 (in a comment, so `where` names the enclosing fn)
Fox.getAmbientSound port crates/horizon-client/src/mobs/ai.rs::play_ambient ticked in #3512; `Fox.getAmbientSound` is cited at crates/horizon-client/src/mobs/ai.rs:1093 (in a comment, so `where` names the enclosing fn)
Fox.getLeashOffset missing minor: a lead hangs at the default offset (eye height), not at 0.55 of it
Fox.getLeashOffset port crates/horizon-client/src/mobs/leash.rs::leash_offset 0.55 of the eye height
Fox.FoxAlertableEntitiesSelector.test inline crates/horizon-client/src/mobs/fox.rs::alertable gap: minor: any other mob counts even when asleep or sneaking, and a trusted mob is not skipped (no trust)
Fox.FoxEatBerriesGoal.onReachedTarget inline crates/horizon-client/src/mobs/fox.rs::EatBerries::tick after 40 ticks at the bush, picks when mob griefing is on
Fox.FoxEatBerriesGoal.pickGlowBerry port crates/horizon-client/src/mobs/fox.rs::EatBerries::pick CaveVines.use: one glow berry, berries off, pick sound with 0.8 to 1.2 pitch
@@ -90,7 +90,7 @@ CopperGolem.createAttributes skip:data attributes come from entity-types.json
CopperGolem.defineSynchedData port crates/horizon-client/src/game/lan.rs::mob_meta weather state and golem state
CopperGolem.canTurnToStatue inline crates/horizon-client/src/mobs/copper_golem.rs::update_weathering oxidized, standing in air, 0.0058 chance per tick on the level random
CopperGolem.playHeadSpinSound port crates/horizon-client/src/mobs/copper_golem.rs::ai_step gap: minor: local spin sound by oxidation level, but a silent golem still plays it
CopperGolem.getLeashOffset missing minor: a lead hangs at the default offset, not 0.75 of the eye height with no forward shift
CopperGolem.getLeashOffset port crates/horizon-client/src/mobs/leash.rs::leash_offset 0.75 of the eye height on the centre, no forwards shift
CopperGolemAi.initCoreActivity port crates/horizon-client/src/mobs/animal_brain.rs::copper_golem_package InteractWithDoor sits in the golem's core activity, so its path through a closed wooden door no longer stops at the door
CopperGolemAi.initIdleActivity port crates/horizon-client/src/mobs/animal_brain.rs::copper_golem_package transport between chests, look at player, then stroll (2 blocks) or do nothing while the transport cooldown runs
CopperGolemAi.getTargetReachedInteractions inline crates/horizon-client/src/mobs/transport_items.rs::reached_interaction pickup, pickup nothing, place, place nothing from what the chest holds and what the golem carries
@@ -105,12 +105,12 @@ IronGolem.readAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::m
IronGolem.hurtServer port crates/horizon-client/src/mobs.rs::Mob::damage_with golem::crackiness is read before the hit and compared after; a changed level plays entity.iron_golem.damage at 1.0/1.0
IronGolem.isPlayerCreated inline crates/horizon-client/src/mobs/goals.rs::Mob::spares_players the flag is extra.player_created; spares_players reads it, and entity_nbt.rs writes and reads it
IronGolem.setPlayerCreated inline crates/horizon-client/src/game/golems.rs::Game::check_golem_spawn sets extra.player_created on the golem built from blocks; mob_from_nbt sets it on load
IronGolem.getLeashOffset missing minor: a lead hangs at the default offset, not 0.875 of the eye height
IronGolem.getLeashOffset port crates/horizon-client/src/mobs/leash.rs::leash_offset 0.875 of the eye height, the default width/2 forwards
SnowGolem.registerGoals port crates/horizon-client/src/mobs/golem.rs::register_snow gap: minor: stroll uses the 0.001 water-avoiding probability, vanilla 1.0000001E-5
SnowGolem.shear port crates/horizon-client/src/game/creatures.rs::Game::interact_shear_mob shear sound, pumpkin off, shearing loot table at eye height
SnowGolem.hasPumpkin inline crates/horizon-client/src/game/creatures.rs::Game::interact_shear_mob extra.sheared is the inverse; synced as DATA_PUMPKIN_ID in lan.rs and remote_mob_data.rs
SnowGolem.setPumpkin inline crates/horizon-client/src/game/creatures.rs::Game::interact_shear_mob sets extra.sheared (shears, dispenser); nothing puts a pumpkin back, as in vanilla
SnowGolem.getLeashOffset missing minor: a lead hangs at the default offset, not 0.75 of the eye height
SnowGolem.getLeashOffset port crates/horizon-client/src/mobs/leash.rs::leash_offset 0.75 of the eye height
HappyGhast.setServerStillTimeout inline crates/horizon-client/src/mobs/happy_ghast.rs::still_tick gap: minor: the timeout is extra.counter (10 when a player stands on top, 10 on dismount, 0 on boarding); the one-off position sync to tracking players is not sent, lan.rs only marks the entity precise
HappyGhast.registerGoals port crates/horizon-client/src/mobs/happy_ghast.rs::setup adult goals: float, tempt (harness and food for a bare adult, food otherwise), float around within 16
HappyGhast.adultGhastSetup port crates/horizon-client/src/mobs/happy_ghast.rs::setup adult half: ghast move control, happy ghast look control, goals, brain stopped
1 Fox.defineSynchedData port crates/horizon-client/src/game/lan.rs::mob_meta gap: minor: the type and the flags byte are synced; the two trusted-entity slots are not
21 Fox.setTarget missing minor: only clears the defending flag, which is never set
22 Fox.playAmbientSound port crates/horizon-client/src/mobs/ai.rs::play_ambient ticked in #3512; `Fox.playAmbientSound` is cited at crates/horizon-client/src/mobs/ai.rs:1095 (in a comment, so `where` names the enclosing fn)
23 Fox.getAmbientSound port crates/horizon-client/src/mobs/ai.rs::play_ambient ticked in #3512; `Fox.getAmbientSound` is cited at crates/horizon-client/src/mobs/ai.rs:1093 (in a comment, so `where` names the enclosing fn)
24 Fox.getLeashOffset missing port crates/horizon-client/src/mobs/leash.rs::leash_offset minor: a lead hangs at the default offset (eye height), not at 0.55 of it 0.55 of the eye height
25 Fox.FoxAlertableEntitiesSelector.test inline crates/horizon-client/src/mobs/fox.rs::alertable gap: minor: any other mob counts even when asleep or sneaking, and a trusted mob is not skipped (no trust)
26 Fox.FoxEatBerriesGoal.onReachedTarget inline crates/horizon-client/src/mobs/fox.rs::EatBerries::tick after 40 ticks at the bush, picks when mob griefing is on
27 Fox.FoxEatBerriesGoal.pickGlowBerry port crates/horizon-client/src/mobs/fox.rs::EatBerries::pick CaveVines.use: one glow berry, berries off, pick sound with 0.8 to 1.2 pitch
90 CopperGolem.defineSynchedData port crates/horizon-client/src/game/lan.rs::mob_meta weather state and golem state
91 CopperGolem.canTurnToStatue inline crates/horizon-client/src/mobs/copper_golem.rs::update_weathering oxidized, standing in air, 0.0058 chance per tick on the level random
92 CopperGolem.playHeadSpinSound port crates/horizon-client/src/mobs/copper_golem.rs::ai_step gap: minor: local spin sound by oxidation level, but a silent golem still plays it
93 CopperGolem.getLeashOffset missing port crates/horizon-client/src/mobs/leash.rs::leash_offset minor: a lead hangs at the default offset, not 0.75 of the eye height with no forward shift 0.75 of the eye height on the centre, no forwards shift
94 CopperGolemAi.initCoreActivity port crates/horizon-client/src/mobs/animal_brain.rs::copper_golem_package InteractWithDoor sits in the golem's core activity, so its path through a closed wooden door no longer stops at the door
95 CopperGolemAi.initIdleActivity port crates/horizon-client/src/mobs/animal_brain.rs::copper_golem_package transport between chests, look at player, then stroll (2 blocks) or do nothing while the transport cooldown runs
96 CopperGolemAi.getTargetReachedInteractions inline crates/horizon-client/src/mobs/transport_items.rs::reached_interaction pickup, pickup nothing, place, place nothing from what the chest holds and what the golem carries
105 IronGolem.hurtServer port crates/horizon-client/src/mobs.rs::Mob::damage_with golem::crackiness is read before the hit and compared after; a changed level plays entity.iron_golem.damage at 1.0/1.0
106 IronGolem.isPlayerCreated inline crates/horizon-client/src/mobs/goals.rs::Mob::spares_players the flag is extra.player_created; spares_players reads it, and entity_nbt.rs writes and reads it
107 IronGolem.setPlayerCreated inline crates/horizon-client/src/game/golems.rs::Game::check_golem_spawn sets extra.player_created on the golem built from blocks; mob_from_nbt sets it on load
108 IronGolem.getLeashOffset missing port crates/horizon-client/src/mobs/leash.rs::leash_offset minor: a lead hangs at the default offset, not 0.875 of the eye height 0.875 of the eye height, the default width/2 forwards
109 SnowGolem.registerGoals port crates/horizon-client/src/mobs/golem.rs::register_snow gap: minor: stroll uses the 0.001 water-avoiding probability, vanilla 1.0000001E-5
110 SnowGolem.shear port crates/horizon-client/src/game/creatures.rs::Game::interact_shear_mob shear sound, pumpkin off, shearing loot table at eye height
111 SnowGolem.hasPumpkin inline crates/horizon-client/src/game/creatures.rs::Game::interact_shear_mob extra.sheared is the inverse; synced as DATA_PUMPKIN_ID in lan.rs and remote_mob_data.rs
112 SnowGolem.setPumpkin inline crates/horizon-client/src/game/creatures.rs::Game::interact_shear_mob sets extra.sheared (shears, dispenser); nothing puts a pumpkin back, as in vanilla
113 SnowGolem.getLeashOffset missing port crates/horizon-client/src/mobs/leash.rs::leash_offset minor: a lead hangs at the default offset, not 0.75 of the eye height 0.75 of the eye height
114 HappyGhast.setServerStillTimeout inline crates/horizon-client/src/mobs/happy_ghast.rs::still_tick gap: minor: the timeout is extra.counter (10 when a player stands on top, 10 on dismount, 0 on boarding); the one-off position sync to tracking players is not sent, lan.rs only marks the entity precise
115 HappyGhast.registerGoals port crates/horizon-client/src/mobs/happy_ghast.rs::setup adult goals: float, tempt (harness and food for a bare adult, food otherwise), float around within 16
116 HappyGhast.adultGhastSetup port crates/horizon-client/src/mobs/happy_ghast.rs::setup adult half: ghast move control, happy ghast look control, goals, brain stopped