diff --git a/doc/en/scripting/builtins/libpack.md b/doc/en/scripting/builtins/libpack.md index 0fbc4b158..aab6e11d1 100644 --- a/doc/en/scripting/builtins/libpack.md +++ b/doc/en/scripting/builtins/libpack.md @@ -95,3 +95,9 @@ Returns information about the pack (not necessarily installed). - `?` - optional - `~` - weak for example `!teal` + +To obtain information about multiple packs, use table of ids to avoid re-scanning. + +```lua +pack.get_info(packids: table) -> {id={...}, id2={...}, ...} +``` diff --git a/doc/ru/scripting/builtins/libpack.md b/doc/ru/scripting/builtins/libpack.md index 543ea7a35..c3591584e 100644 --- a/doc/ru/scripting/builtins/libpack.md +++ b/doc/ru/scripting/builtins/libpack.md @@ -63,7 +63,7 @@ pack.get_base_packs() -> массив строк Возвращает id всех базовых паков (неудаляемых) -```python +```lua pack.get_info(packid: str) -> { id: str, title: str, @@ -82,3 +82,10 @@ pack.get_info(packid: str) -> { - `?` - optional - `~` - weak например `!teal` + +Для получения информации о нескольких паках используйте таблицу id, чтобы не +производить сканирование для каждого пака. + +```lua +pack.get_info(packids: table) -> {id={...}, id2={...}, ...} +``` diff --git a/src/logic/scripting/lua/libs/libpack.cpp b/src/logic/scripting/lua/libs/libpack.cpp index c436ec4e9..d48b54d46 100644 --- a/src/logic/scripting/lua/libs/libpack.cpp +++ b/src/logic/scripting/lua/libs/libpack.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "assets/AssetsLoader.hpp" #include "content/Content.hpp" @@ -123,6 +124,44 @@ static int l_pack_get_info( return 1; } +static int pack_get_infos(lua::State* L) { + std::set ids; + size_t len = lua::objlen(L, 1); + for (size_t i = 1; i <= len; i++) { + lua::rawgeti(L, i); + ids.insert(lua::require_string(L, -1)); + lua::pop(L, 1); + } + std::unordered_map packs; + auto content = engine->getContent(); + const auto& loadedPacks = engine->getContentPacks(); + for (const auto& pack : loadedPacks) { + if (ids.find(pack.id) != ids.end()) { + packs[pack.id] = pack; + ids.erase(pack.id); + } + } + if (!ids.empty()) { + fs::path worldFolder(""); + if (level) { + worldFolder = level->getWorld()->wfile->getFolder(); + } + auto manager = engine->createPacksManager(worldFolder); + manager.scan(); + auto vec = + manager.getAll(std::vector(ids.begin(), ids.end())); + for (const auto& pack : vec) { + packs[pack.id] = pack; + } + } + lua::createtable(L, 0, packs.size()); + for (const auto& [id, pack] : packs) { + l_pack_get_info(L, pack, content); + lua::setfield(L, id); + } + return 1; +} + /// @brief pack.get_info(packid: str) -> { /// title: str, /// creator: str, @@ -131,6 +170,11 @@ static int l_pack_get_info( /// [optional] has_indices: bool /// } or nil static int l_pack_get_info(lua::State* L) { + if (lua::istable(L, 1)) { + return pack_get_infos(L); + } else if (!lua::isstring(L, 1)) { + throw std::runtime_error("string or table expected"); + } auto packid = lua::tostring(L, 1); auto content = engine->getContent(); @@ -140,7 +184,6 @@ static int l_pack_get_info(lua::State* L) { return pack.id == packid; }); if (found == packs.end()) { - // TODO: optimize fs::path worldFolder(""); if (level) { worldFolder = level->getWorld()->wfile->getFolder();