diff --git a/res/texts/en_US.txt b/res/texts/en_US.txt index 53cee5d6..71db2ddc 100644 --- a/res/texts/en_US.txt +++ b/res/texts/en_US.txt @@ -1,6 +1,7 @@ # Menu menu.missing-content=Missing Content! world.convert-request=Content indices have changed! Convert world files? +error.pack-not-found=Could not to find pack # Bindings movement.forward=Forward diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt index 6fadd6f8..aba6a2df 100644 --- a/res/texts/ru_RU.txt +++ b/res/texts/ru_RU.txt @@ -6,6 +6,8 @@ Cancel=Отмена Back=Назад Continue=Продолжить +error.pack-not-found=Не удалось найти пакет + # Меню menu.New World=Новый Мир menu.Quit=Выход diff --git a/res/texts/su_SU.txt b/res/texts/su_SU.txt index 4e391a07..b57bb587 100644 --- a/res/texts/su_SU.txt +++ b/res/texts/su_SU.txt @@ -6,6 +6,8 @@ Cancel=Отмена Back = Обратно Continue=Продолжить +error.pack-not-found=Не удалось найти пакет + # Меню menu.New World = Новый Мир menu.Quit=Выход diff --git a/src/assets/asset_loaders.cpp b/src/assets/asset_loaders.cpp index 1240d2ce..7b50fd82 100644 --- a/src/assets/asset_loaders.cpp +++ b/src/assets/asset_loaders.cpp @@ -12,17 +12,13 @@ #include "../graphics/Atlas.h" #include "../graphics/Font.h" -using std::string; -using std::vector; -using std::unique_ptr; -using std::filesystem::path; namespace fs = std::filesystem; bool assetload::texture(Assets* assets, const ResPaths* paths, - const string filename, - const string name) { + const std::string filename, + const std::string name) { Texture* texture = png::load_texture(paths->find(filename).string()); if (texture == nullptr) { std::cerr << "failed to load texture '" << name << "'" << std::endl; @@ -34,16 +30,19 @@ bool assetload::texture(Assets* assets, bool assetload::shader(Assets* assets, const ResPaths* paths, - const string filename, - const string name) { - path vertexFile = paths->find(filename+".glslv"); - path fragmentFile = paths->find(filename+".glslf"); + const std::string filename, + const std::string name) { + fs::path vertexFile = paths->find(filename+".glslv"); + fs::path fragmentFile = paths->find(filename+".glslf"); - string vertexSource = files::read_string(vertexFile); - string fragmentSource = files::read_string(fragmentFile); + std::string vertexSource = files::read_string(vertexFile); + std::string fragmentSource = files::read_string(fragmentFile); - Shader* shader = Shader::loadShader(vertexFile.string(), fragmentFile.string(), - vertexSource, fragmentSource); + Shader* shader = Shader::loadShader( + vertexFile.string(), + fragmentFile.string(), + vertexSource, fragmentSource); + if (shader == nullptr) { std::cerr << "failed to load shader '" << name << "'" << std::endl; return false; @@ -54,19 +53,25 @@ bool assetload::shader(Assets* assets, bool assetload::atlas(Assets* assets, const ResPaths* paths, - const string directory, - const string name) { + const std::string directory, + const std::string name) { AtlasBuilder builder; for (const auto& file : paths->listdir(directory)) { - if (file.extension() == ".png") { - string name = file.stem().string(); - if (builder.has(name)) { - continue; // skip duplicates - } - std::unique_ptr image (png::load_image(file.string()));//but what if load_image return nullptr? - image->fixAlphaColor(); - builder.add(name, image.release()); + // png is only supported format + if (file.extension() != ".png") + continue; + std::string name = file.stem().string(); + // skip duplicates + if (builder.has(name)) { + continue; } + std::unique_ptr image (png::load_image(file.string())); + if (image == nullptr) { + std::cerr << "could not to load " << file.string() << std::endl; + continue; + } + image->fixAlphaColor(); + builder.add(name, image.release()); } Atlas* atlas = builder.build(2); assets->store(atlas, name); @@ -75,11 +80,11 @@ bool assetload::atlas(Assets* assets, bool assetload::font(Assets* assets, const ResPaths* paths, - const string filename, - const string name) { - vector pages; + const std::string filename, + const std::string name) { + std::vector pages; for (size_t i = 0; i <= 4; i++) { - string name = filename + "_" + std::to_string(i) + ".png"; + std::string name = filename + "_" + std::to_string(i) + ".png"; name = paths->find(name).string(); Texture* texture = png::load_texture(name); if (texture == nullptr) { diff --git a/src/content/ContentPack.cpp b/src/content/ContentPack.cpp index e8de0784..372ec84a 100644 --- a/src/content/ContentPack.cpp +++ b/src/content/ContentPack.cpp @@ -1,9 +1,11 @@ #include "ContentPack.h" +#include #include -#include "../files/files.h" #include "../coders/json.h" +#include "../files/files.h" +#include "../files/engine_paths.h" namespace fs = std::filesystem; @@ -44,3 +46,21 @@ void ContentPack::scan(fs::path rootfolder, packs.push_back(read(folder)); } } + +std::vector ContentPack::worldPacksList(fs::path folder) { + fs::path listfile = folder / fs::path("packs.list"); + if (!fs::is_regular_file(listfile)) { + std::cerr << "warning: packs.list not found (will be created)"; + std::cerr << std::endl; + files::write_string(listfile, "# autogenerated, do not modify\nbase\n"); + } + return files::read_list(listfile); +} + +fs::path ContentPack::findPack(const EnginePaths* paths, std::string name) { + auto folder = paths->getResources() / fs::path("content") / fs::path(name); + if (!fs::is_directory(folder)) { + throw std::runtime_error("could not to find pack '"+name+"'"); + } + return folder; +} diff --git a/src/content/ContentPack.h b/src/content/ContentPack.h index 4c15fe27..23814d3c 100644 --- a/src/content/ContentPack.h +++ b/src/content/ContentPack.h @@ -5,6 +5,8 @@ #include #include +class EnginePaths; + struct ContentPack { std::string id = "none"; std::string title = "untitled"; @@ -19,6 +21,8 @@ struct ContentPack { static ContentPack read(std::filesystem::path folder); static void scan(std::filesystem::path folder, std::vector& packs); + static std::vector worldPacksList(std::filesystem::path folder); + static std::filesystem::path findPack(const EnginePaths* paths, std::string name); }; #endif // CONTENT_CONTENT_PACK_H_ diff --git a/src/files/files.cpp b/src/files/files.cpp index 399c548e..118e9b2f 100644 --- a/src/files/files.cpp +++ b/src/files/files.cpp @@ -7,15 +7,10 @@ #include #include "../coders/json.h" -using std::ios; -using std::string; -using std::unique_ptr; -using std::ifstream; -using std::ofstream; -using std::filesystem::path; +namespace fs = std::filesystem; -bool files::write_bytes(path filename, const char* data, size_t size) { - ofstream output(filename, ios::binary); +bool files::write_bytes(fs::path filename, const char* data, size_t size) { + std::ofstream output(filename, std::ios::binary); if (!output.is_open()) return false; output.write(data, size); @@ -23,8 +18,8 @@ bool files::write_bytes(path filename, const char* data, size_t size) { return true; } -uint files::append_bytes(path filename, const char* data, size_t size) { - ofstream output(filename, ios::binary | ios::app); +uint files::append_bytes(fs::path filename, const char* data, size_t size) { + std::ofstream output(filename, std::ios::binary | std::ios::app); if (!output.is_open()) return 0; uint position = output.tellp(); @@ -33,8 +28,8 @@ uint files::append_bytes(path filename, const char* data, size_t size) { return position; } -bool files::read(path filename, char* data, size_t size) { - ifstream output(filename, ios::binary); +bool files::read(fs::path filename, char* data, size_t size) { + std::ifstream output(filename, std::ios::binary); if (!output.is_open()) return false; output.read(data, size); @@ -42,31 +37,32 @@ bool files::read(path filename, char* data, size_t size) { return true; } -char* files::read_bytes(path filename, size_t& length) { - ifstream input(filename, ios::binary); +char* files::read_bytes(fs::path filename, size_t& length) { + std::ifstream input(filename, std::ios::binary); if (!input.is_open()) return nullptr; input.seekg(0, std::ios_base::end); length = input.tellg(); input.seekg(0, std::ios_base::beg); - unique_ptr data(new char[length]); + std::unique_ptr data(new char[length]); input.read(data.get(), length); input.close(); return data.release(); } -std::string files::read_string(path filename) { +std::string files::read_string(fs::path filename) { size_t size; - unique_ptr chars (read_bytes(filename, size)); + std::unique_ptr chars (read_bytes(filename, size)); if (chars == nullptr) { - throw std::runtime_error("could not to load file '"+filename.string()+"'"); + throw std::runtime_error("could not to load file '"+ + filename.string()+"'"); } - return string(chars.get(), size); + return std::string(chars.get(), size); } -bool files::write_string(path filename, const string content) { - ofstream file(filename); +bool files::write_string(fs::path filename, const std::string content) { + std::ofstream file(filename); if (!file) { return false; } @@ -74,8 +70,8 @@ bool files::write_string(path filename, const string content) { return true; } -json::JObject* files::read_json(path file) { - string text = files::read_string(file); +json::JObject* files::read_json(fs::path file) { + std::string text = files::read_string(file); try { return json::parse(file.string(), text); } catch (const parsing_error& error) { @@ -83,3 +79,20 @@ json::JObject* files::read_json(path file) { throw std::runtime_error("could not to parse "+file.string()); } } + +std::vector files::read_list(std::filesystem::path filename) { + std::ifstream file(filename); + if (!file) { + throw std::runtime_error("could not to open file "+filename.u8string()); + } + std::vector lines; + std::string line; + while (std::getline(file, line)) { + if (line.length() == 0) + continue; + if (line[0] == '#') + continue; + lines.push_back(line); + } + return lines; +} diff --git a/src/files/files.h b/src/files/files.h index 8442f78b..9285f8c8 100644 --- a/src/files/files.h +++ b/src/files/files.h @@ -2,6 +2,7 @@ #define FILES_FILES_H_ #include +#include #include #include "../typedefs.h" @@ -17,6 +18,7 @@ namespace files { extern std::string read_string(std::filesystem::path filename); extern bool write_string(std::filesystem::path filename, const std::string content); extern json::JObject* read_json(std::filesystem::path file); + extern std::vector read_list(std::filesystem::path file); } #endif /* FILES_FILES_H_ */ \ No newline at end of file diff --git a/src/frontend/menu.cpp b/src/frontend/menu.cpp index e132f8db..18cc149a 100644 --- a/src/frontend/menu.cpp +++ b/src/frontend/menu.cpp @@ -159,15 +159,27 @@ Panel* create_main_menu_panel(Engine* engine, PagesControl* menu) { button->color(vec4(1.0f, 1.0f, 1.0f, 0.1f)); button->listenAction([=](GUI* gui) { // TODO: complete and move somewhere + + auto folder = paths->getWorldsFolder()/u8path(name); auto resdir = engine->getPaths()->getResources(); auto& packs = engine->getContentPacks(); packs.clear(); - packs.push_back(ContentPack::read(resdir/path("content/base"))); + auto packnames = ContentPack::worldPacksList(folder); + for (auto name : packnames) { + path packfolder; + try { + packfolder = ContentPack::findPack(paths, name); + } catch (std::runtime_error& error) { + guiutil::alert(gui, langs::get(L"error.pack-not-found")+ + L": "+util::str2wstr_utf8(name)); + return; + } + packs.push_back(ContentPack::read(packfolder)); + } engine->loadContent(); auto* content = engine->getContent(); auto& settings = engine->getSettings(); - auto folder = paths->getWorldsFolder()/u8path(name); std::filesystem::create_directories(folder); ContentLUT* lut = World::checkIndices(folder, content); if (lut) { @@ -279,7 +291,7 @@ Panel* create_new_world_panel(Engine* engine, PagesControl* menu) { // TODO: complete and move somewhere auto resdir = engine->getPaths()->getResources(); - auto packs = engine->getContentPacks(); + auto& packs = engine->getContentPacks(); packs.clear(); packs.push_back(ContentPack::read(resdir/path("content/base"))); engine->loadContent();