diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mods.cpp | 74 | ||||
-rw-r--r-- | src/mods.h | 3 | ||||
-rw-r--r-- | src/script/lua_api/l_mainmenu.cpp | 148 | ||||
-rw-r--r-- | src/script/lua_api/l_mainmenu.h | 8 |
4 files changed, 163 insertions, 70 deletions
diff --git a/src/mods.cpp b/src/mods.cpp index 2cfc02b66..6fa578f2f 100644 --- a/src/mods.cpp +++ b/src/mods.cpp @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <cctype> #include <fstream> #include <json/json.h> +#include <algorithm> #include "mods.h" #include "filesys.h" #include "log.h" @@ -28,14 +29,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "convert_json.h" -static bool parseDependsLine(std::istream &is, - std::string &dep, std::set<char> &symbols) +bool parseDependsString(std::string &dep, + std::unordered_set<char> &symbols) { - std::getline(is, dep); dep = trim(dep); symbols.clear(); size_t pos = dep.size(); - while(pos > 0 && !string_allowed(dep.substr(pos-1, 1), MODNAME_ALLOWED_CHARS)){ + while (pos > 0 && !string_allowed(dep.substr(pos-1, 1), MODNAME_ALLOWED_CHARS)) { // last character is a symbol, not part of the modname symbols.insert(dep[pos-1]); --pos; @@ -60,28 +60,66 @@ void parseModContents(ModSpec &spec) // Handle modpacks (defined by containing modpack.txt) std::ifstream modpack_is((spec.path+DIR_DELIM+"modpack.txt").c_str()); - if(modpack_is.good()){ //a modpack, recursively get the mods in it + if (modpack_is.good()) { // a modpack, recursively get the mods in it modpack_is.close(); // We don't actually need the file spec.is_modpack = true; spec.modpack_content = getModsInPath(spec.path, true); - // modpacks have no dependencies; they are defined and // tracked separately for each mod in the modpack - } - else{ // not a modpack, parse the dependencies - std::ifstream is((spec.path+DIR_DELIM+"depends.txt").c_str()); - while(is.good()){ - std::string dep; - std::set<char> symbols; - if(parseDependsLine(is, dep, symbols)){ - if(symbols.count('?') != 0){ - spec.optdepends.insert(dep); - } - else{ - spec.depends.insert(dep); + + } else { + // Attempt to load dependencies from mod.conf + bool mod_conf_has_depends = false; + if (info.exists("depends")) { + mod_conf_has_depends = true; + std::string dep = info.get("depends"); + dep.erase(std::remove_if(dep.begin(), dep.end(), + static_cast<int(*)(int)>(&std::isspace)), dep.end()); + for (const auto &dependency : str_split(dep, ',')) { + spec.depends.insert(dependency); + } + } + + if (info.exists("optional_depends")) { + mod_conf_has_depends = true; + std::string dep = info.get("optional_depends"); + dep.erase(std::remove_if(dep.begin(), dep.end(), + static_cast<int(*)(int)>(&std::isspace)), dep.end()); + for (const auto &dependency : str_split(dep, ',')) { + spec.optdepends.insert(dependency); + } + } + + // Fallback to depends.txt + if (!mod_conf_has_depends) { + std::vector<std::string> dependencies; + + std::ifstream is((spec.path + DIR_DELIM + "depends.txt").c_str()); + while (is.good()) { + std::string dep; + std::getline(is, dep); + dependencies.push_back(dep); + } + + for (auto &dependency : dependencies) { + std::unordered_set<char> symbols; + if (parseDependsString(dependency, symbols)) { + if (symbols.count('?') != 0) { + spec.optdepends.insert(dependency); + } else { + spec.depends.insert(dependency); + } } } } + + if (info.exists("description")) { + spec.desc = info.get("description"); + } else { + std::ifstream is((spec.path + DIR_DELIM + "description.txt").c_str()); + spec.desc = std::string((std::istreambuf_iterator<char>(is)), + std::istreambuf_iterator<char>()); + } } } diff --git a/src/mods.h b/src/mods.h index 037d6bd1c..3063edaa2 100644 --- a/src/mods.h +++ b/src/mods.h @@ -37,6 +37,8 @@ struct ModSpec { std::string name; std::string path; + std::string desc; + //if normal mod: std::unordered_set<std::string> depends; std::unordered_set<std::string> optdepends; @@ -44,6 +46,7 @@ struct ModSpec bool part_of_modpack = false; bool is_modpack = false; + // if modpack: std::map<std::string,ModSpec> modpack_content; ModSpec(const std::string &name_ = "", const std::string &path_ = ""): diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 95696bc20..027b7b0f8 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -258,56 +258,6 @@ int ModApiMainMenu::l_get_worlds(lua_State *L) } /******************************************************************************/ -int ModApiMainMenu::l_get_games(lua_State *L) -{ - std::vector<SubgameSpec> games = getAvailableGames(); - - lua_newtable(L); - int top = lua_gettop(L); - unsigned int index = 1; - - for (const SubgameSpec &game : games) { - lua_pushnumber(L,index); - lua_newtable(L); - int top_lvl2 = lua_gettop(L); - - lua_pushstring(L,"id"); - lua_pushstring(L, game.id.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"path"); - lua_pushstring(L, game.path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"gamemods_path"); - lua_pushstring(L, game.gamemods_path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"name"); - lua_pushstring(L, game.name.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"menuicon_path"); - lua_pushstring(L, game.menuicon_path.c_str()); - lua_settable(L, top_lvl2); - - lua_pushstring(L,"addon_mods_paths"); - lua_newtable(L); - int table2 = lua_gettop(L); - int internal_index=1; - for (const std::string &addon_mods_path : game.addon_mods_paths) { - lua_pushnumber(L,internal_index); - lua_pushstring(L, addon_mods_path.c_str()); - lua_settable(L, table2); - internal_index++; - } - lua_settable(L, top_lvl2); - lua_settable(L, top); - index++; - } - return 1; -} -/******************************************************************************/ int ModApiMainMenu::l_get_favorites(lua_State *L) { std::string listtype = "local"; @@ -478,6 +428,103 @@ int ModApiMainMenu::l_delete_favorite(lua_State *L) } /******************************************************************************/ +int ModApiMainMenu::l_get_games(lua_State *L) +{ + std::vector<SubgameSpec> games = getAvailableGames(); + + lua_newtable(L); + int top = lua_gettop(L); + unsigned int index = 1; + + for (const SubgameSpec &game : games) { + lua_pushnumber(L, index); + lua_newtable(L); + int top_lvl2 = lua_gettop(L); + + lua_pushstring(L, "id"); + lua_pushstring(L, game.id.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L, "path"); + lua_pushstring(L, game.path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L, "gamemods_path"); + lua_pushstring(L, game.gamemods_path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L, "name"); + lua_pushstring(L, game.name.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L, "menuicon_path"); + lua_pushstring(L, game.menuicon_path.c_str()); + lua_settable(L, top_lvl2); + + lua_pushstring(L, "addon_mods_paths"); + lua_newtable(L); + int table2 = lua_gettop(L); + int internal_index = 1; + for (const std::string &addon_mods_path : game.addon_mods_paths) { + lua_pushnumber(L, internal_index); + lua_pushstring(L, addon_mods_path.c_str()); + lua_settable(L, table2); + internal_index++; + } + lua_settable(L, top_lvl2); + lua_settable(L, top); + index++; + } + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_get_mod_info(lua_State *L) +{ + std::string path = luaL_checkstring(L, 1); + + ModSpec spec; + spec.path = path; + parseModContents(spec); + + lua_newtable(L); + + lua_pushstring(L, spec.name.c_str()); + lua_setfield(L, -2, "name"); + + lua_pushstring(L, spec.is_modpack ? "modpack" : "mod"); + lua_setfield(L, -2, "type"); + + lua_pushstring(L, spec.desc.c_str()); + lua_setfield(L, -2, "description"); + + lua_pushstring(L, spec.path.c_str()); + lua_setfield(L, -2, "path"); + + // Dependencies + lua_newtable(L); + int i = 1; + for (const auto &dep : spec.depends) { + lua_pushstring(L, dep.c_str()); + lua_rawseti(L, -2, i); + i++; + } + lua_setfield(L, -2, "depends"); + + // Optional Dependencies + lua_newtable(L); + i = 1; + for (const auto &dep : spec.optdepends) { + lua_pushstring(L, dep.c_str()); + lua_rawseti(L, -2, i); + i++; + } + lua_setfield(L, -2, "optional_depends"); + + return 1; +} + +/******************************************************************************/ int ModApiMainMenu::l_show_keys_menu(lua_State *L) { GUIEngine* engine = getGuiEngine(L); @@ -968,6 +1015,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_table_index); API_FCT(get_worlds); API_FCT(get_games); + API_FCT(get_mod_info); API_FCT(start); API_FCT(close); API_FCT(get_favorites); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index ffaab7dca..2faeaf63e 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -71,8 +71,6 @@ private: static int l_get_worlds(lua_State *L); - static int l_get_games(lua_State *L); - static int l_get_mapgen_names(lua_State *L); static int l_get_favorites(lua_State *L); @@ -81,6 +79,12 @@ private: static int l_gettext(lua_State *L); + //packages + + static int l_get_games(lua_State *L); + + static int l_get_mod_info(lua_State *L); + //gui static int l_show_keys_menu(lua_State *L); |