aboutsummaryrefslogtreecommitdiff
path: root/src/shared/item/items.cc
diff options
context:
space:
mode:
authorNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-12 21:57:46 +1100
committerNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-12 21:57:46 +1100
commite4483eca01b48b943cd0461e24a74ae1a3139ed4 (patch)
treeed58c3c246e3af1af337697695d780aa31f6ad9a /src/shared/item/items.cc
parent1cc08c51eb4b0f95c30c0a98ad1fc5ad3459b2df (diff)
Update to most recent version (old initial commit)
Diffstat (limited to 'src/shared/item/items.cc')
-rw-r--r--src/shared/item/items.cc164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/shared/item/items.cc b/src/shared/item/items.cc
new file mode 100644
index 0000000..a5540fb
--- /dev/null
+++ b/src/shared/item/items.cc
@@ -0,0 +1,164 @@
+#include "shared/item/items.hh"
+
+namespace shared {
+namespace item {
+
+item_t make_item(const item::type_t& type,
+ const std::uint32_t& quantity) noexcept {
+ if (type >= block::type_offset) {
+ return std::make_shared<block>(type, quantity);
+ }
+ // TODO others
+ return std::make_shared<block>(type, quantity);
+}
+
+item_t make_item(const enum shared::world::block::type& type,
+ const std::uint32_t& quantity) noexcept {
+ return std::make_shared<block>(type, quantity);
+}
+
+item_t make_item(const proto::item& item) noexcept {
+ const auto type = item.type();
+
+ constexpr auto offset = shared::item::block::type_offset;
+ if (type >= offset) {
+ const auto block =
+ static_cast<enum shared::world::block::type>(type - offset);
+ return make_item(block, item.quantity());
+ }
+ return make_item(static_cast<item::type_t>(item.type()), item.quantity());
+}
+
+items::items(const proto::item_array& proto) noexcept {
+ const auto length = static_cast<unsigned long>(proto.items_size());
+ for (auto i = 0ul; i < length; ++i) {
+
+ const auto& item = proto.items().at(static_cast<int>(i));
+
+ const auto index = item.index();
+ this->contents[index] = make_item(item);
+ }
+}
+
+// Annoying logic because we have to add into existing first, then start
+// adding new stacks after.
+bool items::maybe_add(const item::type_t& type, const std::uint32_t& quantity,
+ const make_item_func_t& func) noexcept {
+
+ const auto stack_size = item::get_max_stack(type);
+
+ std::uint32_t added = 0;
+ const auto get_existing =
+ std::ranges::find_if(this->contents, [&](const auto& item) {
+ if (item == nullptr) {
+ return false;
+ }
+ if (item->type != type) {
+ return false;
+ }
+ if (item->quantity >= stack_size) {
+ return false;
+ }
+ return true;
+ });
+ for (auto it = get_existing; get_existing != std::end(this->contents);
+ it = get_existing) {
+
+ const auto addition =
+ std::min(quantity - added, stack_size - (*it)->quantity);
+ (*it)->quantity += addition;
+ added += addition;
+ if (added != quantity) {
+ continue;
+ }
+
+ return true;
+ }
+
+ for (auto& item : this->contents) {
+ if (item != nullptr) {
+ continue;
+ }
+
+ const auto addition = std::min(quantity - added, stack_size);
+ item = func(type, addition);
+ added += addition;
+ if (added != quantity) {
+ continue;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool items::maybe_remove(const item::type_t& type,
+ const std::uint32_t& quantity) noexcept {
+ const auto existing_it =
+ std::ranges::find_if(this->contents, [&type](const auto& i) {
+ if (i == nullptr) {
+ return false;
+ }
+ return type == i->get_type();
+ });
+ if (existing_it == std::end(this->contents)) {
+ return false;
+ }
+
+ auto& existing = (*existing_it)->quantity;
+ if (existing > quantity) {
+ existing -= quantity;
+ return true;
+ }
+
+ if (existing == quantity) {
+ (*existing_it) = nullptr;
+ return true;
+ }
+
+ const auto diff = quantity - existing;
+ (*existing_it) = nullptr;
+ return this->maybe_remove(type, diff);
+}
+
+void items::pack(proto::item_array* const proto) const noexcept {
+ const auto items = proto->mutable_items();
+ for (auto i = 0ul; i < std::size(this->contents); ++i) {
+ const auto& item = contents[i];
+ if (item == nullptr) {
+ continue;
+ }
+
+ proto::item proto_item;
+ item->pack(&proto_item, static_cast<std::uint32_t>(i));
+ items->Add(std::move(proto_item));
+ }
+}
+
+void items::increment(const std::uint32_t& index,
+ const make_item_func_t& func) noexcept {
+ auto& item = this->contents[index];
+ if (item == nullptr) {
+ return;
+ }
+ if (item->quantity < shared::item::item::get_max_stack(item->type)) {
+ ++item->quantity;
+ return;
+ }
+ this->maybe_add(item->type, 1, func);
+}
+
+void items::decrement(const std::uint32_t& index) noexcept {
+ auto& item = this->contents[index];
+ if (item == nullptr) {
+ return;
+ }
+ item->quantity -= 1;
+ if (item->quantity == 0) {
+ item = nullptr;
+ }
+}
+
+} // namespace item
+} // namespace shared