Fix drag clicks

This commit is contained in:
TheMode 2021-08-29 00:07:58 +02:00
parent e5ecee2089
commit a75910fe3f
3 changed files with 40 additions and 44 deletions

View File

@ -401,18 +401,7 @@ public class Inventory extends AbstractInventory implements Viewable {
final InventoryClickResult clickResult = clickProcessor.dragging(player,
slot != -999 ? (isInWindow ? this : playerInventory) : null,
clickSlot, button,
clicked, cursor,
s -> isClickInWindow(s) ? getItemStack(s) :
playerInventory.getItemStack(PlayerInventoryUtils.convertSlot(s, offset)),
(s, item) -> {
if (isClickInWindow(s)) {
setItemStack(s, item);
} else {
playerInventory.setItemStack(PlayerInventoryUtils.convertSlot(s, offset), item);
}
});
clicked, cursor);
if (clickResult == null || clickResult.isCancel()) {
updateAll(player);
return false;

View File

@ -317,9 +317,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final ItemStack cursor = getCursorItem();
final ItemStack clicked = slot != -999 ? getItemStackFromPacketSlot(slot) : ItemStack.AIR;
final InventoryClickResult clickResult = clickProcessor.dragging(player, this,
slot, button,
clicked, cursor, this::getItemStackFromPacketSlot,
this::setItemStackFromPacketSlot);
convertPlayerInventorySlot(slot, OFFSET), button, clicked, cursor);
if (clickResult == null || clickResult.isCancel()) {
update();
return false;

View File

@ -1,8 +1,5 @@
package net.minestom.server.inventory.click;
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import net.minestom.server.entity.EquipmentSlot;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
@ -18,18 +15,18 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@ApiStatus.Internal
public final class InventoryClickProcessor {
// Dragging maps
private final Map<Player, IntSet> leftDraggingMap = new ConcurrentHashMap<>();
private final Map<Player, IntSet> rightDraggingMap = new ConcurrentHashMap<>();
private final Map<Player, List<DragData>> leftDraggingMap = new ConcurrentHashMap<>();
private final Map<Player, List<DragData>> rightDraggingMap = new ConcurrentHashMap<>();
public @NotNull InventoryClickResult leftClick(@NotNull Player player, @NotNull AbstractInventory inventory,
int slot,
@ -162,23 +159,21 @@ public final class InventoryClickProcessor {
public @Nullable InventoryClickResult dragging(@NotNull Player player, @Nullable AbstractInventory inventory,
int slot, int button,
@NotNull ItemStack clicked, @NotNull ItemStack cursor,
@NotNull Int2ObjectFunction<ItemStack> itemGetter,
@NotNull BiConsumer<Integer, ItemStack> itemSetter) {
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
InventoryClickResult clickResult = null;
final StackingRule stackingRule = cursor.getStackingRule();
if (slot != -999) {
// Add slot
if (button == 1) {
// Add left
IntSet left = leftDraggingMap.get(player);
List<DragData> left = leftDraggingMap.get(player);
if (left == null) return null;
left.add(slot);
left.add(new DragData(slot, inventory));
} else if (button == 5) {
// Add right
IntSet right = rightDraggingMap.get(player);
List<DragData> right = rightDraggingMap.get(player);
if (right == null) return null;
right.add(slot);
right.add(new DragData(slot, inventory));
} else if (button == 9) {
// Add middle
// TODO
@ -188,18 +183,18 @@ public final class InventoryClickProcessor {
if (button == 0) {
// Start left
clickResult = startCondition(player, inventory, slot, ClickType.START_LEFT_DRAGGING, clicked, cursor);
if (!clickResult.isCancel()) this.leftDraggingMap.put(player, new IntOpenHashSet());
if (!clickResult.isCancel()) this.leftDraggingMap.put(player, new ArrayList<>());
} else if (button == 2) {
// End left
final IntSet slots = leftDraggingMap.remove(player);
final List<DragData> 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) {
for (DragData s : slots) {
// Apply each drag element
final ItemStack slotItem = itemGetter.apply(s);
clickResult = startCondition(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
final ItemStack slotItem = s.inventory.getItemStack(s.slot);
clickResult = startCondition(player, s.inventory, s.slot, ClickType.LEFT_DRAGGING, slotItem, cursor);
if (clickResult.isCancel()) {
return clickResult;
}
@ -210,8 +205,10 @@ public final class InventoryClickProcessor {
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);
for (DragData dragData : slots) {
final var inv = dragData.inventory;
final int s = dragData.slot;
ItemStack slotItem = inv.getItemStack(s);
final StackingRule slotItemRule = slotItem.getStackingRule();
final int amount = slotItemRule.getAmount(slotItem);
if (stackingRule.canBeStacked(cursor, slotItem)) {
@ -231,7 +228,7 @@ public final class InventoryClickProcessor {
slotItem = stackingRule.apply(cursor, slotSize);
finalCursorAmount -= slotSize;
}
itemSetter.accept(s, slotItem);
inv.setItemStack(s, slotItem);
callClickEvent(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
}
// Update the cursor
@ -239,18 +236,18 @@ public final class InventoryClickProcessor {
} else if (button == 4) {
// Start right
clickResult = startCondition(player, inventory, slot, ClickType.START_RIGHT_DRAGGING, clicked, cursor);
if (!clickResult.isCancel()) this.rightDraggingMap.put(player, new IntOpenHashSet());
if (!clickResult.isCancel()) this.rightDraggingMap.put(player, new ArrayList<>());
} else if (button == 6) {
// End right
final IntSet slots = rightDraggingMap.remove(player);
final List<DragData> slots = rightDraggingMap.remove(player);
if (slots == null) return null;
final int size = slots.size();
int cursorAmount = stackingRule.getAmount(cursor);
if (size > cursorAmount) return null;
// Verify if each slot can be modified (or cancel the whole drag)
for (int s : slots) {
ItemStack slotItem = itemGetter.apply(s);
clickResult = startCondition(player, inventory, s, ClickType.RIGHT_DRAGGING, slotItem, cursor);
for (DragData s : slots) {
final ItemStack slotItem = s.inventory.getItemStack(s.slot);
clickResult = startCondition(player, s.inventory, s.slot, ClickType.RIGHT_DRAGGING, slotItem, cursor);
if (clickResult.isCancel()) {
return clickResult;
}
@ -259,8 +256,10 @@ public final class InventoryClickProcessor {
if (clickResult.isCancel()) return clickResult;
// Place all waiting drag action
int finalCursorAmount = cursorAmount;
for (int s : slots) {
ItemStack slotItem = itemGetter.apply(s);
for (DragData dragData : slots) {
final var inv = dragData.inventory;
final int s = dragData.slot;
ItemStack slotItem = inv.getItemStack(s);
StackingRule slotItemRule = slotItem.getStackingRule();
if (stackingRule.canBeStacked(cursor, slotItem)) {
// Compatible item in the slot, increment by 1
@ -274,7 +273,7 @@ public final class InventoryClickProcessor {
slotItem = stackingRule.apply(cursor, 1);
finalCursorAmount -= 1;
}
itemSetter.accept(s, slotItem);
inv.setItemStack(s, slotItem);
callClickEvent(player, inventory, s, ClickType.RIGHT_DRAGGING, slotItem, cursor);
}
// Update the cursor
@ -462,4 +461,14 @@ public final class InventoryClickProcessor {
this.leftDraggingMap.remove(player);
this.rightDraggingMap.remove(player);
}
private static final class DragData {
private final int slot;
private final AbstractInventory inventory;
public DragData(int slot, AbstractInventory inventory) {
this.slot = slot;
this.inventory = inventory;
}
}
}