feat: add isTransferSection and isResultSlot
This commit is contained in:
1 parent
f61d9eed00
commit
70ced743d5
1 file changed
+153
@@ -0,0 +1,153 @@
|
|||||||
|
#include "vf/SlotAction.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// The half of a menu a shift-click aims at. Craft inputs and result slots are
|
||||||
|
// deliberately not part of it: shift-clicking in a player inventory moves items
|
||||||
|
// between the rows and the hotbar, it does not stuff the 2x2 grid.
|
||||||
|
bool isTransferSection(MenuSlot::Role role) {
|
||||||
|
switch (role) {
|
||||||
|
case MenuSlot::Role::Storage:
|
||||||
|
case MenuSlot::Role::FuelInput:
|
||||||
|
case MenuSlot::Role::SmeltInput:
|
||||||
|
case MenuSlot::Role::SmeltOutput:
|
||||||
|
case MenuSlot::Role::BrewBottle:
|
||||||
|
case MenuSlot::Role::BrewIngredient:
|
||||||
|
case MenuSlot::Role::EnchantItem:
|
||||||
|
case MenuSlot::Role::EnchantLapis:
|
||||||
|
case MenuSlot::Role::AnvilInput:
|
||||||
|
case MenuSlot::Role::AnvilResult:
|
||||||
|
case MenuSlot::Role::TradeInput:
|
||||||
|
case MenuSlot::Role::TradeResult:
|
||||||
|
return true;
|
||||||
|
case MenuSlot::Role::Inventory:
|
||||||
|
case MenuSlot::Role::Hotbar:
|
||||||
|
case MenuSlot::Role::OffHand:
|
||||||
|
case MenuSlot::Role::CraftInput:
|
||||||
|
case MenuSlot::Role::CraftResult:
|
||||||
|
case MenuSlot::Role::Count:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> collectRoles(const ContainerMenu& menu, bool wantTransferSection) {
|
||||||
|
std::vector<int> found;
|
||||||
|
for (int i = 0; i < menu.slotCount(); ++i) {
|
||||||
|
if (isTransferSection(menu.slot(i).role) == wantTransferSection) found.push_back(i);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Where a shift-click from `index` should land. Container half to player half
|
||||||
|
// and back; in a menu that has no container half, the player's rows and the
|
||||||
|
// hotbar swap roles instead.
|
||||||
|
std::vector<int> transferTargetsFor(const ContainerMenu& menu, int index) {
|
||||||
|
std::vector<int> container = collectRoles(menu, true);
|
||||||
|
MenuSlot::Role role = menu.slot(index).role;
|
||||||
|
|
||||||
|
if (isTransferSection(role)) return menu.playerSectionSlots();
|
||||||
|
if (!container.empty()) return container;
|
||||||
|
|
||||||
|
std::vector<int> targets;
|
||||||
|
MenuSlot::Role wanted =
|
||||||
|
role == MenuSlot::Role::Hotbar ? MenuSlot::Role::Inventory : MenuSlot::Role::Hotbar;
|
||||||
|
for (int i = 0; i < menu.slotCount(); ++i) {
|
||||||
|
if (menu.slot(i).role == wanted) targets.push_back(i);
|
||||||
|
}
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isResultSlot(const ContainerMenu& menu, int index) {
|
||||||
|
return menu.layout().resultSlot >= 0 && index == menu.layout().resultSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void touchCraftInput(ContainerMenu& menu, int index) {
|
||||||
|
if (menu.slot(index).role == MenuSlot::Role::CraftInput) menu.refreshResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Every removal from a slot goes through here so the crafting grid can never
|
||||||
|
// hand out a result without paying for it.
|
||||||
|
MetaStack takeFromSlot(ContainerMenu& menu, int index, int amount, SlotActionResult& out) {
|
||||||
|
if (isResultSlot(menu, index)) {
|
||||||
|
CraftingView view = menu.crafting();
|
||||||
|
MetaStack crafted = view.takeResult();
|
||||||
|
if (!crafted.empty()) {
|
||||||
|
out.craftedResult = true;
|
||||||
|
out.craftedCount += crafted.count;
|
||||||
|
}
|
||||||
|
return crafted;
|
||||||
|
}
|
||||||
|
MetaStack taken = menu.takeFrom(index, amount);
|
||||||
|
touchCraftInput(menu, index);
|
||||||
|
return taken;
|
||||||
|
}
|
||||||
|
|
||||||
|
int putIntoSlot(ContainerMenu& menu, int index, MetaStack& incoming) {
|
||||||
|
int moved = menu.insertAt(index, incoming);
|
||||||
|
if (moved > 0) touchCraftInput(menu, index);
|
||||||
|
return moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool swapWithSlot(ContainerMenu& menu, int index, CursorStack& cursor) {
|
||||||
|
MenuSlot& target = menu.slot(index);
|
||||||
|
if (target.takeOnly) return false;
|
||||||
|
if (!menu.canPlace(index, cursor.held)) return false;
|
||||||
|
if (target.cell.limitFor(cursor.held) < cursor.held.count) return false;
|
||||||
|
cursor.held = target.cell.swapWith(cursor.held);
|
||||||
|
touchCraftInput(menu, index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotActionResult leftClick(ContainerMenu& menu, CursorStack& cursor, const SlotAction& action) {
|
||||||
|
SlotActionResult out;
|
||||||
|
int index = action.slotIndex;
|
||||||
|
if (!menu.validIndex(index)) return out;
|
||||||
|
|
||||||
|
if (cursor.empty()) {
|
||||||
|
MetaStack taken = takeFromSlot(menu, index, menu.stackAt(index).count, 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)) {
|
||||||
|
const MetaStack& pending = menu.stackAt(index);
|
||||||
|
if (pending.empty() || !stacksMergeable(cursor.held, pending)) return out;
|
||||||
|
if (cursor.held.room() < pending.count) return out;
|
||||||
|
MetaStack crafted = takeFromSlot(menu, index, pending.count, out);
|
||||||
|
out.moved = crafted.count;
|
||||||
|
transferAll(crafted, cursor.held);
|
||||||
|
out.cursorChanged = true;
|
||||||
|
out.applied = true;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int moved = putIntoSlot(menu, index, cursor.held);
|
||||||
|
if (moved > 0) {
|
||||||
|
out.moved = moved;
|
||||||
|
out.cursorChanged = true;
|
||||||
|
out.applied = true;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menu.stackAt(index).empty() || stacksMergeable(menu.stackAt(index), cursor.held)) return out;
|
||||||
|
if (!swapWithSlot(menu, index, cursor)) return out;
|
||||||
|
out.moved = cursor.held.count + menu.stackAt(index).count;
|
||||||
|
out.cursorChanged = true;
|
||||||
|
out.applied = true;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotActionResult rightClick(ContainerMenu& menu, CursorStack& cursor, const SlotAction& action) {
|
||||||
|
SlotActionResult out;
|
||||||
|
int index = action.slotIndex;
|
||||||
|
if (!menu.validIndex(index)) return out;
|
||||||
|
|
||||||
Reference in new issue
Block a user