From 2ffe470e2e64aef592c3c702dfa81bb8fe096b07 Mon Sep 17 00:00:00 2001 From: xRookieFight Date: Mon, 10 Aug 2026 19:25:57 +0300 Subject: [PATCH] test: cover inlined hover event NBT payload (#2852) --- crates/pumpkin-util/src/text/mod.rs | 54 ++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/crates/pumpkin-util/src/text/mod.rs b/crates/pumpkin-util/src/text/mod.rs index 8bffbb4ed..b07dac041 100644 --- a/crates/pumpkin-util/src/text/mod.rs +++ b/crates/pumpkin-util/src/text/mod.rs @@ -1282,7 +1282,8 @@ pub enum TextContent { /// Tests for the text component implementations. #[cfg(test)] mod test { - use crate::text::{TextComponent, color::NamedColor}; + use crate::text::{TextComponent, color::NamedColor, hover::HoverEvent}; + use std::borrow::Cow; #[test] fn serialize_text_component() { @@ -1303,4 +1304,55 @@ mod test { let decoded = pumpkin_nbt::Nbt::read_unnamed(&mut reader).unwrap(); assert_eq!(decoded, expected_compound.into()); } + + /// The client expects the hover event payload to be inlined next to `action`. + /// Nesting it under `item`/`entity` makes the component fail to decode and + /// kicks the player off the server. + #[test] + fn hover_event_payload_is_inlined() { + let show_item = TextComponent::text("sword") + .hover_event(HoverEvent::ShowItem { + id: Cow::Borrowed("minecraft:diamond_sword"), + count: Some(1), + }) + .0 + .to_nbt_compound(); + let hover = show_item.get_compound("hover_event").unwrap(); + assert_eq!(hover.get_string("action"), Some("show_item")); + assert_eq!(hover.get_string("id"), Some("minecraft:diamond_sword")); + assert_eq!(hover.get_int("count"), Some(1)); + assert!(hover.get_compound("item").is_none()); + + let show_entity = TextComponent::text("pig") + .hover_event(HoverEvent::show_entity( + "6ba1a740-9a3b-4b7c-8f2c-8f5a5c1a0a11", + "minecraft:pig", + None, + )) + .0 + .to_nbt_compound(); + let hover = show_entity.get_compound("hover_event").unwrap(); + assert_eq!(hover.get_string("action"), Some("show_entity")); + assert_eq!(hover.get_string("id"), Some("minecraft:pig")); + assert_eq!( + hover.get_string("uuid"), + Some("6ba1a740-9a3b-4b7c-8f2c-8f5a5c1a0a11") + ); + assert!(hover.get_compound("entity").is_none()); + } + + /// `count` is optional for the client, so it must stay out of the payload + /// when it was never set. + #[test] + fn hover_show_item_omits_unset_count() { + let compound = TextComponent::text("sword") + .hover_event(HoverEvent::ShowItem { + id: Cow::Borrowed("minecraft:diamond_sword"), + count: None, + }) + .0 + .to_nbt_compound(); + let hover = compound.get_compound("hover_event").unwrap(); + assert!(hover.get_int("count").is_none()); + } }