feat: add enchantCode and validEnchantKind
This commit is contained in:
1 parent
7ca8ae21c3
commit
0bb301ea22
1 file changed
+160
@@ -0,0 +1,160 @@
|
|||||||
|
#include "vf/ItemStack.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace vf {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
int16_t enchantCode(EnchantKind kind) { return static_cast<int16_t>(kind); }
|
||||||
|
|
||||||
|
bool validEnchantKind(int32_t raw) {
|
||||||
|
return raw >= 0 && raw < static_cast<int32_t>(EnchantKind::Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validItemId(int32_t raw) { return raw > 0 && raw < static_cast<int32_t>(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<float>(left) / static_cast<float>(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;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user