mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
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:
@@ -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
|
||||
)
|
||||
@@ -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();
|
||||
|
||||
@@ -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 <filesystem>
|
||||
|
||||
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<BlockData>& 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<int>();
|
||||
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<std::string>();
|
||||
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<float>(*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
|
||||
211
src/gameplay/block_manager.cpp
Normal file
211
src/gameplay/block_manager.cpp
Normal file
@@ -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 <filesystem>
|
||||
|
||||
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<int>();
|
||||
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<std::string>();
|
||||
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<BlockType>(*id),
|
||||
*is_liquid, *is_passable, *is_cross_plane,
|
||||
*is_transparent, *is_gas, *is_discard,
|
||||
*is_blend, *is_transitional, static_cast<float>(*roughness)};
|
||||
|
||||
if (!m_datas.emplace(static_cast<BlockType>(*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
|
||||
@@ -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
|
||||
@@ -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<BlockType>(&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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<std::unique_ptr<Texture>>&
|
||||
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> texture =
|
||||
std::make_unique<Texture>(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> texture =
|
||||
std::make_unique<Texture>(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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ColumnLayout>();
|
||||
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<RowLayout>();
|
||||
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<RowLayout>();
|
||||
row = &r;
|
||||
}
|
||||
auto& slot = row->add_child<ItemSlot>();
|
||||
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<ItemSlot>();
|
||||
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;
|
||||
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user