ソースを参照

Add updating to online content browser

rubenwardy 6 年 前
コミット
3eb363f813

+ 71 - 35
builtin/mainmenu/dlg_contentstore.lua

@@ -15,6 +15,30 @@
 --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_"

+ 68 - 43
builtin/mainmenu/pkgmgr.lua

@@ -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

+ 3 - 0
src/content/content.cpp

@@ -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()) {

+ 2 - 0
src/content/content.h

@@ -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;

+ 3 - 0
src/content/mods.cpp

@@ -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;

+ 1 - 0
src/content/mods.h

@@ -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;

+ 1 - 0
src/content/packages.cpp

@@ -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) {

+ 3 - 1
src/content/packages.h

@@ -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);
 	}
 };
 

+ 5 - 1
src/content/subgames.cpp

@@ -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)

+ 3 - 2
src/content/subgames.h

@@ -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)
 	{

+ 32 - 21
src/script/lua_api/l_mainmenu.cpp

@@ -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++;
 	}