From 3c5021e4c958768b661f77b81663c6d9b662f4f9 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 22 Jun 2025 23:54:50 -0400 Subject: [PATCH] So far most of the bugs are solved but there's still some edge cases in the inventory dance. --- gui/dnd_loot.cpp | 2 +- gui/status_ui.cpp | 20 +++++++++----------- inventory.cpp | 28 ++++++++++++++++++---------- inventory.hpp | 3 ++- tests/inventory.cpp | 13 ++++++++++--- worldbuilder.cpp | 1 + 6 files changed, 41 insertions(+), 26 deletions(-) diff --git a/gui/dnd_loot.cpp b/gui/dnd_loot.cpp index 860a1c1..9a8c297 100644 --- a/gui/dnd_loot.cpp +++ b/gui/dnd_loot.cpp @@ -126,7 +126,7 @@ namespace gui { switch(ev) { case INV_SELECT: - commit_drop($loot_ui.$gui, $status_ui.$gui, $grab_source, data); + if(commit_drop($loot_ui.$gui, $status_ui.$gui, $grab_source, data)) { END(Event::CLOSE); } diff --git a/gui/status_ui.cpp b/gui/status_ui.cpp index b75bced..1774770 100644 --- a/gui/status_ui.cpp +++ b/gui/status_ui.cpp @@ -103,18 +103,16 @@ namespace gui { auto& slot_name = $slot_to_name.at(gui_id); auto& inventory = $level.world->get_the(); - for(auto [ent, slot] : inventory.by_entity) { - fmt::println("BY_ENTITY: ent={}, slot={}", ent, slot); + inventory.dump(); + + if(inventory.add(slot_name, world_entity)) { + $level.world->make_constant(world_entity); + update(); + return true; + } else { + dbc::log("there's something there already"); + return false; } - - for(auto [slot, ent] : inventory.by_slot) { - fmt::println("BY_SLOT: ent={}, slot={}", ent, slot); - } - - $level.world->make_constant(world_entity); - inventory.add(slot_name, world_entity); - update(); - return true; } bool StatusUI::drop_item(DinkyECS::Entity item_id) { diff --git a/inventory.cpp b/inventory.cpp index 34db973..703b630 100644 --- a/inventory.cpp +++ b/inventory.cpp @@ -1,17 +1,15 @@ #include "inventory.hpp" namespace inventory { - void Model::add(const Slot &in_slot, DinkyECS::Entity ent) { - if(by_entity.contains(ent)) { - // doing it this way so we can get the offending entity, otherwise it - // crashes on the by_entity.at when this test _passes_ - dbc::sentinel(fmt::format("failed to add item to inventory, entity {} is already in the inventory slot {}", ent, by_entity.at(ent))); - } + bool Model::add(const Slot &in_slot, DinkyECS::Entity ent) { + invariant(); + + if(by_slot.contains(in_slot)) return false; by_entity.insert_or_assign(ent, in_slot); by_slot.insert_or_assign(in_slot, ent); - invariant(); + return true; } Slot& Model::get(DinkyECS::Entity ent) { @@ -49,9 +47,6 @@ namespace inventory { } void Model::invariant() { - dbc::check(by_slot.size() == by_entity.size(), "by_slot and by_entity have differing sizes"); - // std::unordered_map find_dupes; - for(auto& [slot, ent] : by_slot) { dbc::check(by_entity.at(ent) == slot, fmt::format("mismatched slot {} in by_slot doesn't match entity {}", slot, ent)); @@ -61,5 +56,18 @@ namespace inventory { dbc::check(by_slot.at(slot) == ent, fmt::format("mismatched entity {} in by_entity doesn't match entity {}", ent, slot)); } + + dbc::check(by_slot.size() == by_entity.size(), "by_slot and by_entity have differing sizes"); + } + + void Model::dump() { + invariant(); + fmt::println("INVENTORY has {} slots, sizes equal? {}, contents:", + by_entity.size(), by_entity.size() == by_slot.size()); + + for(auto [slot, ent] : by_slot) { + fmt::println("slot={}, ent={}, both={}, equal={}", + slot, ent, by_entity.contains(ent), by_entity.at(ent) == slot); + } } } diff --git a/inventory.hpp b/inventory.hpp index 782cbf9..bcb7e44 100644 --- a/inventory.hpp +++ b/inventory.hpp @@ -8,7 +8,7 @@ namespace inventory { std::unordered_map by_slot; std::unordered_map by_entity; - void add(const Slot &in_slot, DinkyECS::Entity ent); + bool add(const Slot &in_slot, DinkyECS::Entity ent); Slot& get(DinkyECS::Entity ent); DinkyECS::Entity get(const Slot& slot); bool has(DinkyECS::Entity ent); @@ -17,5 +17,6 @@ namespace inventory { void remove(DinkyECS::Entity ent); void remove(const Slot& slot); void invariant(); + void dump(); }; } diff --git a/tests/inventory.cpp b/tests/inventory.cpp index ecdcca0..1d691cb 100644 --- a/tests/inventory.cpp +++ b/tests/inventory.cpp @@ -9,12 +9,17 @@ TEST_CASE("base test", "[inventory]") { inventory::Model inv; DinkyECS::Entity test_ent = 1; - inv.add("hand_l", test_ent); + bool good = inv.add("hand_l", test_ent); inv.invariant(); + REQUIRE(good); auto& slot = inv.get(test_ent); REQUIRE(slot == "hand_l"); + // confirm that we get false when trying to do it again + good = inv.add("hand_l", test_ent); + REQUIRE(!good); + auto ent = inv.get(slot); REQUIRE(ent == test_ent); @@ -27,7 +32,8 @@ TEST_CASE("base test", "[inventory]") { REQUIRE(!inv.has(ent)); // test remove just by slot - inv.add("hand_r", test_ent); + good = inv.add("hand_r", test_ent); + REQUIRE(good); REQUIRE(inv.has("hand_r")); REQUIRE(inv.has(test_ent)); inv.invariant(); @@ -37,7 +43,8 @@ TEST_CASE("base test", "[inventory]") { REQUIRE(!inv.has(test_ent)); // test remove just by entity - inv.add("pocket_l", test_ent); + good = inv.add("pocket_l", test_ent); + REQUIRE(good); REQUIRE(inv.has("pocket_l")); REQUIRE(inv.has(test_ent)); inv.invariant(); diff --git a/worldbuilder.cpp b/worldbuilder.cpp index 7d235c4..5107495 100644 --- a/worldbuilder.cpp +++ b/worldbuilder.cpp @@ -179,6 +179,7 @@ void WorldBuilder::configure_starting_items(DinkyECS::World &world) { auto &inventory = world.get_the(); inventory.add("hand_r", torch_id); + world.make_constant(torch_id); } void WorldBuilder::place_entities(DinkyECS::World &world) {