diff --git a/assets/item/air.json b/assets/item/air.json index 8fe69c8..ab8272d 100644 --- a/assets/item/air.json +++ b/assets/item/air.json @@ -1,5 +1,6 @@ { "id": 0, "name": "air", - "description": "" + "description": "", + "type": "block" } \ No newline at end of file diff --git a/assets/item/dirt.json b/assets/item/dirt.json index acd1206..70f9e19 100644 --- a/assets/item/dirt.json +++ b/assets/item/dirt.json @@ -2,5 +2,6 @@ "id": 2, "name": "dirt", "description": "", - "texture": "texture/item/block/dirt.png" -} + "texture": "texture/item/block/dirt.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/grass.json b/assets/item/grass.json index 8ff4b76..228d566 100644 --- a/assets/item/grass.json +++ b/assets/item/grass.json @@ -2,5 +2,6 @@ "id": 9, "name": "grass", "description": "", - "texture": "texture/item/block/grass.png" -} + "texture": "texture/item/block/grass.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/grass_block.json b/assets/item/grass_block.json index 781bc8a..e00e186 100644 --- a/assets/item/grass_block.json +++ b/assets/item/grass_block.json @@ -2,5 +2,6 @@ "id": 1, "name": "grass_block", "description": "", - "texture": "texture/item/block/grass_block.png" + "texture": "texture/item/block/grass_block.png", + "type": "block" } \ No newline at end of file diff --git a/assets/item/leaf.json b/assets/item/leaf.json index 59a5257..6263836 100644 --- a/assets/item/leaf.json +++ b/assets/item/leaf.json @@ -2,5 +2,6 @@ "id": 6, "name": "leaf", "description": "", - "texture": "texture/item/block/leaf.png" -} + "texture": "texture/item/block/leaf.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/log.json b/assets/item/log.json index 2a6f38b..aeceded 100644 --- a/assets/item/log.json +++ b/assets/item/log.json @@ -2,5 +2,6 @@ "id": 5, "name": "log", "description": "", - "texture": "texture/item/block/log.png" -} + "texture": "texture/item/block/log.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/sand.json b/assets/item/sand.json index 59a506e..5d022c0 100644 --- a/assets/item/sand.json +++ b/assets/item/sand.json @@ -2,5 +2,6 @@ "id": 4, "name": "sand", "description": "", - "texture": "texture/item/block/sand.png" -} + "texture": "texture/item/block/sand.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/snowy_grass_block.json b/assets/item/snowy_grass_block.json index 27f4382..f1eb8f1 100644 --- a/assets/item/snowy_grass_block.json +++ b/assets/item/snowy_grass_block.json @@ -2,5 +2,6 @@ "id": 8, "name": "snowy_grass_block", "description": "", - "texture": "texture/item/block/snowy_grass_block.png" -} + "texture": "texture/item/block/snowy_grass_block.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/stone.json b/assets/item/stone.json index 1ad7bd5..8e177b8 100644 --- a/assets/item/stone.json +++ b/assets/item/stone.json @@ -2,5 +2,6 @@ "id": 3, "name": "stone", "description": "", - "texture": "texture/item/block/stone.png" -} + "texture": "texture/item/block/stone.png", + "type": "block" +} \ No newline at end of file diff --git a/assets/item/water.json b/assets/item/water.json index 25b6318..0f6e7ee 100644 --- a/assets/item/water.json +++ b/assets/item/water.json @@ -2,5 +2,6 @@ "id": 7, "name": "water", "description": "", - "texture": "texture/item/block/water.png" -} + "texture": "texture/item/block/water.png", + "type": "block" +} \ No newline at end of file diff --git a/include/Cubed/gameplay/block.hpp b/include/Cubed/gameplay/block.hpp index bc4499d..14fa0c7 100644 --- a/include/Cubed/gameplay/block.hpp +++ b/include/Cubed/gameplay/block.hpp @@ -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& 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 m_datas; - static inline bool is_init = false; - static inline std::unordered_map m_cross_plane_map; + BlockData() { + name = ""; + name_key = ""; + } }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/gameplay/block_manager.hpp b/include/Cubed/gameplay/block_manager.hpp new file mode 100644 index 0000000..9ff4ed2 --- /dev/null +++ b/include/Cubed/gameplay/block_manager.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "Cubed/gameplay/block.hpp" + +#include +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; + using acc = BlockMap::accessor; + using cacc = BlockMap::const_accessor; + using IDMap = tbb::concurrent_hash_map; + using CrossPlaneMap = tbb::concurrent_hash_map; + + 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 \ No newline at end of file diff --git a/include/Cubed/gameplay/item.hpp b/include/Cubed/gameplay/item.hpp index 922ee8c..ae590fe 100644 --- a/include/Cubed/gameplay/item.hpp +++ b/include/Cubed/gameplay/item.hpp @@ -1,14 +1,38 @@ #pragma once +#include "Cubed/gameplay/block.hpp" + #include #include +#include namespace Cubed { using ItemID = uint16_t; +enum class ItemKind { + NONE, + BLOCK, + SPAWN_EGG + +}; + +using ItemProperty = std::variant; + 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 \ No newline at end of file diff --git a/include/Cubed/gameplay/item_manager.hpp b/include/Cubed/gameplay/item_manager.hpp index 00058bb..1bf04d3 100644 --- a/include/Cubed/gameplay/item_manager.hpp +++ b/include/Cubed/gameplay/item_manager.hpp @@ -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; - + using BlockToIDMap = tbb::concurrent_hash_map; void add(const std::filesystem::path& path); ItemMap m_map; IDMap m_id_map; + BlockToIDMap m_block_to_id_map; static constexpr ItemData EMPTY; }; diff --git a/include/Cubed/gameplay/item_stack.hpp b/include/Cubed/gameplay/item_stack.hpp index 5e723a2..70fd02f 100644 --- a/include/Cubed/gameplay/item_stack.hpp +++ b/include/Cubed/gameplay/item_stack.hpp @@ -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 diff --git a/include/Cubed/texture_manager.hpp b/include/Cubed/texture_manager.hpp index 998ffd7..1bcf160 100644 --- a/include/Cubed/texture_manager.hpp +++ b/include/Cubed/texture_manager.hpp @@ -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>; + 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 m_cross_plane_array; std::unique_ptr m_normal_texture_array; std::unique_ptr m_skin; - std::vector> m_item_textures; + ItemTextureMap m_item_textures; std::unordered_map> 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>& 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 \ No newline at end of file diff --git a/include/Cubed/ui/inventory_ui.hpp b/include/Cubed/ui/inventory_ui.hpp index f53ea7e..c676e9e 100644 --- a/include/Cubed/ui/inventory_ui.hpp +++ b/include/Cubed/ui/inventory_ui.hpp @@ -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; diff --git a/include/Cubed/ui/item_slot.hpp b/include/Cubed/ui/item_slot.hpp index ff06f8a..36bf015 100644 --- a/include/Cubed/ui/item_slot.hpp +++ b/include/Cubed/ui/item_slot.hpp @@ -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 m_background; std::unique_ptr m_foreground; - BlockType m_block_type; + ItemID m_id; float m_scale = 1.0f; bool m_hovered = false; }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c0494f5..2665999 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -105,4 +105,5 @@ target_sources(${PROJECT_NAME} gameplay/systems/wander_ai_system.cpp tools/json_utils.cpp gameplay/item_manager.cpp + gameplay/block_manager.cpp ) \ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp index cde9eb5..688abcc 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -2,6 +2,7 @@ #include "Cubed/config.hpp" #include "Cubed/debug_collector.hpp" +#include "Cubed/gameplay/block_manager.hpp" #include "Cubed/gameplay/item_manager.hpp" #include "Cubed/localization.hpp" #include "Cubed/tools/arg_parser.hpp" @@ -74,6 +75,7 @@ void App::init(int argc, char** argv) { Localization::instance().load_language( m_game_config.get("language", default_value)); } + BlockManager::init(); ItemManager::instance().init(); m_window.init(m_argument); m_window.imgui_init(); @@ -81,7 +83,7 @@ void App::init(int argc, char** argv) { Logger::info("Window Init Success"); m_audio.init(); - BlockManager::init(); + m_renderer.init(); Logger::info("Renderer Init Success"); // MapTable::init_map(); diff --git a/src/gameplay/block.cpp b/src/gameplay/block.cpp index 884b772..e69de29 100644 --- a/src/gameplay/block.cpp +++ b/src/gameplay/block.cpp @@ -1,191 +0,0 @@ -#include "Cubed/gameplay/block.hpp" - -#include "Cubed/localization.hpp" -#include "Cubed/tools/cubed_assert.hpp" -#include "Cubed/tools/log.hpp" -#include "Cubed/tools/toml.utils.hpp" - -#include - -namespace fs = std::filesystem; - -using namespace std::string_literals; -using namespace Cubed::TOML; -namespace { -std::string block_data_dir = ASSETS_PATH + "data/block"s; - -} // namespace - -namespace Cubed { - -const std::vector& BlockManager::datas() { - ASSERT(is_init); - return m_datas; -} - -unsigned BlockManager::sums() { - ASSERT(is_init); - return m_datas.size(); -} -unsigned BlockManager::cross_plane_sum() { - ASSERT(is_init); - return m_cross_plane_map.size(); -} - -const std::string& BlockManager::name_form_id(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].name; - } - return m_datas[id].name; -} -std::string BlockManager::local_name(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return tr(m_datas[0].name_key); - } - return tr(m_datas[id].name_key); -} -bool BlockManager::is_gas(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_gas; - } - return m_datas[id].is_gas; -} -bool BlockManager::is_liquid(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_liquid; - } - return m_datas[id].is_liquid; -} - -bool BlockManager::is_cross_plane(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_cross_plane; - } - return m_datas[id].is_cross_plane; -} - -bool BlockManager::is_transparent(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_transparent; - } - return m_datas[id].is_transparent; -} -bool BlockManager::is_passable(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_passable; - } - return m_datas[id].is_passable; -} - -bool BlockManager::is_discard(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_discard; - } - return m_datas[id].is_discard; -} -bool BlockManager::is_blend(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_blend; - } - return m_datas[id].is_blend; -} -bool BlockManager::is_transitional(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].is_transitional; - } - return m_datas[id].is_transitional; -} - -float BlockManager::roughness(BlockType id) { - if (id >= sums()) { - Logger::error("Id {}, is Over The Max Id", id, sums() - 1); - return m_datas[0].roughness; - } - return m_datas[id].roughness; -} - -void BlockManager::init() { - fs::path data_path{block_data_dir}; - - for (auto entry : fs::recursive_directory_iterator(data_path)) { - if (!entry.is_regular_file()) { - continue; - } - if (entry.path().filename() == "template.toml") { - continue; - } - toml::table block; - try { - block = toml::parse_file(entry.path().string()); - } catch (const toml::parse_error& err) { - Logger::error("Load Block Data {} Fail, Parser Error {}", - entry.path().string(), err.what()); - ASSERT(false); - } - auto id = block["id"].value(); - if (id == std::nullopt) { - Logger::error("Very Serious Error, Block Id Not Find !!!, Please " - "Check The Block Data Integrity"); - std::abort(); - } - auto name = block["name"].value(); - if (name == std::nullopt) { - Logger::error("Very Serious Error, Block Name Not Find !!!, Please " - "Check The Block Data Integrity"); - std::abort(); - } - auto is_liquid = safe_get_value(block, "is_liquid", false); - auto is_passable = safe_get_value(block, "is_passable", false); - auto is_cross_plane = safe_get_value(block, "is_cross_plane", false); - auto is_transparent = safe_get_value(block, "is_transparent", false); - auto is_gas = safe_get_value(block, "is_gas", false); - auto is_discard = safe_get_value(block, "is_discard", false); - auto is_blend = safe_get_value(block, "is_blend", false); - auto is_transitional = safe_get_value(block, "is_transitional", false); - auto roughness = safe_get_value(block, "roughness", 1.0); - auto name_key = safe_get_value(block, "name_key", "Unknow_key"); - m_datas.emplace_back(*name, *name_key, *id, *is_liquid, *is_passable, - *is_cross_plane, *is_transparent, *is_gas, - *is_discard, *is_blend, *is_transitional, - static_cast(*roughness)); - } - std::sort( - m_datas.begin(), m_datas.end(), - [](const BlockData& a, const BlockData& b) { return a.id < b.id; }); - - set_up_cross_plane_map(); - is_init = true; -} - -BlockType BlockManager::cross_plane_index(BlockType id) { - auto it = m_cross_plane_map.find(id); - if (it == m_cross_plane_map.end()) { - Logger::error("Can't Find Cross Plane Id {}", id); - ASSERT(false); - throw std::out_of_range{"Can't Find Cross Plane Id" + - std::to_string(id)}; - } - return it->second; -} - -void BlockManager::set_up_cross_plane_map() { - unsigned cur_id = 0; - for (const auto& data : m_datas) { - if (data.is_cross_plane) { - m_cross_plane_map[data.id] = cur_id; - cur_id++; - } - } -} - -} // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/block_manager.cpp b/src/gameplay/block_manager.cpp new file mode 100644 index 0000000..084db01 --- /dev/null +++ b/src/gameplay/block_manager.cpp @@ -0,0 +1,211 @@ +#include "Cubed/gameplay/block_manager.hpp" + +#include "Cubed/localization.hpp" +#include "Cubed/tools/cubed_assert.hpp" +#include "Cubed/tools/log.hpp" +#include "Cubed/tools/toml.utils.hpp" + +#include + +namespace fs = std::filesystem; + +using namespace std::string_literals; +using namespace Cubed::TOML; +namespace { +std::string block_data_dir = ASSETS_PATH + "data/block"s; + +} // namespace + +namespace Cubed { + +unsigned BlockManager::sums() { + ASSERT(is_init); + return m_datas.size(); +} +unsigned BlockManager::cross_plane_sum() { + ASSERT(is_init); + return m_cross_plane_map.size(); +} + +const std::string& BlockManager::name_form_id(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.name; + } + return c->second.name; +} +std::string BlockManager::local_name(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.name_key; + } + return tr(c->second.name_key); +} +bool BlockManager::is_gas(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_gas; + } + return c->second.is_gas; +} +bool BlockManager::is_liquid(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_liquid; + } + return c->second.is_liquid; +} + +bool BlockManager::is_cross_plane(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_cross_plane; + } + return c->second.is_cross_plane; +} + +bool BlockManager::is_transparent(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_transparent; + } + return c->second.is_transparent; +} +bool BlockManager::is_passable(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_passable; + } + return c->second.is_passable; +} + +bool BlockManager::is_discard(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_discard; + } + return c->second.is_discard; +} +bool BlockManager::is_blend(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_blend; + } + return c->second.is_blend; +} +bool BlockManager::is_transitional(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.is_transitional; + } + return c->second.is_transitional; +} + +float BlockManager::roughness(BlockType id) { + cacc c; + if (!m_datas.find(c, id)) { + ASSERT(false); + return EMPTY.roughness; + } + return c->second.roughness; +} + +void BlockManager::init() { + fs::path data_path{block_data_dir}; + + for (auto entry : fs::recursive_directory_iterator(data_path)) { + if (!entry.is_regular_file()) { + continue; + } + if (entry.path().filename() == "template.toml") { + continue; + } + toml::table block; + try { + block = toml::parse_file(entry.path().string()); + } catch (const toml::parse_error& err) { + Logger::error("Load Block Data {} Fail, Parser Error {}", + entry.path().string(), err.what()); + ASSERT(false); + } + auto id = block["id"].value(); + if (id == std::nullopt) { + Logger::error("Very Serious Error, Block Id Not Find !!!, Please " + "Check The Block Data Integrity"); + std::abort(); + } + auto name = block["name"].value(); + if (name == std::nullopt) { + Logger::error("Very Serious Error, Block Name Not Find !!!, Please " + "Check The Block Data Integrity"); + std::abort(); + } + auto is_liquid = safe_get_value(block, "is_liquid", false); + auto is_passable = safe_get_value(block, "is_passable", false); + auto is_cross_plane = safe_get_value(block, "is_cross_plane", false); + auto is_transparent = safe_get_value(block, "is_transparent", false); + auto is_gas = safe_get_value(block, "is_gas", false); + auto is_discard = safe_get_value(block, "is_discard", false); + auto is_blend = safe_get_value(block, "is_blend", false); + auto is_transitional = safe_get_value(block, "is_transitional", false); + auto roughness = safe_get_value(block, "roughness", 1.0); + auto name_key = safe_get_value(block, "name_key", "Unknow_key"); + BlockData data{ + *name, *name_key, static_cast(*id), + *is_liquid, *is_passable, *is_cross_plane, + *is_transparent, *is_gas, *is_discard, + *is_blend, *is_transitional, static_cast(*roughness)}; + + if (!m_datas.emplace(static_cast(*id), std::move(data))) { + Logger::error("Block Type {} already exist!", *id); + } + } + + set_up_cross_plane_map(); + is_init = true; +} + +BlockType BlockManager::cross_plane_index(BlockType id) { + CrossPlaneMap::const_accessor c; + if (!m_cross_plane_map.find(c, id)) { + Logger::error("Can't Find Cross Plane Id {}", id); + ASSERT(false); + throw std::out_of_range{"Can't Find Cross Plane Id" + + std::to_string(id)}; + } + + return c->second; +} + +BlockType BlockManager::id_from_name(const std::string& name) { + IDMap::const_accessor c; + if (m_id_map.find(c, name)) { + return c->second; + } + Logger::error("BlockManager: Can't fin Block {}", name); + ASSERT(false); + return 0; +} + +void BlockManager::set_up_cross_plane_map() { + 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); + + cur_id++; + } + } +} + +} // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/item_manager.cpp b/src/gameplay/item_manager.cpp index e13fdfd..026c15c 100644 --- a/src/gameplay/item_manager.cpp +++ b/src/gameplay/item_manager.cpp @@ -1,5 +1,6 @@ #include "Cubed/gameplay/item_manager.hpp" +#include "Cubed/gameplay/block_manager.hpp" #include "Cubed/tools/cubed_assert.hpp" #include "Cubed/tools/log.hpp" @@ -63,27 +64,41 @@ void ItemManager::add(const std::filesystem::path& path) { if (doc.HasMember("texture")) { data.path = doc["texture"].GetString(); } + if (doc.HasMember("type")) { + std::string type = doc["type"].GetString(); + data.kind = get_item_kind(type); + } + acc a; if (m_map.emplace(a, data.id, std::move(data))) { if (!m_id_map.emplace(a->second.name, a->first)) { Logger::error("ItemManager: Can't Insterd {} {} to id map", a->second.name, a->first); } + if (a->second.kind == ItemKind::BLOCK) { + BlockType b = BlockManager::id_from_name(a->second.name); + m_block_to_id_map.emplace(b, a->first); + } + } else { Logger::error("ItemManager: Can't Insterd {} to map", path.string()); } } const ItemData& ItemManager::get_item_data(std::string_view key) const { - IDMap::const_accessor cacc; ItemID id = 0; - if (m_id_map.find(cacc, key)) { - id = cacc->second; - } else { - Logger::error("Can't Find key {} in id map", key); - ASSERT(false); - return EMPTY; + { + IDMap::const_accessor cacc; + + if (m_id_map.find(cacc, key)) { + id = cacc->second; + } else { + Logger::error("Can't Find key {} in id map", key); + ASSERT(false); + return EMPTY; + } } + return get_item_data(id); } const ItemData& ItemManager::get_item_data(ItemID id) const { @@ -102,5 +117,5 @@ const ItemData& ItemManager::get(std::string_view key) { const ItemData& ItemManager::get(ItemID id) { return instance().get_item_data(id); } - +ItemID ItemManager::size() { return instance().m_map.size(); } } // namespace Cubed \ No newline at end of file diff --git a/src/gameplay/local_player.cpp b/src/gameplay/local_player.cpp index 83522cc..070eb75 100644 --- a/src/gameplay/local_player.cpp +++ b/src/gameplay/local_player.cpp @@ -3,9 +3,10 @@ #include "Cubed/audio/audio_engine.hpp" #include "Cubed/config.hpp" #include "Cubed/debug_collector.hpp" +#include "Cubed/gameplay/block_manager.hpp" #include "Cubed/gameplay/client_world.hpp" #include "Cubed/gameplay/hitbox_manager.hpp" - +#include "Cubed/gameplay/item_manager.hpp" namespace Cubed { namespace { @@ -406,7 +407,10 @@ void LocalPlayer::place_block(float dt) { } } if (m_mouse_state.right) { - auto type = m_hotbar[m_selected_hotbar].type; + 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)) { @@ -683,7 +687,7 @@ void LocalPlayer::init(std::string_view name) { }); for (int i = 0; i < 10; i++) { - m_hotbar[i].type = i; + m_hotbar[i].id = i; } } diff --git a/src/texture_manager.cpp b/src/texture_manager.cpp index 2b026f5..66173ed 100644 --- a/src/texture_manager.cpp +++ b/src/texture_manager.cpp @@ -2,10 +2,11 @@ #include "Cubed/config.hpp" #include "Cubed/constants.hpp" +#include "Cubed/gameplay/block_manager.hpp" +#include "Cubed/gameplay/item_manager.hpp" #include "Cubed/tools/cubed_assert.hpp" #include "Cubed/tools/log.hpp" #include "Cubed/tools/shader_tools.hpp" - namespace { constexpr int BLOCK_SIZE = 16; constexpr int BLOCK_NORMAL_SIZE = 128; @@ -69,7 +70,7 @@ const Texture* TextureManager::get_pbr_texture() const { return m_normal_texture_array.get(); } -const std::vector>& +const TextureManager::ItemTextureMap& TextureManager::get_item_textures() const { return m_item_textures; } @@ -121,23 +122,20 @@ void TextureManager::load_block_texture(unsigned id) { } } -void TextureManager::load_block_item_texture(unsigned id) { +void TextureManager::load_item_texture() { + for (ItemID i = 0; i < ItemManager::size(); ++i) { + auto& item = ItemManager::get(i); + auto data = Tools::load_image_data(item.path); + std::unique_ptr texture = + std::make_unique(TextureType::TEXTURE_2D); + texture->tex_image_2d(TextureFormat::RGBA8, TextureFormat::RGBA, + GL_UNSIGNED_BYTE, data.data, BLOCK_ITEM_SIZE, + BLOCK_ITEM_SIZE); - ASSERT_MSG(id < BlockManager::sums(), "Exceed the max block sum limit"); - std::string name{BlockManager::name_form_id(id)}; + texture->set_nearest(); - std::string path = "texture/item/block/" + name + ".png"; - - auto data = Tools::load_image_data(path); - std::unique_ptr texture = - std::make_unique(TextureType::TEXTURE_2D); - texture->tex_image_2d(TextureFormat::RGBA8, TextureFormat::RGBA, - GL_UNSIGNED_BYTE, data.data, BLOCK_ITEM_SIZE, - BLOCK_ITEM_SIZE); - - texture->set_nearest(); - - m_item_textures.push_back(std::move(texture)); + m_item_textures.try_emplace(item.id, std::move(texture)); + } } void TextureManager::load_cross_plane_texture(unsigned id) { @@ -224,7 +222,7 @@ void TextureManager::init_block() { BLOCK_NORMAL_SIZE, BLOCK_NORMAL_SIZE, BlockManager::sums() * 6); for (unsigned i = 0; i < BlockManager::sums(); i++) { load_block_texture(i); - load_block_item_texture(i); + load_pbr_texture(i); } diff --git a/src/ui/inventory_ui.cpp b/src/ui/inventory_ui.cpp index d59e864..acdcd50 100644 --- a/src/ui/inventory_ui.cpp +++ b/src/ui/inventory_ui.cpp @@ -1,6 +1,7 @@ #include "Cubed/ui/inventory_ui.hpp" #include "Cubed/app.hpp" +#include "Cubed/gameplay/block_manager.hpp" #include "Cubed/scene/scene_manager.hpp" #include "Cubed/scene/world_scene.hpp" #include "Cubed/ui/column_layout.hpp" @@ -20,21 +21,26 @@ void InventoryUI::init() { auto& column = back->add_child(); column.set_anchor(Anchor::CENTER); column.set_child_anchor(ColumnLayoutAnchor::LEFT); - auto& block_textures = texture_manager.get_item_textures(); - auto sum = block_textures.size(); + auto& item_textures = texture_manager.get_item_textures(); + auto sum = item_textures.size(); { auto& row_layout = column.add_child(); auto row = &row_layout; - for (size_t i = 1; i < sum; ++i) { - if ((i - 1) % 10 == 0) { + size_t i = 0; + for (auto& [id, texture] : item_textures) { + if (i % 10 == 0) { auto& r = column.add_child(); row = &r; } auto& slot = row->add_child(); slot.set_default_background(texture_manager); slot.set_scale(5.0f); - slot.set_item(i, block_textures[i].get()); + + slot.set_item(id, texture.get()); m_slots.emplace_back(&slot); + ++i; + } + for (size_t i = 1; i < sum; ++i) { } } { @@ -62,10 +68,12 @@ void InventoryUI::init() { auto& item = row.add_child(); item.set_default_background(texture_manager); item.set_scale(5.0f); - if (h.type == 0) { + if (h.id == 0) { item.set_item(0, nullptr); } else { - item.set_item(h.type, block_textures[h.type].get()); + auto it = item_textures.find(h.id); + ASSERT(it != item_textures.end()); + item.set_item(h.id, it->second.get()); } m_hotbar.emplace_back(&item); } @@ -89,7 +97,7 @@ void InventoryUI::update(float dt) { void InventoryUI::update_item_info() { auto show_item_info = [this](ItemSlot* slot) { if (slot && !m_selected_image->has_texture()) { - auto type = slot->block(); + auto type = slot->id(); if (type != 0) { m_item_info->set_text(BlockManager::local_name(type)) .set_visible(true); @@ -117,16 +125,17 @@ bool InventoryUI::handle_mouse_button_event(const MouseButtonEvent& e) { if (e.action == KeyAction::PRESS && e.key == MouseKey::LEFT_BUTTON) { auto& texture_manager = m_scene.scene_manager().app().texture_manager(); - auto& blocks = texture_manager.get_item_textures(); + auto& item_textures = texture_manager.get_item_textures(); if (!m_selected_image->has_texture()) { { auto slot = get_hovered_slot(); if (slot) { - m_selected_block = slot->block(); - if (m_selected_block != 0) { - m_selected_image->set_texture( - blocks[m_selected_block].get(), true); + m_selected_id = slot->id(); + if (m_selected_id != 0) { + auto it = item_textures.find(m_selected_id); + ASSERT(it != item_textures.end()); + m_selected_image->set_texture(it->second.get(), true); m_selected_image->set_visible(true); return true; } @@ -135,10 +144,11 @@ bool InventoryUI::handle_mouse_button_event(const MouseButtonEvent& e) { { auto [slot, pos] = get_hovered_hotbar_slot(); if (slot) { - m_selected_block = slot->block(); - if (m_selected_block != 0) { - m_selected_image->set_texture( - blocks[m_selected_block].get(), true); + m_selected_id = slot->id(); + if (m_selected_id != 0) { + auto it = item_textures.find(m_selected_id); + ASSERT(it != item_textures.end()); + m_selected_image->set_texture(it->second.get(), true); m_hotbar[pos]->set_item(0, nullptr); auto& player = m_scene.client_world().get_player(); player.set_hotbar(pos, {0, 0}); @@ -154,10 +164,11 @@ bool InventoryUI::handle_mouse_button_event(const MouseButtonEvent& e) { auto [slot, pos] = get_hovered_hotbar_slot(); if (slot) { auto& player = m_scene.client_world().get_player(); - player.set_hotbar(pos, {m_selected_block, 1}); - if (m_selected_block != 0) { - m_hotbar[pos]->set_item(m_selected_block, - blocks[m_selected_block].get()); + player.set_hotbar(pos, {m_selected_id, 1}); + if (m_selected_id != 0) { + auto it = item_textures.find(m_selected_id); + ASSERT(it != item_textures.end()); + m_hotbar[pos]->set_item(m_selected_id, it->second.get()); } } return true; diff --git a/src/ui/item_slot.cpp b/src/ui/item_slot.cpp index fa2984a..a2bf10d 100644 --- a/src/ui/item_slot.cpp +++ b/src/ui/item_slot.cpp @@ -19,9 +19,9 @@ ItemSlot& ItemSlot::set_scale(float scale) { update_border(); return *this; } -ItemSlot& ItemSlot::set_item(BlockType id, const Texture* texture) { +ItemSlot& ItemSlot::set_item(ItemID id, const Texture* texture) { m_foreground->set_texture(texture, false); - m_block_type = id; + m_id = id; return *this; } float ItemSlot::width() const { @@ -77,6 +77,6 @@ bool ItemSlot::handle_mouse_move_event(const MouseMoveEvent& e) { return Widget::handle_mouse_move_event(e); } -BlockType ItemSlot::block() const { return m_block_type; } +ItemID ItemSlot::id() const { return m_id; } bool ItemSlot::hovered() const { return m_hovered; } } // namespace Cubed \ No newline at end of file diff --git a/src/ui/world_ui_manager.cpp b/src/ui/world_ui_manager.cpp index dd1a5b6..2d82576 100644 --- a/src/ui/world_ui_manager.cpp +++ b/src/ui/world_ui_manager.cpp @@ -131,7 +131,7 @@ void WorldUIManager::update_hotbar() { auto hotbar = player.get_hotbar(); size_t selected = player.selected_hotbar(); for (size_t i = 0; i < LocalPlayer::HOTBAR_SUM; ++i) { - auto type = hotbar[i].type; + auto type = hotbar[i].id; if (selected == i) { m_hotbar_slot[i]->set_border_visale(true); } else { @@ -140,7 +140,9 @@ void WorldUIManager::update_hotbar() { if (type == 0) { m_hotbar_slot[i]->set_item(0, nullptr); } else { - m_hotbar_slot[i]->set_item(type, item_texture[type].get()); + auto it = item_texture.find(type); + ASSERT(it != item_texture.end()); + m_hotbar_slot[i]->set_item(type, it->second.get()); } } }