mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-20 07:02:32 +01:00
Drag click cleanup, fix cursor item not being updated (thanks 1.17.1)
This commit is contained in:
parent
c17f07e1d0
commit
70c757e8b5
@ -146,155 +146,121 @@ public final class InventoryClickProcessor {
|
|||||||
@NotNull Int2ObjectFunction<ItemStack> itemGetter,
|
@NotNull Int2ObjectFunction<ItemStack> itemGetter,
|
||||||
@NotNull BiConsumer<Integer, ItemStack> itemSetter) {
|
@NotNull BiConsumer<Integer, ItemStack> itemSetter) {
|
||||||
InventoryClickResult clickResult = null;
|
InventoryClickResult clickResult = null;
|
||||||
|
|
||||||
final StackingRule stackingRule = cursor.getStackingRule();
|
final StackingRule stackingRule = cursor.getStackingRule();
|
||||||
|
if (slot != -999) {
|
||||||
if (slot == -999) {
|
// Add slot
|
||||||
// Start or end left/right drag
|
if (button == 1) {
|
||||||
|
// Add left
|
||||||
|
IntSet left = leftDraggingMap.get(player);
|
||||||
|
if (left == null) return null;
|
||||||
|
left.add(slot);
|
||||||
|
} else if (button == 5) {
|
||||||
|
// Add right
|
||||||
|
IntSet right = rightDraggingMap.get(player);
|
||||||
|
if (right == null) return null;
|
||||||
|
right.add(slot);
|
||||||
|
} else if (button == 9) {
|
||||||
|
// Add middle
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Drag instruction
|
||||||
if (button == 0) {
|
if (button == 0) {
|
||||||
// Start left
|
// Start left
|
||||||
clickResult = startCondition(player, inventory, slot, ClickType.START_LEFT_DRAGGING, clicked, cursor);
|
clickResult = startCondition(player, inventory, slot, ClickType.START_LEFT_DRAGGING, clicked, cursor);
|
||||||
if (!clickResult.isCancel())
|
if (!clickResult.isCancel()) this.leftDraggingMap.put(player, new IntOpenHashSet());
|
||||||
this.leftDraggingMap.put(player, new IntOpenHashSet());
|
} else if (button == 2) {
|
||||||
|
// End left
|
||||||
|
final IntSet slots = leftDraggingMap.remove(player);
|
||||||
|
if (slots == null) return null;
|
||||||
|
final int slotCount = slots.size();
|
||||||
|
final int cursorAmount = stackingRule.getAmount(cursor);
|
||||||
|
if (slotCount > cursorAmount) return null;
|
||||||
|
for (int s : slots) {
|
||||||
|
// Apply each drag element
|
||||||
|
final ItemStack slotItem = itemGetter.apply(s);
|
||||||
|
clickResult = startCondition(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
|
||||||
|
if (clickResult.isCancel()) {
|
||||||
|
return clickResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clickResult = startCondition(player, inventory, slot, ClickType.END_LEFT_DRAGGING, clicked, cursor);
|
||||||
|
if (clickResult.isCancel()) return clickResult;
|
||||||
|
// Should be size of each defined slot (if not full)
|
||||||
|
final int slotSize = (int) ((float) cursorAmount / (float) slotCount);
|
||||||
|
// Place all waiting drag action
|
||||||
|
int finalCursorAmount = cursorAmount;
|
||||||
|
for (int s : slots) {
|
||||||
|
ItemStack slotItem = itemGetter.apply(s);
|
||||||
|
final StackingRule slotItemRule = slotItem.getStackingRule();
|
||||||
|
final int amount = slotItemRule.getAmount(slotItem);
|
||||||
|
if (stackingRule.canBeStacked(cursor, slotItem)) {
|
||||||
|
if (stackingRule.canApply(slotItem, amount + slotSize)) {
|
||||||
|
// Append divided amount to slot
|
||||||
|
slotItem = stackingRule.apply(slotItem, a -> a + slotSize);
|
||||||
|
finalCursorAmount -= slotSize;
|
||||||
|
} else {
|
||||||
|
// Amount too big, fill as much as possible
|
||||||
|
final int maxSize = stackingRule.getMaxSize(cursor);
|
||||||
|
final int removedAmount = maxSize - amount;
|
||||||
|
slotItem = stackingRule.apply(slotItem, maxSize);
|
||||||
|
finalCursorAmount -= removedAmount;
|
||||||
|
}
|
||||||
|
} else if (slotItem.isAir()) {
|
||||||
|
// Slot is empty, add divided amount
|
||||||
|
slotItem = stackingRule.apply(cursor, slotSize);
|
||||||
|
finalCursorAmount -= slotSize;
|
||||||
|
}
|
||||||
|
itemSetter.accept(s, slotItem);
|
||||||
|
callClickEvent(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
|
||||||
|
}
|
||||||
|
// Update the cursor
|
||||||
|
clickResult.setCursor(stackingRule.apply(cursor, finalCursorAmount));
|
||||||
} else if (button == 4) {
|
} else if (button == 4) {
|
||||||
// Start right
|
// Start right
|
||||||
clickResult = startCondition(player, inventory, slot, ClickType.START_RIGHT_DRAGGING, clicked, cursor);
|
clickResult = startCondition(player, inventory, slot, ClickType.START_RIGHT_DRAGGING, clicked, cursor);
|
||||||
if (!clickResult.isCancel())
|
if (!clickResult.isCancel()) this.rightDraggingMap.put(player, new IntOpenHashSet());
|
||||||
this.rightDraggingMap.put(player, new IntOpenHashSet());
|
|
||||||
} else if (button == 2) {
|
|
||||||
// End left
|
|
||||||
if (!leftDraggingMap.containsKey(player))
|
|
||||||
return null;
|
|
||||||
final IntSet slots = leftDraggingMap.get(player);
|
|
||||||
final int slotCount = slots.size();
|
|
||||||
final int cursorAmount = stackingRule.getAmount(cursor);
|
|
||||||
if (slotCount > cursorAmount)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
boolean cancel = false;
|
|
||||||
|
|
||||||
for (int s : slots) {
|
|
||||||
ItemStack slotItem = itemGetter.apply(s);
|
|
||||||
clickResult = startCondition(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
|
|
||||||
if (clickResult.isCancel()) {
|
|
||||||
cancel = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cancel |= startCondition(player, inventory, slot, ClickType.END_LEFT_DRAGGING, clicked, cursor).isCancel();
|
|
||||||
|
|
||||||
// Should be size of each defined slot (if not full)
|
|
||||||
final int slotSize = (int) ((float) cursorAmount / (float) slotCount);
|
|
||||||
int finalCursorAmount = cursorAmount;
|
|
||||||
|
|
||||||
if (!cancel) {
|
|
||||||
for (int s : slots) {
|
|
||||||
ItemStack slotItem = itemGetter.apply(s);
|
|
||||||
StackingRule slotItemRule = slotItem.getStackingRule();
|
|
||||||
|
|
||||||
final int maxSize = stackingRule.getMaxSize(cursor);
|
|
||||||
if (stackingRule.canBeStacked(cursor, slotItem)) {
|
|
||||||
final int amount = slotItemRule.getAmount(slotItem);
|
|
||||||
if (stackingRule.canApply(slotItem, amount + slotSize)) {
|
|
||||||
slotItem = stackingRule.apply(slotItem, a -> a + slotSize);
|
|
||||||
finalCursorAmount -= slotSize;
|
|
||||||
} else {
|
|
||||||
final int removedAmount = maxSize - amount;
|
|
||||||
slotItem = stackingRule.apply(slotItem, maxSize);
|
|
||||||
finalCursorAmount -= removedAmount;
|
|
||||||
}
|
|
||||||
} else if (slotItem.isAir()) {
|
|
||||||
slotItem = stackingRule.apply(cursor, slotSize);
|
|
||||||
finalCursorAmount -= slotSize;
|
|
||||||
}
|
|
||||||
itemSetter.accept(s, slotItem);
|
|
||||||
|
|
||||||
callClickEvent(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no slots were dragged over, no need to apply any kind of stacking rules
|
|
||||||
if (clickResult != null) {
|
|
||||||
cursor = stackingRule.apply(cursor, finalCursorAmount);
|
|
||||||
clickResult.setCursor(cursor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
leftDraggingMap.remove(player);
|
|
||||||
} else if (button == 6) {
|
} else if (button == 6) {
|
||||||
// End right
|
// End right
|
||||||
if (!rightDraggingMap.containsKey(player))
|
final IntSet slots = rightDraggingMap.remove(player);
|
||||||
return null;
|
if (slots == null) return null;
|
||||||
final IntSet slots = rightDraggingMap.get(player);
|
|
||||||
final int size = slots.size();
|
final int size = slots.size();
|
||||||
int cursorAmount = stackingRule.getAmount(cursor);
|
int cursorAmount = stackingRule.getAmount(cursor);
|
||||||
if (size > cursorAmount)
|
if (size > cursorAmount) return null;
|
||||||
return null;
|
// Verify if each slot can be modified (or cancel the whole drag)
|
||||||
|
|
||||||
boolean cancel = false;
|
|
||||||
|
|
||||||
for (int s : slots) {
|
for (int s : slots) {
|
||||||
ItemStack slotItem = itemGetter.apply(s);
|
ItemStack slotItem = itemGetter.apply(s);
|
||||||
|
|
||||||
clickResult = startCondition(player, inventory, s, ClickType.RIGHT_DRAGGING, slotItem, cursor);
|
clickResult = startCondition(player, inventory, s, ClickType.RIGHT_DRAGGING, slotItem, cursor);
|
||||||
|
|
||||||
if (clickResult.isCancel()) {
|
if (clickResult.isCancel()) {
|
||||||
cancel = true;
|
return clickResult;
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
clickResult = startCondition(player, inventory, slot, ClickType.END_RIGHT_DRAGGING, clicked, cursor);
|
||||||
cancel |= startCondition(player, inventory, slot, ClickType.END_RIGHT_DRAGGING, clicked, cursor).isCancel();
|
if (clickResult.isCancel()) return clickResult;
|
||||||
|
// Place all waiting drag action
|
||||||
if (!cancel) {
|
int finalCursorAmount = cursorAmount;
|
||||||
for (int s : slots) {
|
for (int s : slots) {
|
||||||
ItemStack draggedItem = cursor;
|
ItemStack slotItem = itemGetter.apply(s);
|
||||||
ItemStack slotItem = itemGetter.apply(s);
|
StackingRule slotItemRule = slotItem.getStackingRule();
|
||||||
|
if (stackingRule.canBeStacked(cursor, slotItem)) {
|
||||||
StackingRule slotItemRule = slotItem.getStackingRule();
|
// Compatible item in the slot, increment by 1
|
||||||
if (stackingRule.canBeStacked(draggedItem, slotItem)) {
|
final int amount = slotItemRule.getAmount(slotItem) + 1;
|
||||||
final int amount = slotItemRule.getAmount(slotItem) + 1;
|
if (stackingRule.canApply(slotItem, amount)) {
|
||||||
if (stackingRule.canApply(slotItem, amount)) {
|
slotItem = stackingRule.apply(slotItem, amount);
|
||||||
slotItem = stackingRule.apply(slotItem, amount);
|
finalCursorAmount -= 1;
|
||||||
itemSetter.accept(s, slotItem);
|
|
||||||
cursorAmount -= 1;
|
|
||||||
}
|
|
||||||
} else if (slotItem.isAir()) {
|
|
||||||
draggedItem = stackingRule.apply(draggedItem, 1);
|
|
||||||
itemSetter.accept(s, draggedItem);
|
|
||||||
cursorAmount -= 1;
|
|
||||||
}
|
}
|
||||||
|
} else if (slotItem.isAir()) {
|
||||||
callClickEvent(player, inventory, s, ClickType.RIGHT_DRAGGING, draggedItem, cursor);
|
// No item at the slot, place one
|
||||||
}
|
slotItem = stackingRule.apply(cursor, 1);
|
||||||
|
finalCursorAmount -= 1;
|
||||||
// If no slots were dragged over, no need to apply any kind of stacking rules
|
|
||||||
if (clickResult != null) {
|
|
||||||
cursor = stackingRule.apply(cursor, cursorAmount);
|
|
||||||
clickResult.setCursor(cursor);
|
|
||||||
}
|
}
|
||||||
|
itemSetter.accept(s, slotItem);
|
||||||
|
callClickEvent(player, inventory, s, ClickType.RIGHT_DRAGGING, slotItem, cursor);
|
||||||
}
|
}
|
||||||
|
// Update the cursor
|
||||||
rightDraggingMap.remove(player);
|
clickResult.setCursor(stackingRule.apply(cursor, finalCursorAmount));
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Add slot
|
|
||||||
if (button == 1) {
|
|
||||||
// Add left slot
|
|
||||||
if (!leftDraggingMap.containsKey(player))
|
|
||||||
return null;
|
|
||||||
leftDraggingMap.get(player).add(slot);
|
|
||||||
|
|
||||||
} else if (button == 5) {
|
|
||||||
// Add right slot
|
|
||||||
if (!rightDraggingMap.containsKey(player))
|
|
||||||
return null;
|
|
||||||
rightDraggingMap.get(player).add(slot);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return clickResult;
|
return clickResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,8 +13,6 @@ import net.minestom.server.network.packet.client.play.ClientPongPacket;
|
|||||||
import net.minestom.server.network.packet.server.play.PingPacket;
|
import net.minestom.server.network.packet.server.play.PingPacket;
|
||||||
import net.minestom.server.network.packet.server.play.SetSlotPacket;
|
import net.minestom.server.network.packet.server.play.SetSlotPacket;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class WindowListener {
|
public class WindowListener {
|
||||||
|
|
||||||
public static void clickWindowListener(ClientClickWindowPacket packet, Player player) {
|
public static void clickWindowListener(ClientClickWindowPacket packet, Player player) {
|
||||||
@ -33,11 +31,10 @@ public class WindowListener {
|
|||||||
|
|
||||||
boolean successful = false;
|
boolean successful = false;
|
||||||
|
|
||||||
// prevent click in a non interactive slot (why does it exist?)
|
// prevent click in a non-interactive slot (why does it exist?)
|
||||||
if (slot == -1) {
|
if (slot == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clickType == ClientClickWindowPacket.ClickType.PICKUP) {
|
if (clickType == ClientClickWindowPacket.ClickType.PICKUP) {
|
||||||
if (button == 0) {
|
if (button == 0) {
|
||||||
if (slot != -999) {
|
if (slot != -999) {
|
||||||
@ -70,11 +67,7 @@ public class WindowListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Prevent the player from picking a ghost item in cursor
|
// Prevent the player from picking a ghost item in cursor
|
||||||
if (Objects.equals(player.getOpenInventory(), inventory)) {
|
refreshCursorItem(player, inventory);
|
||||||
assert inventory instanceof Inventory;
|
|
||||||
refreshCursorItem(player, (Inventory) inventory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent ghost item when the click is cancelled
|
// Prevent ghost item when the click is cancelled
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
player.getInventory().update();
|
player.getInventory().update();
|
||||||
@ -82,7 +75,7 @@ public class WindowListener {
|
|||||||
((Inventory) inventory).update(player);
|
((Inventory) inventory).update(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// (Why is the ping packet necessary?)
|
||||||
PingPacket pingPacket = new PingPacket();
|
PingPacket pingPacket = new PingPacket();
|
||||||
pingPacket.id = (1 << 30) | (windowId << 16);
|
pingPacket.id = (1 << 30) | (windowId << 16);
|
||||||
player.getPlayerConnection().sendPacket(pingPacket);
|
player.getPlayerConnection().sendPacket(pingPacket);
|
||||||
@ -108,9 +101,15 @@ public class WindowListener {
|
|||||||
* @param player the player to refresh the cursor item
|
* @param player the player to refresh the cursor item
|
||||||
* @param inventory the player open inventory, null if not any (could be player inventory)
|
* @param inventory the player open inventory, null if not any (could be player inventory)
|
||||||
*/
|
*/
|
||||||
private static void refreshCursorItem(Player player, Inventory inventory) {
|
private static void refreshCursorItem(Player player, AbstractInventory inventory) {
|
||||||
ItemStack cursorItem = inventory != null ?
|
ItemStack cursorItem;
|
||||||
inventory.getCursorItem(player) : player.getInventory().getCursorItem();
|
if (inventory instanceof PlayerInventory) {
|
||||||
|
cursorItem = ((PlayerInventory) inventory).getCursorItem();
|
||||||
|
} else if (inventory instanceof Inventory) {
|
||||||
|
cursorItem = ((Inventory) inventory).getCursorItem(player);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
||||||
|
}
|
||||||
final SetSlotPacket setSlotPacket = SetSlotPacket.createCursorPacket(cursorItem);
|
final SetSlotPacket setSlotPacket = SetSlotPacket.createCursorPacket(cursorItem);
|
||||||
player.getPlayerConnection().sendPacket(setSlotPacket);
|
player.getPlayerConnection().sendPacket(setSlotPacket);
|
||||||
}
|
}
|
||||||
@ -120,9 +119,7 @@ public class WindowListener {
|
|||||||
((PlayerInventory) inventory).setCursorItem(itemStack);
|
((PlayerInventory) inventory).setCursorItem(itemStack);
|
||||||
} else if (inventory instanceof Inventory) {
|
} else if (inventory instanceof Inventory) {
|
||||||
((Inventory) inventory).setCursorItem(player, itemStack);
|
((Inventory) inventory).setCursorItem(player, itemStack);
|
||||||
} else {
|
|
||||||
System.err.println("Invalid inventory: " + inventory.getClass());
|
|
||||||
}
|
}
|
||||||
|
throw new RuntimeException("Invalid inventory: " + inventory.getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user