mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-02 14:38:26 +01:00
Simplify InventoryClickProcessor
This commit is contained in:
parent
5607652378
commit
be07fdb647
@ -20,7 +20,6 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -28,155 +27,103 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class InventoryClickProcessor {
|
||||
|
||||
public final class InventoryClickProcessor {
|
||||
// Dragging maps
|
||||
private final Map<Player, IntSet> leftDraggingMap = new ConcurrentHashMap<>();
|
||||
private final Map<Player, IntSet> rightDraggingMap = new ConcurrentHashMap<>();
|
||||
|
||||
@NotNull
|
||||
public InventoryClickResult leftClick(@Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.LEFT_CLICK, clicked, cursor);
|
||||
clicked = clickResult.getClicked();
|
||||
cursor = clickResult.getCursor();
|
||||
|
||||
if (clickResult.isCancel()) {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
if (cursor.isAir() && clicked.isAir()) {
|
||||
clickResult.setCancel(true);
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
public @NotNull InventoryClickResult leftClick(@Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final var result = startCondition(inventory, player, slot, ClickType.LEFT_CLICK, clicked, cursor);
|
||||
if (result.isCancel()) return result;
|
||||
clicked = result.getClicked();
|
||||
cursor = result.getCursor();
|
||||
final StackingRule cursorRule = cursor.getStackingRule();
|
||||
final StackingRule clickedRule = clicked.getStackingRule();
|
||||
|
||||
ItemStack resultCursor;
|
||||
ItemStack resultClicked;
|
||||
|
||||
if (cursorRule.canBeStacked(cursor, clicked)) {
|
||||
// Try to stack items
|
||||
final int totalAmount = cursorRule.getAmount(cursor) + clickedRule.getAmount(clicked);
|
||||
final int maxSize = cursorRule.getMaxSize(cursor);
|
||||
|
||||
if (!clickedRule.canApply(clicked, totalAmount)) {
|
||||
resultCursor = cursorRule.apply(cursor, totalAmount - maxSize);
|
||||
resultClicked = clickedRule.apply(clicked, maxSize);
|
||||
// Size is too big, stack as much as possible into clicked
|
||||
result.setCursor(cursorRule.apply(cursor, totalAmount - maxSize));
|
||||
result.setClicked(clickedRule.apply(clicked, maxSize));
|
||||
} else {
|
||||
resultCursor = cursorRule.apply(cursor, 0);
|
||||
resultClicked = clickedRule.apply(clicked, totalAmount);
|
||||
// Merge cursor item clicked
|
||||
result.setCursor(cursorRule.apply(cursor, 0));
|
||||
result.setClicked(clickedRule.apply(clicked, totalAmount));
|
||||
}
|
||||
} else {
|
||||
resultCursor = clicked;
|
||||
resultClicked = cursor;
|
||||
// Items are not compatible, swap them
|
||||
result.setCursor(clicked);
|
||||
result.setClicked(cursor);
|
||||
}
|
||||
|
||||
clickResult.setClicked(resultClicked);
|
||||
clickResult.setCursor(resultCursor);
|
||||
|
||||
return clickResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public InventoryClickResult rightClick(@Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.RIGHT_CLICK, clicked, cursor);
|
||||
|
||||
if (clickResult.isCancel()) {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
if (cursor.isAir() && clicked.isAir()) {
|
||||
clickResult.setCancel(true);
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
public @NotNull InventoryClickResult rightClick(@Nullable Inventory inventory, @NotNull Player player,
|
||||
int slot,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final var result = startCondition(inventory, player, slot, ClickType.RIGHT_CLICK, clicked, cursor);
|
||||
if (result.isCancel()) return result;
|
||||
clicked = result.getClicked();
|
||||
cursor = result.getCursor();
|
||||
final StackingRule cursorRule = cursor.getStackingRule();
|
||||
final StackingRule clickedRule = clicked.getStackingRule();
|
||||
|
||||
ItemStack resultCursor;
|
||||
ItemStack resultClicked;
|
||||
|
||||
if (clickedRule.canBeStacked(clicked, cursor)) {
|
||||
// Items can be stacked
|
||||
final int amount = clickedRule.getAmount(clicked) + 1;
|
||||
if (!clickedRule.canApply(clicked, amount)) {
|
||||
return clickResult;
|
||||
// Size too large, stop here
|
||||
return result;
|
||||
} else {
|
||||
resultCursor = cursorRule.apply(cursor, operand -> operand - 1);
|
||||
resultClicked = clickedRule.apply(clicked, amount);
|
||||
// Add 1 to clicked
|
||||
result.setCursor(cursorRule.apply(cursor, operand -> operand - 1));
|
||||
result.setClicked(clickedRule.apply(clicked, amount));
|
||||
}
|
||||
} else {
|
||||
// Items cannot be stacked
|
||||
if (cursor.isAir()) {
|
||||
// Take half of clicked
|
||||
final int amount = (int) Math.ceil((double) clickedRule.getAmount(clicked) / 2d);
|
||||
resultCursor = cursorRule.apply(clicked, amount);
|
||||
resultClicked = clickedRule.apply(clicked, operand -> operand / 2);
|
||||
result.setCursor(cursorRule.apply(clicked, amount));
|
||||
result.setClicked(clickedRule.apply(clicked, operand -> operand / 2));
|
||||
} else {
|
||||
if (clicked.isAir()) {
|
||||
resultCursor = cursorRule.apply(cursor, operand -> operand - 1);
|
||||
resultClicked = clickedRule.apply(cursor, 1);
|
||||
// Put 1 to clicked
|
||||
result.setCursor(cursorRule.apply(cursor, operand -> operand - 1));
|
||||
result.setClicked(clickedRule.apply(cursor, 1));
|
||||
} else {
|
||||
resultCursor = clicked;
|
||||
resultClicked = cursor;
|
||||
// Swap items
|
||||
result.setCursor(clicked);
|
||||
result.setClicked(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clickResult.setClicked(resultClicked);
|
||||
clickResult.setCursor(resultCursor);
|
||||
|
||||
return clickResult;
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public InventoryClickResult changeHeld(@Nullable Inventory inventory, @NotNull Player player, int slot, int key,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
public @NotNull InventoryClickResult changeHeld(@Nullable Inventory inventory, @NotNull Player player,
|
||||
int slot, int key,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
// Verify the clicked item
|
||||
InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.CHANGE_HELD, clicked, cursor);
|
||||
if (clickResult.isCancel()) return clickResult;
|
||||
// Verify the destination (held bar)
|
||||
clickResult = startCondition(null, player, key, ClickType.CHANGE_HELD, clicked, cursor);
|
||||
if (clickResult.isCancel()) return clickResult;
|
||||
|
||||
if (cursor.isAir() && clicked.isAir()) {
|
||||
clickResult.setCancel(true);
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
ItemStack resultClicked;
|
||||
ItemStack resultHeld;
|
||||
if (clicked.isAir()) {
|
||||
// Set held item [key] to slot
|
||||
resultClicked = cursor;
|
||||
resultHeld = ItemStack.AIR;
|
||||
} else {
|
||||
if (cursor.isAir()) {
|
||||
// if held item [key] is air then set clicked to held
|
||||
resultClicked = ItemStack.AIR;
|
||||
} else {
|
||||
// Otherwise, replace held item and held
|
||||
resultClicked = cursor;
|
||||
}
|
||||
resultHeld = clicked;
|
||||
}
|
||||
|
||||
clickResult.setClicked(resultClicked);
|
||||
clickResult.setCursor(resultHeld);
|
||||
// Swap items
|
||||
clickResult.setClicked(cursor);
|
||||
clickResult.setCursor(clicked);
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
public @Nullable InventoryClickResult shiftClick(AbstractInventory targetInventory, @Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.START_SHIFT_CLICK, clicked, cursor);
|
||||
|
||||
if (clickResult.isCancel()) {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
if (clicked.isAir())
|
||||
return null;
|
||||
|
||||
var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> {
|
||||
if (clickResult.isCancel()) return clickResult;
|
||||
if (clicked.isAir()) return null;
|
||||
final var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> {
|
||||
InventoryClickResult result = startCondition(targetInventory, player, index, ClickType.SHIFT_CLICK, itemStack, cursor);
|
||||
if (result.isCancel()) {
|
||||
clickResult.setRefresh(true);
|
||||
@ -184,7 +131,6 @@ public class InventoryClickProcessor {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
ItemStack itemResult = TransactionOption.ALL.fill(targetInventory, pair.left(), pair.right());
|
||||
clickResult.setClicked(itemResult);
|
||||
return clickResult;
|
||||
@ -193,15 +139,9 @@ public class InventoryClickProcessor {
|
||||
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;
|
||||
|
||||
var pair = TransactionType.ADD.process(targetInventory, clicked, (index, itemStack) -> {
|
||||
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);
|
||||
@ -211,18 +151,16 @@ public class InventoryClickProcessor {
|
||||
}
|
||||
return true;
|
||||
}, start, end, step);
|
||||
|
||||
ItemStack itemResult = TransactionOption.ALL.fill(targetInventory, pair.left(), pair.right());
|
||||
clickResult.setClicked(itemResult);
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InventoryClickResult dragging(@Nullable Inventory inventory, @NotNull Player player,
|
||||
int slot, int button,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor,
|
||||
@NotNull Int2ObjectFunction<ItemStack> itemGetter,
|
||||
@NotNull BiConsumer<Integer, ItemStack> itemSetter) {
|
||||
public @Nullable InventoryClickResult dragging(@Nullable Inventory inventory, @NotNull Player player,
|
||||
int slot, int button,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor,
|
||||
@NotNull Int2ObjectFunction<ItemStack> itemGetter,
|
||||
@NotNull BiConsumer<Integer, ItemStack> itemSetter) {
|
||||
InventoryClickResult clickResult = null;
|
||||
|
||||
final StackingRule stackingRule = cursor.getStackingRule();
|
||||
@ -232,13 +170,11 @@ public class InventoryClickProcessor {
|
||||
if (button == 0) {
|
||||
// Start left
|
||||
clickResult = startCondition(inventory, player, slot, ClickType.START_LEFT_DRAGGING, clicked, cursor);
|
||||
|
||||
if (!clickResult.isCancel())
|
||||
this.leftDraggingMap.put(player, new IntOpenHashSet());
|
||||
} else if (button == 4) {
|
||||
// Start right
|
||||
clickResult = startCondition(inventory, player, slot, ClickType.START_RIGHT_DRAGGING, clicked, cursor);
|
||||
|
||||
if (!clickResult.isCancel())
|
||||
this.rightDraggingMap.put(player, new IntOpenHashSet());
|
||||
} else if (button == 2) {
|
||||
@ -255,12 +191,9 @@ public class InventoryClickProcessor {
|
||||
|
||||
for (int s : slots) {
|
||||
ItemStack slotItem = itemGetter.apply(s);
|
||||
|
||||
clickResult = startCondition(inventory, player, s, ClickType.LEFT_DRAGGING, slotItem, cursor);
|
||||
|
||||
if (clickResult.isCancel()) {
|
||||
cancel = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -381,17 +314,11 @@ public class InventoryClickProcessor {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InventoryClickResult doubleClick(@NotNull AbstractInventory clickedInventory, @Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull final ItemStack cursor) {
|
||||
public @Nullable 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()) {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
if (cursor.isAir())
|
||||
return null;
|
||||
if (clickResult.isCancel()) return clickResult;
|
||||
if (cursor.isAir()) return null;
|
||||
|
||||
final StackingRule cursorRule = cursor.getStackingRule();
|
||||
final int amount = cursorRule.getAmount(cursor);
|
||||
@ -418,7 +345,6 @@ public class InventoryClickProcessor {
|
||||
};
|
||||
|
||||
var playerInventory = player.getInventory();
|
||||
|
||||
if (Objects.equals(clickedInventory, inventory)) {
|
||||
// Clicked inside inventory
|
||||
remain = func.apply(inventory, remain);
|
||||
@ -449,10 +375,9 @@ public class InventoryClickProcessor {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public InventoryClickResult drop(@Nullable Inventory inventory, @NotNull Player player,
|
||||
boolean all, int slot, int button,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
public @NotNull InventoryClickResult drop(@Nullable Inventory inventory, @NotNull Player player,
|
||||
boolean all, int slot, int button,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final InventoryClickResult clickResult = startCondition(inventory, player, slot, ClickType.DROP, clicked, cursor);
|
||||
|
||||
if (clickResult.isCancel()) {
|
||||
@ -465,7 +390,6 @@ public class InventoryClickProcessor {
|
||||
ItemStack resultClicked = clicked;
|
||||
ItemStack resultCursor = cursor;
|
||||
|
||||
|
||||
if (slot == -999) {
|
||||
// Click outside
|
||||
if (button == 0) {
|
||||
@ -518,9 +442,10 @@ public class InventoryClickProcessor {
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private InventoryClickResult startCondition(@NotNull InventoryClickResult clickResult, @Nullable Inventory inventory,
|
||||
@NotNull Player player, int slot, @NotNull ClickType clickType) {
|
||||
private @NotNull InventoryClickResult startCondition(@Nullable Inventory inventory,
|
||||
@NotNull Player player, int slot, @NotNull ClickType clickType,
|
||||
@NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor);
|
||||
boolean isPlayerInventory = inventory == null;
|
||||
final int inventorySlot = isPlayerInventory ? 0 : inventory.getSize();
|
||||
isPlayerInventory = isPlayerInventory ? isPlayerInventory : slot >= inventorySlot;
|
||||
@ -531,81 +456,67 @@ public class InventoryClickProcessor {
|
||||
slot = slot - inventorySlot + PlayerInventoryUtils.OFFSET;
|
||||
}
|
||||
|
||||
// Call ItemStack#onInventoryClick
|
||||
{
|
||||
//clickResult.getClicked().onInventoryClick(player, clickType, slot, isPlayerInventory);
|
||||
}
|
||||
|
||||
// Reset the didCloseInventory field
|
||||
// Wait for inventory conditions + events to possibly close the inventory
|
||||
player.UNSAFE_changeDidCloseInventory(false);
|
||||
|
||||
// PreClickEvent
|
||||
// InventoryPreClickEvent
|
||||
{
|
||||
InventoryPreClickEvent inventoryPreClickEvent = new InventoryPreClickEvent(inventory, player, slot, clickType,
|
||||
clickResult.getClicked(), clickResult.getCursor());
|
||||
EventDispatcher.call(inventoryPreClickEvent);
|
||||
clickResult.setCursor(inventoryPreClickEvent.getCursorItem());
|
||||
clickResult.setClicked(inventoryPreClickEvent.getClickedItem());
|
||||
|
||||
if (inventoryPreClickEvent.isCancelled()) {
|
||||
clickResult.setRefresh(true);
|
||||
clickResult.setCancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Inventory conditions
|
||||
final List<InventoryCondition> inventoryConditions = isPlayerInventory ?
|
||||
player.getInventory().getInventoryConditions() : inventory.getInventoryConditions();
|
||||
if (!inventoryConditions.isEmpty()) {
|
||||
{
|
||||
final var inventoryConditions = isPlayerInventory ?
|
||||
player.getInventory().getInventoryConditions() : inventory.getInventoryConditions();
|
||||
if (!inventoryConditions.isEmpty()) {
|
||||
for (InventoryCondition inventoryCondition : inventoryConditions) {
|
||||
var result = new InventoryConditionResult(clickResult.getClicked(), clickResult.getCursor());
|
||||
inventoryCondition.accept(player, slot, clickType, result);
|
||||
|
||||
for (InventoryCondition inventoryCondition : inventoryConditions) {
|
||||
InventoryConditionResult result = new InventoryConditionResult(clickResult.getClicked(), clickResult.getCursor());
|
||||
inventoryCondition.accept(player, slot, clickType, result);
|
||||
|
||||
clickResult.setCursor(result.getCursorItem());
|
||||
clickResult.setClicked(result.getClickedItem());
|
||||
|
||||
if (result.isCancel()) {
|
||||
clickResult.setRefresh(true);
|
||||
clickResult.setCursor(result.getCursorItem());
|
||||
clickResult.setClicked(result.getClickedItem());
|
||||
if (result.isCancel()) {
|
||||
clickResult.setRefresh(true);
|
||||
clickResult.setCancel(true);
|
||||
}
|
||||
}
|
||||
// Cancel the click if the inventory has been closed by Player#closeInventory within an inventory listener
|
||||
if (player.didCloseInventory()) {
|
||||
clickResult.setCancel(true);
|
||||
player.UNSAFE_changeDidCloseInventory(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the click if the inventory has been closed by Player#closeInventory within an inventory listener
|
||||
if (player.didCloseInventory()) {
|
||||
}
|
||||
// Sanity check
|
||||
{
|
||||
if (clickResult.getCursor().isAir() && clickResult.getClicked().isAir()) {
|
||||
// One of the item must not be air
|
||||
clickResult.setCancel(true);
|
||||
player.UNSAFE_changeDidCloseInventory(false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return clickResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private InventoryClickResult startCondition(@Nullable Inventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
final InventoryClickResult clickResult = new InventoryClickResult(clicked, cursor);
|
||||
return startCondition(clickResult, inventory, player, slot, clickType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private InventoryClickResult startCondition(@Nullable AbstractInventory inventory, @NotNull Player player, int slot,
|
||||
@NotNull ClickType clickType, @NotNull ItemStack clicked, @NotNull ItemStack cursor) {
|
||||
private @NotNull InventoryClickResult startCondition(@Nullable AbstractInventory inventory, @NotNull Player player, 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) {
|
||||
InventoryClickEvent inventoryClickEvent = new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor);
|
||||
EventDispatcher.call(inventoryClickEvent);
|
||||
EventDispatcher.call(new InventoryClickEvent(inventory, player, slot, clickType, clicked, cursor));
|
||||
}
|
||||
|
||||
public void clearCache(@NotNull Player player) {
|
||||
this.leftDraggingMap.remove(player);
|
||||
this.rightDraggingMap.remove(player);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user