summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mods.cpp74
-rw-r--r--src/mods.h3
-rw-r--r--src/script/lua_api/l_mainmenu.cpp148
-rw-r--r--src/script/lua_api/l_mainmenu.h8
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);