From 1514338144cfda7773d46a4b3603b83a24a72865 Mon Sep 17 00:00:00 2001 From: zhenyan121 <3367366583@qq.com> Date: Tue, 4 Aug 2026 16:58:57 +0800 Subject: [PATCH] fix: stabilize block item registration and display Store item names as owned strings in ItemManager, set block type property for block items, validate item kind before placement, and handle items without textures gracefully in inventory UI. --- include/Cubed/gameplay/block_manager.hpp | 3 ++- include/Cubed/gameplay/item_manager.hpp | 2 +- include/Cubed/texture_manager.hpp | 2 +- src/gameplay/block_manager.cpp | 19 ++++++++++++------- src/gameplay/item_manager.cpp | 3 ++- src/gameplay/local_player.cpp | 24 +++++++++++++----------- src/texture_manager.cpp | 7 ++++++- src/ui/inventory_ui.cpp | 16 +++++++++------- 8 files changed, 46 insertions(+), 30 deletions(-) diff --git a/include/Cubed/gameplay/block_manager.hpp b/include/Cubed/gameplay/block_manager.hpp index 7d7609a..b84d497 100644 --- a/include/Cubed/gameplay/block_manager.hpp +++ b/include/Cubed/gameplay/block_manager.hpp @@ -40,6 +40,7 @@ private: static inline IDMap m_id_map; static inline bool is_init = false; static inline CrossPlaneMap m_cross_plane_map; - static void set_up_cross_plane_map(); + static void set_up_cross_plane_map( + const std::vector>& types); }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/item_manager.hpp b/include/Cubed/gameplay/item_manager.hpp index 6ebc81e..c9fc02c 100644 --- a/include/Cubed/gameplay/item_manager.hpp +++ b/include/Cubed/gameplay/item_manager.hpp @@ -25,7 +25,7 @@ private: using acc = ItemMap::accessor; using cacc = ItemMap::const_accessor; - using IDMap = tbb::concurrent_hash_map; + using IDMap = tbb::concurrent_hash_map; using BlockToIDMap = tbb::concurrent_hash_map; void add(const std::filesystem::path& path); diff --git a/include/Cubed/texture_manager.hpp b/include/Cubed/texture_manager.hpp index 1bcf160..b078106 100644 --- a/include/Cubed/texture_manager.hpp +++ b/include/Cubed/texture_manager.hpp @@ -47,7 +47,7 @@ private: void load_block_status(unsigned status_id); void load_block_texture(unsigned block_id); - void load_item_texture(); + void init_item_texture(); void load_cross_plane_texture(unsigned id); const Texture* load_image_texture(const std::string& path); void load_pbr_texture(unsigned id); diff --git a/src/gameplay/block_manager.cpp b/src/gameplay/block_manager.cpp index 084db01..6285d6c 100644 --- a/src/gameplay/block_manager.cpp +++ b/src/gameplay/block_manager.cpp @@ -5,6 +5,7 @@ #include "Cubed/tools/log.hpp" #include "Cubed/tools/toml.utils.hpp" +#include #include namespace fs = std::filesystem; @@ -122,7 +123,7 @@ float BlockManager::roughness(BlockType id) { void BlockManager::init() { fs::path data_path{block_data_dir}; - + std::vector> types; for (auto entry : fs::recursive_directory_iterator(data_path)) { if (!entry.is_regular_file()) { continue; @@ -169,9 +170,12 @@ void BlockManager::init() { if (!m_datas.emplace(static_cast(*id), std::move(data))) { Logger::error("Block Type {} already exist!", *id); } + m_id_map.emplace(*name, static_cast(*id)); + types.emplace_back(*is_cross_plane, static_cast(*id)); } - - set_up_cross_plane_map(); + std::sort(types.begin(), types.end(), + [](const auto& a, const auto& b) { return a.second < b.second; }); + set_up_cross_plane_map(types); is_init = true; } @@ -197,11 +201,12 @@ BlockType BlockManager::id_from_name(const std::string& name) { return 0; } -void BlockManager::set_up_cross_plane_map() { +void BlockManager::set_up_cross_plane_map( + const std::vector>& types) { unsigned cur_id = 0; - for (const auto& [id, data] : m_datas) { - if (data.is_cross_plane) { - m_cross_plane_map.emplace(data.id, cur_id); + for (auto id : types) { + if (id.first) { + m_cross_plane_map.emplace(id.second, cur_id); cur_id++; } diff --git a/src/gameplay/item_manager.cpp b/src/gameplay/item_manager.cpp index b1191d2..20280ec 100644 --- a/src/gameplay/item_manager.cpp +++ b/src/gameplay/item_manager.cpp @@ -79,6 +79,7 @@ void ItemManager::add(const std::filesystem::path& path) { if (a->second.kind == ItemKind::BLOCK) { BlockType b = BlockManager::id_from_name(a->second.name); m_block_to_id_map.emplace(b, a->first); + a->second.property = b; } } else { @@ -91,7 +92,7 @@ const ItemData& ItemManager::get_item_data(std::string_view key) const { { IDMap::const_accessor cacc; - if (m_id_map.find(cacc, key)) { + if (m_id_map.find(cacc, std::string(key))) { id = cacc->second; } else { Logger::error("Can't Find key {} in id map", key); diff --git a/src/gameplay/local_player.cpp b/src/gameplay/local_player.cpp index 070eb75..6e51387 100644 --- a/src/gameplay/local_player.cpp +++ b/src/gameplay/local_player.cpp @@ -408,17 +408,19 @@ void LocalPlayer::place_block(float dt) { } if (m_mouse_state.right) { auto& data = ItemManager::get(m_hotbar[m_selected_hotbar].id); - auto* t = std::get_if(&data.property); - ASSERT(t); - auto type = *t; - if (type != 0) { - glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal; - if (!m_world.is_solid(near_pos)) { - Hitbox block_box = ClientWorld::get_block_aabb(near_pos); - auto player_box = HitboxManager::hitbox("cubed:player"); - player_box.box.center += get_player_pos(); - if (!player_box.box.intersects(block_box)) { - m_world.report_block_change(near_pos, type); + if (data.kind == ItemKind::BLOCK) { + auto* t = std::get_if(&data.property); + ASSERT(t); + auto type = *t; + if (type != 0) { + glm::ivec3 near_pos = m_look_block->pos + m_look_block->normal; + if (!m_world.is_solid(near_pos)) { + Hitbox block_box = ClientWorld::get_block_aabb(near_pos); + auto player_box = HitboxManager::hitbox("cubed:player"); + player_box.box.center += get_player_pos(); + if (!player_box.box.intersects(block_box)) { + m_world.report_block_change(near_pos, type); + } } } } diff --git a/src/texture_manager.cpp b/src/texture_manager.cpp index 66173ed..d42f4e6 100644 --- a/src/texture_manager.cpp +++ b/src/texture_manager.cpp @@ -122,9 +122,13 @@ void TextureManager::load_block_texture(unsigned id) { } } -void TextureManager::load_item_texture() { +void TextureManager::init_item_texture() { for (ItemID i = 0; i < ItemManager::size(); ++i) { auto& item = ItemManager::get(i); + if (item.path.empty()) { + m_item_textures.try_emplace(item.id, nullptr); + continue; + } auto data = Tools::load_image_data(item.path); std::unique_ptr texture = std::make_unique(TextureType::TEXTURE_2D); @@ -279,6 +283,7 @@ void TextureManager::init_texture() { Logger::info("Map Init Success"); init_block(); + init_item_texture(); init_block_status(); init_ui(); init_skin(); diff --git a/src/ui/inventory_ui.cpp b/src/ui/inventory_ui.cpp index acdcd50..282522c 100644 --- a/src/ui/inventory_ui.cpp +++ b/src/ui/inventory_ui.cpp @@ -1,12 +1,11 @@ #include "Cubed/ui/inventory_ui.hpp" #include "Cubed/app.hpp" -#include "Cubed/gameplay/block_manager.hpp" +#include "Cubed/gameplay/item_manager.hpp" #include "Cubed/scene/scene_manager.hpp" #include "Cubed/scene/world_scene.hpp" #include "Cubed/ui/column_layout.hpp" #include "Cubed/ui/image.hpp" - namespace Cubed { InventoryUI::InventoryUI(WorldScene& scene) : m_scene(scene) {} @@ -22,12 +21,15 @@ void InventoryUI::init() { column.set_anchor(Anchor::CENTER); column.set_child_anchor(ColumnLayoutAnchor::LEFT); auto& item_textures = texture_manager.get_item_textures(); - auto sum = item_textures.size(); + { auto& row_layout = column.add_child(); auto row = &row_layout; size_t i = 0; for (auto& [id, texture] : item_textures) { + if (id == 0) { + continue; + } if (i % 10 == 0) { auto& r = column.add_child(); row = &r; @@ -40,8 +42,6 @@ void InventoryUI::init() { m_slots.emplace_back(&slot); ++i; } - for (size_t i = 1; i < sum; ++i) { - } } { auto& label = back->add_child