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.
This commit is contained in:
2026-08-04 16:58:57 +08:00
parent 8af30e159d
commit 1514338144
8 changed files with 46 additions and 30 deletions

View File

@@ -40,6 +40,7 @@ private:
static inline IDMap m_id_map; static inline IDMap m_id_map;
static inline bool is_init = false; static inline bool is_init = false;
static inline CrossPlaneMap m_cross_plane_map; static inline CrossPlaneMap m_cross_plane_map;
static void set_up_cross_plane_map(); static void set_up_cross_plane_map(
const std::vector<std::pair<bool, BlockType>>& types);
}; };
} // namespace Cubed } // namespace Cubed

View File

@@ -25,7 +25,7 @@ private:
using acc = ItemMap::accessor; using acc = ItemMap::accessor;
using cacc = ItemMap::const_accessor; using cacc = ItemMap::const_accessor;
using IDMap = tbb::concurrent_hash_map<std::string_view, ItemID>; using IDMap = tbb::concurrent_hash_map<std::string, ItemID>;
using BlockToIDMap = tbb::concurrent_hash_map<BlockType, ItemID>; using BlockToIDMap = tbb::concurrent_hash_map<BlockType, ItemID>;
void add(const std::filesystem::path& path); void add(const std::filesystem::path& path);

View File

@@ -47,7 +47,7 @@ private:
void load_block_status(unsigned status_id); void load_block_status(unsigned status_id);
void load_block_texture(unsigned block_id); void load_block_texture(unsigned block_id);
void load_item_texture(); void init_item_texture();
void load_cross_plane_texture(unsigned id); void load_cross_plane_texture(unsigned id);
const Texture* load_image_texture(const std::string& path); const Texture* load_image_texture(const std::string& path);
void load_pbr_texture(unsigned id); void load_pbr_texture(unsigned id);

View File

@@ -5,6 +5,7 @@
#include "Cubed/tools/log.hpp" #include "Cubed/tools/log.hpp"
#include "Cubed/tools/toml.utils.hpp" #include "Cubed/tools/toml.utils.hpp"
#include <algorithm>
#include <filesystem> #include <filesystem>
namespace fs = std::filesystem; namespace fs = std::filesystem;
@@ -122,7 +123,7 @@ float BlockManager::roughness(BlockType id) {
void BlockManager::init() { void BlockManager::init() {
fs::path data_path{block_data_dir}; fs::path data_path{block_data_dir};
std::vector<std::pair<bool, BlockType>> types;
for (auto entry : fs::recursive_directory_iterator(data_path)) { for (auto entry : fs::recursive_directory_iterator(data_path)) {
if (!entry.is_regular_file()) { if (!entry.is_regular_file()) {
continue; continue;
@@ -169,9 +170,12 @@ void BlockManager::init() {
if (!m_datas.emplace(static_cast<BlockType>(*id), std::move(data))) { if (!m_datas.emplace(static_cast<BlockType>(*id), std::move(data))) {
Logger::error("Block Type {} already exist!", *id); Logger::error("Block Type {} already exist!", *id);
} }
m_id_map.emplace(*name, static_cast<BlockType>(*id));
types.emplace_back(*is_cross_plane, static_cast<BlockType>(*id));
} }
std::sort(types.begin(), types.end(),
set_up_cross_plane_map(); [](const auto& a, const auto& b) { return a.second < b.second; });
set_up_cross_plane_map(types);
is_init = true; is_init = true;
} }
@@ -197,11 +201,12 @@ BlockType BlockManager::id_from_name(const std::string& name) {
return 0; return 0;
} }
void BlockManager::set_up_cross_plane_map() { void BlockManager::set_up_cross_plane_map(
const std::vector<std::pair<bool, BlockType>>& types) {
unsigned cur_id = 0; unsigned cur_id = 0;
for (const auto& [id, data] : m_datas) { for (auto id : types) {
if (data.is_cross_plane) { if (id.first) {
m_cross_plane_map.emplace(data.id, cur_id); m_cross_plane_map.emplace(id.second, cur_id);
cur_id++; cur_id++;
} }

View File

@@ -79,6 +79,7 @@ void ItemManager::add(const std::filesystem::path& path) {
if (a->second.kind == ItemKind::BLOCK) { if (a->second.kind == ItemKind::BLOCK) {
BlockType b = BlockManager::id_from_name(a->second.name); BlockType b = BlockManager::id_from_name(a->second.name);
m_block_to_id_map.emplace(b, a->first); m_block_to_id_map.emplace(b, a->first);
a->second.property = b;
} }
} else { } else {
@@ -91,7 +92,7 @@ const ItemData& ItemManager::get_item_data(std::string_view key) const {
{ {
IDMap::const_accessor cacc; IDMap::const_accessor cacc;
if (m_id_map.find(cacc, key)) { if (m_id_map.find(cacc, std::string(key))) {
id = cacc->second; id = cacc->second;
} else { } else {
Logger::error("Can't Find key {} in id map", key); Logger::error("Can't Find key {} in id map", key);

View File

@@ -408,6 +408,7 @@ void LocalPlayer::place_block(float dt) {
} }
if (m_mouse_state.right) { if (m_mouse_state.right) {
auto& data = ItemManager::get(m_hotbar[m_selected_hotbar].id); auto& data = ItemManager::get(m_hotbar[m_selected_hotbar].id);
if (data.kind == ItemKind::BLOCK) {
auto* t = std::get_if<BlockType>(&data.property); auto* t = std::get_if<BlockType>(&data.property);
ASSERT(t); ASSERT(t);
auto type = *t; auto type = *t;
@@ -424,6 +425,7 @@ void LocalPlayer::place_block(float dt) {
} }
} }
} }
}
int LocalPlayer::selected_hotbar() const { return m_selected_hotbar; } int LocalPlayer::selected_hotbar() const { return m_selected_hotbar; }
void LocalPlayer::set_hotbar(int pos, const ItemStack& item) { void LocalPlayer::set_hotbar(int pos, const ItemStack& item) {

View File

@@ -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) { for (ItemID i = 0; i < ItemManager::size(); ++i) {
auto& item = ItemManager::get(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); auto data = Tools::load_image_data(item.path);
std::unique_ptr<Texture> texture = std::unique_ptr<Texture> texture =
std::make_unique<Texture>(TextureType::TEXTURE_2D); std::make_unique<Texture>(TextureType::TEXTURE_2D);
@@ -279,6 +283,7 @@ void TextureManager::init_texture() {
Logger::info("Map Init Success"); Logger::info("Map Init Success");
init_block(); init_block();
init_item_texture();
init_block_status(); init_block_status();
init_ui(); init_ui();
init_skin(); init_skin();

View File

@@ -1,12 +1,11 @@
#include "Cubed/ui/inventory_ui.hpp" #include "Cubed/ui/inventory_ui.hpp"
#include "Cubed/app.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/scene_manager.hpp"
#include "Cubed/scene/world_scene.hpp" #include "Cubed/scene/world_scene.hpp"
#include "Cubed/ui/column_layout.hpp" #include "Cubed/ui/column_layout.hpp"
#include "Cubed/ui/image.hpp" #include "Cubed/ui/image.hpp"
namespace Cubed { namespace Cubed {
InventoryUI::InventoryUI(WorldScene& scene) : m_scene(scene) {} InventoryUI::InventoryUI(WorldScene& scene) : m_scene(scene) {}
@@ -22,12 +21,15 @@ void InventoryUI::init() {
column.set_anchor(Anchor::CENTER); column.set_anchor(Anchor::CENTER);
column.set_child_anchor(ColumnLayoutAnchor::LEFT); column.set_child_anchor(ColumnLayoutAnchor::LEFT);
auto& item_textures = texture_manager.get_item_textures(); auto& item_textures = texture_manager.get_item_textures();
auto sum = item_textures.size();
{ {
auto& row_layout = column.add_child<RowLayout>(); auto& row_layout = column.add_child<RowLayout>();
auto row = &row_layout; auto row = &row_layout;
size_t i = 0; size_t i = 0;
for (auto& [id, texture] : item_textures) { for (auto& [id, texture] : item_textures) {
if (id == 0) {
continue;
}
if (i % 10 == 0) { if (i % 10 == 0) {
auto& r = column.add_child<RowLayout>(); auto& r = column.add_child<RowLayout>();
row = &r; row = &r;
@@ -40,8 +42,6 @@ void InventoryUI::init() {
m_slots.emplace_back(&slot); m_slots.emplace_back(&slot);
++i; ++i;
} }
for (size_t i = 1; i < sum; ++i) {
}
} }
{ {
auto& label = back->add_child<Label>(); auto& label = back->add_child<Label>();
@@ -97,10 +97,12 @@ void InventoryUI::update(float dt) {
void InventoryUI::update_item_info() { void InventoryUI::update_item_info() {
auto show_item_info = [this](ItemSlot* slot) { auto show_item_info = [this](ItemSlot* slot) {
if (slot && !m_selected_image->has_texture()) { if (slot && !m_selected_image->has_texture()) {
auto type = slot->id(); auto type = slot->id();
if (type != 0) { if (type != 0) {
m_item_info->set_text(BlockManager::local_name(type)) auto& data = ItemManager::get(type);
.set_visible(true); m_item_info->set_text(data.name).set_visible(true);
return true; return true;
} }
} }