start trying to drag, it doesn't work though
This commit is contained in:
parent
2acd1ed02a
commit
3b93892f26
@ -142,7 +142,7 @@ pub enum MouseDragType {
|
|||||||
Right,
|
Right,
|
||||||
Middle,
|
Middle,
|
||||||
}
|
}
|
||||||
|
#[derive(PartialEq)]
|
||||||
pub enum MouseDragState {
|
pub enum MouseDragState {
|
||||||
Start(MouseDragType),
|
Start(MouseDragType),
|
||||||
AddSlot(usize),
|
AddSlot(usize),
|
||||||
|
|||||||
@ -58,13 +58,13 @@ impl DragHandler {
|
|||||||
|
|
||||||
pub fn apply_drag<T: Container>(
|
pub fn apply_drag<T: Container>(
|
||||||
&self,
|
&self,
|
||||||
carried_item: &mut Option<ItemStack>,
|
maybe_carried_item: &mut Option<ItemStack>,
|
||||||
container: &mut T,
|
container: &mut T,
|
||||||
container_id: &u64,
|
container_id: &u64,
|
||||||
player: i32,
|
player: i32,
|
||||||
) -> Result<(), InventoryError> {
|
) -> Result<(), InventoryError> {
|
||||||
// Minecraft client does still send dragging packets when not carrying an item!
|
// Minecraft client does still send dragging packets when not carrying an item!
|
||||||
if carried_item.is_none() {
|
if maybe_carried_item.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,60 +84,60 @@ impl DragHandler {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|stack| stack.map(|item| item.to_owned()))
|
.map(|stack| stack.map(|item| item.to_owned()))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
let Some(carried_item) = maybe_carried_item else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
match drag.drag_type {
|
match drag.drag_type {
|
||||||
// This is only valid in Creative GameMode.
|
// This is only valid in Creative GameMode.
|
||||||
// Checked in any function that uses this function.
|
// Checked in any function that uses this function.
|
||||||
MouseDragType::Middle => {
|
MouseDragType::Middle => {
|
||||||
for slot in &drag.slots {
|
for slot in &drag.slots {
|
||||||
*slots[*slot] = *carried_item;
|
*slots[*slot] = *maybe_carried_item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseDragType::Right => {
|
MouseDragType::Right => {
|
||||||
let amount_of_items = carried_item.unwrap().item_count as usize;
|
let mut single_item = *carried_item;
|
||||||
let mut single_item = carried_item.unwrap();
|
|
||||||
single_item.item_count = 1;
|
single_item.item_count = 1;
|
||||||
let changing_slots = drag.changing_slots(
|
|
||||||
amount_of_items,
|
let changing_slots =
|
||||||
&slots_cloned,
|
drag.possibly_changing_slots(&slots_cloned, carried_item.item_id);
|
||||||
carried_item.as_ref().unwrap(),
|
|
||||||
);
|
|
||||||
let mut amount_removed = 0;
|
|
||||||
changing_slots.for_each(|slot| {
|
changing_slots.for_each(|slot| {
|
||||||
amount_removed += 1;
|
if carried_item.item_count != 0 {
|
||||||
*slots[slot] = Some(single_item)
|
carried_item.item_count -= 1;
|
||||||
|
if let Some(stack) = &mut slots[slot] {
|
||||||
|
// TODO: Check for stack max here
|
||||||
|
if stack.item_count + 1 < 64 {
|
||||||
|
stack.item_count += 1;
|
||||||
|
} else {
|
||||||
|
carried_item.item_count += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*slots[slot] = Some(single_item)
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut remaining = carried_item.unwrap();
|
if carried_item.item_count == 0 {
|
||||||
if remaining.item_count == amount_removed {
|
*maybe_carried_item = None
|
||||||
*carried_item = None
|
|
||||||
} else {
|
|
||||||
remaining.item_count -= amount_removed;
|
|
||||||
*carried_item = Some(remaining)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseDragType::Left => {
|
MouseDragType::Left => {
|
||||||
let amount_of_items = carried_item.unwrap().item_count as usize;
|
|
||||||
// TODO: Handle dragging a stack with greater amount than item allows as max unstackable
|
// TODO: Handle dragging a stack with greater amount than item allows as max unstackable
|
||||||
// In that specific case, follow MouseDragType::Right behaviours instead!
|
// In that specific case, follow MouseDragType::Right behaviours instead!
|
||||||
|
|
||||||
let changing_slots = drag.changing_slots(
|
let changing_slots =
|
||||||
amount_of_items,
|
drag.possibly_changing_slots(&slots_cloned, carried_item.item_id);
|
||||||
&slots_cloned,
|
|
||||||
carried_item.as_ref().unwrap(),
|
|
||||||
);
|
|
||||||
let amount_of_slots = changing_slots.clone().count();
|
let amount_of_slots = changing_slots.clone().count();
|
||||||
let (amount_per_slot, remainder) =
|
let (amount_per_slot, remainder) =
|
||||||
(carried_item.unwrap().item_count as usize).div_rem_euclid(&amount_of_slots);
|
(carried_item.item_count as usize).div_rem_euclid(&amount_of_slots);
|
||||||
let mut item_in_each_slot = carried_item.unwrap();
|
let mut item_in_each_slot = *carried_item;
|
||||||
item_in_each_slot.item_count = amount_per_slot as u8;
|
item_in_each_slot.item_count = amount_per_slot as u8;
|
||||||
changing_slots.for_each(|slot| *slots[slot] = Some(item_in_each_slot));
|
changing_slots.for_each(|slot| *slots[slot] = Some(item_in_each_slot));
|
||||||
|
|
||||||
if remainder > 0 {
|
if remainder > 0 {
|
||||||
let mut remaining = carried_item.unwrap();
|
carried_item.item_count = remainder as u8;
|
||||||
remaining.item_count = remainder as u8;
|
|
||||||
*carried_item = Some(remaining)
|
|
||||||
} else {
|
} else {
|
||||||
*carried_item = None
|
*maybe_carried_item = None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,25 +152,24 @@ struct Drag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Drag {
|
impl Drag {
|
||||||
fn changing_slots<'a>(
|
fn possibly_changing_slots<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
amount_of_items: usize,
|
|
||||||
slots: &'a [Option<ItemStack>],
|
slots: &'a [Option<ItemStack>],
|
||||||
carried_item: &'a ItemStack,
|
carried_item_id: u32,
|
||||||
) -> impl Iterator<Item = usize> + 'a + Clone {
|
) -> impl Iterator<Item = usize> + 'a + Clone {
|
||||||
self.slots
|
self.slots.iter().filter_map(move |slot_index| {
|
||||||
.iter()
|
let slot = &slots[*slot_index];
|
||||||
.enumerate()
|
|
||||||
.take_while(move |(slot_number, _)| *slot_number <= amount_of_items)
|
match slot {
|
||||||
.filter_map(move |(_, slot)| match &slots[*slot] {
|
|
||||||
Some(item_slot) => {
|
Some(item_slot) => {
|
||||||
if *item_slot == *carried_item {
|
if item_slot.item_id == carried_item_id {
|
||||||
Some(*slot)
|
Some(*slot_index)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Some(*slot),
|
None => Some(*slot_index),
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ use pumpkin_protocol::client::play::{
|
|||||||
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::ItemStack;
|
use pumpkin_world::item::ItemStack;
|
||||||
use std::sync::Mutex;
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub fn open_container(
|
pub fn open_container(
|
||||||
@ -135,6 +135,7 @@ impl Player {
|
|||||||
packet.button,
|
packet.button,
|
||||||
packet.slot,
|
packet.slot,
|
||||||
);
|
);
|
||||||
|
let mut update_whole_container = false;
|
||||||
|
|
||||||
match click.click_type {
|
match click.click_type {
|
||||||
ClickType::MouseClick(mouse_click) => {
|
ClickType::MouseClick(mouse_click) => {
|
||||||
@ -157,19 +158,26 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClickType::DoubleClick => {
|
ClickType::DoubleClick => {
|
||||||
|
update_whole_container = true;
|
||||||
if let container_click::Slot::Normal(slot) = click.slot {
|
if let container_click::Slot::Normal(slot) = click.slot {
|
||||||
self.double_click(slot)
|
self.double_click(opened_container.as_deref_mut(), slot)
|
||||||
} else {
|
} else {
|
||||||
Err(InventoryError::InvalidPacket)
|
Err(InventoryError::InvalidPacket)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClickType::MouseDrag { drag_state } => {
|
ClickType::MouseDrag { drag_state } => {
|
||||||
|
if drag_state == MouseDragState::End {
|
||||||
|
update_whole_container = true;
|
||||||
|
}
|
||||||
self.mouse_drag(drag_handler, opened_container.as_deref_mut(), drag_state)
|
self.mouse_drag(drag_handler, opened_container.as_deref_mut(), drag_state)
|
||||||
}
|
}
|
||||||
ClickType::DropType(_drop_type) => todo!(),
|
ClickType::DropType(_drop_type) => todo!(),
|
||||||
}?;
|
}?;
|
||||||
if let Some(mut opened_container) = opened_container {
|
if let Some(mut opened_container) = opened_container {
|
||||||
if let container_click::Slot::Normal(slot_index) = click.slot {
|
if update_whole_container {
|
||||||
|
drop(opened_container);
|
||||||
|
self.send_whole_container_change(server).await?;
|
||||||
|
} else if let container_click::Slot::Normal(slot_index) = click.slot {
|
||||||
let combined_container = OptionallyCombinedContainer::new(
|
let combined_container = OptionallyCombinedContainer::new(
|
||||||
&mut self.inventory,
|
&mut self.inventory,
|
||||||
Some(&mut opened_container),
|
Some(&mut opened_container),
|
||||||
@ -280,7 +288,40 @@ impl Player {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn double_click(&mut self, _slot: usize) -> Result<(), InventoryError> {
|
fn double_click(
|
||||||
|
&mut self,
|
||||||
|
opened_container: Option<&mut Box<dyn Container>>,
|
||||||
|
slot: usize,
|
||||||
|
) -> Result<(), InventoryError> {
|
||||||
|
let mut container = OptionallyCombinedContainer::new(&mut self.inventory, opened_container);
|
||||||
|
let mut slots = container.all_slots();
|
||||||
|
|
||||||
|
let Some(item) = slots.get_mut(slot) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
let Some(mut carried_item) = **item else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
**item = None;
|
||||||
|
|
||||||
|
for slot in slots.iter_mut().filter_map(|slot| slot.as_mut()) {
|
||||||
|
if slot.item_id == carried_item.item_id {
|
||||||
|
// TODO: Check for max stack size
|
||||||
|
if slot.item_count + carried_item.item_count <= 64 {
|
||||||
|
slot.item_count = 0;
|
||||||
|
carried_item.item_count = 64;
|
||||||
|
} else {
|
||||||
|
let to_remove = slot.item_count - (64 - carried_item.item_count);
|
||||||
|
slot.item_count -= to_remove;
|
||||||
|
carried_item.item_count += to_remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
if carried_item.item_count == 64 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.carried_item = Some(carried_item);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,12 +357,10 @@ impl Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_container_changes(
|
async fn get_current_players_in_container(
|
||||||
&mut self,
|
&mut self,
|
||||||
server: &Server,
|
server: &Server,
|
||||||
slot_index: usize,
|
) -> Vec<Arc<Mutex<Player>>> {
|
||||||
slot: Slot,
|
|
||||||
) -> Result<(), InventoryError> {
|
|
||||||
let player_ids = server
|
let player_ids = server
|
||||||
.open_containers
|
.open_containers
|
||||||
.get(&self.open_container.unwrap())
|
.get(&self.open_container.unwrap())
|
||||||
@ -352,8 +391,16 @@ impl Player {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
drop(world);
|
players
|
||||||
for player in players {
|
}
|
||||||
|
|
||||||
|
async fn send_container_changes(
|
||||||
|
&mut self,
|
||||||
|
server: &Server,
|
||||||
|
slot_index: usize,
|
||||||
|
slot: Slot,
|
||||||
|
) -> Result<(), InventoryError> {
|
||||||
|
for player in self.get_current_players_in_container(server).await {
|
||||||
let mut player = player.lock().unwrap();
|
let mut player = player.lock().unwrap();
|
||||||
let total_opened_containers = player.inventory.total_opened_containers;
|
let total_opened_containers = player.inventory.total_opened_containers;
|
||||||
|
|
||||||
@ -366,7 +413,20 @@ impl Player {
|
|||||||
);
|
);
|
||||||
player.client.send_packet(&packet);
|
player.client.send_packet(&packet);
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_whole_container_change(&mut self, server: &Server) -> Result<(), InventoryError> {
|
||||||
|
let players = self.get_current_players_in_container(server).await;
|
||||||
|
|
||||||
|
for player in players {
|
||||||
|
let mut player = player.lock().unwrap();
|
||||||
|
let mut container = player
|
||||||
|
.get_open_container(server)
|
||||||
|
.map(|container| container.lock().unwrap());
|
||||||
|
player.set_container_content(container.as_deref_mut());
|
||||||
|
drop(container)
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user