feat: add isBrewIngredient and appendSection

This commit is contained in:
dualfroz committed 2026-09-06 22:18:54 +02:00
1 parent d7cc7d9172
commit c914991683
1 file changed
+156
+156
View File
@@ -0,0 +1,156 @@
#include "vf/ContainerMenu.h"
#include <algorithm>
namespace vf {
namespace {
const MetaStack& emptyStack() {
static const MetaStack nothing;
return nothing;
}
bool isBrewIngredient(ItemId item) {
// Brewing.h models potions with PotionItem, not ItemId, so only the
// ingredients that also exist as items can be filtered here.
return item == ItemId::RedstoneDust || item == ItemId::Glowstone ||
item == ItemId::Gunpowder;
}
void appendSection(std::vector<MenuSlot>& slots, MenuSlot::Role role, int count,
SlotFilter::Kind filter, bool takeOnly, int capacity) {
for (int i = 0; i < count; ++i) {
MenuSlot menuSlot;
menuSlot.role = role;
menuSlot.filter.kind = filter;
menuSlot.takeOnly = takeOnly;
menuSlot.cell.capacity = capacity;
slots.push_back(menuSlot);
}
}
void appendPlayerSections(std::vector<MenuSlot>& slots, MenuLayout& layout, bool withOffHand) {
layout.inventoryFirst = static_cast<int>(slots.size());
layout.inventoryCount = playerInventorySlots;
appendSection(slots, MenuSlot::Role::Inventory, playerInventorySlots, SlotFilter::Kind::Any,
false, 0);
layout.hotbarFirst = static_cast<int>(slots.size());
layout.hotbarCount = playerHotbarSlots;
appendSection(slots, MenuSlot::Role::Hotbar, playerHotbarSlots, SlotFilter::Kind::Any, false, 0);
if (withOffHand) {
layout.offHandSlot = static_cast<int>(slots.size());
appendSection(slots, MenuSlot::Role::OffHand, 1, SlotFilter::Kind::Any, false, 0);
}
}
} // namespace
const char* slotFilterKindName(SlotFilter::Kind kind) {
switch (kind) {
case SlotFilter::Kind::Any: return "any";
case SlotFilter::Kind::Nothing: return "nothing";
case SlotFilter::Kind::Fuel: return "fuel";
case SlotFilter::Kind::Smeltable: return "smeltable";
case SlotFilter::Kind::Lapis: return "lapis";
case SlotFilter::Kind::Enchantable: return "enchantable";
case SlotFilter::Kind::Repairable: return "repairable";
case SlotFilter::Kind::BrewIngredient: return "brewIngredient";
case SlotFilter::Kind::Count: break;
}
return "unknown";
}
bool SlotFilter::accepts(const MetaStack& stack, const CraftingRegistry* registry) const {
if (stack.empty()) return false;
switch (kind) {
case Kind::Any: return true;
case Kind::Nothing: return false;
case Kind::Fuel: return isFuel(stack.item);
case Kind::Smeltable:
return registry != nullptr && registry->smeltingFor(stack.item) != nullptr;
case Kind::Lapis: return stack.item == ItemId::LapisLazuli;
case Kind::Enchantable: return enchantabilityOf(stack.item) > 0;
case Kind::Repairable: return stack.meta.durability.damageable();
case Kind::BrewIngredient: return isBrewIngredient(stack.item);
case Kind::Count: break;
}
return false;
}
int StackSlot::limitFor(const MetaStack& candidate) const {
if (candidate.empty()) return 0;
int limit = candidate.maxCount();
if (capacity > 0 && capacity < limit) limit = capacity;
return limit;
}
int StackSlot::room(const MetaStack& candidate) const {
if (candidate.empty()) return 0;
if (stack.empty()) return limitFor(candidate);
if (!stacksMergeable(stack, candidate)) return 0;
int left = limitFor(stack) - stack.count;
return left > 0 ? left : 0;
}
int StackSlot::insert(MetaStack& incoming) {
int allowed = room(incoming);
if (allowed <= 0) return 0;
return transferStack(incoming, stack, allowed).moved;
}
MetaStack StackSlot::take(int amount) { return splitOff(stack, amount); }
MetaStack StackSlot::takeAll() { return splitOff(stack, stack.count); }
MetaStack StackSlot::swapWith(const MetaStack& incoming) {
MetaStack previous = stack;
stack = incoming;
return previous;
}
const char* menuKindName(MenuKind kind) {
switch (kind) {
case MenuKind::PlayerInventory: return "playerInventory";
case MenuKind::CraftingTable: return "craftingTable";
case MenuKind::Chest: return "chest";
case MenuKind::LargeChest: return "largeChest";
case MenuKind::Furnace: return "furnace";
case MenuKind::BrewingStand: return "brewingStand";
case MenuKind::EnchantingTable: return "enchantingTable";
case MenuKind::Anvil: return "anvil";
case MenuKind::Villager: return "villager";
case MenuKind::Hopper: return "hopper";
case MenuKind::Count: break;
}
return "unknown";
}
const char* menuSlotRoleName(MenuSlot::Role role) {
switch (role) {
case MenuSlot::Role::Storage: return "storage";
case MenuSlot::Role::Inventory: return "inventory";
case MenuSlot::Role::Hotbar: return "hotbar";
case MenuSlot::Role::CraftInput: return "craftInput";
case MenuSlot::Role::CraftResult: return "craftResult";
case MenuSlot::Role::FuelInput: return "fuelInput";
case MenuSlot::Role::SmeltInput: return "smeltInput";
case MenuSlot::Role::SmeltOutput: return "smeltOutput";
case MenuSlot::Role::BrewBottle: return "brewBottle";
case MenuSlot::Role::BrewIngredient: return "brewIngredient";
case MenuSlot::Role::EnchantItem: return "enchantItem";
case MenuSlot::Role::EnchantLapis: return "enchantLapis";
case MenuSlot::Role::AnvilInput: return "anvilInput";
case MenuSlot::Role::AnvilResult: return "anvilResult";
case MenuSlot::Role::TradeInput: return "tradeInput";
case MenuSlot::Role::TradeResult: return "tradeResult";
case MenuSlot::Role::OffHand: return "offHand";
case MenuSlot::Role::Count: break;
}
return "unknown";
}
namespace {