mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
native_summon: a root a mod kept out has no id
spawn_loaded_entities hands out the id before native_entity_joins runs, and a cancelled orb doesn't give it back, so the fallback returned an id no entity holds. Take it only when an orb holds that id (root_id), and test both cases. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01XnU6QT61YPiPzVNysmVHsH
This commit is contained in:
1 file changed
+24
-4
@@ -89,6 +89,16 @@ fn position_ok(pos: [f64; 3]) -> bool {
|
||||
&& (-20_000_000.0..20_000_000.0).contains(&pos[1])
|
||||
}
|
||||
|
||||
/// The id of a summoned stack's root: its command target's, else `first`,
|
||||
/// the first id handed out, when an entity no command target stands for
|
||||
/// (`live`) holds it.
|
||||
fn root_id(target: Option<Target>, first: u32, live: impl Fn(u32) -> bool) -> Option<u32> {
|
||||
match target {
|
||||
Some(t) => target_id(t),
|
||||
None => live(first).then_some(first),
|
||||
}
|
||||
}
|
||||
|
||||
/// The entity id a summoned stack's root is known by.
|
||||
fn target_id(t: Target) -> Option<u32> {
|
||||
match t {
|
||||
@@ -146,10 +156,9 @@ impl Game<'_> {
|
||||
let target = self.spawn_entity_from_nbt(tag);
|
||||
self.native_mobs_joined(from, false);
|
||||
// The root is the first entity spawned, also for kinds no command
|
||||
// target stands for (experience orbs).
|
||||
target
|
||||
.and_then(target_id)
|
||||
.or((self.next_entity >= first).then_some(first))
|
||||
// target stands for (experience orbs). An id handed out to an entity
|
||||
// a mod then kept out is not given back, so the root must be there.
|
||||
root_id(target, first, |id| self.orbs.iter().any(|o| o.id == id))
|
||||
}
|
||||
/// Moves entity `id`, one Horizon keeps without simulating (a display, a
|
||||
/// marker, an interaction), to `pos` facing `yaw` and `pitch` in degrees;
|
||||
@@ -314,6 +323,17 @@ mod tests {
|
||||
assert_eq!(rider.get(&"Pos".into()), Some(&pos));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_orb_root_has_an_id_only_while_it_is_in_the_level() {
|
||||
// Spawned: the orb holds the first id.
|
||||
assert_eq!(root_id(None, 36, |id| id == 36), Some(36));
|
||||
// A mod kept it out: id 36 was handed out, but no entity holds it.
|
||||
assert_eq!(root_id(None, 36, |_| false), None);
|
||||
// A command target answers for itself.
|
||||
assert_eq!(root_id(Some(Target::Mob(40)), 36, |_| false), Some(40));
|
||||
assert_eq!(root_id(Some(Target::Player), 36, |_| true), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn summon_positions_are_summons() {
|
||||
assert!(position_ok([0.5, 64.0, 0.5]));
|
||||
|
||||
Reference in new issue
Block a user