More inventory cleanup

This commit is contained in:
TheMode 2021-08-12 18:06:23 +02:00
parent 6b151c1f7c
commit c17f07e1d0
5 changed files with 65 additions and 129 deletions

View File

@ -68,7 +68,6 @@ public interface Block extends ProtocolObject, TagReadable, BlockConstants {
return withTag(Tag.NBT, compound); return withTag(Tag.NBT, compound);
} }
/** /**
* Creates a new block with the specified {@link BlockHandler handler}. * Creates a new block with the specified {@link BlockHandler handler}.
* *

View File

@ -268,8 +268,7 @@ public class Inventory extends AbstractInventory implements Viewable {
final int clickSlot = isInWindow ? slot : PlayerInventoryUtils.convertSlot(slot, offset); final int clickSlot = isInWindow ? slot : PlayerInventoryUtils.convertSlot(slot, offset);
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot); final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot);
final InventoryClickResult clickResult = clickProcessor.leftClick(isInWindow ? this : null, player, slot, clicked, cursor); final InventoryClickResult clickResult = clickProcessor.leftClick(player, this, slot, clicked, cursor);
if (clickResult.doRefresh()) { if (clickResult.doRefresh()) {
updateFromClick(clickResult, player); updateFromClick(clickResult, player);
} }
@ -295,8 +294,7 @@ public class Inventory extends AbstractInventory implements Viewable {
final int clickSlot = isInWindow ? slot : PlayerInventoryUtils.convertSlot(slot, offset); final int clickSlot = isInWindow ? slot : PlayerInventoryUtils.convertSlot(slot, offset);
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot); final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot);
final InventoryClickResult clickResult = clickProcessor.rightClick(isInWindow ? this : null, player, slot, clicked, cursor); final InventoryClickResult clickResult = clickProcessor.rightClick(player, this, slot, clicked, cursor);
if (clickResult.doRefresh()) { if (clickResult.doRefresh()) {
updateFromClick(clickResult, player); updateFromClick(clickResult, player);
} }
@ -323,10 +321,10 @@ public class Inventory extends AbstractInventory implements Viewable {
final ItemStack cursor = getCursorItem(player); // Isn't used in the algorithm final ItemStack cursor = getCursorItem(player); // Isn't used in the algorithm
final InventoryClickResult clickResult = clickProcessor.shiftClick( final InventoryClickResult clickResult = clickProcessor.shiftClick(
isInWindow ? this : playerInventory,
isInWindow ? playerInventory : this, isInWindow ? playerInventory : this,
isInWindow ? this : null, 0, isInWindow ? playerInventory.getInnerSize() : getInnerSize(), 1,
player, slot, clicked, cursor); player, slot, clicked, cursor);
if (clickResult == null) if (clickResult == null)
return false; return false;
@ -353,8 +351,7 @@ public class Inventory extends AbstractInventory implements Viewable {
final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot); final ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot);
final ItemStack heldItem = playerInventory.getItemStack(key); final ItemStack heldItem = playerInventory.getItemStack(key);
final InventoryClickResult clickResult = clickProcessor.changeHeld(isInWindow ? this : null, player, slot, key, clicked, heldItem); final InventoryClickResult clickResult = clickProcessor.changeHeld(player, this, slot, key, clicked, heldItem);
if (clickResult.doRefresh()) { if (clickResult.doRefresh()) {
updateFromClick(clickResult, player); updateFromClick(clickResult, player);
} }
@ -391,7 +388,7 @@ public class Inventory extends AbstractInventory implements Viewable {
ItemStack.AIR : (isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot)); ItemStack.AIR : (isInWindow ? getItemStack(slot) : playerInventory.getItemStack(clickSlot));
final ItemStack cursor = getCursorItem(player); final ItemStack cursor = getCursorItem(player);
final InventoryClickResult clickResult = clickProcessor.drop(isInWindow ? this : null, player, final InventoryClickResult clickResult = clickProcessor.drop(player, this,
all, slot, button, clicked, cursor); all, slot, button, clicked, cursor);
if (clickResult.doRefresh()) { if (clickResult.doRefresh()) {
@ -422,7 +419,7 @@ public class Inventory extends AbstractInventory implements Viewable {
ItemStack.AIR; ItemStack.AIR;
final ItemStack cursor = getCursorItem(player); final ItemStack cursor = getCursorItem(player);
final InventoryClickResult clickResult = clickProcessor.dragging(isInWindow ? this : null, player, final InventoryClickResult clickResult = clickProcessor.dragging(player, this,
slot, button, slot, button,
clicked, cursor, clicked, cursor,

View File

@ -262,8 +262,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final ItemStack cursor = getCursorItem(); final ItemStack cursor = getCursorItem();
final ItemStack clicked = getItemStack(convertedSlot); final ItemStack clicked = getItemStack(convertedSlot);
final InventoryClickResult clickResult = clickProcessor.leftClick(null, player, convertedSlot, clicked, cursor); final InventoryClickResult clickResult = clickProcessor.leftClick(player, this, convertedSlot, clicked, cursor);
if (clickResult.doRefresh()) if (clickResult.doRefresh())
sendSlotRefresh((short) slot, clicked); sendSlotRefresh((short) slot, clicked);
@ -282,8 +281,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final ItemStack cursor = getCursorItem(); final ItemStack cursor = getCursorItem();
final ItemStack clicked = getItemStack(convertedSlot); final ItemStack clicked = getItemStack(convertedSlot);
final InventoryClickResult clickResult = clickProcessor.rightClick(null, player, convertedSlot, clicked, cursor); final InventoryClickResult clickResult = clickProcessor.rightClick(player, this, convertedSlot, clicked, cursor);
if (clickResult.doRefresh()) if (clickResult.doRefresh())
sendSlotRefresh((short) slot, clicked); sendSlotRefresh((short) slot, clicked);
@ -308,9 +306,8 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final boolean outsideDrop = slot == -999; final boolean outsideDrop = slot == -999;
final ItemStack clicked = outsideDrop ? ItemStack.AIR : getItemStack(slot, OFFSET); final ItemStack clicked = outsideDrop ? ItemStack.AIR : getItemStack(slot, OFFSET);
final InventoryClickResult clickResult = clickProcessor.drop(null, player, final InventoryClickResult clickResult = clickProcessor.drop(player, this,
all, slot, button, clicked, cursor); all, slot, button, clicked, cursor);
if (clickResult.doRefresh()) if (clickResult.doRefresh())
sendSlotRefresh((short) slot, clicked); sendSlotRefresh((short) slot, clicked);
@ -329,10 +326,10 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final boolean hotBarClick = convertSlot(slot, OFFSET) < 9; final boolean hotBarClick = convertSlot(slot, OFFSET) < 9;
final int start = hotBarClick ? 9 : 0; final int start = hotBarClick ? 9 : 0;
final int end = hotBarClick ? getSize() - 9 : 8; final int end = hotBarClick ? getSize() - 9 : 8;
final InventoryClickResult clickResult = clickProcessor.shiftClick(this, final InventoryClickResult clickResult = clickProcessor.shiftClick(
this, this,
start, end, 1, start, end, 1,
player, slot, clicked, cursor); player, slot, clicked, cursor);
if (clickResult == null) if (clickResult == null)
return false; return false;
@ -350,8 +347,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final ItemStack heldItem = getItemStack(key); final ItemStack heldItem = getItemStack(key);
final ItemStack clicked = getItemStack(slot, OFFSET); final ItemStack clicked = getItemStack(slot, OFFSET);
final InventoryClickResult clickResult = clickProcessor.changeHeld(null, player, slot, key, clicked, heldItem); final InventoryClickResult clickResult = clickProcessor.changeHeld(player, this, slot, key, clicked, heldItem);
if (clickResult.doRefresh()) { if (clickResult.doRefresh()) {
sendSlotRefresh((short) slot, clicked); sendSlotRefresh((short) slot, clicked);
} }
@ -373,11 +369,10 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
final ItemStack cursor = getCursorItem(); final ItemStack cursor = getCursorItem();
final ItemStack clicked = slot != -999 ? getItemStack(slot, OFFSET) : ItemStack.AIR; final ItemStack clicked = slot != -999 ? getItemStack(slot, OFFSET) : ItemStack.AIR;
final InventoryClickResult clickResult = clickProcessor.dragging(null, player, final InventoryClickResult clickResult = clickProcessor.dragging(player, this,
slot, button, slot, button,
clicked, cursor, s -> getItemStack(s, OFFSET), clicked, cursor, s -> getItemStack(s, OFFSET),
(s, item) -> setItemStack(s, OFFSET, item)); (s, item) -> setItemStack(s, OFFSET, item));
if (clickResult == null) { if (clickResult == null) {
return false; return false;
} }
@ -393,7 +388,7 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
@Override @Override
public boolean doubleClick(@NotNull Player player, int slot) { public boolean doubleClick(@NotNull Player player, int slot) {
final ItemStack cursor = getCursorItem(); final ItemStack cursor = getCursorItem();
final InventoryClickResult clickResult = clickProcessor.doubleClick(this, null, player, slot, cursor); final InventoryClickResult clickResult = clickProcessor.doubleClick(this, this, player, slot, cursor);
if (clickResult == null) if (clickResult == null)
return false; return false;
if (clickResult.doRefresh()) if (clickResult.doRefresh())

View File

@ -21,9 +21,7 @@ public interface TransactionType {
*/ */
TransactionType ADD = (inventory, itemStack, slotPredicate, start, end, step) -> { TransactionType ADD = (inventory, itemStack, slotPredicate, start, end, step) -> {
Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>();
final StackingRule stackingRule = itemStack.getStackingRule(); final StackingRule stackingRule = itemStack.getStackingRule();
// Check filled slot (not air) // Check filled slot (not air)
for (int i = start; i < end; i += step) { for (int i = start; i < end; i += step) {
ItemStack inventoryItem = inventory.getItemStack(i); ItemStack inventoryItem = inventory.getItemStack(i);
@ -33,9 +31,7 @@ public interface TransactionType {
if (stackingRule.canBeStacked(itemStack, inventoryItem)) { if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
final int itemAmount = stackingRule.getAmount(inventoryItem); final int itemAmount = stackingRule.getAmount(inventoryItem);
final int maxSize = stackingRule.getMaxSize(inventoryItem); final int maxSize = stackingRule.getMaxSize(inventoryItem);
if (itemAmount == maxSize) if (itemAmount == maxSize) continue;
continue;
if (!slotPredicate.test(i, inventoryItem)) { if (!slotPredicate.test(i, inventoryItem)) {
// Cancelled transaction // Cancelled transaction
continue; continue;
@ -55,25 +51,19 @@ public interface TransactionType {
} }
} }
} }
// Check air slot to fill // Check air slot to fill
for (int i = start; i < end; i += step) { for (int i = start; i < end; i += step) {
ItemStack inventoryItem = inventory.getItemStack(i); ItemStack inventoryItem = inventory.getItemStack(i);
if (!inventoryItem.isAir()) { if (!inventoryItem.isAir()) continue;
continue;
}
if (!slotPredicate.test(i, inventoryItem)) { if (!slotPredicate.test(i, inventoryItem)) {
// Cancelled transaction // Cancelled transaction
continue; continue;
} }
// Fill the slot // Fill the slot
itemChangesMap.put(i, itemStack); itemChangesMap.put(i, itemStack);
itemStack = stackingRule.apply(itemStack, 0); itemStack = stackingRule.apply(itemStack, 0);
break; break;
} }
return Pair.of(itemStack, itemChangesMap); return Pair.of(itemStack, itemChangesMap);
}; };
@ -85,10 +75,8 @@ public interface TransactionType {
Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>();
final StackingRule stackingRule = itemStack.getStackingRule(); final StackingRule stackingRule = itemStack.getStackingRule();
for (int i = start; i < end; i += step) { for (int i = start; i < end; i += step) {
ItemStack inventoryItem = inventory.getItemStack(i); final ItemStack inventoryItem = inventory.getItemStack(i);
if (inventoryItem.isAir()) { if (inventoryItem.isAir()) continue;
continue;
}
if (stackingRule.canBeStacked(itemStack, inventoryItem)) { if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
if (!slotPredicate.test(i, inventoryItem)) { if (!slotPredicate.test(i, inventoryItem)) {
// Cancelled transaction // Cancelled transaction
@ -110,7 +98,6 @@ public interface TransactionType {
} }
} }
} }
return Pair.of(itemStack, itemChangesMap); return Pair.of(itemStack, itemChangesMap);
}; };

View File

@ -15,7 +15,6 @@ import net.minestom.server.inventory.condition.InventoryCondition;
import net.minestom.server.inventory.condition.InventoryConditionResult; import net.minestom.server.inventory.condition.InventoryConditionResult;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.item.StackingRule; import net.minestom.server.item.StackingRule;
import net.minestom.server.utils.inventory.PlayerInventoryUtils;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -32,9 +31,10 @@ public final class InventoryClickProcessor {
private final Map<Player, IntSet> leftDraggingMap = new ConcurrentHashMap<>(); private final Map<Player, IntSet> leftDraggingMap = new ConcurrentHashMap<>();
private final Map<Player, IntSet> rightDraggingMap = new ConcurrentHashMap<>(); private final Map<Player, IntSet> rightDraggingMap = new ConcurrentHashMap<>();
public @NotNull InventoryClickResult leftClick(@Nullable Inventory inventory, @NotNull Player player, int slot, public @NotNull InventoryClickResult leftClick(@NotNull Player player, @NotNull AbstractInventory inventory,
int slot,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
final var result = startCondition(inventory, player, slot, ClickType.LEFT_CLICK, clicked, cursor); final var result = startCondition(player, inventory, slot, ClickType.LEFT_CLICK, clicked, cursor);
if (result.isCancel()) return result; if (result.isCancel()) return result;
clicked = result.getClicked(); clicked = result.getClicked();
cursor = result.getCursor(); cursor = result.getCursor();
@ -61,10 +61,10 @@ public final class InventoryClickProcessor {
return result; return result;
} }
public @NotNull InventoryClickResult rightClick(@Nullable Inventory inventory, @NotNull Player player, public @NotNull InventoryClickResult rightClick(@NotNull Player player, @NotNull AbstractInventory inventory,
int slot, int slot,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
final var result = startCondition(inventory, player, slot, ClickType.RIGHT_CLICK, clicked, cursor); final var result = startCondition(player, inventory, slot, ClickType.RIGHT_CLICK, clicked, cursor);
if (result.isCancel()) return result; if (result.isCancel()) return result;
clicked = result.getClicked(); clicked = result.getClicked();
cursor = result.getCursor(); cursor = result.getCursor();
@ -103,14 +103,14 @@ public final class InventoryClickProcessor {
return result; return result;
} }
public @NotNull InventoryClickResult changeHeld(@Nullable Inventory inventory, @NotNull Player player, public @NotNull InventoryClickResult changeHeld(@NotNull Player player, @NotNull AbstractInventory inventory,
int slot, int key, int slot, int key,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
// Verify the clicked item // Verify the clicked item
InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.CHANGE_HELD, clicked, cursor); InventoryClickResult clickResult = startCondition(player, inventory, slot, ClickType.CHANGE_HELD, clicked, cursor);
if (clickResult.isCancel()) return clickResult; if (clickResult.isCancel()) return clickResult;
// Verify the destination (held bar) // Verify the destination (held bar)
clickResult = startCondition(null, player, key, ClickType.CHANGE_HELD, clicked, cursor); clickResult = startCondition(player, player.getInventory(), key, ClickType.CHANGE_HELD, clicked, cursor);
if (clickResult.isCancel()) return clickResult; if (clickResult.isCancel()) return clickResult;
// Swap items // Swap items
clickResult.setClicked(cursor); clickResult.setClicked(cursor);
@ -118,33 +118,17 @@ public final class InventoryClickProcessor {
return clickResult; return clickResult;
} }
public @Nullable InventoryClickResult shiftClick(AbstractInventory targetInventory, @Nullable Inventory inventory, @NotNull Player player, int slot, public @Nullable InventoryClickResult shiftClick(@NotNull AbstractInventory inventory, @NotNull AbstractInventory targetInventory,
int start, int end, int step,
@NotNull Player player, int slot,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.START_SHIFT_CLICK, clicked, cursor); InventoryClickResult clickResult = startCondition(player, inventory, slot, ClickType.START_SHIFT_CLICK, clicked, cursor);
if (clickResult.isCancel()) return clickResult; if (clickResult.isCancel()) return clickResult;
if (clicked.isAir()) return null; if (clicked.isAir()) return null;
final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> { final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> {
InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor); if (inventory == targetInventory && index == slot)
if (result.isCancel()) { return false; // Prevent item lose/duplication
clickResult.setRefresh(true); InventoryClickResult result = startCondition(player, targetInventory, index, ClickType.SHIFT_CLICK, itemStack, cursor);
return false;
}
return true;
});
ItemStack itemResult = TransactionOption.ALL.fill(targetInventory, pair.left(), pair.right());
clickResult.setClicked(itemResult);
return clickResult;
}
public @Nullable InventoryClickResult shiftClick(@NotNull AbstractInventory targetInventory, int start, int end, int step, @NotNull Player player, int slot,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
InventoryClickResult clickResult = startCondition(null, player, slot, ClickType.START_SHIFT_CLICK, clicked, cursor);
if (clickResult.isCancel()) return clickResult;
if (clicked.isAir()) return null;
final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> {
if (index == slot) // Prevent item lose/duplication
return false;
InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor);
if (result.isCancel()) { if (result.isCancel()) {
clickResult.setRefresh(true); clickResult.setRefresh(true);
return false; return false;
@ -156,7 +140,7 @@ public final class InventoryClickProcessor {
return clickResult; return clickResult;
} }
public @Nullable InventoryClickResult dragging(@Nullable Inventory inventory, @NotNull Player player, public @Nullable InventoryClickResult dragging(@NotNull Player player, @NotNull AbstractInventory inventory,
int slot, int button, int slot, int button,
@NotNull ItemStack clicked, @NotNull ItemStack cursor, @NotNull ItemStack clicked, @NotNull ItemStack cursor,
@NotNull Int2ObjectFunction<ItemStack> itemGetter, @NotNull Int2ObjectFunction<ItemStack> itemGetter,
@ -169,12 +153,12 @@ public final class InventoryClickProcessor {
// Start or end left/right drag // Start or end left/right drag
if (button == 0) { if (button == 0) {
// Start left // Start left
clickResult = startCondition(inventory, player, 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 == 4) { } else if (button == 4) {
// Start right // Start right
clickResult = startCondition(inventory, player, 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) { } else if (button == 2) {
@ -191,14 +175,14 @@ public final class InventoryClickProcessor {
for (int s : slots) { for (int s : slots) {
ItemStack slotItem = itemGetter.apply(s); ItemStack slotItem = itemGetter.apply(s);
clickResult = startCondition(inventory, player, s, ClickType.LEFT_DRAGGING, slotItem, cursor); clickResult = startCondition(player, inventory, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
if (clickResult.isCancel()) { if (clickResult.isCancel()) {
cancel = true; cancel = true;
break; break;
} }
} }
cancel |= startCondition(inventory, player, slot, ClickType.END_LEFT_DRAGGING, clicked, cursor).isCancel(); cancel |= startCondition(player, inventory, slot, ClickType.END_LEFT_DRAGGING, clicked, cursor).isCancel();
// Should be size of each defined slot (if not full) // Should be size of each defined slot (if not full)
final int slotSize = (int) ((float) cursorAmount / (float) slotCount); final int slotSize = (int) ((float) cursorAmount / (float) slotCount);
@ -252,7 +236,7 @@ public final class InventoryClickProcessor {
for (int s : slots) { for (int s : slots) {
ItemStack slotItem = itemGetter.apply(s); ItemStack slotItem = itemGetter.apply(s);
clickResult = startCondition(inventory, player, s, ClickType.RIGHT_DRAGGING, slotItem, cursor); clickResult = startCondition(player, inventory, s, ClickType.RIGHT_DRAGGING, slotItem, cursor);
if (clickResult.isCancel()) { if (clickResult.isCancel()) {
cancel = true; cancel = true;
@ -261,7 +245,7 @@ public final class InventoryClickProcessor {
} }
} }
cancel |= startCondition(inventory, player, slot, ClickType.END_RIGHT_DRAGGING, clicked, cursor).isCancel(); cancel |= startCondition(player, inventory, slot, ClickType.END_RIGHT_DRAGGING, clicked, cursor).isCancel();
if (!cancel) { if (!cancel) {
for (int s : slots) { for (int s : slots) {
@ -314,9 +298,9 @@ public final class InventoryClickProcessor {
return clickResult; return clickResult;
} }
public @Nullable InventoryClickResult doubleClick(@NotNull AbstractInventory clickedInventory, @Nullable Inventory inventory, @NotNull Player player, int slot, public @Nullable InventoryClickResult doubleClick(@NotNull AbstractInventory clickedInventory, @NotNull AbstractInventory inventory, @NotNull Player player, int slot,
@NotNull final ItemStack cursor) { @NotNull final ItemStack cursor) {
InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.START_DOUBLE_CLICK, ItemStack.AIR, cursor); InventoryClickResult clickResult = startCondition(player, inventory, slot, ClickType.START_DOUBLE_CLICK, ItemStack.AIR, cursor);
if (clickResult.isCancel()) return clickResult; if (clickResult.isCancel()) return clickResult;
if (cursor.isAir()) return null; if (cursor.isAir()) return null;
@ -324,19 +308,15 @@ public final class InventoryClickProcessor {
final int amount = cursorRule.getAmount(cursor); final int amount = cursorRule.getAmount(cursor);
final int maxSize = cursorRule.getMaxSize(cursor); final int maxSize = cursorRule.getMaxSize(cursor);
final int remainingAmount = maxSize - amount; final int remainingAmount = maxSize - amount;
if (remainingAmount == 0) { if (remainingAmount == 0) {
// Item is already full // Item is already full
return clickResult; return clickResult;
} }
final BiFunction<AbstractInventory, ItemStack, ItemStack> func = (inv, rest) -> {
ItemStack remain = cursorRule.apply(cursor, remainingAmount);
BiFunction<AbstractInventory, ItemStack, ItemStack> func = (inv, rest) -> {
var pair = TransactionType.TAKE.process(inv, rest, (index, itemStack) -> { var pair = TransactionType.TAKE.process(inv, rest, (index, itemStack) -> {
if (index == slot) // Prevent item lose/duplication if (index == slot) // Prevent item lose/duplication
return false; return false;
InventoryClickResult result = startCondition(inventory, player, index, ClickType.DOUBLE_CLICK, itemStack, cursor); final InventoryClickResult result = startCondition(player, inventory, index, ClickType.DOUBLE_CLICK, itemStack, cursor);
return !result.isCancel(); return !result.isCancel();
}); });
var itemResult = pair.left(); var itemResult = pair.left();
@ -344,14 +324,16 @@ public final class InventoryClickProcessor {
return TransactionOption.ALL.fill(inv, itemResult, map); return TransactionOption.ALL.fill(inv, itemResult, map);
}; };
var playerInventory = player.getInventory(); ItemStack remain = cursorRule.apply(cursor, remainingAmount);
final var playerInventory = player.getInventory();
// Retrieve remain
if (Objects.equals(clickedInventory, inventory)) { if (Objects.equals(clickedInventory, inventory)) {
// Clicked inside inventory // Clicked inside inventory
remain = func.apply(inventory, remain); remain = func.apply(inventory, remain);
if (!remain.isAir()) { if (!remain.isAir()) {
remain = func.apply(playerInventory, remain); remain = func.apply(playerInventory, remain);
} }
} else if (inventory != null && clickedInventory == playerInventory) { } else if (clickedInventory == playerInventory) {
// Clicked inside player inventory, but with another inventory open // Clicked inside player inventory, but with another inventory open
remain = func.apply(playerInventory, remain); remain = func.apply(playerInventory, remain);
if (!remain.isAir()) { if (!remain.isAir()) {
@ -362,27 +344,22 @@ public final class InventoryClickProcessor {
remain = func.apply(playerInventory, remain); remain = func.apply(playerInventory, remain);
} }
ItemStack resultCursor; // Update cursor based on the remaining
if (remain.isAir()) { if (remain.isAir()) {
// Item has been filled // Item has been filled
resultCursor = cursorRule.apply(cursor, maxSize); clickResult.setCursor(cursorRule.apply(cursor, maxSize));
} else { } else {
final int tookAmount = remainingAmount - cursorRule.getAmount(remain); final int tookAmount = remainingAmount - cursorRule.getAmount(remain);
resultCursor = cursorRule.apply(cursor, amount + tookAmount); clickResult.setCursor(cursorRule.apply(cursor, amount + tookAmount));
} }
clickResult.setCursor(resultCursor);
return clickResult; return clickResult;
} }
public @NotNull InventoryClickResult drop(@Nullable Inventory inventory, @NotNull Player player, public @NotNull InventoryClickResult drop(@NotNull Player player, @NotNull AbstractInventory inventory,
boolean all, int slot, int button, boolean all, int slot, int button,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.DROP, clicked, cursor); final InventoryClickResult clickResult = startCondition(player, inventory, slot, ClickType.DROP, clicked, cursor);
if (clickResult.isCancel()) return clickResult;
if (clickResult.isCancel()) {
return clickResult;
}
final StackingRule clickedRule = clicked.getStackingRule(); final StackingRule clickedRule = clicked.getStackingRule();
final StackingRule cursorRule = cursor.getStackingRule(); final StackingRule cursorRule = cursor.getStackingRule();
@ -442,26 +419,20 @@ public final class InventoryClickProcessor {
return clickResult; return clickResult;
} }
private @NotNull InventoryClickResult startCondition(@Nullable Inventory inventory, private @NotNull InventoryClickResult startCondition(@NotNull Player player,
@NotNull Player player, int slot, @NotNull ClickType clickType, @NotNull AbstractInventory inventory,
int slot, @NotNull ClickType clickType,
@NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
final InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor); final InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor);
boolean isPlayerInventory = inventory == null; final Inventory eventInventory = inventory instanceof Inventory ? (Inventory) inventory : null;
final int inventorySlot = isPlayerInventory ? 0 : inventory.getSize(); clickResult.setPlayerInventory(eventInventory == null);
isPlayerInventory = isPlayerInventory ? isPlayerInventory : slot >= inventorySlot;
clickResult.setPlayerInventory(isPlayerInventory);
if (isPlayerInventory && inventory != null) {
slot = slot - inventorySlot + PlayerInventoryUtils.OFFSET;
}
// Reset the didCloseInventory field // Reset the didCloseInventory field
// Wait for inventory conditions + events to possibly close the inventory // Wait for inventory conditions + events to possibly close the inventory
player.UNSAFE_changeDidCloseInventory(false); player.UNSAFE_changeDidCloseInventory(false);
// InventoryPreClickEvent // InventoryPreClickEvent
{ {
InventoryPreClickEvent inventoryPreClickEvent = new InventoryPreClickEvent(inventory, player, slot, clickType, InventoryPreClickEvent inventoryPreClickEvent = new InventoryPreClickEvent(eventInventory, player, slot, clickType,
clickResult.getClicked(), clickResult.getCursor()); clickResult.getClicked(), clickResult.getCursor());
EventDispatcher.call(inventoryPreClickEvent); EventDispatcher.call(inventoryPreClickEvent);
clickResult.setCursor(inventoryPreClickEvent.getCursorItem()); clickResult.setCursor(inventoryPreClickEvent.getCursorItem());
@ -473,8 +444,7 @@ public final class InventoryClickProcessor {
} }
// Inventory conditions // Inventory conditions
{ {
final var inventoryConditions = isPlayerInventory ? final var inventoryConditions = inventory.getInventoryConditions();
player.getInventory().getInventoryConditions() : inventory.getInventoryConditions();
if (!inventoryConditions.isEmpty()) { if (!inventoryConditions.isEmpty()) {
for (InventoryCondition inventoryCondition : inventoryConditions) { for (InventoryCondition inventoryCondition : inventoryConditions) {
var result = new InventoryConditionResult(clickResult.getClicked(), clickResult.getCursor()); var result = new InventoryConditionResult(clickResult.getClicked(), clickResult.getCursor());
@ -494,25 +464,13 @@ public final class InventoryClickProcessor {
} }
} }
} }
// Sanity check
{
if (clickResult.getCursor().isAir() && clickResult.getClicked().isAir()) {
// One of the item must not be air
clickResult.setCancel(true);
}
}
return clickResult; return clickResult;
} }
private @NotNull InventoryClickResult startCondition(@Nullable AbstractInventory inventory, @NotNull Player player, int slot, private void callClickEvent(@NotNull Player player, @Nullable AbstractInventory inventory, int slot,
@NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
return startCondition(inventory instanceof Inventory ? (Inventory) inventory : null,
player, slot, clickType, clicked, cursor);
}
private void callClickEvent(@NotNull Player player, @Nullable Inventory inventory, int slot,
@NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) { @NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
EventDispatcher.call(new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor)); final Inventory eventInventory = inventory instanceof Inventory ? (Inventory) inventory : null;
EventDispatcher.call(new InventoryClickEvent(eventInventory, player, slot, clickType, clicked, cursor));
} }
public void clearCache(@NotNull Player player) { public void clearCache(@NotNull Player player) {