refactor(item): decouple items from block types

The item system now supports an ItemKind and property, allowing item JSON to declare a type instead of assuming every item is a block. BlockManager was moved to its own header, redesigned around concurrent hash maps, and exposes id_from_name(). Texture and UI code now key items by ItemID, while block placement resolves the block type from the item registry.
This commit is contained in:
2026-08-04 16:14:00 +08:00
parent 2358cfd9a4
commit 0259ca71ce
28 changed files with 436 additions and 323 deletions

View File

@@ -63,35 +63,10 @@ struct BlockData {
is_gas(gas), is_passable(passable), is_cross_plane(cross_plane),
is_transparent(transparent), is_discard(discard), is_blend(blend),
is_transitional(transitional), roughness(r) {}
};
class BlockManager {
public:
static const std::vector<BlockData>& datas();
static void init();
static unsigned sums();
static unsigned cross_plane_sum();
static const std::string& name_form_id(BlockType id);
static std::string local_name(BlockType id);
static bool is_gas(BlockType id);
static bool is_liquid(BlockType id);
static bool is_cross_plane(BlockType id);
static bool is_transparent(BlockType id);
static bool is_passable(BlockType id);
static bool is_discard(BlockType id);
static bool is_blend(BlockType id);
static bool is_transitional(BlockType id);
static float roughness(BlockType id);
static BlockType cross_plane_index(BlockType id);
private:
static void set_up_cross_plane_map();
static inline std::vector<BlockData> m_datas;
static inline bool is_init = false;
static inline std::unordered_map<BlockType, BlockType> m_cross_plane_map;
BlockData() {
name = "";
name_key = "";
}
};
} // namespace Cubed

View File

@@ -0,0 +1,45 @@
#pragma once
#include "Cubed/gameplay/block.hpp"
#include <tbb/concurrent_hash_map.h>
namespace Cubed {
class BlockManager {
public:
static void init();
static unsigned sums();
static unsigned cross_plane_sum();
static const std::string& name_form_id(BlockType id);
static std::string local_name(BlockType id);
static bool is_gas(BlockType id);
static bool is_liquid(BlockType id);
static bool is_cross_plane(BlockType id);
static bool is_transparent(BlockType id);
static bool is_passable(BlockType id);
static bool is_discard(BlockType id);
static bool is_blend(BlockType id);
static bool is_transitional(BlockType id);
static float roughness(BlockType id);
static BlockType cross_plane_index(BlockType id);
static BlockType id_from_name(const std::string& name);
private:
using BlockMap = tbb::concurrent_hash_map<BlockType, BlockData>;
using acc = BlockMap::accessor;
using cacc = BlockMap::const_accessor;
using IDMap = tbb::concurrent_hash_map<std::string, BlockType>;
using CrossPlaneMap = tbb::concurrent_hash_map<BlockType, BlockType>;
static const BlockData EMPTY;
static inline BlockMap m_datas;
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();
};
} // namespace Cubed

View File

@@ -1,14 +1,38 @@
#pragma once
#include "Cubed/gameplay/block.hpp"
#include <cstdint>
#include <string>
#include <variant>
namespace Cubed {
using ItemID = uint16_t;
enum class ItemKind {
NONE,
BLOCK,
SPAWN_EGG
};
using ItemProperty = std::variant<BlockType, std::string>;
struct ItemData {
ItemID id = 0;
std::string name;
std::string description;
std::string path;
ItemKind kind = ItemKind::NONE;
ItemProperty property;
};
inline constexpr ItemKind get_item_kind(std::string_view kind) {
if (kind == "block") {
return ItemKind::BLOCK;
}
if (kind == "SPAWN_EGG") {
return ItemKind::SPAWN_EGG;
}
return ItemKind::NONE;
}
} // namespace Cubed

View File

@@ -15,6 +15,8 @@ public:
static const ItemData& get(std::string_view key);
static const ItemData& get(ItemID id);
static ItemID size();
const ItemData& get_item_data(std::string_view key) const;
const ItemData& get_item_data(ItemID id) const;
@@ -24,12 +26,13 @@ private:
using cacc = ItemMap::const_accessor;
using IDMap = tbb::concurrent_hash_map<std::string_view, ItemID>;
using BlockToIDMap = tbb::concurrent_hash_map<BlockType, ItemID>;
void add(const std::filesystem::path& path);
ItemMap m_map;
IDMap m_id_map;
BlockToIDMap m_block_to_id_map;
static constexpr ItemData EMPTY;
};

View File

@@ -1,8 +1,9 @@
#pragma once
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/item.hpp"
namespace Cubed {
struct ItemStack {
BlockType type = 0;
ItemID id = 0;
size_t sum = 0;
};
} // namespace Cubed

View File

@@ -1,6 +1,7 @@
#pragma once
#include "Cubed/config.hpp"
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/item.hpp"
#include "Cubed/input/event.hpp"
#include "Cubed/render/texture.hpp"
@@ -10,6 +11,26 @@
namespace Cubed {
class TextureManager {
public:
using ItemTextureMap = std::unordered_map<ItemID, std::shared_ptr<Texture>>;
TextureManager(Config& config);
~TextureManager();
void delete_texture();
const Texture* get_block_status_array() const;
const Texture* get_texture_array() const;
const Texture* get_cross_plane_array() const;
const Texture* get_image_texture(const std::string& path);
const Texture* get_pbr_texture() const;
const ItemTextureMap& get_item_textures() const;
const Texture* get_skin() const;
void init_texture();
void need_reload();
void update();
int max_aniso() const;
bool handle_event(const Event& e);
private:
bool m_need_reload = false;
bool m_init = false;
@@ -18,7 +39,7 @@ private:
std::unique_ptr<Texture> m_cross_plane_array;
std::unique_ptr<Texture> m_normal_texture_array;
std::unique_ptr<Texture> m_skin;
std::vector<std::unique_ptr<Texture>> m_item_textures;
ItemTextureMap m_item_textures;
std::unordered_map<std::string, std::unique_ptr<Texture>> m_ui_map;
GLfloat m_max_aniso = 0.0f;
Config& m_config;
@@ -26,7 +47,7 @@ private:
void load_block_status(unsigned status_id);
void load_block_texture(unsigned block_id);
void load_block_item_texture(unsigned id);
void load_item_texture();
void load_cross_plane_texture(unsigned id);
const Texture* load_image_texture(const std::string& path);
void load_pbr_texture(unsigned id);
@@ -37,25 +58,6 @@ private:
void init_skin();
void hot_reload();
bool handle_key_event(const KeyEvent& e);
public:
TextureManager(Config& config);
~TextureManager();
void delete_texture();
const Texture* get_block_status_array() const;
const Texture* get_texture_array() const;
const Texture* get_cross_plane_array() const;
const Texture* get_image_texture(const std::string& path);
const Texture* get_pbr_texture() const;
const std::vector<std::unique_ptr<Texture>>& get_item_textures() const;
const Texture* get_skin() const;
void init_texture();
void need_reload();
void update();
int max_aniso() const;
bool handle_event(const Event& e);
};
} // namespace Cubed

View File

@@ -20,7 +20,7 @@ private:
Label* m_item_info = nullptr;
Image* m_selected_image = nullptr;
BlockType m_selected_block = 0;
BlockType m_selected_id = 0;
void update_item_info();
bool handle_mouse_button_event(const MouseButtonEvent& e) override;

View File

@@ -1,6 +1,6 @@
#pragma once
#include "Cubed/gameplay/block.hpp"
#include "Cubed/gameplay/item.hpp"
#include "Cubed/ui/image.hpp"
#include "Cubed/ui/widget.hpp"
namespace Cubed {
@@ -13,11 +13,11 @@ public:
ItemSlot& set_default_background(TextureManager& m_texture_manager);
ItemSlot& set_scale(float m_scale);
ItemSlot& set_item(BlockType id, const Texture* texture);
ItemSlot& set_item(ItemID id, const Texture* texture);
float width() const override;
float height() const override;
bool handle_mouse_move_event(const MouseMoveEvent& e) override;
BlockType block() const;
ItemID id() const;
bool hovered() const;
private:
@@ -26,7 +26,7 @@ private:
void on_update(float dt) override;
std::unique_ptr<Image> m_background;
std::unique_ptr<Image> m_foreground;
BlockType m_block_type;
ItemID m_id;
float m_scale = 1.0f;
bool m_hovered = false;
};