Files
factory-hole-core/include/Components/Inventory.hpp
2026-02-15 18:42:47 +09:00

210 lines
5.7 KiB
C++

#pragma once
#include <array>
#include "flecs.h"
#include "Types/Item.hpp"
#include "Types/Filter.h"
#include "Util/SharedBuffer.h"
#include "Util/Span.h"
template <typename IntegralType>
struct InventoryT
{
struct InventoryMeta
{
IntegralType MaxSize{ std::numerics_limits<IntegralType>::max() };
};
public:
InventoryT() = default;
InventoryT(size_t itemAmount) { Slots = { static_cast<int>(items.size()), InventoryMeta{} }; }
public:
IntegralType GetItemsAmount(uint16_t id) const { Assert(id); return Slots[id]; }
IntegralType GetItemsAmount(Item item) const { return GetItemsAmount(item.ItemID); }
void RemoveItems(uint16_t id, IntegralType amount) { Assert(id); Slots[id]-= amount; }
void RemoveItems(Item id, IntegralType amount) { RemoveItems(id.ItemID, amount); }
template <typename OtherIntegralType>
void RemoveItems(ItemAmountT<OtherIntegralType> amount) { RemoveItems(amount.Item, amount.Amount); }
void AddItems(uint16_t id, IntegralType amount) { Assert(id); Slots[id]+= amount; }
void AddItems(Item id, IntegralType amount) { AddItems(id.ItemID, amount); }
template <typename OtherIntegralType>
void AddItems(ItemAmountT<OtherIntegralType> item) { AddItems(item.Item.ItemID, item.Amount); }
template <typename OtherIntegralType>
void AddItems(const InventoryT<OtherIntegralType> other)
{
DEV_ASSERT(Slots.GetSize() == other.Slots.GetSize());
for (uint32_t i{}; i < Slots.GetSize(); ++i)
Slots[i] += other.Slots[i];
}
void Clear()
{
for (IntegralType i{}; i < Slots.GetSize(); ++i)
Slots[i] = 0;
}
void Assert(uint16_t id)
{
DEV_ASSERT(id < Slots.GetSize() && id != Item::null);
}
public:
operator bool() const { return Slots; }
public:
SharedBuffer<IntegralType, InventoryMeta> Slots;
};
typedef InventoryT<uint16_t> Inventory16;
typedef InventoryT<uint32_t> Inventory32;
typedef InventoryT<uint64_t> Inventory64;
typedef Inventory32 Inventory;
typedef Inventory64 WorldInventory;
struct FixedInventoryEntry
{
FixedInventoryEntry() = default;
FixedInventoryEntry(Item item, uint16_t amount, uint16_t maxAmount) : Item{ item }, Amount{ amount }, MaxAmount{ maxAmount } {};
Item Item{};
uint16_t Amount{};
uint16_t MaxAmount{std::numeric_limits<uint16_t>::max()};
};
template <uint8_t Size>
struct FixedInventoryBase
{
FixedInventoryBase() = default;
template <typename It>
FixedInventoryBase(const It& it)
{
int counter{};
for (const auto& val : it)
Data[counter++] = val;
}
tcb::span<FixedInventoryEntry> GetInventoryData()
{
return {&Data[0], InventorySize);
}
tcb::span<const FixedInventoryEntry> GetInventoryData() const
{
return {&Data[0], InventorySize};
}
uint8_t InventorySize{ Size };
std::array<FixedInventoryEntry, Size> Data{};
};
typedef FixedInventoryBase<1> FixedInventory1;
typedef FixedInventoryBase<2> FixedInventory2;
typedef FixedInventoryBase<3> FixedInventory3;
typedef FixedInventoryBase<4> FixedInventory4;
typedef FixedInventoryBase<5> FixedInventory5;
typedef FixedInventoryBase<6> FixedInventory6;
typedef FixedInventoryBase<7> FixedInventory7;
typedef FixedInventoryBase<8> FixedInventory8;
struct InventoryAreaOfEffect
{
InventoryAreaOfEffect(bool isCircle, uint8_t size)
: IsCircle{ isCircle }
, Size{ size }
{
}
uint8_t IsCircle : 1;
uint8_t Size : 7;
};
static_assert(sizeof(InventoryAreaOfEffect) == 1);
struct ItemProcessor
{
ItemProcessor() = default;
ItemProcessor(uint32_t ticks) : ProcessedTicks{ ticks } {};
uint32_t ProcessedTicks;
};
inline void Flecs_Inventory(flecs::world& world)
{
world.component<FixedInventoryEntry>()
.member<Item>("Item")
.member<uint16_t>("Amount")
.member<uint16_t>("MaxAmount");
world.component<FixedInventory1>()
.add(flecs::Inheritable)
.opaque(world.vector<FixedInventoryEntry>())
.serialize([](const flecs::serializer *s, const FixedInventory1 *data) {
for (uint8_t i = 0; i < data->InventorySize; ++i)
s->value(data->Data[i]);
return 0;
})
.count([](const FixedInventory1 *data) -> size_t {
return data->InventorySize;
})
.ensure_element([](FixedInventory1 *data, size_t elem) -> FixedInventoryEntry* {
return &data->Data[elem];
});
world.component<FixedInventory2>().is_a<FixedInventory1>();
world.component<FixedInventory3>().is_a<FixedInventory1>();
world.component<FixedInventory4>().is_a<FixedInventory1>();
world.component<FixedInventory5>().is_a<FixedInventory1>();
world.component<FixedInventory6>().is_a<FixedInventory1>();
world.component<FixedInventory7>().is_a<FixedInventory1>();
world.component<FixedInventory8>().is_a<FixedInventory1>();
world.component<Inventory>()
.opaque(world.vector<uint32_t>())
.serialize([](const flecs::serializer *s, const Inventory *data) {
if (!data->Slots) return 0;
for (uint32_t i = 0; i < data->Slots.GetSize(); ++i)
s->value(data->Slots[i]);
return 0;
})
.count([](const Inventory *data) -> size_t {
if (!data->Slots) return 0;
return data->Slots.GetSize();
});
world.component<WorldInventory>()
.add(flecs::Singleton)
.opaque(world.vector<uint64_t>())
.serialize([](const flecs::serializer *s, const Inventory *data) {
if (!data->Slots) return 0;
for (uint64_t i = 0; i < data->Slots.GetSize(); ++i)
s->value(data->Slots[i]);
return 0;
})
.count([](const Inventory *data) -> size_t {
if (!data->Slots) return 0;
return data->Slots.GetSize();
});
world.component<InventoryAreaOfEffect>()
.opaque(world.component()
.member<uint8_t>("IsCircle")
.member<uint8_t>("Size"))
.serialize([](const flecs::serializer *s, const InventoryAreaOfEffect *data) {
uint8_t isCircle = data->IsCircle;
uint8_t size = data->Size;
s->member("IsCircle");
s->value(isCircle);
s->member("Size");
s->value(size);
return 0;
});
world.component<ItemProcessor>()
.member<uint32_t>("ProcessedTicks");
}