Merge pull request #1911 from vlesmentie/fix/structure-chest-enchantments

🤖 Agent: Thanks vlesmentie! Structure chests keep the enchantments their loot table rolled. Tested together with the other wave 1 contributor PRs on current main: fmt, clippy -D warnings and the horizon-client tests (1,120 lib tests and the rest) pass; the 114 harnesses the batch affects pass; lan_e2e anvil, grindstone, replant, instant_digging, digging, frames and leads pass with the host in-frame and on its server thread.
This commit is contained in:
Ludovic Marie
2026-10-26 03:11:16 +01:00
committed by GitHub
+44 -9
View File
@@ -176,14 +176,10 @@ pub fn block_entities(
.iter_mut()
.zip(loot.fill(&table, seed, 27, Some(biome)))
{
*slot = stack.map(|s| {
let mut item = loot_item(&s);
// An ominous bottle's level (the default, 0, is no component).
if let Some(level) = s.ominous_amplifier.filter(|l| *l > 0) {
item.data_mut().ominous_amplifier = Some(level.clamp(0, 4) as u8);
}
item
});
// With what the rolls put on them: enchantments
// (enchant_with_levels in End city chests), potions and an
// ominous bottle's level.
*slot = stack.map(|s| loot_item_with_components(&s));
}
}
out.push(((x, y, z), entity));
@@ -222,7 +218,7 @@ pub fn unpack_entity_loot(
let slots: Vec<Option<ItemStack>> = loot
.fill(&table, seed, 27, Some(biome))
.into_iter()
.map(|s| s.map(|s| loot_item(&s)))
.map(|s| s.map(|s| loot_item_with_components(&s)))
.collect();
nbt.remove(&JavaString::from("LootTable"));
nbt.remove(&JavaString::from("LootTableSeed"));
@@ -235,6 +231,45 @@ mod tests {
use super::*;
use horizon_world::loot::{ExplorationMap, LootStack};
#[test]
fn placed_chest_loot_keeps_its_enchantments_and_potions() {
let stack =
|item: &str, enchantments: Vec<(String, i32)>, potion: Option<&str>| LootStack {
item: item.into(),
count: 1,
damage: 0,
enchantments,
potion: potion.map(str::to_owned),
map: false,
exploration: None,
ominous_amplifier: None,
};
// An End city chest's enchant_with_levels roll.
let boots = loot_item_with_components(&stack(
"minecraft:diamond_boots",
vec![
("minecraft:protection".into(), 3),
("minecraft:unbreaking".into(), 2),
],
None,
));
assert_eq!(boots.enchantments().len(), 2);
// A book's go into stored_enchantments.
let book = loot_item_with_components(&stack(
"minecraft:enchanted_book",
vec![("minecraft:mending".into(), 1)],
None,
));
assert!(book.enchantments().is_empty());
assert_eq!(book.stored_enchantments().len(), 1);
let arrow = loot_item_with_components(&stack(
"minecraft:tipped_arrow",
Vec::new(),
Some("minecraft:slowness"),
));
assert_eq!(arrow.potion(), Some("minecraft:slowness"));
}
#[test]
fn exploration_maps_wait_in_custom_data_until_searched() {
let mut stack = LootStack {