From 0bb301ea224eea60e001d0276de18151a61f47aa Mon Sep 17 00:00:00 2001 From: DualFroz Date: Mon, 7 Sep 2026 19:45:19 +0200 Subject: [PATCH] feat: add enchantCode and validEnchantKind --- core/src/ItemStack.cpp | 160 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 core/src/ItemStack.cpp diff --git a/core/src/ItemStack.cpp b/core/src/ItemStack.cpp new file mode 100644 index 0000000..8e2fff6 --- /dev/null +++ b/core/src/ItemStack.cpp @@ -0,0 +1,160 @@ +#include "vf/ItemStack.h" + +#include + +namespace vf { + +namespace { + +int16_t enchantCode(EnchantKind kind) { return static_cast(kind); } + +bool validEnchantKind(int32_t raw) { + return raw >= 0 && raw < static_cast(EnchantKind::Count); +} + +bool validItemId(int32_t raw) { return raw > 0 && raw < static_cast(ItemId::Count); } + +const NbtTag* findTyped(const NbtTag& compound, const std::string& key, NbtType type) { + const NbtTag* found = compound.find(key); + if (found == nullptr || found->kind() != type) return nullptr; + return found; +} + +int32_t intField(const NbtTag& compound, const std::string& key, NbtType type, int32_t fallback) { + const NbtTag* found = findTyped(compound, key, type); + return found == nullptr ? fallback : found->asInt(); +} + +} // namespace + +float Durability::fraction() const { + if (max <= 0) return 1.0f; + int left = remaining(); + return static_cast(left) / static_cast(max); +} + +bool sameEnchants(const EnchantSet& a, const EnchantSet& b) { + if (a.entries.size() != b.entries.size()) return false; + for (const Enchantment& entry : a.entries) { + if (b.levelOf(entry.kind) != entry.level) return false; + } + return true; +} + +bool StackMeta::pristine() const { + return durability.used == 0 && enchants.empty() && customName.empty() && !unbreakable && + repairCost == 0; +} + +bool StackMeta::operator==(const StackMeta& other) const { + return durability == other.durability && unbreakable == other.unbreakable && + repairCost == other.repairCost && customName == other.customName && + sameEnchants(enchants, other.enchants); +} + +int stackLimitFor(ItemId item) { + if (item == ItemId::None) return 0; + return maxStackSize(item); +} + +int MetaStack::maxCount() const { + if (item == ItemId::None) return 0; + if (meta.durability.damageable() || !meta.enchants.empty() || meta.unbreakable || + !meta.customName.empty()) { + return 1; + } + return stackLimitFor(item); +} + +int MetaStack::room() const { + if (item == ItemId::None) return 0; + int left = maxCount() - count; + return left > 0 ? left : 0; +} + +void MetaStack::clear() { + item = ItemId::None; + count = 0; + meta = StackMeta{}; +} + +MetaStack makeStack(ItemId item, int count) { + MetaStack stack; + if (item == ItemId::None || count <= 0) return stack; + stack.item = item; + stack.count = count; + if (isTool(item)) stack.meta.durability = {0, toolMaxDurability(item)}; + int cap = stack.maxCount(); + if (stack.count > cap) stack.count = cap; + return stack; +} + +MetaStack makeTool(ItemId toolItem) { + MetaStack stack; + if (!isTool(toolItem)) return stack; + stack.item = toolItem; + stack.count = 1; + stack.meta.durability = {0, toolMaxDurability(toolItem)}; + return stack; +} + +MetaStack makeNamedStack(ItemId item, int count, const std::string& name) { + MetaStack stack = makeStack(item, count); + if (stack.empty()) return stack; + stack.meta.customName = name; + int cap = stack.maxCount(); + if (stack.count > cap) stack.count = cap; + return stack; +} + +MetaStack makeEnchantedTool(ItemId toolItem, const EnchantSet& enchants) { + MetaStack stack = makeTool(toolItem); + if (stack.empty()) return stack; + stack.meta.enchants = enchants; + return stack; +} + +bool stacksMergeable(const MetaStack& a, const MetaStack& b) { + if (a.empty() || b.empty()) return false; + if (a.item != b.item) return false; + return a.meta == b.meta; +} + +bool stacksIdentical(const MetaStack& a, const MetaStack& b) { + if (a.empty() && b.empty()) return true; + return stacksMergeable(a, b) && a.count == b.count; +} + +StackTransfer transferStack(MetaStack& from, MetaStack& into, int amount) { + StackTransfer transfer; + if (from.empty() || amount <= 0) { + transfer.sourceEmptied = from.empty(); + return transfer; + } + + if (into.empty()) { + into.item = from.item; + into.meta = from.meta; + into.count = 0; + } else if (!stacksMergeable(from, into)) { + transfer.incompatible = true; + return transfer; + } + + int movable = std::min({amount, from.count, into.room()}); + if (movable <= 0) { + transfer.destinationFull = true; + return transfer; + } + + into.count += movable; + from.count -= movable; + transfer.moved = movable; + if (from.count <= 0) { + from.clear(); + transfer.sourceEmptied = true; + } + transfer.destinationFull = into.full(); + return transfer; +} +