Send decorated pot sherds to LAN guests

Decorated pots showed no sherds for LAN guests. A pot is not a block entity here, so the hub and the chunk encoder read the saved tag for it and send the sherds, loot table and item (DecoratedPotBlockEntity.getUpdateTag, saveCustomOnly). Inserting into a pot marks it for update, and a client stores a pot update with the chunk.
This commit is contained in:
Kacpherek committed 2026-10-27 21:59:46 +01:00
1 parent 2ad7b68710
commit 1deb3bd36c
4 files changed
+44 -3

No files matched your search

@@ -131,6 +131,8 @@ impl Game<'_> {
map.insert("item".into(), save::item_to_nbt(item));
}
spill::put_saved_entity(&mut self.world, pos, tag);
// The sherds and item go to the guests (BlockEntityData).
self.mark_block_entity_updated((pos[0], pos[1], pos[2]));
self.consume_held();
self.audio.play(
"minecraft:block.decorated_pot.insert",
+17
View File
@@ -1148,6 +1148,23 @@ impl Game<'_> {
else {
return;
};
// A decorated pot is no block entity here: its tag is kept with the chunk.
if name == "minecraft:decorated_pot" {
if let Tag::Compound(fields) = tag
&& !fields.is_empty()
{
let mut full = fields.clone();
full.insert("id".into(), Tag::String(name.into()));
for (k, v) in ["x", "y", "z"].into_iter().zip(pos) {
full.insert(k.into(), Tag::Int(v));
}
super::spill::put_saved_entity(&mut self.world, pos, Tag::Compound(full));
// The section is drawn again with the pot's sherds.
let state = self.world.block(pos[0], pos[1], pos[2]);
let _ = self.world.set(pos[0], pos[1], pos[2], state);
}
return;
}
let Some(entity) = self.world.block_entities.get(&key) else {
return;
};
+17
View File
@@ -824,6 +824,7 @@ impl ChunkEncoder {
tag: block_entities
.get(&pos)
.and_then(entity_tag)
.or_else(|| pot_tag(chunk, pos))
.unwrap_or(Tag::End),
});
}
@@ -984,6 +985,22 @@ pub fn entity_tag(entity: &BlockEntity) -> Option<Tag> {
}
}
/// The update tag of the decorated pot at `pos` (DecoratedPotBlockEntity.getUpdateTag,
/// saveCustomOnly). A pot is not a block entity here: its tag is the chunk's saved one.
pub fn pot_tag(chunk: &Chunk, pos: (i32, i32, i32)) -> Option<Tag> {
let at = chunk.saved.as_ref()?.block_entities.iter().find(|t| {
t.get("id") == Some(&Tag::String("minecraft:decorated_pot".into()))
&& t.get("x") == Some(&Tag::Int(pos.0))
&& t.get("y") == Some(&Tag::Int(pos.1))
&& t.get("z") == Some(&Tag::Int(pos.2))
})?;
let entries: Vec<_> = ["sherds", "LootTable", "LootTableSeed", "item"]
.into_iter()
.filter_map(|k| Some((k, at.get(k)?.clone())))
.collect();
(!entries.is_empty()).then(|| Tag::compound(entries))
}
/// Light sections run from one below the world to one above it. A layer
/// exists where vanilla's light storage keeps one: within one section of a
/// non-air section of this column or a neighbouring one (`around`, bit i for
+8 -3
View File
@@ -1566,10 +1566,15 @@ impl Hub {
}
// Block entities with data the client shows.
for &(x, y, z) in &positions {
let Some(entity) = world.block_entities.get(&(x, y, z)) else {
continue;
// A decorated pot is no block entity: its tag is the chunk's saved one.
let tag = match world.block_entities.get(&(x, y, z)) {
Some(entity) => super::chunks::entity_tag(entity),
None => world
.chunks
.get(&(x >> 4, z >> 4))
.and_then(|c| super::chunks::pot_tag(c, (x, y, z))),
};
let Some(tag) = super::chunks::entity_tag(entity) else {
let Some(tag) = tag else {
continue;
};
let state = world.block(x, y, z).0;