valence_equipment/
inventory_sync.rs1use valence_inventory::player_inventory::PlayerInventory;
2use valence_inventory::{HeldItem, Inventory, UpdateSelectedSlotEvent};
3use valence_server::entity::player::PlayerEntity;
4
5use super::*;
6
7#[derive(Debug, Default, Clone, Component)]
10pub struct EquipmentInventorySync;
11
12pub(crate) fn equipment_inventory_sync(
18 mut clients: Query<
19 (&mut Equipment, &mut Inventory, &mut HeldItem),
20 (
21 Or<(Changed<Equipment>, Changed<Inventory>, Changed<HeldItem>)>,
22 With<EquipmentInventorySync>,
23 With<PlayerEntity>,
24 ),
25 >,
26) {
27 for (mut equipment, mut inventory, held_item) in &mut clients {
28 if equipment.changed & (1 << Equipment::MAIN_HAND_IDX) != 0 {
30 let item = equipment.main_hand().clone();
31 inventory.set_slot(held_item.slot(), item);
32 } else {
33 let item = inventory.slot(held_item.slot()).clone();
39 equipment.set_main_hand(item);
40 }
41
42 let slots = [
43 (Equipment::OFF_HAND_IDX, PlayerInventory::SLOT_OFFHAND),
44 (Equipment::HEAD_IDX, PlayerInventory::SLOT_HEAD),
45 (Equipment::CHEST_IDX, PlayerInventory::SLOT_CHEST),
46 (Equipment::LEGS_IDX, PlayerInventory::SLOT_LEGS),
47 (Equipment::FEET_IDX, PlayerInventory::SLOT_FEET),
48 ];
49
50 for (equipment_slot, inventory_slot) in slots {
54 if equipment.changed & (1 << equipment_slot) != 0 {
56 let item = equipment.slot(equipment_slot).clone();
57 inventory.set_slot(inventory_slot, item);
58 } else if inventory.is_changed() {
59 let item = inventory.slot(inventory_slot).clone();
60 equipment.set_slot(equipment_slot, item);
61 }
62 }
63 }
64}
65
66pub(crate) fn equipment_held_item_sync_from_client(
69 mut clients: Query<(&HeldItem, &Inventory, &mut Equipment), With<EquipmentInventorySync>>,
70 mut events: EventReader<UpdateSelectedSlotEvent>,
71) {
72 for event in events.read() {
73 let Ok((held_item, inventory, mut equipment)) = clients.get_mut(event.client) else {
74 continue;
75 };
76
77 let item = inventory.slot(held_item.slot()).clone();
78 equipment.set_main_hand(item);
79 }
80}
81
82pub(crate) fn on_attach_inventory_sync(
83 entities: Query<Option<&PlayerEntity>, (Added<EquipmentInventorySync>, With<Inventory>)>,
84) {
85 for entity in &entities {
86 if entity.is_none() {
87 tracing::warn!(
88 "EquipmentInventorySync attached to non-player entity, this will have no effect"
89 );
90 }
91 }
92}