Add all functionality of mode zero for packet SClickContainer
This commit is contained in:
parent
b90fd4c62d
commit
e0a20c1194
@ -1,5 +1,5 @@
|
|||||||
use crate::WindowType;
|
use crate::WindowType;
|
||||||
use pumpkin_world::item::Item;
|
use pumpkin_world::item::ItemStack;
|
||||||
|
|
||||||
pub struct ClickMode {
|
pub struct ClickMode {
|
||||||
pub slot: Slot,
|
pub slot: Slot,
|
||||||
@ -11,7 +11,7 @@ pub struct Click {
|
|||||||
pub state_id: u32,
|
pub state_id: u32,
|
||||||
pub window_type: WindowType,
|
pub window_type: WindowType,
|
||||||
pub changed_items: Vec<ItemChange>,
|
pub changed_items: Vec<ItemChange>,
|
||||||
pub carried_item: Option<Item>,
|
pub carried_item: Option<ItemStack>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClickMode {
|
impl ClickMode {
|
||||||
@ -166,11 +166,10 @@ pub enum ClickType {
|
|||||||
},
|
},
|
||||||
DoubleClick,
|
DoubleClick,
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum MouseClick {
|
pub enum MouseClick {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
Middle,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum KeyClick {
|
pub enum KeyClick {
|
||||||
@ -202,5 +201,5 @@ pub enum MouseDragState {
|
|||||||
|
|
||||||
pub enum ItemChange {
|
pub enum ItemChange {
|
||||||
Remove { slot: usize },
|
Remove { slot: usize },
|
||||||
Add { slot: usize, item: Item },
|
Add { slot: usize, item: ItemStack },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
|
use crate::container_click::MouseClick;
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
|
use pumpkin_world::item::ItemStack;
|
||||||
|
|
||||||
pub mod container_click;
|
pub mod container_click;
|
||||||
pub mod player;
|
pub mod player;
|
||||||
pub mod window_property;
|
pub mod window_property;
|
||||||
|
|
||||||
/// https://wiki.vg/Inventory
|
/// https://wiki.vg/Inventory
|
||||||
#[derive(Debug, ToPrimitive, FromPrimitive, Clone)]
|
#[derive(Debug, ToPrimitive, FromPrimitive, Clone, Eq, PartialEq)]
|
||||||
pub enum WindowType {
|
pub enum WindowType {
|
||||||
// not used
|
// not used
|
||||||
Generic9x1,
|
Generic9x1,
|
||||||
@ -55,25 +57,120 @@ impl WindowType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Container {
|
pub trait Container {
|
||||||
const SLOTS: usize;
|
fn window_type(&self) -> &WindowType;
|
||||||
|
|
||||||
fn item_mut(&mut self, slot: usize) -> &mut Item;
|
fn handle_item_change(
|
||||||
|
&mut self,
|
||||||
|
carried_item: &mut Option<ItemStack>,
|
||||||
|
slot: usize,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_item_take(
|
||||||
|
carried_item: &mut Option<ItemStack>,
|
||||||
|
item_slot: &mut Option<ItemStack>,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
) {
|
||||||
|
let Some(item) = item_slot else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let mut new_item = *item;
|
||||||
|
|
||||||
|
match mouse_click {
|
||||||
|
MouseClick::Left => {
|
||||||
|
*item_slot = None;
|
||||||
|
}
|
||||||
|
MouseClick::Right => {
|
||||||
|
let half = item.item_count / 2;
|
||||||
|
item.item_count -= half;
|
||||||
|
new_item.item_count = half;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*carried_item = Some(new_item);
|
||||||
|
}
|
||||||
|
pub fn handle_item_change(
|
||||||
|
carried_slot: &mut Option<ItemStack>,
|
||||||
|
current_slot: &mut Option<ItemStack>,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
) {
|
||||||
|
match (current_slot.as_mut(), carried_slot.as_mut()) {
|
||||||
|
// Swap or combine current and carried
|
||||||
|
(Some(current), Some(carried)) => {
|
||||||
|
if current.item_id == carried.item_id {
|
||||||
|
combine_stacks(carried_slot, current, mouse_click);
|
||||||
|
} else if mouse_click == MouseClick::Left {
|
||||||
|
let carried = *carried;
|
||||||
|
*carried_slot = Some(current.to_owned());
|
||||||
|
*current_slot = Some(carried.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Put held stack into empty slot
|
||||||
|
(None, Some(carried)) => match mouse_click {
|
||||||
|
MouseClick::Left => {
|
||||||
|
*current_slot = Some(carried.to_owned());
|
||||||
|
*carried_slot = None;
|
||||||
|
}
|
||||||
|
MouseClick::Right => {
|
||||||
|
carried.item_count -= 1;
|
||||||
|
let mut new = *carried;
|
||||||
|
new.item_count = 1;
|
||||||
|
*current_slot = Some(new);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Take stack into carried
|
||||||
|
(Some(_current), None) => handle_item_take(carried_slot, current_slot, mouse_click),
|
||||||
|
(None, None) => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn combine_stacks(
|
||||||
|
carried_slot: &mut Option<ItemStack>,
|
||||||
|
slot: &mut ItemStack,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
) {
|
||||||
|
let Some(carried_item) = carried_slot else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let carried_change = match mouse_click {
|
||||||
|
MouseClick::Left => carried_item.item_count,
|
||||||
|
MouseClick::Right => 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Check for item stack max size here
|
||||||
|
if slot.item_count + carried_change <= 64 {
|
||||||
|
slot.item_count += carried_change;
|
||||||
|
carried_item.item_count -= carried_change;
|
||||||
|
if carried_item.item_count == 0 {
|
||||||
|
*carried_slot = None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let left_over = slot.item_count + carried_change - 64;
|
||||||
|
slot.item_count = 64;
|
||||||
|
carried_item.item_count = left_over;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContainerStruct<const SLOTS: usize> {
|
pub struct ContainerStruct<const SLOTS: usize> {
|
||||||
slots: [Option<Item>; SLOTS],
|
slots: [Option<ItemStack>; SLOTS],
|
||||||
state_id: usize,
|
_state_id: usize,
|
||||||
open_by: Option<Vec<i32>>,
|
_open_by: Option<Vec<i32>>,
|
||||||
|
window_type: WindowType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const T: usize> ContainerStruct<T> {
|
impl<const T: usize> Container for ContainerStruct<T> {
|
||||||
pub fn take_item(&mut self, slot: usize) -> Item {
|
fn window_type(&self) -> &WindowType {
|
||||||
assert!(slot < T);
|
&self.window_type
|
||||||
let Some(item) = self.slots[slot] else {
|
}
|
||||||
panic!()
|
|
||||||
};
|
fn handle_item_change(
|
||||||
self.slots[slot] = None;
|
&mut self,
|
||||||
self.state_id += 1;
|
carried_slot: &mut Option<ItemStack>,
|
||||||
item
|
slot: usize,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
) {
|
||||||
|
let current_slot = &mut self.slots[slot];
|
||||||
|
handle_item_change(carried_slot, current_slot, mouse_click)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
use pumpkin_world::item::Item;
|
use crate::container_click::MouseClick;
|
||||||
|
use crate::{handle_item_change, Container, WindowType};
|
||||||
|
use pumpkin_world::item::ItemStack;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct PlayerInventory {
|
pub struct PlayerInventory {
|
||||||
// Main Inventory + Hotbar
|
// Main Inventory + Hotbar
|
||||||
crafting: [Option<Item>; 4],
|
crafting: [Option<ItemStack>; 4],
|
||||||
crafting_output: Option<Item>,
|
crafting_output: Option<ItemStack>,
|
||||||
items: [Option<Item>; 36],
|
items: [Option<ItemStack>; 36],
|
||||||
armor: [Option<Item>; 4],
|
armor: [Option<ItemStack>; 4],
|
||||||
offhand: Option<Item>,
|
offhand: Option<ItemStack>,
|
||||||
// current selected slot in hotbar
|
// current selected slot in hotbar
|
||||||
selected: usize,
|
selected: usize,
|
||||||
}
|
}
|
||||||
@ -42,7 +45,7 @@ impl PlayerInventory {
|
|||||||
/// ## Item allowed override
|
/// ## Item allowed override
|
||||||
/// An override, which when enabled, makes it so that invalid items, can be placed in slots they normally can't.
|
/// An override, which when enabled, makes it so that invalid items, can be placed in slots they normally can't.
|
||||||
/// Useful functionality for plugins in the future.
|
/// Useful functionality for plugins in the future.
|
||||||
pub fn set_slot(&mut self, slot: usize, item: Option<Item>, item_allowed_override: bool) {
|
pub fn set_slot(&mut self, slot: usize, item: Option<ItemStack>, item_allowed_override: bool) {
|
||||||
match slot {
|
match slot {
|
||||||
0 => {
|
0 => {
|
||||||
// TODO: Add crafting check here
|
// TODO: Add crafting check here
|
||||||
@ -85,18 +88,30 @@ impl PlayerInventory {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn get_slot(&mut self, slot: usize) -> &mut Option<ItemStack> {
|
||||||
|
match slot {
|
||||||
|
0 => {
|
||||||
|
// TODO: Add crafting check here
|
||||||
|
&mut self.crafting_output
|
||||||
|
}
|
||||||
|
1..=4 => &mut self.crafting[slot - 1],
|
||||||
|
5..=8 => &mut self.armor[slot - 5],
|
||||||
|
9..=44 => &mut self.items[slot - 9],
|
||||||
|
45 => &mut self.offhand,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn set_selected(&mut self, slot: usize) {
|
pub fn set_selected(&mut self, slot: usize) {
|
||||||
assert!((0..9).contains(&slot));
|
assert!((0..9).contains(&slot));
|
||||||
self.selected = slot;
|
self.selected = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn held_item(&self) -> Option<&Item> {
|
pub fn held_item(&self) -> Option<&ItemStack> {
|
||||||
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>> {
|
pub fn slots(&self) -> Vec<Option<&ItemStack>> {
|
||||||
let mut slots = vec![self.crafting_output.as_ref()];
|
let mut slots = vec![self.crafting_output.as_ref()];
|
||||||
slots.extend(self.crafting.iter().map(|c| c.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.armor.iter().map(|c| c.as_ref()));
|
||||||
@ -104,4 +119,29 @@ impl PlayerInventory {
|
|||||||
slots.push(self.offhand.as_ref());
|
slots.push(self.offhand.as_ref());
|
||||||
slots
|
slots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn slots_mut(&mut self) -> Vec<&mut Option<ItemStack>> {
|
||||||
|
let mut slots = vec![&mut self.crafting_output];
|
||||||
|
slots.extend(self.crafting.iter_mut());
|
||||||
|
slots.extend(self.armor.iter_mut());
|
||||||
|
slots.extend(self.items.iter_mut());
|
||||||
|
slots.push(&mut self.offhand);
|
||||||
|
slots
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Container for PlayerInventory {
|
||||||
|
fn window_type(&self) -> &WindowType {
|
||||||
|
&WindowType::Generic9x1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_item_change(
|
||||||
|
&mut self,
|
||||||
|
carried_slot: &mut Option<ItemStack>,
|
||||||
|
slot: usize,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
) {
|
||||||
|
let item_slot = self.get_slot(slot);
|
||||||
|
handle_item_change(carried_slot, item_slot, mouse_click)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use pumpkin_macros::packet;
|
|||||||
use serde::de::SeqAccess;
|
use serde::de::SeqAccess;
|
||||||
use serde::{de, Deserialize};
|
use serde::{de, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
#[packet(0x0E)]
|
#[packet(0x0E)]
|
||||||
pub struct SClickContainer {
|
pub struct SClickContainer {
|
||||||
pub window_id: u8,
|
pub window_id: u8,
|
||||||
@ -52,12 +53,17 @@ impl<'de> Deserialize<'de> for SClickContainer {
|
|||||||
let length_of_array = seq
|
let length_of_array = seq
|
||||||
.next_element::<VarInt>()?
|
.next_element::<VarInt>()?
|
||||||
.ok_or(de::Error::custom("Failed to decode VarInt"))?;
|
.ok_or(de::Error::custom("Failed to decode VarInt"))?;
|
||||||
let array_of_changed_slots = if length_of_array.0 != 0 {
|
let mut array_of_changed_slots = vec![];
|
||||||
seq.next_element::<Vec<(i16, Slot)>>()?
|
for _ in 0..length_of_array.0 {
|
||||||
.ok_or(de::Error::custom("Unable to parse changed slots list"))?
|
let slot_number = seq
|
||||||
} else {
|
.next_element::<i16>()?
|
||||||
vec![]
|
.ok_or(de::Error::custom("Unable to parse slot"))?;
|
||||||
};
|
let slot = seq
|
||||||
|
.next_element::<Slot>()?
|
||||||
|
.ok_or(de::Error::custom("Unable to parse item"))?;
|
||||||
|
array_of_changed_slots.push((slot_number, slot));
|
||||||
|
}
|
||||||
|
|
||||||
let carried_item = seq
|
let carried_item = seq
|
||||||
.next_element::<Slot>()?
|
.next_element::<Slot>()?
|
||||||
.ok_or(de::Error::custom("Failed to decode carried item"))?;
|
.ok_or(de::Error::custom("Failed to decode carried item"))?;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::VarInt;
|
use crate::VarInt;
|
||||||
use pumpkin_world::item::Item;
|
use pumpkin_world::item::ItemStack;
|
||||||
use serde::ser::SerializeSeq;
|
use serde::ser::SerializeSeq;
|
||||||
use serde::{
|
use serde::{
|
||||||
de::{self, SeqAccess},
|
de::{self, SeqAccess},
|
||||||
@ -130,9 +130,9 @@ impl Serialize for Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Slot {
|
impl Slot {
|
||||||
pub fn to_item(self) -> Option<Item> {
|
pub fn to_item(self) -> Option<ItemStack> {
|
||||||
let item_id = self.item_id?.0.try_into().unwrap();
|
let item_id = self.item_id?.0.try_into().unwrap();
|
||||||
Some(Item {
|
Some(ItemStack {
|
||||||
item_id,
|
item_id,
|
||||||
item_count: self.item_count.0.try_into().unwrap(),
|
item_count: self.item_count.0.try_into().unwrap(),
|
||||||
})
|
})
|
||||||
@ -150,8 +150,8 @@ impl Slot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Item> for Slot {
|
impl From<&ItemStack> for Slot {
|
||||||
fn from(item: &Item) -> Self {
|
fn from(item: &ItemStack) -> Self {
|
||||||
Slot {
|
Slot {
|
||||||
item_count: item.item_count.into(),
|
item_count: item.item_count.into(),
|
||||||
item_id: Some(item.item_id.into()),
|
item_id: Some(item.item_id.into()),
|
||||||
@ -164,8 +164,8 @@ impl From<&Item> for Slot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<&Item>> for Slot {
|
impl From<Option<&ItemStack>> for Slot {
|
||||||
fn from(item: Option<&Item>) -> Self {
|
fn from(item: Option<&ItemStack>) -> Self {
|
||||||
item.map(Slot::from).unwrap_or(Slot::empty())
|
item.map(Slot::from).unwrap_or(Slot::empty())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::item::Item;
|
use crate::item::ItemStack;
|
||||||
|
|
||||||
impl Item {
|
impl ItemStack {
|
||||||
pub fn is_helmet(&self) -> bool {
|
pub fn is_helmet(&self) -> bool {
|
||||||
[
|
[
|
||||||
// Leather
|
// Leather
|
||||||
|
|||||||
@ -11,9 +11,9 @@ pub enum Rarity {
|
|||||||
Epic,
|
Epic,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Item {
|
pub struct ItemStack {
|
||||||
pub item_count: u32,
|
pub item_count: u8,
|
||||||
// This ID is the numerical protocol ID, not the usual minecraft::block ID.
|
// This ID is the numerical protocol ID, not the usual minecraft::block ID.
|
||||||
pub item_id: u32,
|
pub item_id: u32,
|
||||||
// TODO: Add Item Components
|
// TODO: Add Item Components
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
|
use num_traits::FromPrimitive;
|
||||||
use pumpkin_core::text::TextComponent;
|
use pumpkin_core::text::TextComponent;
|
||||||
|
use pumpkin_inventory::container_click;
|
||||||
use pumpkin_inventory::container_click::MouseClick;
|
use pumpkin_inventory::container_click::MouseClick;
|
||||||
use pumpkin_inventory::window_property::{WindowProperty, WindowPropertyTrait};
|
use pumpkin_inventory::window_property::{WindowProperty, WindowPropertyTrait};
|
||||||
use pumpkin_inventory::WindowType;
|
use pumpkin_inventory::{Container, WindowType};
|
||||||
use pumpkin_inventory::{container_click, ContainerStruct};
|
|
||||||
use pumpkin_protocol::client::play::{
|
use pumpkin_protocol::client::play::{
|
||||||
CCloseContainer, COpenScreen, CSetContainerContent, CSetContainerProperty, CSetContainerSlot,
|
CCloseContainer, COpenScreen, CSetContainerContent, CSetContainerProperty, CSetContainerSlot,
|
||||||
};
|
};
|
||||||
use pumpkin_protocol::server::play::SClickContainer;
|
use pumpkin_protocol::server::play::SClickContainer;
|
||||||
use pumpkin_protocol::slot::Slot;
|
use pumpkin_protocol::slot::Slot;
|
||||||
use pumpkin_world::item::Item;
|
use pumpkin_world::item::ItemStack;
|
||||||
|
|
||||||
use crate::entity::player::Player;
|
use crate::entity::player::Player;
|
||||||
use crate::server::Server;
|
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub fn open_container(
|
pub fn open_container(
|
||||||
@ -19,8 +19,8 @@ impl Player {
|
|||||||
window_type: WindowType,
|
window_type: WindowType,
|
||||||
minecraft_menu_id: &str,
|
minecraft_menu_id: &str,
|
||||||
window_title: Option<&str>,
|
window_title: Option<&str>,
|
||||||
items: Option<Vec<Option<&Item>>>,
|
items: Option<Vec<Option<&ItemStack>>>,
|
||||||
carried_item: Option<&Item>,
|
carried_item: Option<&ItemStack>,
|
||||||
) {
|
) {
|
||||||
let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY
|
let menu_protocol_id = (*pumpkin_world::global_registry::REGISTRY
|
||||||
.get("minecraft:menu")
|
.get("minecraft:menu")
|
||||||
@ -43,8 +43,8 @@ impl Player {
|
|||||||
pub fn set_container_content<'a>(
|
pub fn set_container_content<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
window_type: WindowType,
|
window_type: WindowType,
|
||||||
items: Option<Vec<Option<&'a Item>>>,
|
items: Option<Vec<Option<&'a ItemStack>>>,
|
||||||
carried_item: Option<&'a Item>,
|
carried_item: Option<&'a ItemStack>,
|
||||||
) {
|
) {
|
||||||
let slots: Vec<Slot> = {
|
let slots: Vec<Slot> = {
|
||||||
if let Some(mut items) = items {
|
if let Some(mut items) = items {
|
||||||
@ -80,7 +80,7 @@ impl Player {
|
|||||||
&mut self,
|
&mut self,
|
||||||
window_type: WindowType,
|
window_type: WindowType,
|
||||||
slot: usize,
|
slot: usize,
|
||||||
item: Option<&Item>,
|
item: Option<&ItemStack>,
|
||||||
) {
|
) {
|
||||||
self.client.send_packet(&CSetContainerSlot::new(
|
self.client.send_packet(&CSetContainerSlot::new(
|
||||||
window_type as i8,
|
window_type as i8,
|
||||||
@ -136,13 +136,45 @@ impl Player {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match click.mode.click_type {
|
match click.mode.click_type {
|
||||||
ClickType::MouseClick(mouse_click) => self.mouse_click(mouse_click),
|
ClickType::MouseClick(mouse_click) => {
|
||||||
|
self.mouse_click(mouse_click, click.window_type, click.mode.slot)
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouse_click(&mut self, mouse_click: MouseClick) {
|
pub fn mouse_click(
|
||||||
dbg!(mouse_click);
|
&mut self,
|
||||||
|
mouse_click: MouseClick,
|
||||||
|
window_type: WindowType,
|
||||||
|
slot: container_click::Slot,
|
||||||
|
) {
|
||||||
|
let Some(_) = &self.open_container else {
|
||||||
|
// Inventory
|
||||||
|
if window_type == WindowType::Generic9x1 {
|
||||||
|
match slot {
|
||||||
|
container_click::Slot::Normal(slot) => {
|
||||||
|
self.inventory
|
||||||
|
.handle_item_change(&mut self.carried_item, slot, mouse_click)
|
||||||
|
}
|
||||||
|
container_click::Slot::OutsideInventory => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
dbg!(&self.carried_item);
|
||||||
|
let filled_inventory_slots = self
|
||||||
|
.inventory
|
||||||
|
.slots()
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(slot, item)| item.map(|item| (slot, item.item_count)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
dbg!(filled_inventory_slots);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::{client::Client, server::Server};
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use pumpkin_core::text::TextComponent;
|
use pumpkin_core::text::TextComponent;
|
||||||
use pumpkin_entity::{entity_type::EntityType, Entity, EntityId};
|
use pumpkin_entity::{entity_type::EntityType, Entity, EntityId};
|
||||||
use pumpkin_inventory::player::PlayerInventory;
|
use pumpkin_inventory::player::PlayerInventory;
|
||||||
|
use pumpkin_inventory::Container;
|
||||||
use pumpkin_protocol::{
|
use pumpkin_protocol::{
|
||||||
bytebuf::packet_id::Packet,
|
bytebuf::packet_id::Packet,
|
||||||
client::play::{CGameEvent, CPlayDisconnect, CSyncPlayerPosition, CSystemChatMessage},
|
client::play::{CGameEvent, CPlayDisconnect, CSyncPlayerPosition, CSystemChatMessage},
|
||||||
@ -16,11 +18,10 @@ use pumpkin_protocol::{
|
|||||||
},
|
},
|
||||||
ConnectionState, RawPacket, ServerPacket, VarInt,
|
ConnectionState, RawPacket, ServerPacket, VarInt,
|
||||||
};
|
};
|
||||||
|
use pumpkin_world::item::ItemStack;
|
||||||
use pumpkin_world::vector3::Vector3;
|
use pumpkin_world::vector3::Vector3;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{client::Client, server::Server};
|
|
||||||
|
|
||||||
pub struct Player {
|
pub struct Player {
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
@ -31,8 +32,8 @@ pub struct Player {
|
|||||||
pub food: i32,
|
pub food: i32,
|
||||||
pub food_saturation: f32,
|
pub food_saturation: f32,
|
||||||
pub inventory: PlayerInventory,
|
pub inventory: PlayerInventory,
|
||||||
pub open_container: Option<()>,
|
pub open_container: Option<Box<dyn Container>>,
|
||||||
|
pub carried_item: Option<ItemStack>,
|
||||||
// Client side value, Should be not trusted
|
// Client side value, Should be not trusted
|
||||||
pub on_ground: bool,
|
pub on_ground: bool,
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ impl Player {
|
|||||||
velocity: Vector3::new(0.0, 0.0, 0.0),
|
velocity: Vector3::new(0.0, 0.0, 0.0),
|
||||||
inventory: PlayerInventory::new(),
|
inventory: PlayerInventory::new(),
|
||||||
open_container: None,
|
open_container: None,
|
||||||
|
carried_item: None,
|
||||||
gamemode,
|
gamemode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user