Skip to content

Commit

Permalink
resync readonly inventory after block interaction (#671)
Browse files Browse the repository at this point in the history
fixes a desync where a player with readonly inventory perfoms a block
interaction (such as placing a block).
  • Loading branch information
maxomatic458 authored Oct 25, 2024
1 parent c57193a commit 8f3f84d
Showing 1 changed file with 32 additions and 1 deletion.
33 changes: 32 additions & 1 deletion crates/valence_inventory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use player_inventory::PlayerInventory;
use tracing::{debug, warn};
use valence_server::client::{Client, FlushPacketsSet, SpawnClientsSet};
use valence_server::event_loop::{EventLoopPreUpdate, PacketEvent};
use valence_server::interact_block::InteractBlockEvent;
pub use valence_server::protocol::packets::play::click_slot_c2s::{ClickMode, SlotChange};
use valence_server::protocol::packets::play::open_screen_s2c::WindowType;
pub use valence_server::protocol::packets::play::player_action_c2s::PlayerAction;
Expand All @@ -22,7 +23,7 @@ use valence_server::protocol::packets::play::{
};
use valence_server::protocol::{VarInt, WritePacket};
use valence_server::text::IntoText;
use valence_server::{GameMode, ItemKind, ItemStack, Text};
use valence_server::{GameMode, Hand, ItemKind, ItemStack, Text};

pub mod player_inventory;
mod validate;
Expand Down Expand Up @@ -54,6 +55,7 @@ impl Plugin for InventoryPlugin {
handle_creative_inventory_action,
handle_close_handled_screen,
handle_player_actions,
resync_readonly_inventory_after_block_interaction,
),
)
.init_resource::<InventorySettings>()
Expand Down Expand Up @@ -1336,6 +1338,35 @@ fn handle_player_actions(
}
}

/// If the player tries to place a block while their inventory is readonly
/// it will be desynced, therefore we set the slot as changed.
fn resync_readonly_inventory_after_block_interaction(
mut clients: Query<(&mut Inventory, &HeldItem)>,
mut events: EventReader<InteractBlockEvent>,
) {
for event in events.read() {
let Ok((mut inventory, held_item)) = clients.get_mut(event.client) else {
continue;
};

if !inventory.readonly {
continue;
}

let slot = if event.hand == Hand::Main {
held_item.slot()
} else {
PlayerInventory::SLOT_OFFHAND
};

if inventory.slot(slot).is_empty() {
continue;
}

inventory.changed |= 1 << slot;
}
}

// TODO: make this event user friendly.
#[derive(Event, Clone, Debug)]
pub struct CreativeInventoryActionEvent {
Expand Down

0 comments on commit 8f3f84d

Please sign in to comment.