diff --git a/include/asset_loader.h b/include/asset_loader.h index 5bdb0b91..eabc6ef5 100644 --- a/include/asset_loader.h +++ b/include/asset_loader.h @@ -23,6 +23,7 @@ #include #include +#include class load_failure_t { @@ -33,7 +34,8 @@ public: ASSET_FOLDER_NOT_FOUND, MODEL_FOLDER_NOT_FOUND, TEXTURE_FOLDER_NOT_FOUND, - TAGS_FOLDER_NOT_FOUND + TAGS_FOLDER_NOT_FOUND, + INCORRECT_NAMESPACE }; load_failure_t(const type_t type): type{type} // NOLINT @@ -56,6 +58,8 @@ public: return "Texture folder could not be found"; case TAGS_FOLDER_NOT_FOUND: return "Tags folder could not be found"; + case INCORRECT_NAMESPACE: + return "Namespace names of models, textures, or data files do not match!"; default: return "Unknown failure type"; } @@ -65,6 +69,23 @@ private: type_t type; }; +struct namespaced_object +{ + std::string namespace_str; + std::string key_str; +}; + +struct model_data_t +{ + std::optional parent; + std::optional> textures; +}; + +struct namespace_data_t +{ + blt::hashmap_t models; +}; + struct assets_data_t { database_t db; diff --git a/src/asset_loader.cpp b/src/asset_loader.cpp index 2e3cb5cd..1c8ec76f 100644 --- a/src/asset_loader.cpp +++ b/src/asset_loader.cpp @@ -19,14 +19,17 @@ #include #include -#include +#include +#include +#include +#include +#include +using json = nlohmann::json; -asset_loader_t::asset_loader_t(std::string asset_folder, std::string name, std::optional data_folder): data{database_t{name + ".assets"}, - std::move(asset_folder), - std::move(data_folder), - std::move(name)} -{ +asset_loader_t::asset_loader_t(std::string asset_folder, std::string name, std::optional data_folder): data{ + database_t{name + ".assets"}, std::move(asset_folder), std::move(data_folder), std::move(name) } +{} blt::expected asset_loader_t::load_assets() { @@ -38,7 +41,7 @@ blt::expected asset_loader_t::load_assets() /* * Tables */ - auto texture_table = db.builder().create_table("textures"); + auto texture_table = data.db.builder().create_table("textures"); texture_table.with_column("name").primary_key(); texture_table.with_column("width").not_null(); texture_table.with_column("height").not_null(); @@ -49,41 +52,119 @@ blt::expected asset_loader_t::load_assets() std::optional texture_folder; std::optional tags_folder; - for (const auto& entry : std::filesystem::directory_iterator(data.asset_folder)) + for (const auto& entry : std::filesystem::recursive_directory_iterator(data.asset_folder)) { if (!entry.is_directory()) continue; - if (entry.path().string().find("models") != std::string::npos) + if (entry.path().filename().compare("models") == 0) { model_folder = entry.path(); } - if (entry.path().string().find("textures") != std::string::npos) + if (entry.path().filename().compare("textures") == 0) { texture_folder = entry.path(); } } + if (!model_folder) + return blt::unexpected(load_failure_t::MODEL_FOLDER_NOT_FOUND); + + if (!texture_folder) + return blt::unexpected(load_failure_t::TEXTURE_FOLDER_NOT_FOUND); + + if (!exists(*model_folder / "block")) + return blt::unexpected(load_failure_t::MODEL_FOLDER_NOT_FOUND); + + if (!exists(*texture_folder / "block")) + return blt::unexpected(load_failure_t::TEXTURE_FOLDER_NOT_FOUND); + + const auto namespace_name = model_folder->parent_path().filename(); + if (data.data_folder) { - for (const auto& entry : std::filesystem::directory_iterator(*data.data_folder)) + for (const auto& entry : std::filesystem::recursive_directory_iterator(*data.data_folder)) { if (!entry.is_directory()) continue; if (entry.path().string().find("tags") != std::string::npos) { tags_folder = entry.path(); + break; } } } - if (!model_folder) - return blt::unexpected(load_failure_t::MODEL_FOLDER_NOT_FOUND); - if (!texture_folder) - return blt::unexpected(load_failure_t::TEXTURE_FOLDER_NOT_FOUND); if (data.data_folder && !tags_folder) return blt::unexpected(load_failure_t::TAGS_FOLDER_NOT_FOUND); - auto namespace_name = model_folder->parent_path(); + if (data.data_folder && !exists(*tags_folder / "block")) + return blt::unexpected(load_failure_t::TAGS_FOLDER_NOT_FOUND); + + BLT_INFO("Loading assets '{}' for namespace '{}'", data.name, namespace_name.string()); + if (texture_folder->parent_path().filename() != namespace_name) + return blt::unexpected(load_failure_t::INCORRECT_NAMESPACE); + + blt::hashmap_t namespaced_models; + + for (auto entry : std::filesystem::recursive_directory_iterator(*model_folder / "block")) + { + if (!entry.path().has_extension()) + continue; + if (!entry.is_regular_file()) + continue; + if (entry.path().extension().compare(".json") != 0) + continue; + std::filesystem::path relative_path; + { + auto p_begin = entry.path().begin(); + auto p_end = entry.path().end(); + auto m_begin = model_folder->begin(); + while (p_begin != p_end && m_begin != model_folder->end() && *p_begin == *m_begin) + { + ++p_begin; + ++m_begin; + } + for (; p_begin != p_end; ++p_begin) + relative_path /= p_begin->stem(); + } + + std::ifstream file{entry.path()}; + json data = json::parse(file); + + std::optional parent; + std::vector textures; + + if (data.contains("parent")) + { + const auto lparent = data["parent"].get(); + const auto parts = blt::string::split_sv(lparent, ":"); + if (parts.size() == 1) + parent = namespaced_object{namespace_name.string(), std::string{parts[0]}}; + else + parent = namespaced_object{std::string{parts[0]}, std::string{parts[1]}}; + } + if (data.contains("textures")) + { + for (const auto& texture_entry : data["textures"]) + { + auto str = texture_entry.get(); + // not a real texture we care about + if (blt::string::starts_with(str, "#")) + continue; + const auto texture_parts = blt::string::split_sv(str, ":"); + if (texture_parts.size() == 1) + textures.push_back(namespaced_object{namespace_name.string(), std::string{texture_parts[0]}}); + else + textures.push_back(namespaced_object{std::string{texture_parts[0]}, std::string{texture_parts[1]}}); + } + } + + if (!namespaced_models.contains(namespace_name.string())) + namespaced_models[namespace_name.string()] = {}; + namespaced_models[namespace_name.string()].models.insert({ + relative_path.string(), model_data_t{parent, textures.empty() ? std::nullopt : std::move(textures)} + }); + } contains = false; return std::move(data); diff --git a/src/main.cpp b/src/main.cpp index 92105996..57a96d16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include #include #include "blt/gfx/renderer/resource_manager.h" #include "blt/gfx/renderer/batch_2d_renderer.h" @@ -59,6 +60,15 @@ int main() { // blt::gfx::init(blt::gfx::window_data{"Minecraft Color Picker", init, update, destroy}.setSyncInterval(1)); + asset_loader_t loader{"../res/assets", "1.21.5", "../res/data"}; + auto result = loader.load_assets(); + + if (!result) + { + BLT_ERROR("Failed to load assets. Reason: {}", result.error().to_string()); + return 1; + } + return 0;