From 475639dec09a27901dffa4766a37c2733a3cccc4 Mon Sep 17 00:00:00 2001 From: Carson McManus Date: Mon, 5 Jun 2023 15:14:03 -0400 Subject: [PATCH] refactor handle_click_slot to primarily emit ClickSlot events, and handle those in a new system --- crates/valence_inventory/src/lib.rs | 113 +++++++++++++++++++--------- 1 file changed, 76 insertions(+), 37 deletions(-) diff --git a/crates/valence_inventory/src/lib.rs b/crates/valence_inventory/src/lib.rs index 1bb6fe3..d019163 100644 --- a/crates/valence_inventory/src/lib.rs +++ b/crates/valence_inventory/src/lib.rs @@ -25,6 +25,7 @@ use std::ops::Range; use bevy_app::prelude::*; use bevy_ecs::prelude::*; +use menu::OpenMenu; use packet::{ ClickMode, ClickSlotC2s, CloseHandledScreenC2s, CloseScreenS2c, CreativeInventoryActionC2s, InventoryS2c, OpenScreenS2c, ScreenHandlerSlotUpdateS2c, SlotChange, UpdateSelectedSlotC2s, @@ -40,6 +41,7 @@ use valence_core::protocol::encode::WritePacket; use valence_core::protocol::var_int::VarInt; use valence_core::text::Text; +pub mod menu; pub mod packet; mod validate; @@ -65,7 +67,8 @@ impl Plugin for InventoryPlugin { .add_systems( ( handle_update_selected_slot, - handle_click_slot, + emit_events_from_packets, + handle_click_slot.after(emit_events_from_packets), handle_creative_inventory_action, handle_close_handled_screen, handle_player_actions, @@ -332,11 +335,11 @@ pub struct ClientInventoryState { state_id: Wrapping, /// Tracks what slots have been changed by this client in this tick, so we /// don't need to send updates for them. - slots_changed: u64, + pub(crate) slots_changed: u64, /// Whether the client has updated the cursor item in this tick. This is not /// on the `CursorItem` component to make maintaining accurate change /// detection for end users easier. - client_updated_cursor_item: bool, + pub(crate) client_updated_cursor_item: bool, // TODO: make this a separate modifiable component. held_item_slot: u16, } @@ -754,7 +757,7 @@ pub struct DropItemStack { pub stack: ItemStack, } -fn handle_click_slot( +fn emit_events_from_packets( mut packets: EventReader, mut clients: Query<( &mut Client, @@ -969,22 +972,6 @@ fn handle_click_slot( continue; } - - cursor_item.set_if_neq(CursorItem(pkt.carried_item.clone())); - - for slot in pkt.slot_changes.clone() { - if (0i16..target_inventory.slot_count() as i16).contains(&slot.idx) { - // The client is interacting with a slot in the target inventory. - target_inventory.set_slot(slot.idx as u16, slot.item); - open_inventory.client_changed |= 1 << slot.idx; - } else { - // The client is interacting with a slot in their own inventory. - let slot_id = - convert_to_player_slot_id(target_inventory.kind, slot.idx as u16); - client_inv.set_slot(slot_id, slot.item); - inv_state.slots_changed |= 1 << slot_id; - } - } } else { // The client is interacting with their own inventory. @@ -1004,23 +991,6 @@ fn handle_click_slot( continue; } - - cursor_item.set_if_neq(CursorItem(pkt.carried_item.clone())); - inv_state.client_updated_cursor_item = true; - - for slot in pkt.slot_changes.clone() { - if (0i16..client_inv.slot_count() as i16).contains(&slot.idx) { - client_inv.set_slot(slot.idx as u16, slot.item); - inv_state.slots_changed |= 1 << slot.idx; - } else { - // The client is trying to interact with a slot that does not exist, - // ignore. - warn!( - "Client attempted to interact with slot {} which does not exist", - slot.idx - ); - } - } } click_slot_events.send(ClickSlot { @@ -1037,6 +1007,75 @@ fn handle_click_slot( } } +fn handle_click_slot( + mut click_slots: EventReader, + mut clients: Query<( + &mut Client, + &mut Inventory, + &mut ClientInventoryState, + Option<&mut OpenInventory>, + &mut CursorItem, + )>, + mut inventories: Query<&mut Inventory, Without>, +) { + for click in click_slots.iter() { + // The player is clicking a slot in an inventory. + let Ok(( + mut client, + mut client_inv, + mut inv_state, + open_inventory, + mut cursor_item + )) = clients.get_mut(click.client) else { + // The client does not exist, ignore. + continue; + }; + + if let Some(mut open_inventory) = open_inventory { + // The player is interacting with an inventory that is open. + + let Ok(mut target_inventory) = inventories.get_mut(open_inventory.entity) else { + // The inventory does not exist, ignore. + continue; + }; + + cursor_item.set_if_neq(CursorItem(click.carried_item.clone())); + inv_state.client_updated_cursor_item = true; + + for slot in click.slot_changes.clone() { + if (0i16..target_inventory.slot_count() as i16).contains(&slot.idx) { + // The client is interacting with a slot in the target inventory. + target_inventory.set_slot(slot.idx as u16, slot.item); + open_inventory.client_changed |= 1 << slot.idx; + } else { + // The client is interacting with a slot in their own inventory. + let slot_id = convert_to_player_slot_id(target_inventory.kind, slot.idx as u16); + client_inv.set_slot(slot_id, slot.item); + inv_state.slots_changed |= 1 << slot_id; + } + } + } else { + // The client is interacting with their own inventory. + cursor_item.set_if_neq(CursorItem(click.carried_item.clone())); + inv_state.client_updated_cursor_item = true; + + for slot in click.slot_changes.clone() { + if (0i16..client_inv.slot_count() as i16).contains(&slot.idx) { + client_inv.set_slot(slot.idx as u16, slot.item); + inv_state.slots_changed |= 1 << slot.idx; + } else { + // The client is trying to interact with a slot that does not exist, + // ignore. + warn!( + "Client attempted to interact with slot {} which does not exist", + slot.idx + ); + } + } + } + } +} + fn handle_player_actions( mut packets: EventReader, mut clients: Query<(&mut Inventory, &mut ClientInventoryState)>,