silly little parser

main
Brett 2025-07-10 19:18:11 -04:00
parent a8985d2fbb
commit d88531c11d
3 changed files with 129 additions and 17 deletions

View File

@ -23,6 +23,7 @@
#include <blt/std/expected.h>
#include <utility>
#include <blt/std/hashmap.h>
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<namespaced_object> parent;
std::optional<std::vector<namespaced_object>> textures;
};
struct namespace_data_t
{
blt::hashmap_t<std::string, model_data_t> models;
};
struct assets_data_t
{
database_t db;

View File

@ -19,14 +19,17 @@
#include <utility>
#include <filesystem>
#include <istream>
#include <fstream>
#include <nlohmann/json.hpp>
#include <blt/logging/logging.h>
#include <blt/std/hashmap.h>
#include <blt/std/string.h>
using json = nlohmann::json;
asset_loader_t::asset_loader_t(std::string asset_folder, std::string name, std::optional<std::string> 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<std::string> data_folder): data{
database_t{name + ".assets"}, std::move(asset_folder), std::move(data_folder), std::move(name)
}
{}
blt::expected<assets_data_t, load_failure_t> asset_loader_t::load_assets()
{
@ -38,7 +41,7 @@ blt::expected<assets_data_t, load_failure_t> 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<std::string>("name").primary_key();
texture_table.with_column<blt::u32>("width").not_null();
texture_table.with_column<blt::u32>("height").not_null();
@ -49,41 +52,119 @@ blt::expected<assets_data_t, load_failure_t> asset_loader_t::load_assets()
std::optional<std::filesystem::path> texture_folder;
std::optional<std::filesystem::path> 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<std::string, namespace_data_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<namespaced_object> parent;
std::vector<namespaced_object> textures;
if (data.contains("parent"))
{
const auto lparent = data["parent"].get<std::string>();
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<std::string>();
// 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);

View File

@ -14,6 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <asset_loader.h>
#include <blt/gfx/window.h>
#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;