228 lines
6.3 KiB
C++
228 lines
6.3 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
|
|
#include "flecs.h"
|
|
|
|
#include "Types/Item.hpp"
|
|
#include "Util/SharedBuffer.h"
|
|
#include "Util/Span.h"
|
|
|
|
template <typename IntegralType>
|
|
struct InventoryT
|
|
{
|
|
struct InventoryMeta
|
|
{
|
|
IntegralType MaxSize{ std::numeric_limits<IntegralType>::max() };
|
|
};
|
|
|
|
public:
|
|
InventoryT() = default;
|
|
InventoryT(size_t itemAmount) { Slots = { static_cast<int>(itemAmount), InventoryMeta{} }; }
|
|
InventoryT(size_t itemAmount, IntegralType maxAmount) { Slots = { static_cast<int>(itemAmount), InventoryMeta{ maxAmount } }; }
|
|
|
|
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];
|
|
}
|
|
|
|
bool IsFull(uint16_t id) const { Assert(id); return Slots[id] >= Slots.GetMetaData()->MaxSize; }
|
|
|
|
void Clear()
|
|
{
|
|
for (IntegralType i{}; i < Slots.GetSize(); ++i)
|
|
Slots[i] = 0;
|
|
}
|
|
|
|
void Assert(uint16_t id) const
|
|
{
|
|
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) : ItemInfo{ item }, Amount{ amount }, MaxAmount{ maxAmount } {};
|
|
|
|
Item ItemInfo{};
|
|
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 }
|
|
, ShapeSize{ size }
|
|
{
|
|
}
|
|
|
|
uint8_t IsCircle : 1;
|
|
uint8_t ShapeSize : 7;
|
|
};
|
|
static_assert(sizeof(InventoryAreaOfEffect) == 1);
|
|
|
|
struct InventoryOwner
|
|
{};
|
|
|
|
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");
|
|
|
|
auto fixedInv1 = world.component<FixedInventory1>();
|
|
fixedInv1.add(flecs::Inheritable);
|
|
fixedInv1
|
|
.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) -> void* {
|
|
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>();
|
|
|
|
auto inv = world.component<Inventory>();
|
|
inv.add(flecs::Inheritable);
|
|
inv
|
|
.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();
|
|
});
|
|
|
|
auto worldInv = world.component<WorldInventory>();
|
|
worldInv.add(flecs::Singleton);
|
|
worldInv
|
|
.opaque(world.vector<uint64_t>())
|
|
.serialize([](const flecs::serializer *s, const WorldInventory *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 WorldInventory *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->ShapeSize;
|
|
s->member("IsCircle");
|
|
s->value(isCircle);
|
|
s->member("Size");
|
|
s->value(size);
|
|
return 0;
|
|
});
|
|
|
|
world.component<ItemProcessor>()
|
|
.member<uint32_t>("ProcessedTicks");
|
|
|
|
world.component<InventoryOwner>();
|
|
|
|
}
|
|
|
|
inline void Inventory_Helper(const flecs::entity& entity, const WorldConfig& config, uint32_t maxPerSlot)
|
|
{
|
|
entity.set<Inventory>(Inventory{config.GetItems().size(), maxPerSlot});
|
|
entity.add<InventoryOwner>();
|
|
} |