#include "dclient/inventory_handler.h" #include "dclient/widgets.h" #include "dclient/widgets/inventory.h" #include "deliantra/data/constants.h" #include "adt/array.h" #include static bool type_name_compare (data::item const &a, data::item const &b) { return a.type != b.type ? a.type < b.type : a.singular < b.singular; } template void unordered_erase (std::vector &vec, size_t index) { vec.at (index) = vec.back (); vec.pop_back (); } template void unordered_erase (std::vector &vec, T const &element) { unordered_erase (vec, &element - &vec.front ()); } inventory_handler::inventory_handler (interface::communicator &comm, widgets &ui) : sender (comm) , ui (&ui) , player_item { } , ground_item { "Floor" } , container_item (&ground_item) { } void inventory_handler::update_container () { container_item = &ground_item; for (data::item const &item : inventories[player_item.tag]) if (item.flags & F_OPEN) { assert (container_item == &ground_item); container_item = &item; #if NDEBUG break; #endif } } void inventory_handler::sort () { for (u32 tag : array (player_item.tag, container_item->tag)) { std::vector &inv = inventories[tag]; std::stable_sort (inv.begin (), inv.end (), type_name_compare); } } void inventory_handler::update_view () const { for (auto pair : array (std::make_pair (&player_item, ui->inventory.get ()), std::make_pair (container_item, ui->container.get ()))) { auto found = inventories.find (pair.first->tag); if (found != inventories.end ()) { pair.second->update (found->second, pair.first->singular); pair.second->visualize (); } } } void inventory_handler::update () { update_container (); sort (); update_view (); } data::item & inventory_handler::get (u32 tag) { if (tag == player_item.tag) return player_item; for (auto &pair : inventories) for (data::item &item : pair.second) if (item.tag == tag) return item; throw "item not found"; } void inventory_handler::delinv (u32 tag) { inventories.erase (tag); } void inventory_handler::delitem (std::vector const &itemtags) { assert (player_item.tag != 0); for (auto &pair : inventories) for (data::item &item : pair.second) for (u32 tag : itemtags) if (item.tag == tag) { assert (tag != player_item.tag); unordered_erase (pair.second, item); } update (); } static data::item & merge (std::vector &inv, data::item const &item) { for (data::item &inv_item : inv) if (inv_item.tag == item.tag) return inv_item = item; inv.push_back (item); return inv.back (); } void inventory_handler::item2 (u32 location, std::vector const &items) { assert (player_item.tag != 0); std::vector &inv = inventories[location]; for (data::item const &item : items) merge (inv, item); update (); } void inventory_handler::player (u32 tag, u32 weight, u32 face, std::string const &name) { player_item.tag = tag; player_item.weight = weight; player_item.face = face; player_item.singular = name; } void inventory_handler::upditem (u08 flags, u32 location, data::item const &item) { data::item *current = &get (item.tag); if (flags & UPD_LOCATION) { data::item save = *current; delitem ({ item.tag }); current = &merge (inventories[location], save); } if (flags & UPD_ANIM) current->anim = item.anim; if (flags & UPD_ANIMSPEED) current->animspeed = item.animspeed; if (flags & UPD_FACE) current->face = item.face; if (flags & UPD_FLAGS) current->flags = item.flags; if (flags & UPD_NROF) current->nrof = item.nrof; if (flags & UPD_WEIGHT) current->weight = item.weight; if (flags & UPD_NAME) { current->singular = item.singular; current->plural = item.plural; } update (); }