diff --git a/Cargo.lock b/Cargo.lock index dfcd045c..ce1e60d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1239,6 +1239,7 @@ version = "0.1.0" dependencies = [ "num-derive", "num-traits", + "pumpkin-world", ] [[package]] diff --git a/pumpkin-inventory/Cargo.toml b/pumpkin-inventory/Cargo.toml index f9f1b10d..83f80a19 100644 --- a/pumpkin-inventory/Cargo.toml +++ b/pumpkin-inventory/Cargo.toml @@ -5,4 +5,7 @@ edition.workspace = true [dependencies] num-traits = "0.2" -num-derive = "0.4" \ No newline at end of file +num-derive = "0.4" + +# For items +pumpkin-world = { path = "../pumpkin-world"} diff --git a/pumpkin-inventory/src/lib.rs b/pumpkin-inventory/src/lib.rs index 5beecd74..1ab7cba1 100644 --- a/pumpkin-inventory/src/lib.rs +++ b/pumpkin-inventory/src/lib.rs @@ -1,5 +1,7 @@ use num_derive::ToPrimitive; +pub mod player; + /// https://wiki.vg/Inventory #[derive(Debug, ToPrimitive)] pub enum WindowType { diff --git a/pumpkin-inventory/src/player.rs b/pumpkin-inventory/src/player.rs new file mode 100644 index 00000000..4e846999 --- /dev/null +++ b/pumpkin-inventory/src/player.rs @@ -0,0 +1,35 @@ +use pumpkin_world::item::Item; + +pub struct PlayerInventory { + // Main Inventory + Hotbar + items: [Option; 36], + armor: [Option; 4], + offhand: Option, + // current selected slot in hortbar + selected: i16, +} + +impl Default for PlayerInventory { + fn default() -> Self { + Self::new() + } +} + +impl PlayerInventory { + pub fn new() -> Self { + Self { + items: [None; 36], + armor: [None; 4], + offhand: None, + // TODO: What when player spawns in with an diffrent index ? + selected: 0, + } + } + + pub fn set_slot(slot: u32, item: Item) {} + + pub fn set_selected(&mut self, slot: i16) { + assert!((0..9).contains(&slot)); + self.selected = slot; + } +} diff --git a/pumpkin-protocol/src/server/play/mod.rs b/pumpkin-protocol/src/server/play/mod.rs index 23842e3c..f1d17178 100644 --- a/pumpkin-protocol/src/server/play/mod.rs +++ b/pumpkin-protocol/src/server/play/mod.rs @@ -1,25 +1,27 @@ -mod c_client_information; -mod c_interact; mod s_chat_command; mod s_chat_message; +mod s_client_information; mod s_confirm_teleport; +mod s_interact; mod s_player_action; mod s_player_command; mod s_player_position; mod s_player_position_rotation; mod s_player_rotation; +mod s_set_held_item; mod s_swing_arm; mod s_use_item_on; -pub use c_client_information::*; -pub use c_interact::*; pub use s_chat_command::*; pub use s_chat_message::*; +pub use s_client_information::*; pub use s_confirm_teleport::*; +pub use s_interact::*; pub use s_player_action::*; pub use s_player_command::*; pub use s_player_position::*; pub use s_player_position_rotation::*; pub use s_player_rotation::*; +pub use s_set_held_item::*; pub use s_swing_arm::*; pub use s_use_item_on::*; diff --git a/pumpkin-protocol/src/server/play/c_client_information.rs b/pumpkin-protocol/src/server/play/s_client_information.rs similarity index 100% rename from pumpkin-protocol/src/server/play/c_client_information.rs rename to pumpkin-protocol/src/server/play/s_client_information.rs diff --git a/pumpkin-protocol/src/server/play/c_interact.rs b/pumpkin-protocol/src/server/play/s_interact.rs similarity index 96% rename from pumpkin-protocol/src/server/play/c_interact.rs rename to pumpkin-protocol/src/server/play/s_interact.rs index ec54a626..62e2b347 100644 --- a/pumpkin-protocol/src/server/play/c_interact.rs +++ b/pumpkin-protocol/src/server/play/s_interact.rs @@ -1,5 +1,4 @@ use pumpkin_macros::packet; -use serde::Deserialize; use crate::{ServerPacket, VarInt}; diff --git a/pumpkin-protocol/src/server/play/s_set_held_item.rs b/pumpkin-protocol/src/server/play/s_set_held_item.rs new file mode 100644 index 00000000..058d812f --- /dev/null +++ b/pumpkin-protocol/src/server/play/s_set_held_item.rs @@ -0,0 +1,8 @@ +use pumpkin_macros::packet; +use serde::Deserialize; + +#[derive(Deserialize)] +#[packet(0x2F)] +pub struct SSetHeldItem { + pub slot: i16, +} diff --git a/pumpkin-world/src/item/mod.rs b/pumpkin-world/src/item/mod.rs index 43084529..ef9ec114 100644 --- a/pumpkin-world/src/item/mod.rs +++ b/pumpkin-world/src/item/mod.rs @@ -9,3 +9,6 @@ pub enum Raritiy { Rare, Epic, } + +#[derive(Clone, Copy)] +pub struct Item {} diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index 6a273915..2af7326c 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -3,8 +3,8 @@ pub mod dimension; pub const WORLD_HEIGHT: usize = 384; pub const WORLD_Y_START_AT: i32 = -64; pub const DIRECT_PALETTE_BITS: u32 = 15; -mod block; +pub mod block; mod global_registry; -mod item; +pub mod item; pub mod radial_chunk_iterator; mod world; diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index af4c1c8d..c6fe5c9b 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -29,7 +29,7 @@ use pumpkin_protocol::{ play::{ SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation, - SPlayerRotation, SSwingArm, SUseItemOn, + SPlayerRotation, SSetHeldItem, SSwingArm, SUseItemOn, }, status::{SPingRequest, SStatusRequest}, }, @@ -301,6 +301,9 @@ impl Client { SUseItemOn::PACKET_ID => { self.handle_use_item_on(server, SUseItemOn::read(bytebuf).unwrap()) } + SSetHeldItem::PACKET_ID => { + self.handle_set_held_item(server, SSetHeldItem::read(bytebuf).unwrap()) + } _ => log::error!("Failed to handle player packet id {}", packet.id.0), } } diff --git a/pumpkin/src/client/player_packet.rs b/pumpkin/src/client/player_packet.rs index ffd1dea2..799ed420 100644 --- a/pumpkin/src/client/player_packet.rs +++ b/pumpkin/src/client/player_packet.rs @@ -8,7 +8,7 @@ use pumpkin_protocol::{ server::play::{ Action, SChatCommand, SChatMessage, SClientInformationPlay, SConfirmTeleport, SInteract, SPlayerAction, SPlayerCommand, SPlayerPosition, SPlayerPositionRotation, SPlayerRotation, - SSwingArm, SUseItemOn, + SSetHeldItem, SSwingArm, SUseItemOn, }, }; use pumpkin_text::TextComponent; @@ -320,4 +320,13 @@ impl Client { location.y += 2; server.broadcast_packet(self, &CBlockUpdate::new(location, 11.into())); } + + pub fn handle_set_held_item(&mut self, _server: &mut Server, held: SSetHeldItem) { + let slot = held.slot; + if !(0..=8).contains(&slot) { + self.kick("Invalid held slot") + } + let player = self.player.as_mut().unwrap(); + player.inventory.set_selected(slot); + } } diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index 52c02390..5f3c28e2 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -2,6 +2,7 @@ use std::str::FromStr; use num_derive::{FromPrimitive, ToPrimitive}; use pumpkin_entity::{entity_type::EntityType, Entity, EntityId}; +use pumpkin_inventory::player::PlayerInventory; use pumpkin_protocol::VarInt; use serde::{Deserialize, Serialize}; @@ -15,6 +16,7 @@ pub struct Player { pub health: f32, pub food: i32, pub food_saturation: f32, + pub inventory: PlayerInventory, // Client side value, Should be not trusted pub on_ground: bool, @@ -22,6 +24,7 @@ pub struct Player { pub sneaking: bool, pub sprinting: bool, + // TODO: prbly should put this into an Living Entitiy or something pub velocity: Vec3, // Current awaiting teleport id, None if did not teleport @@ -41,6 +44,7 @@ impl Player { food: 20, food_saturation: 20.0, velocity: Vec3::new(0.0, 0.0, 0.0), + inventory: PlayerInventory::new(), gamemode, } }