mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-10 17:31:28 +01:00
Simplify double click handling
This commit is contained in:
parent
e9b5779b24
commit
5390cd14f0
@ -55,8 +55,7 @@ public abstract class AbstractInventory implements InventoryClickHandler, DataCo
|
||||
public synchronized <T> @NotNull T processItemStack(@NotNull ItemStack itemStack,
|
||||
@NotNull TransactionType type,
|
||||
@NotNull TransactionOption<T> option) {
|
||||
var pair = type.process(this, itemStack);
|
||||
return option.fill(this, pair.left(), pair.right());
|
||||
return option.fill(type, this, itemStack);
|
||||
}
|
||||
|
||||
public synchronized <T> @NotNull List<@NotNull T> processItemStacks(@NotNull List<@NotNull ItemStack> itemStacks,
|
||||
|
@ -4,7 +4,6 @@ import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.Viewable;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.inventory.click.ClickType;
|
||||
import net.minestom.server.inventory.click.InventoryClickLoopHandler;
|
||||
import net.minestom.server.inventory.click.InventoryClickResult;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.server.play.OpenWindowPacket;
|
||||
@ -468,17 +467,8 @@ public class Inventory extends AbstractInventory implements Viewable {
|
||||
final ItemStack cursor = getCursorItem(player);
|
||||
final boolean isInWindow = isClickInWindow(slot);
|
||||
|
||||
final InventoryClickResult clickResult = clickProcessor.doubleClick(isInWindow ? this : null, player, slot, cursor,
|
||||
// Start by looping through the opened inventory
|
||||
new InventoryClickLoopHandler(0, getSize(), 1,
|
||||
i -> i,
|
||||
this::getItemStack,
|
||||
this::setItemStack),
|
||||
// Looping through player inventory
|
||||
new InventoryClickLoopHandler(0, PlayerInventory.INVENTORY_SIZE, 1,
|
||||
PlayerInventoryUtils::convertToPacketSlot,
|
||||
index -> playerInventory.getItemStack(index, PlayerInventoryUtils.OFFSET),
|
||||
(index, itemStack) -> playerInventory.setItemStack(index, PlayerInventoryUtils.OFFSET, itemStack)));
|
||||
final InventoryClickResult clickResult = clickProcessor.doubleClick(isInWindow ? this : playerInventory,
|
||||
this, player, slot, cursor);
|
||||
|
||||
if (clickResult == null)
|
||||
return false;
|
||||
|
@ -3,7 +3,6 @@ package net.minestom.server.inventory;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.item.ArmorEquipEvent;
|
||||
import net.minestom.server.inventory.click.ClickType;
|
||||
import net.minestom.server.inventory.click.InventoryClickLoopHandler;
|
||||
import net.minestom.server.inventory.click.InventoryClickResult;
|
||||
import net.minestom.server.inventory.condition.InventoryCondition;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
@ -406,12 +405,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
|
||||
@Override
|
||||
public boolean doubleClick(@NotNull Player player, int slot) {
|
||||
final ItemStack cursor = getCursorItem();
|
||||
|
||||
final InventoryClickResult clickResult = clickProcessor.doubleClick(null, player, slot, cursor,
|
||||
new InventoryClickLoopHandler(0, itemStacks.length, 1,
|
||||
i -> i < 9 ? i + 9 : i - 9,
|
||||
index -> itemStacks[index],
|
||||
this::setItemStack));
|
||||
final InventoryClickResult clickResult = clickProcessor.doubleClick(this, null, player, slot, cursor);
|
||||
|
||||
if (clickResult == null)
|
||||
return false;
|
||||
@ -419,6 +413,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
|
||||
if (clickResult.doRefresh())
|
||||
update();
|
||||
|
||||
setItemStack(slot, OFFSET, clickResult.getClicked());
|
||||
setCursorItem(clickResult.getCursor());
|
||||
|
||||
return !clickResult.isCancel();
|
||||
|
@ -44,4 +44,11 @@ public interface TransactionOption<T> {
|
||||
@NotNull T fill(@NotNull AbstractInventory inventory,
|
||||
@NotNull ItemStack result,
|
||||
@NotNull Map<@NotNull Integer, @NotNull ItemStack> itemChangesMap);
|
||||
|
||||
default @NotNull T fill(@NotNull TransactionType type,
|
||||
@NotNull AbstractInventory inventory,
|
||||
@NotNull ItemStack itemStack) {
|
||||
var pair = type.process(inventory, itemStack);
|
||||
return fill(inventory, pair.left(), pair.right());
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.minestom.server.inventory.click;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
@ -9,6 +8,7 @@ import net.minestom.server.event.inventory.InventoryClickEvent;
|
||||
import net.minestom.server.event.inventory.InventoryPreClickEvent;
|
||||
import net.minestom.server.inventory.AbstractInventory;
|
||||
import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.inventory.TransactionOption;
|
||||
import net.minestom.server.inventory.TransactionType;
|
||||
import net.minestom.server.inventory.condition.InventoryCondition;
|
||||
import net.minestom.server.inventory.condition.InventoryConditionResult;
|
||||
@ -21,7 +21,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class InventoryClickProcessor {
|
||||
|
||||
@ -342,8 +344,8 @@ public class InventoryClickProcessor {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InventoryClickResult doubleClick(@Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ItemStack cursor, @NotNull InventoryClickLoopHandler... loopHandlers) {
|
||||
public InventoryClickResult doubleClick(@NotNull AbstractInventory clickedInventory, @Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull final ItemStack cursor) {
|
||||
InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.START_DOUBLE_CLICK, ItemStack.AIR, cursor);
|
||||
|
||||
if (clickResult.isCancel()) {
|
||||
@ -354,49 +356,46 @@ public class InventoryClickProcessor {
|
||||
return null;
|
||||
|
||||
final StackingRule cursorRule = cursor.getStackingRule();
|
||||
int amount = cursorRule.getAmount(cursor);
|
||||
final int amount = cursorRule.getAmount(cursor);
|
||||
final int remainingAmount = cursorRule.getMaxSize() - amount;
|
||||
|
||||
if (!cursorRule.canApply(cursor, amount + 1))
|
||||
return null;
|
||||
ItemStack remain = cursorRule.apply(cursor, remainingAmount);
|
||||
|
||||
for (InventoryClickLoopHandler loopHandler : loopHandlers) {
|
||||
final Int2IntFunction indexModifier = loopHandler.getIndexModifier();
|
||||
final Int2ObjectFunction<ItemStack> itemGetter = loopHandler.getItemGetter();
|
||||
final BiConsumer<Integer, ItemStack> itemSetter = loopHandler.getItemSetter();
|
||||
BiFunction<AbstractInventory, ItemStack, ItemStack> func = (inv, rest) -> {
|
||||
var pair = TransactionType.TAKE.process(inv, rest, (index, itemStack) -> {
|
||||
if (index == slot) // Prevent item lose/duplication
|
||||
return false;
|
||||
InventoryClickResult result = startCondition(inventory, player, index, ClickType.DOUBLE_CLICK, itemStack, cursor);
|
||||
return !result.isCancel();
|
||||
});
|
||||
var itemResult = pair.left();
|
||||
var map = pair.right();
|
||||
return TransactionOption.ALL.fill(inv, itemResult, map);
|
||||
};
|
||||
|
||||
for (int i = loopHandler.getStart(); i < loopHandler.getEnd(); i += loopHandler.getStep()) {
|
||||
final int index = indexModifier.apply(i);
|
||||
if (index == slot)
|
||||
continue;
|
||||
var playerInventory = player.getInventory();
|
||||
|
||||
ItemStack item = itemGetter.apply(index);
|
||||
final StackingRule itemRule = item.getStackingRule();
|
||||
if (!cursorRule.canApply(cursor, amount + 1))
|
||||
break;
|
||||
if (cursorRule.canBeStacked(cursor, item)) {
|
||||
clickResult = startCondition(inventory, player, index, ClickType.DOUBLE_CLICK, item, cursor);
|
||||
if (clickResult.isCancel())
|
||||
break;
|
||||
|
||||
final int totalAmount = amount + cursorRule.getAmount(item);
|
||||
if (!cursorRule.canApply(cursor, totalAmount)) {
|
||||
cursor = cursorRule.apply(cursor, cursorRule.getMaxSize());
|
||||
|
||||
item = itemRule.apply(item, totalAmount - itemRule.getMaxSize());
|
||||
if (Objects.equals(clickedInventory, inventory)) {
|
||||
// Clicked inside inventory
|
||||
remain = func.apply(inventory, remain);
|
||||
if (!remain.isAir()) {
|
||||
remain = func.apply(playerInventory, remain);
|
||||
}
|
||||
} else if (inventory != null && clickedInventory == playerInventory) {
|
||||
// Clicked inside player inventory, but with another inventory open
|
||||
remain = func.apply(playerInventory, remain);
|
||||
if (!remain.isAir()) {
|
||||
remain = func.apply(inventory, remain);
|
||||
}
|
||||
} else {
|
||||
cursor = cursorRule.apply(cursor, totalAmount);
|
||||
item = itemRule.apply(item, 0);
|
||||
}
|
||||
itemSetter.accept(index, item);
|
||||
amount = cursorRule.getAmount(cursor);
|
||||
|
||||
callClickEvent(player, inventory, index, ClickType.DOUBLE_CLICK, item, cursor);
|
||||
}
|
||||
}
|
||||
// Clicked inside player inventory
|
||||
remain = func.apply(playerInventory, remain);
|
||||
}
|
||||
|
||||
clickResult.setCursor(cursor);
|
||||
final int tookAmount = remainingAmount - cursorRule.getAmount(remain);
|
||||
|
||||
ItemStack resultCursor = cursorRule.apply(cursor, amount + tookAmount);
|
||||
clickResult.setCursor(resultCursor);
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user