From a641099d36a0f75bf0aaf94e7efe77e67b7e3db9 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 08:56:59 +0300 Subject: [PATCH 1/7] feat: load block and item scripts after content load --- src/content/ContentLoader.cpp | 49 ++++++++++++++++++------------- src/content/ContentLoader.hpp | 3 ++ src/engine.cpp | 4 ++- src/logic/scripting/scripting.cpp | 11 ++++--- src/logic/scripting/scripting.hpp | 6 ++-- 5 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index cb50e4a5..baf5e06e 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -483,16 +483,6 @@ void ContentLoader::loadBlock( auto configFile = folder / fs::path("blocks/" + name + ".json"); if (fs::exists(configFile)) loadBlock(def, full, configFile); - auto scriptfile = folder / fs::path("scripts/" + def.scriptName + ".lua"); - if (fs::is_regular_file(scriptfile)) { - scripting::load_block_script( - env, - full, - scriptfile, - pack->id + ":scripts/" + def.scriptName + ".lua", - def.rt.funcsset - ); - } if (!def.hidden) { auto& item = builder.items.create(full + BLOCK_ITEM_SUFFIX); item.generated = true; @@ -514,17 +504,6 @@ void ContentLoader::loadItem( auto folder = pack->folder; auto configFile = folder / fs::path("items/" + name + ".json"); if (fs::exists(configFile)) loadItem(def, full, configFile); - - auto scriptfile = folder / fs::path("scripts/" + def.scriptName + ".lua"); - if (fs::is_regular_file(scriptfile)) { - scripting::load_item_script( - env, - full, - scriptfile, - pack->id + ":scripts/" + def.scriptName + ".lua", - def.rt.funcsset - ); - } } static std::tuple create_unit_id( @@ -825,6 +804,34 @@ void ContentLoader::load() { } } +template +static void load_scripts(Content& content, ContentUnitDefs& units) { + for (const auto& [name, def] : units.getDefs()) { + size_t pos = name.find(':'); + if (pos == std::string::npos) { + throw std::runtime_error("invalid content unit name"); + } + const auto runtime = content.getPackRuntime(name.substr(0, pos)); + const auto& pack = runtime->getInfo(); + const auto& folder = pack.folder; + auto scriptfile = folder / fs::path("scripts/" + def->scriptName + ".lua"); + if (fs::is_regular_file(scriptfile)) { + scripting::load_content_script( + runtime->getEnvironment(), + name, + scriptfile, + pack.id + ":scripts/" + def->scriptName + ".lua", + def->rt.funcsset + ); + } + } +} + +void ContentLoader::loadScripts(Content& content) { + load_scripts(content, content.blocks); + load_scripts(content, content.items); +} + void ContentLoader::loadResources(ResourceType type, const dv::value& list) { for (size_t i = 0; i < list.size(); i++) { builder.resourceIndices[static_cast(type)].add( diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp index 22cb33ef..d99aa622 100644 --- a/src/content/ContentLoader.hpp +++ b/src/content/ContentLoader.hpp @@ -17,6 +17,7 @@ struct ContentPack; struct GeneratorDef; class ResPaths; +class Content; class ContentBuilder; class ContentPackRuntime; struct ContentPackStats; @@ -76,4 +77,6 @@ public: void fixPackIndices(); void load(); + + static void loadScripts(Content& content); }; diff --git a/src/engine.cpp b/src/engine.cpp index 85a9e42b..f08175a1 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -361,8 +361,10 @@ void Engine::loadContent() { ContentLoader(&pack, contentBuilder, *resPaths).load(); load_configs(pack.folder); } - content = contentBuilder.build(); + scripting::on_content_load(content.get()); + + ContentLoader::loadScripts(*content); langs::setup(resdir, langs::current->getId(), contentPacks); loadAssets(); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index f0082a3c..77f15473 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -157,10 +157,13 @@ void scripting::process_post_runnables() { } } +void scripting::on_content_load(Content* content) { + scripting::content = content; + scripting::indices = content->getIndices(); +} + void scripting::on_world_load(LevelController* controller) { scripting::level = controller->getLevel(); - scripting::content = level->content; - scripting::indices = level->content->getIndices(); scripting::blocks = controller->getBlocksController(); scripting::controller = controller; @@ -671,7 +674,7 @@ int scripting::get_values_on_stack() { return lua::gettop(lua::get_main_state()); } -void scripting::load_block_script( +void scripting::load_content_script( const scriptenv& senv, const std::string& prefix, const fs::path& file, @@ -692,7 +695,7 @@ void scripting::load_block_script( register_event(env, "on_blocks_tick", prefix + ".blockstick"); } -void scripting::load_item_script( +void scripting::load_content_script( const scriptenv& senv, const std::string& prefix, const fs::path& file, diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index ca0ea433..3cd8a022 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -45,6 +45,8 @@ namespace scripting { void initialize(Engine* engine); + void on_content_load(Content* content); + bool register_event( int env, const std::string& name, const std::string& id ); @@ -128,7 +130,7 @@ namespace scripting { /// @param file item script file /// @param fileName script file path using the engine format /// @param funcsset block callbacks set - void load_block_script( + void load_content_script( const scriptenv& env, const std::string& prefix, const fs::path& file, @@ -142,7 +144,7 @@ namespace scripting { /// @param file item script file /// @param fileName script file path using the engine format /// @param funcsset item callbacks set - void load_item_script( + void load_content_script( const scriptenv& env, const std::string& prefix, const fs::path& file, From 8543be87dfb426ec0e410a1885bf1842afab67c2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 09:36:48 +0300 Subject: [PATCH 2/7] add block.materials table --- src/logic/scripting/scripting.cpp | 12 ++++++++++++ src/voxels/Block.cpp | 9 +++++++++ src/voxels/Block.hpp | 2 ++ 3 files changed, 23 insertions(+) diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 77f15473..0778fd45 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -160,6 +160,18 @@ void scripting::process_post_runnables() { void scripting::on_content_load(Content* content) { scripting::content = content; scripting::indices = content->getIndices(); + + auto L = lua::get_main_state(); + if (lua::getglobal(L, "block")) { + const auto& materials = content->getBlockMaterials(); + lua::createtable(L, 0, materials.size()); + for (const auto& [name, material] : materials) { + lua::pushvalue(L, material->serialize()); + lua::setfield(L, name); + } + lua::setfield(L, "materials"); + lua::pop(L); + } } void scripting::on_world_load(LevelController* controller) { diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index 6d4ff761..520f9f99 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -8,6 +8,15 @@ #include "presets/ParticlesPreset.hpp" #include "util/stringutil.hpp" +dv::value BlockMaterial::serialize() const { + return dv::object({ + {"name", name}, + {"stepsSound", stepsSound}, + {"placeSound", placeSound}, + {"breakSound", breakSound} + }); +} + std::string to_string(BlockModel model) { switch (model) { case BlockModel::none: diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 84835534..4fe51b0d 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -104,6 +104,8 @@ struct BlockMaterial { std::string stepsSound {""}; std::string placeSound {""}; std::string breakSound {""}; + + dv::value serialize() const; }; /// @brief Block properties definition From 0ec081a3ae4d0a3bda531ce0ae613847d9795cff Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 09:47:43 +0300 Subject: [PATCH 3/7] feat: load world scripts after content load --- src/content/ContentLoader.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index baf5e06e..6c94076d 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -707,18 +707,6 @@ void ContentLoader::load() { auto folder = pack->folder; - // Load main world script - fs::path scriptFile = folder / fs::path("scripts/world.lua"); - if (fs::is_regular_file(scriptFile)) { - scripting::load_world_script( - env, - pack->id, - scriptFile, - pack->id + ":scripts/world.lua", - runtime->worldfuncsset - ); - } - // Load world generators fs::path generatorsDir = folder / fs::u8path("generators"); foreach_file(generatorsDir, [this](const fs::path& file) { @@ -830,6 +818,21 @@ static void load_scripts(Content& content, ContentUnitDefs& units) { void ContentLoader::loadScripts(Content& content) { load_scripts(content, content.blocks); load_scripts(content, content.items); + + for (const auto& [packid, runtime] : content.getPacks()) { + const auto& pack = runtime->getInfo(); + // Load main world script + fs::path scriptFile = pack.folder / fs::path("scripts/world.lua"); + if (fs::is_regular_file(scriptFile)) { + scripting::load_world_script( + runtime->getEnvironment(), + pack.id, + scriptFile, + pack.id + ":scripts/world.lua", + runtime->worldfuncsset + ); + } + } } void ContentLoader::loadResources(ResourceType type, const dv::value& list) { From a200c3988b30b57e23546a5c3074378b7d684dc4 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 09:51:34 +0300 Subject: [PATCH 4/7] feat: load entity components after content load --- src/content/ContentLoader.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 6c94076d..0f8bf6a2 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -774,17 +774,6 @@ void ContentLoader::load() { ); }); - // Load entity components - fs::path componentsDir = folder / fs::u8path("scripts/components"); - foreach_file(componentsDir, [this](const fs::path& file) { - auto name = pack->id + ":" + file.stem().u8string(); - scripting::load_entity_component( - name, - file, - pack->id + ":scripts/components/" + file.filename().u8string() - ); - }); - // Process content.json and load defined content units auto contentFile = pack->getContentFile(); if (fs::exists(contentFile)) { @@ -821,8 +810,10 @@ void ContentLoader::loadScripts(Content& content) { for (const auto& [packid, runtime] : content.getPacks()) { const auto& pack = runtime->getInfo(); + const auto& folder = pack.folder; + // Load main world script - fs::path scriptFile = pack.folder / fs::path("scripts/world.lua"); + fs::path scriptFile = folder / fs::path("scripts/world.lua"); if (fs::is_regular_file(scriptFile)) { scripting::load_world_script( runtime->getEnvironment(), @@ -832,6 +823,16 @@ void ContentLoader::loadScripts(Content& content) { runtime->worldfuncsset ); } + // Load entity components + fs::path componentsDir = folder / fs::u8path("scripts/components"); + foreach_file(componentsDir, [&pack](const fs::path& file) { + auto name = pack.id + ":" + file.stem().u8string(); + scripting::load_entity_component( + name, + file, + pack.id + ":scripts/components/" + file.filename().u8string() + ); + }); } } From ea2f7ede0d4b58c41bb27481c588df8d1fd5df5d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 10:02:18 +0300 Subject: [PATCH 5/7] update doc/*/scripting/builtins/libblock.md --- doc/en/scripting/builtins/libblock.md | 3 +++ doc/ru/scripting/builtins/libblock.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index cc86b9a6..5bd0536e 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -10,6 +10,9 @@ block.index(name: str) -> int -- Returns the id of the block material. block.material(blockid: int) -> str +-- Table of materials by their full names (example: base:carpet) +block.materials: table + -- Returns the block display name. block.caption(blockid: int) -> str diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index e7746a37..19a28198 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -10,6 +10,9 @@ block.index(name: str) -> int -- Возвращает id материала блока. block.material(blockid: int) -> str +-- Таблица материалов по их полным именам (пример: base:carpet) +block.materials: table + -- Возвращает название блока, отображаемое в интерфейсе. block.caption(blockid: int) -> str From f2e7a54180c4186e3d2f9cc31c925a4e149f85d2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 12:31:45 +0300 Subject: [PATCH 6/7] add on_replaced block event and on_block_replaced world event --- doc/en/scripting/events.md | 6 ++++++ doc/ru/scripting/events.md | 6 ++++++ src/content/ContentPack.hpp | 1 + src/logic/BlocksController.cpp | 7 +++++++ src/logic/scripting/scripting.cpp | 30 ++++++++++++++++++++++++++++++ src/logic/scripting/scripting.hpp | 3 +++ src/voxels/Block.hpp | 1 + 7 files changed, 54 insertions(+) diff --git a/doc/en/scripting/events.md b/doc/en/scripting/events.md index 8dcd1a06..4b13ec7b 100644 --- a/doc/en/scripting/events.md +++ b/doc/en/scripting/events.md @@ -16,6 +16,12 @@ function on_broken(x, y, z, playerid) Called on block broken by player +```lua +function on_replaced(x, y, z, playerid) +``` + +Called on block replaced with other by player + ```lua function on_interact(x, y, z, playerid) -> bool ``` diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 6d908459..08192cfa 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -16,6 +16,12 @@ function on_broken(x, y, z, playerid) Вызывается после разрушения блока игроком +```lua +function on_replaced(x, y, z, playerid) +``` + +Вызывается после замены блока игроком + ```lua function on_interact(x, y, z, playerid) -> bool ``` diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index b790d0e7..857f4fe0 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -97,6 +97,7 @@ struct ContentPackStats { struct world_funcs_set { bool onblockplaced : 1; + bool onblockreplaced : 1; bool onblockbroken : 1; bool onblockinteract : 1; bool onplayertick : 1; diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index 01679546..980c8bfe 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -75,6 +75,13 @@ void BlocksController::breakBlock( void BlocksController::placeBlock( Player* player, const Block& def, blockstate state, int x, int y, int z ) { + auto voxel = chunks.get(x, y, z); + if (voxel == nullptr) { + return; + } + const auto& prevDef = level.content->getIndices()->blocks.require(voxel->id); + scripting::on_block_replaced(player, prevDef, {x, y, z}); + onBlockInteraction( player, glm::ivec3(x, y, z), def, BlockInteraction::placing ); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 0778fd45..055ecf34 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -284,6 +284,32 @@ void scripting::on_block_placed( } } +void scripting::on_block_replaced( + Player* player, const Block& block, const glm::ivec3& pos +) { + if (block.rt.funcsset.onreplaced) { + std::string name = block.name + ".replaced"; + lua::emit_event(lua::get_main_state(), name, [pos, player](auto L) { + lua::pushivec_stack(L, pos); + lua::pushinteger(L, player ? player->getId() : -1); + return 4; + }); + } + auto args = [&](lua::State* L) { + lua::pushinteger(L, block.rt.id); + lua::pushivec_stack(L, pos); + lua::pushinteger(L, player ? player->getId() : -1); + return 5; + }; + for (auto& [packid, pack] : content->getPacks()) { + if (pack->worldfuncsset.onblockreplaced) { + lua::emit_event( + lua::get_main_state(), packid + ":.blockreplaced", args + ); + } + } +} + void scripting::on_block_broken( Player* player, const Block& block, const glm::ivec3& pos ) { @@ -701,6 +727,8 @@ void scripting::load_content_script( register_event(env, "on_random_update", prefix + ".randupdate"); funcsset.onbroken = register_event(env, "on_broken", prefix + ".broken"); funcsset.onplaced = register_event(env, "on_placed", prefix + ".placed"); + funcsset.onreplaced = + register_event(env, "on_replaced", prefix + ".replaced"); funcsset.oninteract = register_event(env, "on_interact", prefix + ".interact"); funcsset.onblockstick = @@ -752,6 +780,8 @@ void scripting::load_world_script( register_event(env, "on_block_placed", prefix + ":.blockplaced"); funcsset.onblockbroken = register_event(env, "on_block_broken", prefix + ":.blockbroken"); + funcsset.onblockreplaced = + register_event(env, "on_block_replaced", prefix + ":.blockreplaced"); funcsset.onblockinteract = register_event(env, "on_block_interact", prefix + ":.blockinteract"); funcsset.onplayertick = diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index 3cd8a022..0ab3c035 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -71,6 +71,9 @@ namespace scripting { void on_block_placed( Player* player, const Block& block, const glm::ivec3& pos ); + void on_block_replaced( + Player* player, const Block& block, const glm::ivec3& pos + ); void on_block_broken( Player* player, const Block& block, const glm::ivec3& pos ); diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index 4fe51b0d..95768c88 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -39,6 +39,7 @@ struct block_funcs_set { bool update : 1; bool onplaced : 1; bool onbroken : 1; + bool onreplaced : 1; bool oninteract : 1; bool randupdate : 1; bool onblockstick : 1; From 7f41f95013d2fb7e44e4f43165aed180364154bc Mon Sep 17 00:00:00 2001 From: MihailRis Date: Fri, 22 Nov 2024 14:08:01 +0300 Subject: [PATCH 7/7] add version to world info --- doc/en/scripting/builtins/libworld.md | 2 ++ doc/ru/scripting/builtins/libworld.md | 4 +++- res/layouts/pages/worlds.xml.lua | 7 ++++++ res/layouts/templates/world.xml | 1 + src/logic/scripting/lua/libs/libcore.cpp | 7 ++++++ src/logic/scripting/lua/libs/libworld.cpp | 26 +++++++++++++++++------ 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/doc/en/scripting/builtins/libworld.md b/doc/en/scripting/builtins/libworld.md index 349e9106..5bf01abb 100644 --- a/doc/en/scripting/builtins/libworld.md +++ b/doc/en/scripting/builtins/libworld.md @@ -10,6 +10,8 @@ world.get_list() -> tables array { name: str, -- world icon/preview (loading automatically) icon: str + -- engine version the world was saved on + version: {int, int} } -- Returns current day time in range \[0.0-1.0\] diff --git a/doc/ru/scripting/builtins/libworld.md b/doc/ru/scripting/builtins/libworld.md index b82f3b53..9d7d635e 100644 --- a/doc/ru/scripting/builtins/libworld.md +++ b/doc/ru/scripting/builtins/libworld.md @@ -9,7 +9,9 @@ world.get_list() -> массив таблиц { -- название мира name: str, -- предпросмотр (автоматически загружаемая текстура) - icon: str + icon: str, + -- версия движка, на которой был сохранен мир + version: {int, int} } -- Возвращает текущее игровое время от 0.0 до 1.0, где 0.0 и 1.0 - полночь, 0.5 - полдень. diff --git a/res/layouts/pages/worlds.xml.lua b/res/layouts/pages/worlds.xml.lua index 37c348a9..1cbcd53d 100644 --- a/res/layouts/pages/worlds.xml.lua +++ b/res/layouts/pages/worlds.xml.lua @@ -1,6 +1,13 @@ function on_open() local worlds = world.get_list() for _, info in ipairs(worlds) do + local major, minor = core.get_version() + if info.version[1] > major or info.version[2] > minor then + info.versionColor = "#A02010" + else + info.versionColor = "#808080" + end + info.versionString = string.format("%s.%s", unpack(info.version)) document.worlds:add(gui.template("world", info)) end end diff --git a/res/layouts/templates/world.xml b/res/layouts/templates/world.xml index c20223fc..a258604b 100644 --- a/res/layouts/templates/world.xml +++ b/res/layouts/templates/world.xml @@ -14,4 +14,5 @@ onclick='core.delete_world("%{name}")'> + diff --git a/src/logic/scripting/lua/libs/libcore.cpp b/src/logic/scripting/lua/libs/libcore.cpp index 5a100b9c..c656d0e6 100644 --- a/src/logic/scripting/lua/libs/libcore.cpp +++ b/src/logic/scripting/lua/libs/libcore.cpp @@ -20,6 +20,12 @@ using namespace scripting; +static int l_get_version(lua::State* L) { + return lua::pushvec_stack( + L, glm::vec2(ENGINE_VERSION_MAJOR, ENGINE_VERSION_MINOR) + ); +} + /// @brief Creating new world /// @param name Name world /// @param seed Seed world @@ -239,6 +245,7 @@ static int l_quit(lua::State*) { } const luaL_Reg corelib[] = { + {"get_version", lua::wrap}, {"new_world", lua::wrap}, {"open_world", lua::wrap}, {"reopen_world", lua::wrap}, diff --git a/src/logic/scripting/lua/libs/libworld.cpp b/src/logic/scripting/lua/libs/libworld.cpp index 06da877c..5422c873 100644 --- a/src/logic/scripting/lua/libs/libworld.cpp +++ b/src/logic/scripting/lua/libs/libworld.cpp @@ -4,7 +4,9 @@ #include "assets/Assets.hpp" #include "assets/AssetsLoader.hpp" +#include "coders/json.hpp" #include "engine.hpp" +#include "files/files.hpp" #include "files/engine_paths.hpp" #include "world/Level.hpp" #include "world/World.hpp" @@ -32,22 +34,34 @@ static int l_get_list(lua::State* L) { for (size_t i = 0; i < worlds.size(); i++) { lua::createtable(L, 0, 1); - auto name = worlds[i].filename().u8string(); + const auto& folder = worlds[i]; + + auto root = json::parse(files::read_string(folder/fs::u8path("world.json"))); + const auto& versionMap = root["version"]; + int versionMajor = versionMap["major"].asInteger(); + int versionMinor = versionMap["minor"].asInteger(); + + + auto name = folder.filename().u8string(); lua::pushstring(L, name); lua::setfield(L, "name"); auto assets = engine->getAssets(); std::string icon = "world#" + name + ".icon"; if (!AssetsLoader::loadExternalTexture( - assets, - icon, - {worlds[i] / fs::path("icon.png"), - worlds[i] / fs::path("preview.png")} - )) { + assets, + icon, + {worlds[i] / fs::path("icon.png"), + worlds[i] / fs::path("preview.png")} + )) { icon = "gui/no_world_icon"; } lua::pushstring(L, icon); lua::setfield(L, "icon"); + + lua::pushvec2(L, {versionMajor, versionMinor}); + lua::setfield(L, "version"); + lua::rawseti(L, i + 1); } return 1;