Skip to content

Commit

Permalink
Merge pull request #59 from Bryntet/master
Browse files Browse the repository at this point in the history
Add packets CCloseContainer, CSetContainerProperty and SCloseContainer
  • Loading branch information
Snowiiii authored Aug 24, 2024
2 parents c7f15de + 3428f03 commit 92a3f6c
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 3 deletions.
5 changes: 3 additions & 2 deletions pumpkin-inventory/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use num_derive::ToPrimitive;
use num_derive::{FromPrimitive, ToPrimitive};

pub mod player;
pub mod window_property;

/// https://wiki.vg/Inventory
#[derive(Debug, ToPrimitive, Clone)]
#[derive(Debug, ToPrimitive, FromPrimitive, Clone)]
pub enum WindowType {
// not used
Generic9x1,
Expand Down
89 changes: 89 additions & 0 deletions pumpkin-inventory/src/window_property.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use num_derive::ToPrimitive;
use num_traits::ToPrimitive;

pub trait WindowPropertyTrait {
fn to_id(self) -> i16;
}

impl<T: ToPrimitive> WindowPropertyTrait for T {
fn to_id(self) -> i16 {
self.to_i16().unwrap()
}
}

pub struct WindowProperty<T: WindowPropertyTrait> {
window_property: T,
value: i16,
}

impl<T: WindowPropertyTrait> WindowProperty<T> {
pub fn new(window_property: T, value: i16) -> Self {
Self {
window_property,
value,
}
}

pub fn into_tuple(self) -> (i16, i16) {
(self.window_property.to_id(), self.value)
}
}
#[derive(ToPrimitive)]
pub enum Furnace {
FireIcon,
MaximumFuelBurnTime,
ProgressArrow,
MaximumProgress,
}

pub enum EnchantmentTable {
LevelRequirement { slot: u8 },
EnchantmentSeed,
EnchantmentId { slot: u8 },
EnchantmentLevel { slot: u8 },
}

impl WindowPropertyTrait for EnchantmentTable {
fn to_id(self) -> i16 {
use EnchantmentTable::*;

(match self {
LevelRequirement { slot } => slot,
EnchantmentSeed => 3,
EnchantmentId { slot } => 4 + slot,
EnchantmentLevel { slot } => 7 + slot,
}) as i16
}
}
#[derive(ToPrimitive)]
pub enum Beacon {
PowerLevel,
FirstPotionEffect,
SecondPotionEffect,
}

#[derive(ToPrimitive)]
pub enum Anvil {
RepairCost,
}

#[derive(ToPrimitive)]
pub enum BrewingStand {
BrewTime,
FuelTime,
}

#[derive(ToPrimitive)]
pub enum Stonecutter {
SelectedRecipe,
}

#[derive(ToPrimitive)]
pub enum Loom {
SelectedPattern,
}

#[derive(ToPrimitive)]
pub enum Lectern {
PageNumber,
}
14 changes: 14 additions & 0 deletions pumpkin-protocol/src/client/play/c_close_container.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use pumpkin_macros::packet;
use serde::Serialize;

#[derive(Serialize)]
#[packet(0x12)]
pub struct CCloseContainer {
window_id: u8,
}

impl CCloseContainer {
pub const fn new(window_id: u8) -> Self {
Self { window_id }
}
}
19 changes: 19 additions & 0 deletions pumpkin-protocol/src/client/play/c_set_container_property.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use pumpkin_macros::packet;
use serde::Serialize;
#[derive(Serialize)]
#[packet(0x14)]
pub struct CSetContainerProperty {
window_id: u8,
property: i16,
value: i16,
}

impl CSetContainerProperty {
pub const fn new(window_id: u8, property: i16, value: i16) -> Self {
Self {
window_id,
property,
value,
}
}
}
4 changes: 4 additions & 0 deletions pumpkin-protocol/src/client/play/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod c_block_update;
mod c_center_chunk;
mod c_change_difficulty;
mod c_chunk_data;
mod c_close_container;
mod c_disguised_chat_message;
mod c_entity_animation;
mod c_entity_metadata;
Expand All @@ -23,6 +24,7 @@ mod c_player_info_update;
mod c_player_remove;
mod c_remove_entities;
mod c_set_container_content;
mod c_set_container_property;
mod c_set_container_slot;
mod c_set_held_item;
mod c_set_title;
Expand All @@ -44,6 +46,7 @@ pub use c_block_update::*;
pub use c_center_chunk::*;
pub use c_change_difficulty::*;
pub use c_chunk_data::*;
pub use c_close_container::*;
pub use c_disguised_chat_message::*;
pub use c_entity_animation::*;
pub use c_entity_metadata::*;
Expand All @@ -62,6 +65,7 @@ pub use c_player_info_update::*;
pub use c_player_remove::*;
pub use c_remove_entities::*;
pub use c_set_container_content::*;
pub use c_set_container_property::*;
pub use c_set_container_slot::*;
pub use c_set_held_item::*;
pub use c_set_title::*;
Expand Down
2 changes: 2 additions & 0 deletions pumpkin-protocol/src/server/play/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod s_chat_command;
mod s_chat_message;
mod s_client_information;
mod s_close_container;
mod s_confirm_teleport;
mod s_interact;
mod s_ping_request;
Expand All @@ -17,6 +18,7 @@ mod s_use_item_on;
pub use s_chat_command::*;
pub use s_chat_message::*;
pub use s_client_information::*;
pub use s_close_container::*;
pub use s_confirm_teleport::*;
pub use s_interact::*;
pub use s_ping_request::*;
Expand Down
8 changes: 8 additions & 0 deletions pumpkin-protocol/src/server/play/s_close_container.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use pumpkin_macros::packet;
use serde::Deserialize;

#[derive(Deserialize)]
#[packet(0x0F)]
pub struct SCloseContainer {
pub window_id: u8,
}
21 changes: 20 additions & 1 deletion pumpkin/src/client/container.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use pumpkin_core::text::TextComponent;
use pumpkin_inventory::window_property::{WindowProperty, WindowPropertyTrait};
use pumpkin_inventory::WindowType;
use pumpkin_protocol::client::play::{COpenScreen, CSetContainerContent, CSetContainerSlot};
use pumpkin_protocol::client::play::{
CCloseContainer, COpenScreen, CSetContainerContent, CSetContainerProperty, CSetContainerSlot,
};
use pumpkin_protocol::slot::Slot;
use pumpkin_world::item::Item;

Expand Down Expand Up @@ -82,4 +85,20 @@ impl Player {
&item.into(),
))
}

/// The official Minecraft client is weird, and will always just close *any* window that is opened when this gets sent
pub fn close_container(&mut self, window_type: WindowType) {
self.client
.send_packet(&CCloseContainer::new(window_type as u8))
}

pub fn set_container_property<T: WindowPropertyTrait>(
&mut self,
window_type: WindowType,
window_property: WindowProperty<T>,
) {
let (id, value) = window_property.into_tuple();
self.client
.send_packet(&CSetContainerProperty::new(window_type as u8, id, value));
}
}
13 changes: 13 additions & 0 deletions pumpkin/src/client/player_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::{
use num_traits::FromPrimitive;
use pumpkin_core::text::TextComponent;
use pumpkin_entity::EntityId;
use pumpkin_inventory::WindowType;
use pumpkin_protocol::server::play::SCloseContainer;
use pumpkin_protocol::{
client::play::{
Animation, CAcknowledgeBlockChange, CBlockUpdate, CEntityAnimation, CEntityVelocity,
Expand Down Expand Up @@ -406,4 +408,15 @@ impl Player {
self.inventory
.set_slot(packet.slot as usize, packet.clicked_item.to_item(), false);
}

// TODO:
// This function will in the future be used to keep track of if the client is in a valid state.
// But this is not possible yet
pub fn handle_close_container(&mut self, _server: &mut Server, packet: SCloseContainer) {
// window_id 0 represents both 9x1 Generic AND inventory here
let Some(_window_type) = WindowType::from_u8(packet.window_id) else {
self.kick(TextComponent::text("Invalid window ID"));
return;
};
}
}

0 comments on commit 92a3f6c

Please sign in to comment.