diff --git a/crates/horizon-client/src/game/lan_actions.rs b/crates/horizon-client/src/game/lan_actions.rs index 5cc2656be2..4923cd3dec 100644 --- a/crates/horizon-client/src/game/lan_actions.rs +++ b/crates/horizon-client/src/game/lan_actions.rs @@ -1499,6 +1499,17 @@ impl Game<'_> { // loot table is still to roll, and the table stays. let spectator = host.hub.guest(conn).is_some_and(|g| g.spectator()); if spectator && self.boat_loot_pending(self.boats[i].id) { + // ServerPlayer.openMenu: the refused spectator's action bar, red. + let message = + horizon_client::text::Text::translate("container.spectatorCantOpen", &[]) + .with_color(horizon_client::text::RED); + host.hub.send_to( + conn, + &C::SystemChat(play::SystemChat { + content: horizon_client::lan::data::component_nbt(&message.component()), + overlay: true, + }), + ); return false; } self.unpack_boat_loot(i); diff --git a/crates/horizon-client/src/game/storage.rs b/crates/horizon-client/src/game/storage.rs index cbcfb215e4..a37634e594 100644 --- a/crates/horizon-client/src/game/storage.rs +++ b/crates/horizon-client/src/game/storage.rs @@ -51,6 +51,7 @@ impl Game<'_> { } // BaseContainerBlockEntity.canOpen: a spectator opens no container that still // has a loot table to unpack (it clears while it rolls, on first open). + // ServerPlayer.openMenu sends the refused spectator a red action bar. if self .world .chunks @@ -58,6 +59,10 @@ impl Game<'_> { .and_then(|c| c.saved.as_ref()) .is_some_and(|s| s.rolled_loot.iter().any(|r| r.pos == key)) { + self.send_overlay_message( + Text::translate("container.spectatorCantOpen", &[]) + .with_color(horizon_client::text::RED), + ); return; } let Some(entity) = BlockEntity::for_block(&name) else {