From 784f753e72b67a466a3e792b567c0047e61b82ed Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 2 Jul 2025 14:25:44 -0400 Subject: [PATCH] Standardized on using only DinkyECS:Entity for most inventory:::Model operations, then create swap based on the same entities. --- gui/status_ui.cpp | 3 ++- inventory.cpp | 47 +++++++++++++++++++++++++++++---------------- inventory.hpp | 18 ++++++++--------- systems.cpp | 5 +++-- systems.hpp | 2 +- tests/inventory.cpp | 34 +++++++++++++++----------------- 6 files changed, 59 insertions(+), 50 deletions(-) diff --git a/gui/status_ui.cpp b/gui/status_ui.cpp index debf30b..9a1e7f4 100644 --- a/gui/status_ui.cpp +++ b/gui/status_ui.cpp @@ -129,7 +129,8 @@ namespace gui { dbc::log(fmt::format("removing slot: {}", slot_id)); auto& slot_name = $slot_to_name.at(slot_id); auto& inventory = $level.world->get_the(); - inventory.remove(slot_name); + auto world_entity = inventory.get(slot_name); + inventory.remove(world_entity); $gui.remove(slot_id); $gui.remove(slot_id); diff --git a/inventory.cpp b/inventory.cpp index 703b630..d40a34f 100644 --- a/inventory.cpp +++ b/inventory.cpp @@ -1,7 +1,7 @@ #include "inventory.hpp" namespace inventory { - bool Model::add(const Slot &in_slot, DinkyECS::Entity ent) { + bool Model::add(const std::string &in_slot, DinkyECS::Entity ent) { invariant(); if(by_slot.contains(in_slot)) return false; @@ -12,11 +12,11 @@ namespace inventory { return true; } - Slot& Model::get(DinkyECS::Entity ent) { + const std::string& Model::get(DinkyECS::Entity ent) { return by_entity.at(ent); } - DinkyECS::Entity Model::get(const Slot& slot) { + DinkyECS::Entity Model::get(const std::string& slot) { return by_slot.at(slot); } @@ -24,25 +24,14 @@ namespace inventory { return by_entity.contains(ent); } - bool Model::has(const Slot& slot) { + bool Model::has(const std::string& slot) { return by_slot.contains(slot); } - void Model::remove(const Slot& slot, DinkyECS::Entity ent) { - by_entity.erase(ent); - by_slot.erase(slot); - invariant(); - } - void Model::remove(DinkyECS::Entity ent) { auto& slot = by_entity.at(ent); - remove(slot, ent); - invariant(); - } - - void Model::remove(const Slot& slot) { - auto ent = by_slot.at(slot); - remove(slot, ent); + by_entity.erase(ent); + by_slot.erase(slot); invariant(); } @@ -70,4 +59,28 @@ namespace inventory { slot, ent, by_entity.contains(ent), by_entity.at(ent) == slot); } } + + void Model::swap(DinkyECS::Entity a_ent, DinkyECS::Entity b_ent) { + dbc::check(by_entity.contains(a_ent), "a_entity not in inventory"); + dbc::check(by_entity.contains(b_ent), "b_entity not in inventory"); + + if(a_ent == b_ent) return; + + auto a_slot = get(a_ent); + auto b_slot = get(b_ent); + + dbc::check(a_slot != b_slot, "somehow I got two different entities but they gave the same slot?"); + + by_slot.insert_or_assign(a_slot, b_ent); + by_entity.insert_or_assign(b_ent, a_slot); + + by_slot.insert_or_assign(b_slot, a_ent); + by_entity.insert_or_assign(a_ent, b_slot); + } + + size_t Model::count() { + dbc::check(by_slot.size() == by_entity.size(), "entity and slot maps have different sizes"); + + return by_entity.size(); + } } diff --git a/inventory.hpp b/inventory.hpp index f616902..59f8426 100644 --- a/inventory.hpp +++ b/inventory.hpp @@ -6,21 +6,19 @@ // dance when using it. Idea is the System:: ops for this would get it // and then look at the bool and add the constant ops as needed. namespace inventory { - using Slot = std::string; - struct Model { - std::unordered_map by_slot; - std::unordered_map by_entity; + std::unordered_map by_slot; + std::unordered_map by_entity; - bool add(const Slot &in_slot, DinkyECS::Entity ent); - Slot& get(DinkyECS::Entity ent); - DinkyECS::Entity get(const Slot& slot); + bool add(const std::string &in_slot, DinkyECS::Entity ent); + const std::string& get(DinkyECS::Entity ent); + DinkyECS::Entity get(const std::string& slot); bool has(DinkyECS::Entity ent); - bool has(const Slot& slot); - void remove(const Slot& slot, DinkyECS::Entity ent); + bool has(const std::string& slot); void remove(DinkyECS::Entity ent); - void remove(const Slot& slot); void invariant(); void dump(); + void swap(DinkyECS::Entity a_ent, DinkyECS::Entity b_ent); + size_t count(); }; } diff --git a/systems.cpp b/systems.cpp index 5d7891b..3213555 100644 --- a/systems.cpp +++ b/systems.cpp @@ -548,7 +548,8 @@ bool System::place_in_container(World& world, Entity cont_id, const std::string& } } -void System::remove_from_container(World& world, Entity cont_id, const std::string& name) { +void System::remove_from_container(World& world, Entity cont_id, const std::string& slot_id) { auto& container = world.get(cont_id); - container.remove(name); + auto entity = container.get(slot_id); + container.remove(entity); } diff --git a/systems.hpp b/systems.hpp index 92c8bfe..0e00ef5 100644 --- a/systems.hpp +++ b/systems.hpp @@ -34,6 +34,6 @@ namespace System { bool place_in_container(World& world, Entity cont_id, const string& name, Entity world_entity); - void remove_from_container(World& world, Entity cont_id, const string& name); + void remove_from_container(World& world, Entity cont_id, const std::string& name); void remove_from_world(GameLevel &level, Entity entity); } diff --git a/tests/inventory.cpp b/tests/inventory.cpp index 1d691cb..42fec9c 100644 --- a/tests/inventory.cpp +++ b/tests/inventory.cpp @@ -27,28 +27,24 @@ TEST_CASE("base test", "[inventory]") { REQUIRE(inv.has(slot)); // test base remove - inv.remove(slot, ent); + inv.remove(ent); REQUIRE(!inv.has(slot)); REQUIRE(!inv.has(ent)); +} - // test remove just by slot - good = inv.add("hand_r", test_ent); - REQUIRE(good); - REQUIRE(inv.has("hand_r")); - REQUIRE(inv.has(test_ent)); - inv.invariant(); +TEST_CASE("test swapping items", "[inventory-swap]") { + inventory::Model inv; + DinkyECS::Entity hand_l_ent = 10; + DinkyECS::Entity hand_r_ent = 20; - inv.remove("hand_r"); - REQUIRE(!inv.has("hand_r")); - REQUIRE(!inv.has(test_ent)); + inv.add("hand_l", hand_l_ent); + inv.add("hand_r", hand_r_ent); + REQUIRE(inv.count() == 2); - // test remove just by entity - good = inv.add("pocket_l", test_ent); - REQUIRE(good); - REQUIRE(inv.has("pocket_l")); - REQUIRE(inv.has(test_ent)); - inv.invariant(); - inv.remove(test_ent); - REQUIRE(!inv.has("pocket_l")); - REQUIRE(!inv.has(test_ent)); + inv.swap(hand_l_ent, hand_r_ent); + + REQUIRE(inv.get("hand_l") == hand_r_ent); + REQUIRE(inv.get("hand_r") == hand_l_ent); + + REQUIRE(inv.count() == 2); }