From 05bc471106110bc3348acc04268f60b27215886c Mon Sep 17 00:00:00 2001 From: makscoder Date: Thu, 5 Nov 2026 20:59:03 +0300 Subject: [PATCH] A refused spectator opening gets the red action bar ServerPlayer.openMenu, when createMenu returns null for a spectator, sends container.spectatorCantOpen to the action bar (red). Horizon's refusal in spectator_open_menu and the chest-boat guest handler was silent. --- crates/horizon-client/src/game/lan_actions.rs | 11 +++++++++++ crates/horizon-client/src/game/storage.rs | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/crates/horizon-client/src/game/lan_actions.rs b/crates/horizon-client/src/game/lan_actions.rs index 1729b2ad2a..7cd8f4bd98 100644 --- a/crates/horizon-client/src/game/lan_actions.rs +++ b/crates/horizon-client/src/game/lan_actions.rs @@ -1510,6 +1510,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 {