first steps towards making containers openable

This commit is contained in:
Edvin Bryntesson 2024-08-21 13:00:49 +02:00
parent b0df1a74d4
commit 99116190d9
No known key found for this signature in database
6 changed files with 118 additions and 10 deletions

View File

@ -3,7 +3,7 @@ use num_derive::ToPrimitive;
pub mod player; pub mod player;
/// https://wiki.vg/Inventory /// https://wiki.vg/Inventory
#[derive(Debug, ToPrimitive)] #[derive(Debug, ToPrimitive, Clone)]
pub enum WindowType { pub enum WindowType {
// not used // not used
Generic9x1, Generic9x1,
@ -41,3 +41,11 @@ pub enum WindowType {
CartographyTable, CartographyTable,
Stonecutter, Stonecutter,
} }
impl WindowType {
pub const fn default_title(&self) -> &'static str {
match self {
_ => "WINDOW TITLE"
}
}
}

View File

@ -95,4 +95,13 @@ impl PlayerInventory {
debug_assert!((0..9).contains(&self.selected)); debug_assert!((0..9).contains(&self.selected));
self.items[self.selected + 36 - 9].as_ref() self.items[self.selected + 36 - 9].as_ref()
} }
pub fn slots(&self) -> Vec<Option<&Item>> {
let mut slots = vec![self.crafting_output.as_ref()];
slots.extend(self.crafting.iter().map(|c|c.as_ref()));
slots.extend(self.armor.iter().map(|c|c.as_ref()));
slots.extend(self.items.iter().map(|c|c.as_ref()));
slots.push(self.offhand.as_ref());
slots
}
} }

View File

@ -0,0 +1,27 @@
use pumpkin_macros::packet;
use serde::Serialize;
use crate::slot::Slot;
use crate::VarInt;
#[derive(Serialize)]
#[packet(0x13)]
pub struct CSetContainerContent<'a> {
window_id: u8,
state_id: VarInt,
count: VarInt,
slot_data: &'a [Slot],
carried_item: Slot
}
impl<'a> CSetContainerContent<'a> {
pub fn new(window_id: u8,state_id: VarInt, slots: &'a [Slot], carried_item: Slot) -> Self {
Self {
window_id,
state_id,
count: slots.len().try_into().unwrap(),
slot_data: slots,
carried_item
}
}
}

View File

@ -33,6 +33,7 @@ mod c_update_entity_pos;
mod c_update_entity_rot; mod c_update_entity_rot;
mod c_worldevent; mod c_worldevent;
mod player_action; mod player_action;
mod c_set_container_content;
pub use c_acknowledge_block::*; pub use c_acknowledge_block::*;
pub use c_actionbar::*; pub use c_actionbar::*;
@ -69,3 +70,4 @@ pub use c_update_entity_pos::*;
pub use c_update_entity_rot::*; pub use c_update_entity_rot::*;
pub use c_worldevent::*; pub use c_worldevent::*;
pub use player_action::*; pub use player_action::*;
pub use c_set_container_content::*;

View File

@ -3,9 +3,10 @@ use pumpkin_world::item::Item;
use serde::{ use serde::{
de::{self, SeqAccess, Visitor}, de::{self, SeqAccess, Visitor},
Deserialize, Deserialize,
Serialize
}; };
#[derive(Debug, Clone)] #[derive(Debug, Clone, Serialize)]
#[allow(dead_code)] #[allow(dead_code)]
pub struct Slot { pub struct Slot {
item_count: VarInt, item_count: VarInt,
@ -83,12 +84,29 @@ impl Slot {
item_count: self.item_count.0.try_into().unwrap(), item_count: self.item_count.0.try_into().unwrap(),
}) })
} }
}
impl From<Slot> for Item { pub const fn empty() -> Self {
fn from(slot: Slot) -> Self { Slot {
Item { item_count: VarInt(0),
item_count: slot.item_count.0.try_into().unwrap(), item_id: None,
item_id: slot.item_id.unwrap().0.try_into().unwrap(), num_components_to_add: None,
num_components_to_remove: None,
components_to_add: None,
components_to_remove: None,
} }
} }
} }
impl From<&Item> for Slot {
fn from(item: &Item) -> Self {
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_remove: None,
components_to_add: None,
components_to_remove: None,
}
}
}

View File

@ -18,7 +18,7 @@ use pumpkin_protocol::{
client::{ client::{
config::CConfigDisconnect, config::CConfigDisconnect,
login::CLoginDisconnect, login::CLoginDisconnect,
play::{CGameEvent, CPlayDisconnect, CSyncPlayerPostion, CSystemChatMessge}, play::{CGameEvent, CPlayDisconnect, CSyncPlayerPostion, CSystemChatMessge, CSetContainerContent},
}, },
packet_decoder::PacketDecoder, packet_decoder::PacketDecoder,
packet_encoder::PacketEncoder, packet_encoder::PacketEncoder,
@ -40,6 +40,10 @@ use pumpkin_text::TextComponent;
use std::io::Read; use std::io::Read;
use thiserror::Error; use thiserror::Error;
use pumpkin_inventory::WindowType;
use pumpkin_protocol::client::play::COpenScreen;
use pumpkin_protocol::slot::Slot;
use pumpkin_world::item::Item;
pub mod authentication; pub mod authentication;
mod client_packet; mod client_packet;
@ -174,6 +178,46 @@ impl Client {
player.gamemode = gamemode; player.gamemode = gamemode;
self.send_packet(&CGameEvent::new(3, gamemode.to_f32().unwrap())); 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>) {
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);
}
pub fn set_container_content<'a>(&mut self, window_type: WindowType, items: Option<Vec<Option<&'a Item>>>, carried_item: Option<&'a Item>) {
let player = self.player.as_ref().unwrap();
let slots: Vec<Slot> = {if let Some(mut items) = items {
items.extend(player.inventory.slots()
);
items
} else {
player.inventory.slots()
}.into_iter()
.map(|item|{
if let Some(item) = item {
Slot::from(item)
} else {
Slot::empty()
}
}).collect()};
let carried_item = {
if let Some(item) = carried_item {
item.into()
} else {
Slot::empty()
}
};
self.send_packet(&CSetContainerContent::new(window_type as u8, 10.into(), &slots, carried_item))
}
pub async fn process_packets(&mut self, server: &mut Server) { pub async fn process_packets(&mut self, server: &mut Server) {
let mut i = 0; let mut i = 0;
@ -359,7 +403,7 @@ impl Client {
} }
} }
} }
pub fn send_system_message(&mut self, text: TextComponent) { pub fn send_system_message(&mut self, text: TextComponent) {
self.send_packet(&CSystemChatMessge::new(text, false)); self.send_packet(&CSystemChatMessge::new(text, false));
} }