diff --git a/res/layouts/pages/generators.xml.lua b/res/layouts/pages/generators.xml.lua
index 04c1d8bb..19e3ce60 100644
--- a/res/layouts/pages/generators.xml.lua
+++ b/res/layouts/pages/generators.xml.lua
@@ -5,11 +5,11 @@ function on_open()
table.sort(names)
local panel = document.root
- for _,k in ipairs(names) do
+ for k, caption in pairs(names) do
panel:add(gui.template("generator", {
callback=string.format("settings.generator=%q menu:back()", k),
id=k,
- name=settings.generator_name(k)
+ name=settings.generator_name(caption)
}))
end
panel:add("")
diff --git a/res/layouts/pages/new_world.xml.lua b/res/layouts/pages/new_world.xml.lua
index e92d5ae0..5c0c1480 100644
--- a/res/layouts/pages/new_world.xml.lua
+++ b/res/layouts/pages/new_world.xml.lua
@@ -10,12 +10,7 @@ function save_state()
end
function settings.generator_name(id)
- local prefix, name = parse_path(id)
- if prefix == "core" then
- return gui.str(name, "world.generators")
- else
- return id
- end
+ return gui.str(id, "world.generators"):gsub("^%l", string.upper)
end
function create_world()
@@ -39,7 +34,7 @@ function on_open()
document.generator_btn.text = string.format(
"%s: %s",
gui.str("World generator", "world"),
- settings.generator_name(settings.generator)
+ settings.generator_name(generation.get_generators()[settings.generator])
)
document.name_box.text = settings.name or ''
document.seed_box.text = settings.seed or ''
diff --git a/res/texts/ru_RU.txt b/res/texts/ru_RU.txt
index fbae5756..cd2168b2 100644
--- a/res/texts/ru_RU.txt
+++ b/res/texts/ru_RU.txt
@@ -42,7 +42,7 @@ menu.Contents Menu=Меню контентпаков
world.Seed=Зерно
world.Name=Название
world.World generator=Генератор мира
-world.generators.default=Обычный
+world.generators.default=По-умолчанию
world.generators.flat=Плоский
world.Create World=Создать Мир
world.convert-request=Есть изменения в индексах! Конвертировать мир?
diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp
index bc03b810..89fabec0 100644
--- a/src/content/ContentLoader.cpp
+++ b/src/content/ContentLoader.cpp
@@ -54,7 +54,9 @@ static void detect_defs(
continue;
}
if (fs::is_regular_file(file) && files::is_data_file(file)) {
- detected.push_back(prefix.empty() ? name : prefix + ":" + name);
+ auto map = files::read_object(file);
+ std::string id = prefix.empty() ? name : prefix + ":" + name;
+ detected.emplace_back(id);
} else if (fs::is_directory(file) &&
file.extension() != fs::u8path(".files")) {
detect_defs(file, name, detected);
@@ -63,11 +65,38 @@ static void detect_defs(
}
}
-std::vector ContentLoader::scanContent(
+static void detect_defs_pairs(
+ const fs::path& folder,
+ const std::string& prefix,
+ std::vector>& detected
+) {
+ if (fs::is_directory(folder)) {
+ for (const auto& entry : fs::directory_iterator(folder)) {
+ const fs::path& file = entry.path();
+ std::string name = file.stem().string();
+ if (name[0] == '_') {
+ continue;
+ }
+ if (fs::is_regular_file(file) && files::is_data_file(file)) {
+ auto map = files::read_object(file);
+ std::string id = prefix.empty() ? name : prefix + ":" + name;
+ std::string caption = util::id_to_caption(id);
+ map.at("caption").get(caption);
+ detected.emplace_back(id, name);
+ } else if (fs::is_directory(file) &&
+ file.extension() != fs::u8path(".files")) {
+ detect_defs_pairs(file, name, detected);
+ }
+ }
+ }
+}
+
+std::vector> ContentLoader::scanContent(
const ContentPack& pack, ContentType type
) {
- std::vector detected;
- detect_defs(pack.folder / ContentPack::getFolderFor(type), pack.id, detected);
+ std::vector> detected;
+ detect_defs_pairs(
+ pack.folder / ContentPack::getFolderFor(type), pack.id, detected);
return detected;
}
diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp
index efd54efd..0f904172 100644
--- a/src/content/ContentLoader.hpp
+++ b/src/content/ContentLoader.hpp
@@ -70,7 +70,7 @@ public:
const std::string& contentSection
);
- static std::vector scanContent(
+ static std::vector> scanContent(
const ContentPack& pack, ContentType type
);
diff --git a/src/content/loading/GeneratorLoader.cpp b/src/content/loading/GeneratorLoader.cpp
index 72cd330c..2c38de52 100644
--- a/src/content/loading/GeneratorLoader.cpp
+++ b/src/content/loading/GeneratorLoader.cpp
@@ -193,6 +193,7 @@ void ContentLoader::loadGenerator(
return;
}
auto map = files::read_toml(generatorsDir / fs::u8path(name + ".toml"));
+ map.at("caption").get(def.caption);
map.at("biome_parameters").get(def.biomeParameters);
map.at("biome-bpd").get(def.biomesBPD);
map.at("heights-bpd").get(def.heightsBPD);
diff --git a/src/logic/scripting/lua/libs/libgeneration.cpp b/src/logic/scripting/lua/libs/libgeneration.cpp
index d24fae0c..793dc868 100644
--- a/src/logic/scripting/lua/libs/libgeneration.cpp
+++ b/src/logic/scripting/lua/libs/libgeneration.cpp
@@ -52,10 +52,10 @@ static int l_get_generators(lua::State* L) {
int i = 1;
for (const auto& pack : packs) {
- auto names = ContentLoader::scanContent(pack, ContentType::GENERATOR);
- for (const auto& name : names) {
- lua::pushstring(L, name);
- lua::rawseti(L, i);
+ auto pairs = ContentLoader::scanContent(pack, ContentType::GENERATOR);
+ for (const auto& [name, caption] : pairs) {
+ lua::pushstring(L, caption);
+ lua::setfield(L, name);
i++;
}
}
diff --git a/src/util/stringutil.cpp b/src/util/stringutil.cpp
index d1e5ef9f..c104bd5e 100644
--- a/src/util/stringutil.cpp
+++ b/src/util/stringutil.cpp
@@ -405,6 +405,13 @@ std::wstring util::capitalized(const std::wstring& str) {
str.substr(1);
}
+std::string util::capitalized(const std::string& str) {
+ if (str.empty()) return str;
+ static const std::locale loc("");
+ return std::string({static_cast(std::toupper(str[0], loc))}) +
+ str.substr(1);
+}
+
std::wstring util::pascal_case(const std::wstring& str) {
if (str.empty()) return str;
static const std::locale loc("");
diff --git a/src/util/stringutil.hpp b/src/util/stringutil.hpp
index cb251e83..c7bc2fb5 100644
--- a/src/util/stringutil.hpp
+++ b/src/util/stringutil.hpp
@@ -71,6 +71,8 @@ namespace util {
double parse_double(const std::string& str);
double parse_double(const std::string& str, size_t offset, size_t len);
+ std::string capitalized(const std::string& str);
+
std::wstring lower_case(const std::wstring& str);
std::wstring upper_case(const std::wstring& str);
std::wstring capitalized(const std::wstring& str);
diff --git a/src/world/generator/GeneratorDef.cpp b/src/world/generator/GeneratorDef.cpp
index 515d27e7..1dda81d9 100644
--- a/src/world/generator/GeneratorDef.cpp
+++ b/src/world/generator/GeneratorDef.cpp
@@ -10,8 +10,9 @@ VoxelStructure::VoxelStructure(
std::unique_ptr structure
) : fragments({std::move(structure)}), meta(std::move(meta)) {}
-
-GeneratorDef::GeneratorDef(std::string name) : name(std::move(name)) {}
+GeneratorDef::GeneratorDef(std::string name)
+ : name(std::move(name)), caption(util::id_to_caption(name)) {
+}
void GeneratorDef::prepare(const Content* content) {
for (auto& biome : biomes) {
diff --git a/src/world/generator/GeneratorDef.hpp b/src/world/generator/GeneratorDef.hpp
index 10ab6ff4..d978a41c 100644
--- a/src/world/generator/GeneratorDef.hpp
+++ b/src/world/generator/GeneratorDef.hpp
@@ -192,6 +192,9 @@ struct VoxelStructure {
struct GeneratorDef {
/// @brief Generator full name - packid:name
std::string name;
+ /// @brief Generator display name
+ std::string caption;
+
std::unique_ptr script;
/// @brief Sea level (top of seaLayers)