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,
|
||||
Middle,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum MouseDragState {
|
||||
Start(MouseDragType),
|
||||
AddSlot(usize),
|
||||
|
||||
@ -58,13 +58,13 @@ impl DragHandler {
|
||||
|
||||
pub fn apply_drag<T: Container>(
|
||||
&self,
|
||||
carried_item: &mut Option<ItemStack>,
|
||||
maybe_carried_item: &mut Option<ItemStack>,
|
||||
container: &mut T,
|
||||
container_id: &u64,
|
||||
player: i32,
|
||||
) -> Result<(), InventoryError> {
|
||||
// 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(());
|
||||
}
|
||||
|
||||
@ -84,60 +84,60 @@ impl DragHandler {
|
||||
.iter()
|
||||
.map(|stack| stack.map(|item| item.to_owned()))
|
||||
.collect_vec();
|
||||
let Some(carried_item) = maybe_carried_item else {
|
||||
return Ok(());
|
||||
};
|
||||
match drag.drag_type {
|
||||
// This is only valid in Creative GameMode.
|
||||
// Checked in any function that uses this function.
|
||||
MouseDragType::Middle => {
|
||||
for slot in &drag.slots {
|
||||
*slots[*slot] = *carried_item;
|
||||
*slots[*slot] = *maybe_carried_item;
|
||||
}
|
||||
}
|
||||
MouseDragType::Right => {
|
||||
let amount_of_items = carried_item.unwrap().item_count as usize;
|
||||
let mut single_item = carried_item.unwrap();
|
||||
let mut single_item = *carried_item;
|
||||
single_item.item_count = 1;
|
||||
let changing_slots = drag.changing_slots(
|
||||
amount_of_items,
|
||||
&slots_cloned,
|
||||
carried_item.as_ref().unwrap(),
|
||||
);
|
||||
let mut amount_removed = 0;
|
||||
|
||||
let changing_slots =
|
||||
drag.possibly_changing_slots(&slots_cloned, carried_item.item_id);
|
||||
changing_slots.for_each(|slot| {
|
||||
amount_removed += 1;
|
||||
*slots[slot] = Some(single_item)
|
||||
if carried_item.item_count != 0 {
|
||||
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 remaining.item_count == amount_removed {
|
||||
*carried_item = None
|
||||
} else {
|
||||
remaining.item_count -= amount_removed;
|
||||
*carried_item = Some(remaining)
|
||||
if carried_item.item_count == 0 {
|
||||
*maybe_carried_item = None
|
||||
}
|
||||
}
|
||||
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
|
||||
// In that specific case, follow MouseDragType::Right behaviours instead!
|
||||
|
||||
let changing_slots = drag.changing_slots(
|
||||
amount_of_items,
|
||||
&slots_cloned,
|
||||
carried_item.as_ref().unwrap(),
|
||||
);
|
||||
let changing_slots =
|
||||
drag.possibly_changing_slots(&slots_cloned, carried_item.item_id);
|
||||
let amount_of_slots = changing_slots.clone().count();
|
||||
let (amount_per_slot, remainder) =
|
||||
(carried_item.unwrap().item_count as usize).div_rem_euclid(&amount_of_slots);
|
||||
let mut item_in_each_slot = carried_item.unwrap();
|
||||
(carried_item.item_count as usize).div_rem_euclid(&amount_of_slots);
|
||||
let mut item_in_each_slot = *carried_item;
|
||||
item_in_each_slot.item_count = amount_per_slot as u8;
|
||||
changing_slots.for_each(|slot| *slots[slot] = Some(item_in_each_slot));
|
||||
|
||||
if remainder > 0 {
|
||||
let mut remaining = carried_item.unwrap();
|
||||
remaining.item_count = remainder as u8;
|
||||
*carried_item = Some(remaining)
|
||||
carried_item.item_count = remainder as u8;
|
||||
} else {
|
||||
*carried_item = None
|
||||
*maybe_carried_item = None
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,25 +152,24 @@ struct Drag {
|
||||
}
|
||||
|
||||
impl Drag {
|
||||
fn changing_slots<'a>(
|
||||
fn possibly_changing_slots<'a>(
|
||||
&'a self,
|
||||
amount_of_items: usize,
|
||||
slots: &'a [Option<ItemStack>],
|
||||
carried_item: &'a ItemStack,
|
||||
carried_item_id: u32,
|
||||
) -> impl Iterator<Item = usize> + 'a + Clone {
|
||||
self.slots
|
||||
.iter()
|
||||
.enumerate()
|
||||
.take_while(move |(slot_number, _)| *slot_number <= amount_of_items)
|
||||
.filter_map(move |(_, slot)| match &slots[*slot] {
|
||||
self.slots.iter().filter_map(move |slot_index| {
|
||||
let slot = &slots[*slot_index];
|
||||
|
||||
match slot {
|
||||
Some(item_slot) => {
|
||||
if *item_slot == *carried_item {
|
||||
Some(*slot)
|
||||
if item_slot.item_id == carried_item_id {
|
||||
Some(*slot_index)
|
||||
} else {
|
||||
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::slot::Slot;
|
||||
use pumpkin_world::item::ItemStack;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
impl Player {
|
||||
pub fn open_container(
|
||||
@ -135,6 +135,7 @@ impl Player {
|
||||
packet.button,
|
||||
packet.slot,
|
||||
);
|
||||
let mut update_whole_container = false;
|
||||
|
||||
match click.click_type {
|
||||
ClickType::MouseClick(mouse_click) => {
|
||||
@ -157,19 +158,26 @@ impl Player {
|
||||
}
|
||||
}
|
||||
ClickType::DoubleClick => {
|
||||
update_whole_container = true;
|
||||
if let container_click::Slot::Normal(slot) = click.slot {
|
||||
self.double_click(slot)
|
||||
self.double_click(opened_container.as_deref_mut(), slot)
|
||||
} else {
|
||||
Err(InventoryError::InvalidPacket)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
ClickType::DropType(_drop_type) => todo!(),
|
||||
}?;
|
||||
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(
|
||||
&mut self.inventory,
|
||||
Some(&mut opened_container),
|
||||
@ -280,7 +288,40 @@ impl Player {
|
||||
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(())
|
||||
}
|
||||
|
||||
@ -316,12 +357,10 @@ impl Player {
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_container_changes(
|
||||
async fn get_current_players_in_container(
|
||||
&mut self,
|
||||
server: &Server,
|
||||
slot_index: usize,
|
||||
slot: Slot,
|
||||
) -> Result<(), InventoryError> {
|
||||
) -> Vec<Arc<Mutex<Player>>> {
|
||||
let player_ids = server
|
||||
.open_containers
|
||||
.get(&self.open_container.unwrap())
|
||||
@ -352,8 +391,16 @@ impl Player {
|
||||
}
|
||||
})
|
||||
.collect_vec();
|
||||
drop(world);
|
||||
for player in players {
|
||||
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 total_opened_containers = player.inventory.total_opened_containers;
|
||||
|
||||
@ -366,7 +413,20 @@ impl Player {
|
||||
);
|
||||
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(())
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user