feat: add shiftClick and hotbarSwap to SlotAction

This commit is contained in:
dualfroz committed 2026-09-09 18:27:18 +02:00
1 parent 70ced743d5
commit dbf9f81545
1 file changed
+152
+152
View File
@@ -151,3 +151,155 @@ SlotActionResult rightClick(ContainerMenu& menu, CursorStack& cursor, const Slot
int index = action.slotIndex;
if (!menu.validIndex(index)) return out;
if (cursor.empty()) {
if (menu.stackAt(index).empty()) return out;
int half = (menu.stackAt(index).count + 1) / 2;
MetaStack taken = takeFromSlot(menu, index, half, out);
if (taken.empty()) return out;
out.moved = taken.count;
cursor.held = taken;
out.cursorChanged = true;
out.applied = true;
return out;
}
if (isResultSlot(menu, index)) return out;
MetaStack single = splitOff(cursor.held, 1);
int moved = putIntoSlot(menu, index, single);
if (moved == 0) {
transferAll(single, cursor.held);
return out;
}
out.moved = moved;
out.cursorChanged = true;
out.applied = true;
return out;
}
SlotActionResult shiftClick(ContainerMenu& menu, const SlotAction& action) {
SlotActionResult out;
int index = action.slotIndex;
if (!menu.validIndex(index) || menu.stackAt(index).empty()) return out;
if (isResultSlot(menu, index)) {
CraftingView view = menu.crafting();
int rounds = view.craftAll(view.maxCrafts());
if (rounds <= 0) return out;
out.craftedResult = true;
out.craftedCount = rounds;
out.applied = true;
return out;
}
std::vector<int> targets = transferTargetsFor(menu, index);
MetaStack moving = menu.slot(index).cell.takeAll();
int moved = menu.distributeInto(targets, moving);
if (!moving.empty()) {
// Whatever did not fit goes straight back where it came from.
menu.slot(index).cell.insert(moving);
}
touchCraftInput(menu, index);
if (moved == 0) return out;
out.moved = moved;
out.applied = true;
return out;
}
SlotActionResult hotbarSwap(ContainerMenu& menu, const SlotAction& action) {
SlotActionResult out;
int index = action.slotIndex;
const MenuLayout& layout = menu.layout();
if (!menu.validIndex(index) || layout.hotbarFirst < 0) return out;
if (action.hotbarButton < 0 || action.hotbarButton >= layout.hotbarCount) return out;
int hotbarIndex = layout.hotbarFirst + action.hotbarButton;
if (hotbarIndex == index) return out;
if (isResultSlot(menu, index)) {
if (!menu.stackAt(hotbarIndex).empty()) return out;
MetaStack crafted = takeFromSlot(menu, index, menu.stackAt(index).count, out);
if (crafted.empty()) return out;
out.moved = crafted.count;
menu.slot(hotbarIndex).cell.stack = crafted;
out.applied = true;
return out;
}
MenuSlot& source = menu.slot(index);
MenuSlot& hotbar = menu.slot(hotbarIndex);
if (source.takeOnly) return out;
if (source.cell.stack.empty() && hotbar.cell.stack.empty()) return out;
if (!hotbar.cell.stack.empty()) {
if (!menu.canPlace(index, hotbar.cell.stack)) return out;
if (source.cell.limitFor(hotbar.cell.stack) < hotbar.cell.stack.count) return out;
}
out.moved = source.cell.stack.count + hotbar.cell.stack.count;
MetaStack carried = source.cell.stack;
source.cell.stack = hotbar.cell.stack;
hotbar.cell.stack = carried;
touchCraftInput(menu, index);
out.applied = true;
return out;
}
SlotActionResult middleClick(ContainerMenu& menu, CursorStack& cursor, const SlotAction& action) {
SlotActionResult out;
int index = action.slotIndex;
if (!menu.validIndex(index) || !menu.creativeMode()) return out;
if (!cursor.empty() || menu.stackAt(index).empty()) return out;
MetaStack clone = menu.stackAt(index);
clone.count = clone.maxCount();
out.created = clone.count;
cursor.held = clone;
out.cursorChanged = true;
out.applied = true;
return out;
}
SlotActionResult doubleClick(ContainerMenu& menu, CursorStack& cursor) {
SlotActionResult out;
if (cursor.empty() || cursor.held.room() == 0) return out;
// Partial stacks first: a double click is meant to tidy up leftovers before
// it starts breaking apart full stacks.
for (int pass = 0; pass < 2; ++pass) {
for (int i = 0; i < menu.slotCount(); ++i) {
if (cursor.held.room() == 0) break;
MenuSlot& source = menu.slot(i);
if (source.takeOnly || source.cell.stack.empty()) continue;
if (!stacksMergeable(source.cell.stack, cursor.held)) continue;
bool partial = source.cell.stack.count < source.cell.stack.maxCount();
if ((pass == 0) != partial) continue;
int before = cursor.held.count;
transferAll(source.cell.stack, cursor.held);
int gained = cursor.held.count - before;
if (gained > 0) {
out.moved += gained;
touchCraftInput(menu, i);
}
}
}
if (out.moved == 0) return out;
out.cursorChanged = true;
out.applied = true;
return out;
}
SlotActionResult dragStart(ContainerMenu& menu, CursorStack& cursor, DragState& drag,
const SlotAction& action, bool rightButton) {
SlotActionResult out;
if (cursor.empty()) return out;
drag.reset();
drag.active = true;
drag.rightButton = rightButton;
drag.payload = cursor.held;
if (menu.validIndex(action.slotIndex) && menu.canPlace(action.slotIndex, cursor.held)) {
drag.paintedSlots.push_back(action.slotIndex);
}
out.applied = true;
return out;
}