diff --git a/res/content/base/content.json b/res/content/base/content.json new file mode 100644 index 00000000..2429936e --- /dev/null +++ b/res/content/base/content.json @@ -0,0 +1,28 @@ +{ + "blocks": [ + "dirt", + "grass_block", + "lamp", + "glass", + "planks", + "wood", + "leaves", + "stone", + "water", + "sand", + "bazalt", + "grass", + "flower", + "brick", + "metal", + "rust", + "red_lamp", + "green_lamp", + "blue_lamp", + "pane", + "pipe", + "lightbulb", + "torch", + "wallpaper" + ] +} diff --git a/res/content/base/package.json b/res/content/base/package.json index 8e16edd9..f6b17a98 100644 --- a/res/content/base/package.json +++ b/res/content/base/package.json @@ -1,31 +1,6 @@ { "id": "base", + "title": "Base", "version": "0.15", - "description": "basic content package", - "blocks": [ - "dirt", - "grass_block", - "lamp", - "glass", - "planks", - "wood", - "leaves", - "stone", - "water", - "sand", - "bazalt", - "grass", - "flower", - "brick", - "metal", - "rust", - "red_lamp", - "green_lamp", - "blue_lamp", - "pane", - "pipe", - "lightbulb", - "torch", - "wallpaper" - ] + "description": "basic content package" } diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index 1ce93fa1..6fadd6f8 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -15,6 +15,7 @@ menu.missing-content=Отсутствует Контент! menu.Controls=Управление menu.Back to Main Menu=Вернуться в Меню menu.Settings=Настройки +menu.Content=Контент world.Seed=Зерно world.Name=Название world.Create World=Создать Мир diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 39d0d091..de8e8933 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "Content.h" #include "../voxels/Block.h" @@ -10,27 +11,21 @@ #include "../coders/json.h" #include "../typedefs.h" -#include +#include "ContentPack.h" -// don't ask -using glm::vec3; -using std::cout; -using std::cerr; -using std::endl; -using std::string; -using std::unique_ptr; -using std::filesystem::path; +namespace fs = std::filesystem; -ContentLoader::ContentLoader(path folder) : folder(folder) {} +ContentLoader::ContentLoader(const ContentPack* pack) : pack(pack) { +} // TODO: add basic validation and logging -Block* ContentLoader::loadBlock(string name, path file) { - unique_ptr root(files::read_json(file)); - unique_ptr def(new Block(name)); +Block* ContentLoader::loadBlock(std::string name, fs::path file) { + std::unique_ptr root(files::read_json(file)); + std::unique_ptr def(new Block(name)); // block texturing if (root->has("texture")) { - string texture; + std::string texture; root->str("texture", texture); for (uint i = 0; i < 6; i++) def->textureFaces[i] = texture; @@ -42,19 +37,19 @@ Block* ContentLoader::loadBlock(string name, path file) { } // block model - string model = "block"; + std::string model = "block"; root->str("model", model); if (model == "block") def->model = BlockModel::block; else if (model == "aabb") def->model = BlockModel::aabb; else if (model == "X") def->model = BlockModel::xsprite; else if (model == "none") def->model = BlockModel::none; else { - cerr << "unknown model " << model << endl; + std::cerr << "unknown model " << model << std::endl; def->model = BlockModel::none; } // rotation profile - string profile = "none"; + std::string profile = "none"; root->str("rotation", profile); def->rotatable = profile != "none"; if (profile == "pipe") { @@ -62,16 +57,16 @@ Block* ContentLoader::loadBlock(string name, path file) { } else if (profile == "pane") { def->rotations = BlockRotProfile::PANE; } else if (profile != "none") { - cerr << "unknown rotation profile " << profile << endl; + std::cerr << "unknown rotation profile " << profile << std::endl; def->rotatable = false; } // block hitbox AABB [x, y, z, width, height, depth] - json::JArray* hitboxobj = root->arr("hitbox"); - if (hitboxobj) { + json::JArray* boxobj = root->arr("hitbox"); + if (boxobj) { AABB& aabb = def->hitbox; - aabb.a = vec3(hitboxobj->num(0), hitboxobj->num(1), hitboxobj->num(2)); - aabb.b = vec3(hitboxobj->num(3), hitboxobj->num(4), hitboxobj->num(5)); + aabb.a = glm::vec3(boxobj->num(0), boxobj->num(1), boxobj->num(2)); + aabb.b = glm::vec3(boxobj->num(3), boxobj->num(4), boxobj->num(5)); aabb.b += aabb.a; } @@ -96,35 +91,17 @@ Block* ContentLoader::loadBlock(string name, path file) { } void ContentLoader::load(ContentBuilder* builder) { - cout << "-- loading content " << folder << endl; + std::cout << "-- loading pack [" << pack->id << "]" << std::endl; - path file = folder / path("package.json"); - string source = files::read_string(file); - - unique_ptr root = nullptr; - try { - root.reset(json::parse(file.filename().string(), source)); - } catch (const parsing_error& error) { - cerr << error.errorLog() << endl; - throw std::runtime_error("could not load content package"); - } - - string id; - string version; - root->str("id", id); - root->str("version", version); - - cout << " id: " << id << endl; - cout << " version: " << version << endl; + auto folder = pack->folder; + auto root = files::read_json(pack->getContentFile()); json::JArray* blocksarr = root->arr("blocks"); if (blocksarr) { - cout << " blocks: " << blocksarr->size() << endl; for (uint i = 0; i < blocksarr->size(); i++) { - string name = blocksarr->str(i); - cout << " loading block " << id << ":" << name << endl; - path blockfile = folder/path("blocks/"+name+".json"); - builder->add(loadBlock(id+":"+name, blockfile)); + std::string name = blocksarr->str(i); + fs::path blockfile = folder/fs::path("blocks/"+name+".json"); + builder->add(loadBlock(pack->id+":"+name, blockfile)); } } } diff --git a/src/content/ContentLoader.h b/src/content/ContentLoader.h index 5395b288..25559d82 100644 --- a/src/content/ContentLoader.h +++ b/src/content/ContentLoader.h @@ -5,12 +5,13 @@ #include class Block; +class ContentPack; class ContentBuilder; class ContentLoader { - std::filesystem::path folder; + const ContentPack* pack; public: - ContentLoader(std::filesystem::path folder); + ContentLoader(const ContentPack* pack); Block* loadBlock(std::string name, std::filesystem::path file); void load(ContentBuilder* builder); diff --git a/src/content/ContentPack.cpp b/src/content/ContentPack.cpp index 8318e5c8..e8de0784 100644 --- a/src/content/ContentPack.cpp +++ b/src/content/ContentPack.cpp @@ -1 +1,46 @@ #include "ContentPack.h" + +#include + +#include "../files/files.h" +#include "../coders/json.h" + +namespace fs = std::filesystem; + +const std::string ContentPack::PACKAGE_FILENAME = "package.json"; +const std::string ContentPack::CONTENT_FILENAME = "content.json"; + +std::filesystem::path ContentPack::getContentFile() const { + return folder/fs::path(CONTENT_FILENAME); +} + +bool ContentPack::is_pack(std::filesystem::path folder) { + return fs::is_regular_file(folder/fs::path(PACKAGE_FILENAME)); +} + +ContentPack ContentPack::read(std::filesystem::path folder) { + auto root = files::read_json(folder/fs::path(PACKAGE_FILENAME)); + ContentPack pack; + root->str("id", pack.id); + root->str("title", pack.title); + root->str("version", pack.version); + pack.folder = folder; + if (pack.id == "none") + throw std::runtime_error("content-pack id is none: "+folder.u8string()); + return pack; +} + +void ContentPack::scan(fs::path rootfolder, + std::vector& packs) { + if (!fs::is_directory(rootfolder)) { + return; + } + for (auto entry : fs::directory_iterator(rootfolder)) { + fs::path folder = entry.path(); + if (!fs::is_directory(folder)) + continue; + if (!is_pack(folder)) + continue; + packs.push_back(read(folder)); + } +} diff --git a/src/content/ContentPack.h b/src/content/ContentPack.h index 08ab5b81..4c15fe27 100644 --- a/src/content/ContentPack.h +++ b/src/content/ContentPack.h @@ -2,11 +2,23 @@ #define CONTENT_CONTENT_PACK_H_ #include +#include #include struct ContentPack { - std::string id; + std::string id = "none"; + std::string title = "untitled"; + std::string version = "0.0"; std::filesystem::path folder; + + std::filesystem::path getContentFile() const; + + static const std::string PACKAGE_FILENAME; + static const std::string CONTENT_FILENAME; + static bool is_pack(std::filesystem::path folder); + static ContentPack read(std::filesystem::path folder); + static void scan(std::filesystem::path folder, + std::vector& packs); }; #endif // CONTENT_CONTENT_PACK_H_ diff --git a/src/engine.cpp b/src/engine.cpp index b0d75ba2..a4d46fa1 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -51,7 +51,7 @@ Engine::Engine(EngineSettings& settings, EnginePaths* paths) } auto resdir = paths->getResources(); - contentPacks.push_back({"base", resdir/path("content/base")}); + contentPacks.push_back(ContentPack::read(resdir/path("content/base"))); loadContent(); Audio::initialize(); @@ -160,7 +160,7 @@ void Engine::loadContent() { vector resRoots; for (auto& pack : contentPacks) { - ContentLoader loader(pack.folder); + ContentLoader loader(&pack); loader.load(&contentBuilder); resRoots.push_back(pack.folder); } diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index 68fd396c..a3f625ec 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -44,6 +44,7 @@ Panel* create_controls_panel(Engine* engine, PagesControl* menu); Panel* create_settings_panel(Engine* engine, PagesControl* menu); Panel* create_pause_panel(Engine* engine, PagesControl* menu); Panel* create_languages_panel(Engine* engine, PagesControl* menu); +Panel* create_content_panel(Engine* engine, PagesControl* menu); void menus::create_menus(Engine* engine, PagesControl* menu) { menu->add("new-world", create_new_world_panel(engine, menu)); @@ -51,6 +52,7 @@ void menus::create_menus(Engine* engine, PagesControl* menu) { menu->add("controls", create_controls_panel(engine, menu)); menu->add("pause", create_pause_panel(engine, menu)); menu->add("languages", create_languages_panel(engine, menu)); + menu->add("content", create_content_panel(engine, menu)); menu->add("main", create_main_menu_panel(engine, menu)); } @@ -91,7 +93,6 @@ void show_content_missing(GUI* gui, const Content* content, ContentLUT* lut) { panel->add((new Button(langs::get(L"Back to Main Menu", L"menu"), vec4(8.0f)))->listenAction([=](GUI*){ menu->back(); })); - panel->refresh(); menu->add("missing-content", panel); menu->set("missing-content"); } @@ -132,7 +133,6 @@ Panel* create_languages_panel(Engine* engine, PagesControl* menu) { panel->add(button); } panel->add(guiutil::backButton(menu)); - panel->refresh(); return panel; } @@ -181,10 +181,20 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) { } panel->add(worldsPanel); panel->add(guiutil::gotoButton(langs::get(L"Settings", L"menu"), "settings", menu)); + panel->add(guiutil::gotoButton(langs::get(L"Content", L"menu"), "content", menu)); panel->add((new Button(langs::get(L"Quit", L"menu"), vec4(10.f)))->listenAction([](GUI* gui) { Window::setShouldClose(true); })); - panel->refresh(); + return panel; +} + +Panel* create_content_panel(Engine* engine, PagesControl* menu) { + Panel* panel = new Panel(vec2(400, 200), vec4(5.0f), 5.0f); + panel->color(vec4(0.0f)); + + panel->add(new Label(L"work in progress")); + + panel->add(guiutil::backButton(menu)); return panel; } @@ -271,7 +281,6 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) { } panel->add(guiutil::backButton(menu)); - panel->refresh(); return panel; } @@ -315,9 +324,7 @@ Panel* create_controls_panel(Engine* engine, PagesControl* menu) { scrollPanel->add(subpanel); } panel->add(scrollPanel); - panel->add(guiutil::backButton(menu)); - panel->refresh(); return panel; } @@ -439,7 +446,6 @@ Panel* create_settings_panel(Engine* engine, PagesControl* menu) { panel->add(guiutil::gotoButton(langs::get(L"Controls", L"menu"), "controls", menu)); panel->add(guiutil::backButton(menu)); - panel->refresh(); return panel; } diff --git a/src/voxel_engine.cpp b/src/voxel_engine.cpp index 3c3409f1..cc091677 100644 --- a/src/voxel_engine.cpp +++ b/src/voxel_engine.cpp @@ -34,8 +34,8 @@ int main(int argc, char** argv) { toml::Reader reader(wrapper.get(), settings_file.string(), text); reader.read(); } + setup_bindings(); Engine engine(settings, &paths); - setup_bindings(); if (std::filesystem::is_regular_file(controls_file)) { std::cout << "-- loading controls" << std::endl; std::string text = files::read_string(controls_file);