From b26b9644353f84d7cfca4945f9dbedf88d026d33 Mon Sep 17 00:00:00 2001 From: Bafran Date: Fri, 27 Dec 2024 14:34:00 -0800 Subject: [PATCH] Pick Item working for hotbar slots --- pumpkin-inventory/src/player.rs | 18 ++-- .../src/server/play/s_pick_item.rs | 8 +- pumpkin/src/client/player_packet.rs | 91 ++++++++++++------- pumpkin/src/entity/player.rs | 6 +- 4 files changed, 75 insertions(+), 48 deletions(-) diff --git a/pumpkin-inventory/src/player.rs b/pumpkin-inventory/src/player.rs index 81728888..d3d37c97 100644 --- a/pumpkin-inventory/src/player.rs +++ b/pumpkin-inventory/src/player.rs @@ -121,17 +121,15 @@ impl PlayerInventory { self.items[self.selected + 36 - 9] = item; } - pub fn get_hotbar_slot(&mut self) -> Option { - // // first searches the player's hotbar for an empty slot, starting from the current slot and looping around to the slot before it. - // for i in 0..9 { - // let slot = (self.selected + i) % 9; - // if self.items[slot + 36].is_none() { - // return Some(slot + 36); - // } - // } + pub fn get_pick_item_hotbar_slot(&mut self, item_id: u16) -> usize { + for slot in 35..=44 { + match &self.items[slot - 9] { + Some(item) if item.item_id == item_id => return slot, + _ => continue, + } + } - // If there still are no slots that meet that criteria, then the server uses the currently selected slot - Some(self.selected) + self.selected + 36 } diff --git a/pumpkin-protocol/src/server/play/s_pick_item.rs b/pumpkin-protocol/src/server/play/s_pick_item.rs index 56811d91..f337bbb9 100644 --- a/pumpkin-protocol/src/server/play/s_pick_item.rs +++ b/pumpkin-protocol/src/server/play/s_pick_item.rs @@ -1,10 +1,10 @@ +use pumpkin_core::math::position::WorldPosition; use pumpkin_macros::server_packet; use serde::Deserialize; -use crate::VarInt; - #[derive(Deserialize)] #[server_packet("play:pick_item_from_block")] -pub struct SPickItem { - pub slot: VarInt, +pub struct SPickItemFromBlock { + pub pos: WorldPosition, + pub include_data: bool, } diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index 31a4f5e6..811258ca 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -36,11 +36,12 @@ use pumpkin_protocol::{ Action, ActionType, SChatCommand, SChatMessage, SClientCommand, SClientInformationPlay, SConfirmTeleport, SInteract, SPlayPingRequest, SPlayerAbilities, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation, SPlayerRotation, - SSetCreativeSlot, SSetHeldItem, SSwingArm, SUseItemOn, Status, SPickItem, + SSetCreativeSlot, SSetHeldItem, SSwingArm, SUseItemOn, Status, SPickItemFromBlock, }, }; use pumpkin_world::block::{block_registry::get_block_by_item, BlockFace}; use pumpkin_world::item::item_registry::get_item_by_id; +use pumpkin_world::item::ItemStack; use thiserror::Error; fn modulus(a: f32, b: f32) -> f32 { @@ -312,38 +313,66 @@ impl Player { .store(ground.on_ground, std::sync::atomic::Ordering::Relaxed); } - pub async fn handle_pick_item(&self, pick_item: SPickItem) { - let source_slot = pick_item.slot.0 as usize; - let mut inventory = self.inventory().lock().await; - - let dest_slot = inventory.get_hotbar_slot().unwrap() + 36; - let dest_item = inventory.get_slot(source_slot).unwrap().as_ref(); + pub async fn handle_pick_item_from_block(&self, pick_item: SPickItemFromBlock) { + let pos = pick_item.pos; + // If player is in creative mode && include_data, then pick block with additional data + let include_data = pick_item.include_data; + + if self.can_interact_with_block_at(&pos, 1.0) { + let world = self.world(); + let block = world.get_block(pos).await; + if let Ok(block) = block { + let item_id = block.item_id; + let mut inventory = self.inventory().lock().await; + + log::warn!("Item id: {}", item_id); + + let dest_slot = inventory.get_pick_item_hotbar_slot(item_id); + log::warn!("Dest slot: {}", dest_slot); + // let picked_item = ItemStack::new(1, item_id); + // let slot = Slot::from(&picked_item); + // // Returns previous value + // inventory.state_id += 1; + // // Set Container Slot with window ID set to -2, updating the chosen hotbar slot. + // let packet = CSetContainerSlot::new( + // (-2) as i8, + // (inventory.state_id) as i32, + // dest_slot, + // &slot + // ); + // self.client.send_packet(&packet).await; + + // Set held item + let packet = CSetHeldItem::new((dest_slot - 36) as i8); + self.client.send_packet(&packet).await; + } + } else { + log::warn!("Player cannot interact with block at {}", pos); + } - log::warn!("Picking item from slot {} to slot {}", source_slot, dest_slot); - - // Set Container Slot with window ID set to -2, updating the chosen hotbar slot. - let slot = Slot::from(dest_item); - let packet = CSetContainerSlot::new( - (-2) as i8, - (inventory.state_id) as i32, - dest_slot, - &slot - ); - self.client.send_packet(&packet).await; - - // Set Container Slot with window ID set to -2, updating the slot where the picked item used to be. - let slot = Slot::from(None); - let packet = CSetContainerSlot::new( - (-2) as i8, - (inventory.state_id) as i32, - source_slot, - &slot - ); - self.client.send_packet(&packet).await; - // Set Held Item, switching to the newly chosen slot. - let packet = CSetHeldItem::new(dest_slot as i8); - self.client.send_packet(&packet).await; + // Set Container Slot with window ID set to -2, updating the chosen hotbar slot. + // let packet = CSetContainerSlot::new( + // (-2) as i8, + // (inventory.state_id) as i32, + // dest_slot, + // &slot + // ); + // self.client.send_packet(&packet).await; + + // // Set Container Slot with window ID set to -2, updating the slot where the picked item used to be. + // let slot = Slot::from(None); + // let packet = CSetContainerSlot::new( + // (-2) as i8, + // (inventory.state_id) as i32, + // source_slot, + // &slot + // ); + // self.client.send_packet(&packet).await; + + // // Set Held Item, switching to the newly chosen slot. + // let packet = CSetHeldItem::new(dest_slot as i8); + // self.client.send_packet(&packet).await; } pub async fn handle_player_command(&self, command: SPlayerCommand) { diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 2bb6d8b8..84036b19 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -39,7 +39,7 @@ use pumpkin_protocol::{ SChatCommand, SChatMessage, SClientCommand, SClientInformationPlay, SClientTickEnd, SCommandSuggestion, SConfirmTeleport, SInteract, SPlayerAbilities, SPlayerAction, SPlayerCommand, SPlayerInput, SPlayerPosition, SPlayerPositionRotation, SPlayerRotation, - SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem, SUseItemOn, SPickItem, + SSetCreativeSlot, SSetHeldItem, SSetPlayerGround, SSwingArm, SUseItem, SUseItemOn, SPickItemFromBlock, }, RawPacket, ServerPacket, SoundCategory, VarInt, }; @@ -712,8 +712,8 @@ impl Player { SSetPlayerGround::PACKET_ID => { self.handle_player_ground(&SSetPlayerGround::read(bytebuf)?); } - SPickItem::PACKET_ID => { - self.handle_pick_item(SPickItem::read(bytebuf)?).await; + SPickItemFromBlock::PACKET_ID => { + self.handle_pick_item_from_block(SPickItemFromBlock::read(bytebuf)?).await; } SPlayerAbilities::PACKET_ID => { self.handle_player_abilities(SPlayerAbilities::read(bytebuf)?)