diff --git a/pumpkin-protocol/src/client/play/c_set_container_content.rs b/pumpkin-protocol/src/client/play/c_set_container_content.rs index 39a298d47..666039a7f 100644 --- a/pumpkin-protocol/src/client/play/c_set_container_content.rs +++ b/pumpkin-protocol/src/client/play/c_set_container_content.rs @@ -10,12 +10,12 @@ pub struct CSetContainerContent<'a> { state_id: VarInt, count: VarInt, slot_data: &'a [Slot], - carried_item: Slot + carried_item: &'a Slot } impl<'a> CSetContainerContent<'a> { - pub fn new(window_id: u8,state_id: VarInt, slots: &'a [Slot], carried_item: Slot) -> Self { + pub fn new(window_id: u8,state_id: VarInt, slots: &'a [Slot], carried_item: &'a Slot) -> Self { Self { window_id, state_id, diff --git a/pumpkin-protocol/src/slot.rs b/pumpkin-protocol/src/slot.rs index 84ffd662d..51521a960 100644 --- a/pumpkin-protocol/src/slot.rs +++ b/pumpkin-protocol/src/slot.rs @@ -1,12 +1,9 @@ use crate::VarInt; use pumpkin_world::item::Item; -use serde::{ - de::{self, SeqAccess, Visitor}, - Deserialize, - Serialize -}; +use serde::{de::{self, SeqAccess, Visitor}, Deserialize, Serialize, Serializer}; +use serde::ser::SerializeSeq; -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone)] #[allow(dead_code)] pub struct Slot { item_count: VarInt, @@ -76,6 +73,60 @@ impl<'de> Deserialize<'de> for Slot { deserializer.deserialize_seq(VarIntVisitor) } } + +impl Serialize for Slot { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + if self.item_count == 0.into() { + let mut s = serializer.serialize_seq(Some(1))?; + s.serialize_element(&self.item_count)?; + s.end() + } else { + match (&self.num_components_to_add,&self.num_components_to_remove) { + (Some(to_add),Some(to_remove)) => { + let mut s = serializer.serialize_seq(Some(6))?; + s.serialize_element(&self.item_count)?; + s.serialize_element(self.item_id.as_ref().unwrap())?; + s.serialize_element(to_add)?; + s.serialize_element(to_remove)?; + s.serialize_element(self.components_to_add.as_ref().unwrap())?; + s.serialize_element(self.components_to_remove.as_ref().unwrap())?; + s.end() + } + (None, Some(to_remove)) => { + let mut s = serializer.serialize_seq(Some(5))?; + s.serialize_element(&self.item_count)?; + s.serialize_element(self.item_id.as_ref().unwrap())?; + s.serialize_element(&VarInt(0))?; + s.serialize_element(to_remove)?; + s.serialize_element(self.components_to_remove.as_ref().unwrap())?; + s.end() + } + (Some(to_add),None) => { + let mut s = serializer.serialize_seq(Some(5))?; + s.serialize_element(&self.item_count)?; + s.serialize_element(self.item_id.as_ref().unwrap())?; + s.serialize_element(to_add)?; + s.serialize_element(&VarInt(0))?; + s.serialize_element(self.components_to_add.as_ref().unwrap())?; + s.end() + } + (None,None) => { + let mut s = serializer.serialize_seq(Some(4))?; + s.serialize_element(&self.item_count)?; + s.serialize_element(&self.item_id.as_ref().unwrap())?; + s.serialize_element(&VarInt(0))?; + s.serialize_element(&VarInt(0))?; + s.end() + } + } + + } + } +} + impl Slot { pub fn to_item(self) -> Option { let item_id = self.item_id?.0.try_into().unwrap(); @@ -103,7 +154,7 @@ impl From<&Item> for Slot { item_count: item.item_count.into(), item_id: Some(item.item_id.into()), // TODO: add these - num_components_to_add: None, + num_components_to_add:None, num_components_to_remove: None, components_to_add: None, components_to_remove: None, diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 59e38e0f0..bc7d598ff 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -41,6 +41,7 @@ use pumpkin_text::TextComponent; use std::io::Read; use thiserror::Error; use pumpkin_inventory::WindowType; +use pumpkin_protocol::bytebuf::ByteBuffer; use pumpkin_protocol::client::play::COpenScreen; use pumpkin_protocol::slot::Slot; use pumpkin_world::item::Item; @@ -179,23 +180,18 @@ impl Client { self.send_packet(&CGameEvent::new(3, gamemode.to_f32().unwrap())); } - pub fn open_container(&mut self, window_type: WindowType, minecraft_menu_id: &str,window_title: Option<&str>) { + pub fn open_container(&mut self, window_type: WindowType, minecraft_menu_id: &str,window_title: Option<&str>, items: Option>>, carried_item: Option<&Item>) { let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY.get("minecraft:menu").unwrap().entries.get(minecraft_menu_id).expect("Should be a valid menu id").get("protocol_id").unwrap()).into(); let title = TextComponent::text(window_title.unwrap_or(window_type.default_title())); self.send_packet(&COpenScreen::new((window_type.clone() as u8 +1).into(),menu_protocol_id, title)); - let temp_item = Item { - item_id: 91, // Diamond block - item_count: 64 - }; - self.set_container_content(window_type, Some([Some(&temp_item);27].to_vec()), None); + self.set_container_content(window_type, items, carried_item); } pub fn set_container_content<'a>(&mut self, window_type: WindowType, items: Option>>, carried_item: Option<&'a Item>) { let player = self.player.as_ref().unwrap(); let slots: Vec = {if let Some(mut items) = items { - items.extend(player.inventory.slots() - ); + items.extend(player.inventory.slots()); items } else { player.inventory.slots() @@ -215,8 +211,7 @@ impl Client { Slot::empty() } }; - - self.send_packet(&CSetContainerContent::new(window_type as u8, 10.into(), &slots, carried_item)) + self.send_packet(&CSetContainerContent::new(window_type as u8+1, 0.into(), &slots, &carried_item)); } pub async fn process_packets(&mut self, server: &mut Server) {