Add updating to online content browser
authorrubenwardy <rw@rubenwardy.com>
Wed, 16 May 2018 20:52:12 +0000 (21:52 +0100)
committerGitHub <noreply@github.com>
Wed, 16 May 2018 20:52:12 +0000 (21:52 +0100)
builtin/mainmenu/dlg_contentstore.lua
builtin/mainmenu/pkgmgr.lua
src/content/content.cpp
src/content/content.h
src/content/mods.cpp
src/content/mods.h
src/content/packages.cpp
src/content/packages.h
src/content/subgames.cpp
src/content/subgames.h
src/script/lua_api/l_mainmenu.cpp

index e3505456e84b036ce20adffdee1c730e0f2f803e..2c9e80e151b063fd344f18fbc3619ab1a5b0c8fa 100644 (file)
 --with this program; if not, write to the Free Software Foundation, Inc.,
 --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
+local store = {}
+local package_dialog = {}
+
+local search_string = ""
+local cur_page = 1
+local num_per_page = 5
+local filter_type = 1
+local filter_types_titles = {
+       fgettext("All packages"),
+       fgettext("Games"),
+       fgettext("Mods"),
+       fgettext("Texture packs"),
+}
+
+local filter_types_type = {
+       nil,
+       "game",
+       "mod",
+       "txp",
+}
+
+
+
+
 local function download_package(param)
        if core.download_file(param.package.url, param.filename) then
                return {
@@ -39,7 +63,9 @@ local function start_install(calling_dialog, package)
 
        local function callback(result)
                if result.successful then
-                       local path, msg = pkgmgr.install(result.package.type, result.filename, result.package.name)
+                       local path, msg = pkgmgr.install(result.package.type,
+                                       result.filename, result.package.name,
+                                       result.package.path)
                        if not path then
                                gamedata.errormessage = msg
                        else
@@ -69,6 +95,7 @@ local function start_install(calling_dialog, package)
                                        end
                                        set_def("description", result.package.short_description)
                                        set_def("author",      result.package.author)
+                                       conf:set("release",    result.package.release)
                                        conf:write()
                                end
                        end
@@ -85,7 +112,7 @@ local function start_install(calling_dialog, package)
        end
 
        if not core.handle_async(download_package, params, callback) then
-               minetest.log("error", "ERROR: async event failed")
+               core.log("error", "ERROR: async event failed")
                gamedata.errormessage = fgettext("Failed to download $1", package.name)
        end
 
@@ -111,19 +138,35 @@ local function start_install(calling_dialog, package)
 end
 
 
-local package_dialog = {}
-
 function package_dialog.get_formspec()
        local package = package_dialog.package
 
+       store.update_paths()
+
        local formspec = {
-               "size[8,4;true]",
+               "size[9,4;true]",
                "label[2.5,0.2;", core.formspec_escape(package.title), "]",
-               "textarea[0.2,1;8,3;;;", core.formspec_escape(package.short_description), "]",
+               "textarea[0.2,1;9,3;;;", core.formspec_escape(package.short_description), "]",
                "button[0,0;2,1;back;", fgettext("Back"), "]",
-               "button[6,0;2,1;install;", fgettext("Install"), "]",
        }
 
+       if not package.path then
+               formspec[#formspec + 1] = "button[7,0;2,1;install;"
+               formspec[#formspec + 1] = fgettext("Install")
+               formspec[#formspec + 1] = "]"
+       elseif package.installed_release < package.release then
+               formspec[#formspec + 1] = "button[7,0;2,1;install;"
+               formspec[#formspec + 1] = fgettext("Update")
+               formspec[#formspec + 1] = "]"
+               formspec[#formspec + 1] = "button[7,1;2,1;uninstall;"
+               formspec[#formspec + 1] = fgettext("Uninstall")
+               formspec[#formspec + 1] = "]"
+       else
+               formspec[#formspec + 1] = "button[7,0;2,1;uninstall;"
+               formspec[#formspec + 1] = fgettext("Uninstall")
+               formspec[#formspec + 1] = "]"
+       end
+
        -- TODO: screenshots
 
        return table.concat(formspec, "")
@@ -136,7 +179,15 @@ function package_dialog.handle_submit(this, fields, tabname, tabdata)
        end
 
        if fields.install then
-               start_install(package_dialog.package)
+               start_install(this, package_dialog.package)
+               return true
+       end
+
+       if fields.uninstall then
+               local dlg_delmod = create_delete_content_dlg(package_dialog.package)
+               dlg_delmod:set_parent(this)
+               this:hide()
+               dlg_delmod:show()
                return true
        end
 
@@ -151,28 +202,6 @@ function package_dialog.create(package)
                nil)
 end
 
-
-
-
-local store = {}
-local search_string = ""
-local cur_page = 1
-local num_per_page = 5
-local filter_type = 1
-local filter_types_titles = {
-       fgettext("All packages"),
-       fgettext("Games"),
-       fgettext("Mods"),
-       fgettext("Texture packs"),
-}
-
-local filter_types_type = {
-       nil,
-       "game",
-       "mod",
-       "txp",
-}
-
 function store.load()
        store.packages_full = core.get_package_list()
        store.packages = store.packages_full
@@ -209,6 +238,7 @@ function store.update_paths()
 
                if content and content.author == package.author then
                        package.path = content.path
+                       package.installed_release = content.release
                else
                        package.path = nil
                end
@@ -301,17 +331,23 @@ function store.get_formspec()
                formspec[#formspec + 1] = "]"
 
                -- buttons
-               if package.path then
-                       formspec[#formspec + 1] = "button[6,0;1.5,1;uninstall_"
+               if not package.path then
+                       formspec[#formspec + 1] = "button[6,0;1.5,1;install_"
                        formspec[#formspec + 1] = tostring(i)
                        formspec[#formspec + 1] = ";"
-                       formspec[#formspec + 1] = fgettext("Uninstall")
+                       formspec[#formspec + 1] = fgettext("Install")
                        formspec[#formspec + 1] = "]"
-               else
+               elseif package.installed_release < package.release then
                        formspec[#formspec + 1] = "button[6,0;1.5,1;install_"
                        formspec[#formspec + 1] = tostring(i)
                        formspec[#formspec + 1] = ";"
-                       formspec[#formspec + 1] = fgettext("Install")
+                       formspec[#formspec + 1] = fgettext("Update")
+                       formspec[#formspec + 1] = "]"
+               else
+                       formspec[#formspec + 1] = "button[6,0;1.5,1;uninstall_"
+                       formspec[#formspec + 1] = tostring(i)
+                       formspec[#formspec + 1] = ";"
+                       formspec[#formspec + 1] = fgettext("Uninstall")
                        formspec[#formspec + 1] = "]"
                end
                formspec[#formspec + 1] = "button[7.5,0;1.5,1;view_"
index b83488848d9bb436e752d77b3b9a9630d33bf050..2730612e9fa2510d6a8bba4434f8f45df52da776 100644 (file)
@@ -32,6 +32,7 @@ function get_mods(path,retval,modpack)
 
                        toadd.name = name
                        toadd.author = mod_conf.author
+                       toadd.release = tonumber(mod_conf.release or "0")
                        toadd.path = prefix
                        toadd.type = "mod"
 
@@ -74,6 +75,7 @@ function pkgmgr.get_texture_packs()
                        retval[#retval + 1] = {
                                name = item,
                                author = conf:get("author"),
+                               release = tonumber(conf:get("release") or "0"),
                                list_name = name,
                                type = "txp",
                                path = path,
@@ -336,90 +338,113 @@ function pkgmgr.get_worldconfig(worldpath)
 end
 
 --------------------------------------------------------------------------------
-function pkgmgr.install_dir(type, path, basename)
+function pkgmgr.install_dir(type, path, basename, targetpath)
        local basefolder = pkgmgr.get_base_folder(path)
 
-       local targetpath
+       -- There's no good way to detect a texture pack, so let's just assume
+       -- it's correct for now.
        if type == "txp" then
                if basefolder and basefolder.type ~= "invalid" and basefolder.type ~= "txp" then
                        return nil, fgettext("Unable to install a $1 as a texture pack", basefolder.type)
                end
 
                local from = basefolder and basefolder.path or path
-               targetpath = core.get_texturepath() .. DIR_DELIM .. basename
-               core.copy_dir(from, targetpath)
+               if targetpath then
+                       core.delete_dir(targetpath)
+                       core.create_dir(targetpath)
+               else
+                       targetpath = core.get_texturepath() .. DIR_DELIM .. basename
+               end
+               if not core.copy_dir(from, targetpath) then
+                       return nil,
+                               fgettext("Failed to install $1 to $2", basename, targetpath)
+               end
                return targetpath, nil
 
        elseif not basefolder then
                return nil, fgettext("Unable to find a valid mod or modpack")
        end
 
+       --
+       -- Get destination
+       --
        if basefolder.type == "modpack" then
                if type ~= "mod" then
                        return nil, fgettext("Unable to install a modpack as a $1", type)
                end
-               local clean_path = nil
 
-               if basename ~= nil then
-                       clean_path = "mp_" .. basename
-               end
-
-               if clean_path == nil then
-                       clean_path = get_last_folder(cleanup_path(basefolder.path))
-               end
-
-               if clean_path ~= nil then
-                       targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
-                       if not core.copy_dir(basefolder.path,targetpath) then
+               -- Get destination name for modpack
+               if targetpath then
+                       core.delete_dir(targetpath)
+                       core.create_dir(targetpath)
+               else
+                       local clean_path = nil
+                       if basename ~= nil then
+                               clean_path = "mp_" .. basename
+                       end
+                       if not clean_path then
+                               clean_path = get_last_folder(cleanup_path(basefolder.path))
+                       end
+                       if clean_path then
+                               targetpath = core.get_modpath() .. DIR_DELIM .. clean_path
+                       else
                                return nil,
-                                       fgettext("Failed to install $1 to $2", basename, targetpath)
+                                       fgettext("Install Mod: unable to find suitable foldername for modpack $1",
+                                       modfilename)
                        end
-               else
-                       return nil,
-                               fgettext("Install Mod: unable to find suitable foldername for modpack $1",
-                               modfilename)
                end
-
-               pkgmgr.refresh_globals()
-
        elseif basefolder.type == "mod" then
                if type ~= "mod" then
                        return nil, fgettext("Unable to install a mod as a $1", type)
                end
-               local targetfolder = basename
 
-               if targetfolder == nil then
-                       targetfolder = pkgmgr.identify_modname(basefolder.path,"init.lua")
-               end
+               if targetpath then
+                       core.delete_dir(targetpath)
+                       core.create_dir(targetpath)
+               else
+                       local targetfolder = basename
+                       if targetfolder == nil then
+                               targetfolder = pkgmgr.identify_modname(basefolder.path, "init.lua")
+                       end
 
-               --if heuristic failed try to use current foldername
-               if targetfolder == nil then
-                       targetfolder = get_last_folder(basefolder.path)
-               end
+                       -- If heuristic failed try to use current foldername
+                       if targetfolder == nil then
+                               targetfolder = get_last_folder(basefolder.path)
+                       end
 
-               if targetfolder ~= nil and pkgmgr.isValidModname(targetfolder) then
-                       targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
-                       core.copy_dir(basefolder.path, targetpath)
-               else
-                       return nil, fgettext("Install Mod: unable to find real modname for: $1", modfilename)
+                       if targetfolder ~= nil and pkgmgr.isValidModname(targetfolder) then
+                               targetpath = core.get_modpath() .. DIR_DELIM .. targetfolder
+                       else
+                               return nil, fgettext("Install Mod: unable to find real modname for: $1", modfilename)
+                       end
                end
 
-               pkgmgr.refresh_globals()
-
        elseif basefolder.type == "game" then
                if type ~= "game" then
                        return nil, fgettext("Unable to install a game as a $1", type)
                end
 
-               targetpath = core.get_gamepath() .. DIR_DELIM .. basename
-               core.copy_dir(basefolder.path, targetpath)
+               if targetpath then
+                       core.delete_dir(targetpath)
+                       core.create_dir(targetpath)
+               else
+                       targetpath = core.get_gamepath() .. DIR_DELIM .. basename
+               end
+       end
+
+       -- Copy it
+       if not core.copy_dir(basefolder.path, targetpath) then
+               return nil,
+                       fgettext("Failed to install $1 to $2", basename, targetpath)
        end
 
+       pkgmgr.refresh_globals()
+
        return targetpath, nil
 end
 
 --------------------------------------------------------------------------------
-function pkgmgr.install(type, modfilename, basename)
+function pkgmgr.install(type, modfilename, basename, dest)
        local archive_info = pkgmgr.identify_filetype(modfilename)
        local path = pkgmgr.extract(archive_info)
 
@@ -430,7 +455,7 @@ function pkgmgr.install(type, modfilename, basename)
                                archive_info.type)
        end
 
-       local targetpath, msg = pkgmgr.install_dir(type, path, basename)
+       local targetpath, msg = pkgmgr.install_dir(type, path, basename, dest)
        core.delete_dir(path)
        return targetpath, msg
 end
index d45c5feab3a4abace751ebfc1d860849035048ae..d7a2c965238fe7cfbe37ed9aa793c5f556208bf1 100644 (file)
@@ -98,6 +98,9 @@ void parseContentInfo(ContentSpec &spec)
 
                if (conf.exists("author"))
                        spec.author = conf.get("author");
+
+               if (conf.exists("release"))
+                       spec.release = conf.getS32("release");
        }
 
        if (spec.desc.empty()) {
index 782a4fd7a25f5a56c95a177d581f78993205522e..e246ed4113cf1b35b72b0e0d18be5e93515ffe20 100644 (file)
@@ -20,11 +20,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #pragma once
 #include "config.h"
 #include "convert_json.h"
+#include "irrlichttypes.h"
 
 struct ContentSpec
 {
        std::string type;
        std::string author;
+       u32 release = 0;
        std::string name;
        std::string desc;
        std::string path;
index 694bbcca8d7e970d23c5c30d2f9357345435ed6e..a3e70676063ee9a215ee432bf72c327882431ca5 100644 (file)
@@ -56,6 +56,9 @@ void parseModContents(ModSpec &spec)
        if (info.exists("author"))
                spec.author = info.get("author");
 
+       if (info.exists("release"))
+               spec.release = info.getS32("release");
+
        spec.depends.clear();
        spec.optdepends.clear();
        spec.is_modpack = false;
index a7cad07cf340e3fb78790f48ee1b184ccc6a6e94..6e2506dbf9a66e58641e460147e8bdf4e86d840e 100644 (file)
@@ -39,6 +39,7 @@ struct ModSpec
        std::string author;
        std::string path;
        std::string desc;
+       int release = 0;
 
        // if normal mod:
        std::unordered_set<std::string> depends;
index a769c31afe8c6cbbf1d5f876f07759eec3a9d913..d50e63a6bd5461ea740beb986452d2099e2c7e7c 100644 (file)
@@ -49,6 +49,7 @@ std::vector<Package> getPackagesFromURL(const std::string &url)
                package.type = json[i]["type"].asString();
                package.shortDesc = json[i]["shortDesc"].asString();
                package.url = json[i]["url"].asString();
+               package.release = json[i]["release"].asInt();
 
                Json::Value jScreenshots = json[i]["screenshots"];
                for (unsigned int j = 0; j < jScreenshots.size(); ++j) {
index 6774678de1f9acbff51dab08a220856e8d1d7a6f..2290bd60760c01bb799c1799bef3fc2ef7bb690c 100644 (file)
@@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #pragma once
 #include "config.h"
 #include "convert_json.h"
+#include "irrlichttypes.h"
 
 struct Package
 {
@@ -30,12 +31,13 @@ struct Package
 
        std::string shortDesc;
        std::string url; // download URL
+       u32 release;
        std::vector<std::string> screenshots;
 
        bool valid()
        {
                return !(name.empty() || title.empty() || author.empty() ||
-                               type.empty() || url.empty());
+                               type.empty() || url.empty() || release <= 0);
        }
 };
 
index fd6231a1f5cc2da219a9689fab4b3fb6455a8168..9f05b751d6bae23028ff313a9f4f803a805f2ec9 100644 (file)
@@ -116,13 +116,17 @@ SubgameSpec findSubgame(const std::string &id)
        if (conf.exists("author"))
                game_author = conf.get("author");
 
+       int game_release = 0;
+       if (conf.exists("release"))
+               game_release = conf.getS32("release");
+
        std::string menuicon_path;
 #ifndef SERVER
        menuicon_path = getImagePath(
                        game_path + DIR_DELIM + "menu" + DIR_DELIM + "icon.png");
 #endif
        return SubgameSpec(id, game_path, gamemod_path, mods_paths, game_name,
-                       menuicon_path, game_author);
+                       menuicon_path, game_author, game_release);
 }
 
 SubgameSpec findWorldSubgame(const std::string &world_path)
index 70a9d27136fbc316dcc319ab1469964dfe16c3e9..4198ea860d07d3398b7c113632faeefef48d90c1 100644 (file)
@@ -30,6 +30,7 @@ struct SubgameSpec
        std::string id;
        std::string name;
        std::string author;
+       int release;
        std::string path;
        std::string gamemods_path;
        std::set<std::string> addon_mods_paths;
@@ -41,9 +42,9 @@ struct SubgameSpec
                                        std::set<std::string>(),
                        const std::string &name = "",
                        const std::string &menuicon_path = "",
-                       const std::string &author = "") :
+                       const std::string &author = "", int release = 0) :
                        id(id),
-                       name(name), author(author), path(path),
+                       name(name), author(author), release(release), path(path),
                        gamemods_path(gamemods_path), addon_mods_paths(addon_mods_paths),
                        menuicon_path(menuicon_path)
        {
index 241427709bef3eef2efa2a9b4996cd84498f0637..812fdffe7fe218eeeb4776a49f2f3bf3e4895b12 100644 (file)
@@ -443,33 +443,37 @@ int ModApiMainMenu::l_get_games(lua_State *L)
                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,  "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,  "path");
+               lua_pushstring(L,  game.path.c_str());
+               lua_settable(L,    top_lvl2);
 
-               lua_pushstring(L, "type");
-               lua_pushstring(L, "game");
-               lua_settable(L,   top_lvl2);
+               lua_pushstring(L,  "type");
+               lua_pushstring(L,  "game");
+               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,  "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,  "name");
+               lua_pushstring(L,  game.name.c_str());
+               lua_settable(L,    top_lvl2);
 
-               lua_pushstring(L, "author");
-               lua_pushstring(L, game.author.c_str());
-               lua_settable(L,   top_lvl2);
+               lua_pushstring(L,  "author");
+               lua_pushstring(L,  game.author.c_str());
+               lua_settable(L,    top_lvl2);
+
+               lua_pushstring(L,  "release");
+               lua_pushinteger(L, game.release);
+               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,  "menuicon_path");
+               lua_pushstring(L,  game.menuicon_path.c_str());
+               lua_settable(L,    top_lvl2);
 
                lua_pushstring(L, "addon_mods_paths");
                lua_newtable(L);
@@ -508,6 +512,9 @@ int ModApiMainMenu::l_get_content_info(lua_State *L)
        lua_pushstring(L, spec.author.c_str());
        lua_setfield(L, -2, "author");
 
+       lua_pushinteger(L, spec.release);
+       lua_setfield(L, -2, "release");
+
        lua_pushstring(L, spec.desc.c_str());
        lua_setfield(L, -2, "description");
 
@@ -1036,6 +1043,10 @@ int ModApiMainMenu::l_get_package_list(lua_State *L)
                lua_pushstring(L, package.url.c_str());
                lua_settable  (L, top_lvl2);
 
+               lua_pushstring(L, "release");
+               lua_pushinteger(L, package.release);
+               lua_settable  (L, top_lvl2);
+
                lua_settable(L, top);
                index++;
        }