feat: add layoutFor to ContainerMenu

This commit is contained in:
dualfroz committed 2026-09-06 22:30:12 +02:00
1 parent c914991683
commit 77e7fe9c97
1 file changed
+155
+155
View File
@@ -154,3 +154,158 @@ const char* menuSlotRoleName(MenuSlot::Role role) {
namespace { namespace {
std::vector<MenuSlot> buildLayout(MenuKind kind, MenuLayout& layout) {
std::vector<MenuSlot> slots;
layout = MenuLayout{};
layout.kind = kind;
switch (kind) {
case MenuKind::PlayerInventory: {
layout.craftFirst = 0;
layout.craftWidth = 2;
layout.craftHeight = 2;
appendSection(slots, MenuSlot::Role::CraftInput, 4, SlotFilter::Kind::Any, false, 0);
layout.resultSlot = static_cast<int>(slots.size());
appendSection(slots, MenuSlot::Role::CraftResult, 1, SlotFilter::Kind::Nothing, true, 0);
appendPlayerSections(slots, layout, true);
break;
}
case MenuKind::CraftingTable: {
layout.craftFirst = 0;
layout.craftWidth = 3;
layout.craftHeight = 3;
appendSection(slots, MenuSlot::Role::CraftInput, 9, SlotFilter::Kind::Any, false, 0);
layout.resultSlot = static_cast<int>(slots.size());
appendSection(slots, MenuSlot::Role::CraftResult, 1, SlotFilter::Kind::Nothing, true, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::Chest:
case MenuKind::LargeChest: {
int size = kind == MenuKind::Chest ? 27 : 54;
layout.storageFirst = 0;
layout.storageCount = size;
appendSection(slots, MenuSlot::Role::Storage, size, SlotFilter::Kind::Any, false, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::Furnace: {
layout.storageFirst = 0;
layout.storageCount = 3;
appendSection(slots, MenuSlot::Role::SmeltInput, 1, SlotFilter::Kind::Smeltable, false, 0);
appendSection(slots, MenuSlot::Role::FuelInput, 1, SlotFilter::Kind::Fuel, false, 0);
appendSection(slots, MenuSlot::Role::SmeltOutput, 1, SlotFilter::Kind::Nothing, true, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::BrewingStand: {
layout.storageFirst = 0;
layout.storageCount = 5;
appendSection(slots, MenuSlot::Role::BrewBottle, 3, SlotFilter::Kind::Any, false, 1);
appendSection(slots, MenuSlot::Role::BrewIngredient, 1,
SlotFilter::Kind::BrewIngredient, false, 0);
appendSection(slots, MenuSlot::Role::FuelInput, 1, SlotFilter::Kind::Fuel, false, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::EnchantingTable: {
layout.storageFirst = 0;
layout.storageCount = 2;
appendSection(slots, MenuSlot::Role::EnchantItem, 1, SlotFilter::Kind::Enchantable,
false, 0);
appendSection(slots, MenuSlot::Role::EnchantLapis, 1, SlotFilter::Kind::Lapis, false, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::Anvil: {
layout.storageFirst = 0;
layout.storageCount = 3;
appendSection(slots, MenuSlot::Role::AnvilInput, 2, SlotFilter::Kind::Repairable,
false, 0);
appendSection(slots, MenuSlot::Role::AnvilResult, 1, SlotFilter::Kind::Nothing, true, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::Villager: {
layout.storageFirst = 0;
layout.storageCount = 3;
appendSection(slots, MenuSlot::Role::TradeInput, 2, SlotFilter::Kind::Any, false, 0);
appendSection(slots, MenuSlot::Role::TradeResult, 1, SlotFilter::Kind::Nothing, true, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::Hopper: {
layout.storageFirst = 0;
layout.storageCount = 5;
appendSection(slots, MenuSlot::Role::Storage, 5, SlotFilter::Kind::Any, false, 0);
appendPlayerSections(slots, layout, false);
break;
}
case MenuKind::Count:
break;
}
layout.totalSlots = static_cast<int>(slots.size());
return slots;
}
} // namespace
MenuLayout layoutFor(MenuKind kind) {
MenuLayout layout;
buildLayout(kind, layout);
return layout;
}
CraftingView::CraftingView(ContainerMenu& menu) : menu(&menu) {}
int CraftingView::width() const { return menu->layout().craftWidth; }
int CraftingView::height() const { return menu->layout().craftHeight; }
int CraftingView::cellCount() const { return menu->hasCrafting() ? menu->layout().craftCells() : 0; }
MetaStack& CraftingView::input(int x, int y) { return inputAt(y * width() + x); }
const MetaStack& CraftingView::input(int x, int y) const { return inputAt(y * width() + x); }
MetaStack& CraftingView::inputAt(int cell) {
return menu->stackAt(menu->layout().craftFirst + cell);
}
const MetaStack& CraftingView::inputAt(int cell) const {
return menu->stackAt(menu->layout().craftFirst + cell);
}
CraftGrid CraftingView::gridOfIds() const {
CraftGrid grid{};
int w = width();
for (int cell = 0; cell < cellCount(); ++cell) {
const MetaStack& stack = inputAt(cell);
if (stack.empty()) continue;
int row = cell / w;
int column = cell % w;
grid[static_cast<std::size_t>(row * craftGridWidth + column)] = stack.item;
}
return grid;
}
void CraftingView::refresh() {
int resultSlot = menu->layout().resultSlot;
if (resultSlot < 0) return;
MetaStack& target = menu->stackAt(resultSlot);
if (!menu->hasCrafting()) {
target.clear();
return;
}
CraftResult match = menu->registry()->craftMatch(gridOfIds());
if (!match.valid()) {
target.clear();
return;
}
target = makeStack(match.item, match.count);
}
const MetaStack& CraftingView::result() const {
return menu->resultStack();
}
bool CraftingView::hasResult() const { return !result().empty(); }