Server stacks carry their lore to clients

A stack's minecraft:lore (as loaded, or as a server mod wrote it into
StackData.other) is now sent in its component patch, so a native mod's
menu items show lines under their name (prices, changes) in a stock
client.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Ludovic MarieandClaude Opus 5.5 committed 2026-11-01 18:07:34 +01:00
1 parent d1bc26f7af
commit 6deec70473
1 file changed
+36
+36
View File
@@ -1040,6 +1040,16 @@ fn network_stack(
horizon_protocol::item::Component::Text(name.clone()),
));
}
// Lore lines as loaded or as a server mod wrote them (a list of text
// components), so a server menu's items can say more than their name.
if let Some(horizon_world::nbt::Tag::List(lines)) =
s.data().and_then(|d| d.other("minecraft:lore"))
{
stack.added.push((
horizon_protocol::item::component::LORE,
horizon_protocol::item::Component::Lore(lines.clone()),
));
}
// The component as loaded, so a translatable name stays one.
if let Some(name) = s.data().and_then(|d| d.other("minecraft:item_name")) {
stack.added.push((
@@ -1141,6 +1151,32 @@ mod tests {
use horizon_protocol::item::{Component, component};
use horizon_world::nbt::Tag;
#[test]
fn lore_lines_reach_the_client() {
let lines = vec![
Tag::compound([("text", Tag::String("Buy 400".into()))]),
Tag::compound([
("text", Tag::String("▲ 2.0%".into())),
("color", Tag::String("green".into())),
]),
];
let mut item = ItemStack::new("minecraft:diamond", 1);
item.data_mut()
.other
.push(("minecraft:lore".into(), Tag::List(lines.clone())));
let sent = stack_to_network(|_| 7, |_, _| None, &Some(item));
let mut writer = Writer::new();
horizon_protocol::item::Slot::write(&sent, &mut writer);
let mut reader = Reader::new(&writer.data);
let received = horizon_protocol::item::Slot::read(&mut reader)
.unwrap()
.unwrap();
assert_eq!(
received.component(component::LORE),
Some(&Component::Lore(lines))
);
}
#[test]
fn styled_custom_name_survives_inventory_sync() {
let name = Tag::compound([