Notify users to reinstall MTG if worlds exist (#13850)

This commit is contained in:
Gregor Parzefall 2023-10-08 17:47:00 +02:00 committed by GitHub
parent 26bb397852
commit d05da513be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 274 additions and 56 deletions

@ -38,8 +38,18 @@ local dialog_metatable = {
handle_events = function(self,event)
if not self.hidden then return self.eventhandler(self,event) end
end,
hide = function(self) self.hidden = true end,
show = function(self) self.hidden = false end,
hide = function(self)
if not self.hidden then
self.hidden = true
self.eventhandler(self, "DialogHide")
end
end,
show = function(self)
if self.hidden then
self.hidden = false
self.eventhandler(self, "DialogShow")
end
end,
delete = function(self)
if self.parent ~= nil then
self.parent:show()

@ -56,6 +56,9 @@ local filter_types_titles = {
fgettext("Texture packs"),
}
-- Automatic package installation
local auto_install_spec = nil
local number_downloading = 0
local download_queue = {}
@ -532,6 +535,47 @@ function confirm_overwrite.create(package, callback)
nil)
end
local function install_or_update_package(this, package)
local install_parent
if package.type == "mod" then
install_parent = core.get_modpath()
elseif package.type == "game" then
install_parent = core.get_gamepath()
elseif package.type == "txp" then
install_parent = core.get_texturepath()
else
error("Unknown package type: " .. package.type)
end
local function on_confirm()
local deps = get_raw_dependencies(package)
if deps and has_hard_deps(deps) then
local dlg = install_dialog.create(package, deps)
dlg:set_parent(this)
this:hide()
dlg:show()
else
queue_download(package, package.path and REASON_UPDATE or REASON_NEW)
end
end
if package.type == "mod" and #pkgmgr.games == 0 then
local dlg = messagebox("install_game",
fgettext("You need to install a game before you can install a mod"))
dlg:set_parent(this)
this:hide()
dlg:show()
elseif not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then
local dlg = confirm_overwrite.create(package, on_confirm)
dlg:set_parent(this)
this:hide()
dlg:show()
else
on_confirm()
end
end
local function get_file_extension(path)
local parts = path:split(".")
@ -644,6 +688,59 @@ local function sort_and_filter_pkgs()
store.filter_packages(search_string)
end
-- Resolves the package specification stored in auto_install_spec into an actual package.
-- May only be called after the package list has been loaded successfully.
local function resolve_auto_install_spec()
assert(store.load_ok)
if not auto_install_spec then
return nil
end
local resolved = nil
for _, pkg in ipairs(store.packages_full_unordered) do
if pkg.author == auto_install_spec.author and
pkg.name == auto_install_spec.name then
resolved = pkg
break
end
end
if not resolved then
gamedata.errormessage = fgettext("The package $1/$2 was not found.",
auto_install_spec.author, auto_install_spec.name)
ui.update()
auto_install_spec = nil
end
return resolved
end
-- Installs the package specified by auto_install_spec.
-- Only does something if:
-- a. The package list has been loaded successfully.
-- b. The store dialog is currently visible.
local function do_auto_install()
if not store.load_ok then
return
end
local pkg = resolve_auto_install_spec()
if not pkg then
return
end
local store_dlg = ui.find_by_name("store")
if not store_dlg or store_dlg.hidden then
return
end
install_or_update_package(store_dlg, pkg)
auto_install_spec = nil
end
function store.load()
if store.load_ok then
sort_and_filter_pkgs()
@ -658,20 +755,21 @@ function store.load()
{ urlencode = urlencode },
function(result)
if result then
store.load_ok = true
store.load_error = false
store.packages = result.packages
store.packages_full = result.packages
store.packages_full_unordered = result.packages
store.aliases = result.aliases
sort_and_filter_pkgs()
store.load_ok = true
store.load_error = false
sort_and_filter_pkgs()
do_auto_install()
else
store.load_error = true
end
store.loading = false
core.event_handler("Refresh")
ui.update()
end
)
end
@ -725,11 +823,12 @@ end
function store.sort_packages()
local ret = {}
local auto_install_pkg = resolve_auto_install_spec() -- can be nil
-- Add installed content
for i=1, #store.packages_full_unordered do
local package = store.packages_full_unordered[i]
if package.path then
ret[#ret + 1] = package
for _, pkg in ipairs(store.packages_full_unordered) do
if pkg.path and pkg ~= auto_install_pkg then
ret[#ret + 1] = pkg
end
end
@ -747,13 +846,17 @@ function store.sort_packages()
end)
-- Add uninstalled content
for i=1, #store.packages_full_unordered do
local package = store.packages_full_unordered[i]
if not package.path then
ret[#ret + 1] = package
for _, pkg in ipairs(store.packages_full_unordered) do
if not pkg.path and pkg ~= auto_install_pkg then
ret[#ret + 1] = pkg
end
end
-- Put the package that will be auto-installed at the very top
if auto_install_pkg then
table.insert(ret, 1, auto_install_pkg)
end
store.packages_full = ret
end
@ -1048,45 +1151,7 @@ function store.handle_submit(this, fields)
assert(package)
if fields["install_" .. i] then
local install_parent
if package.type == "mod" then
install_parent = core.get_modpath()
elseif package.type == "game" then
install_parent = core.get_gamepath()
elseif package.type == "txp" then
install_parent = core.get_texturepath()
else
error("Unknown package type: " .. package.type)
end
local function on_confirm()
local deps = get_raw_dependencies(package)
if deps and has_hard_deps(deps) then
local dlg = install_dialog.create(package, deps)
dlg:set_parent(this)
this:hide()
dlg:show()
else
queue_download(package, package.path and REASON_UPDATE or REASON_NEW)
end
end
if package.type == "mod" and #pkgmgr.games == 0 then
local dlg = messagebox("install_game",
fgettext("You need to install a game before you can install a mod"))
dlg:set_parent(this)
this:hide()
dlg:show()
elseif not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then
local dlg = confirm_overwrite.create(package, on_confirm)
dlg:set_parent(this)
this:hide()
dlg:show()
else
on_confirm()
end
install_or_update_package(this, package)
return true
end
@ -1110,7 +1175,24 @@ function store.handle_submit(this, fields)
return false
end
function create_store_dlg(type)
function store.handle_events(event)
if event == "DialogShow" then
-- If the store is already loaded, auto-install packages here.
do_auto_install()
return true
end
return false
end
--- Creates a ContentDB dialog.
---
--- @param type string | nil
--- Sets initial package filter. "game", "mod", "txp" or nil (no filter).
--- @param install_spec table | nil
--- Package specification of the form { author = string, name = string }.
--- Sets package to install or update automatically.
function create_store_dlg(type, install_spec)
search_string = ""
cur_page = 1
if type then
@ -1125,10 +1207,15 @@ function create_store_dlg(type)
filter_type = 1
end
-- Keep the old auto_install_spec if the caller doesn't specify one.
if install_spec then
auto_install_spec = install_spec
end
store.load()
return dialog_create("store",
store.get_formspec,
store.handle_submit,
nil)
store.handle_events)
end

@ -0,0 +1,114 @@
--Minetest
--Copyright (C) 2023 Gregor Parzefall
--
--This program is free software; you can redistribute it and/or modify
--it under the terms of the GNU Lesser General Public License as published by
--the Free Software Foundation; either version 2.1 of the License, or
--(at your option) any later version.
--
--This program is distributed in the hope that it will be useful,
--but WITHOUT ANY WARRANTY; without even the implied warranty of
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--GNU Lesser General Public License for more details.
--
--You should have received a copy of the GNU Lesser General Public License along
--with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
function check_reinstall_mtg()
if core.settings:get_bool("no_mtg_notification") then
return
end
local games = core.get_games()
for _, game in ipairs(games) do
if game.id == "minetest" then
core.settings:set_bool("no_mtg_notification", true)
return
end
end
local mtg_world_found = false
local worlds = core.get_worlds()
for _, world in ipairs(worlds) do
if world.gameid == "minetest" then
mtg_world_found = true
break
end
end
if not mtg_world_found then
core.settings:set_bool("no_mtg_notification", true)
return
end
mm_game_theme.reset()
local maintab = ui.find_by_name("maintab")
local dlg = create_reinstall_mtg_dlg()
dlg:set_parent(maintab)
maintab:hide()
dlg:show()
ui.update()
end
local function get_formspec(dialogdata)
local markup = table.concat({
"<big>", fgettext("Minetest Game is no longer installed by default"), "</big>\n",
fgettext("For a long time, the Minetest engine shipped with a default game called \"Minetest Game\". " ..
"Since Minetest 5.8.0, Minetest ships without a default game."), "\n",
fgettext("If you want to continue playing in your Minetest Game worlds, you need to reinstall Minetest Game."),
})
return table.concat({
"formspec_version[6]",
"size[12.8,7]",
"hypertext[0.375,0.375;12.05,5.2;text;", minetest.formspec_escape(markup), "]",
"container[0.375,5.825]",
"style[dismiss;bgcolor=red]",
"button[0,0;4,0.8;dismiss;", fgettext("Dismiss"), "]",
"button[4.25,0;8,0.8;reinstall;", fgettext("Reinstall Minetest Game"), "]",
"container_end[]",
})
end
local function buttonhandler(this, fields)
if fields.reinstall then
-- Don't set "no_mtg_notification" here so that the dialog will be shown
-- again if downloading MTG fails for whatever reason.
this:delete()
local maintab = ui.find_by_name("maintab")
local dlg = create_store_dlg(nil, { author = "Minetest", name = "minetest_game" })
dlg:set_parent(maintab)
maintab:hide()
dlg:show()
return true
end
if fields.dismiss then
core.settings:set_bool("no_mtg_notification", true)
this:delete()
return true
end
end
local function eventhandler(event)
if event == "MenuQuit" then
-- Don't allow closing the dialog with ESC, but still allow exiting
-- Minetest.
core.close()
return true
end
return false
end
function create_reinstall_mtg_dlg()
local dlg = dialog_create("dlg_reinstall_mtg", get_formspec,
buttonhandler, eventhandler)
return dlg
end

@ -50,6 +50,7 @@ dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
dofile(menupath .. DIR_DELIM .. "dlg_register.lua")
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
dofile(menupath .. DIR_DELIM .. "dlg_version_info.lua")
dofile(menupath .. DIR_DELIM .. "dlg_reinstall_mtg.lua")
local tabs = {
content = dofile(menupath .. DIR_DELIM .. "tab_content.lua"),
@ -121,9 +122,11 @@ local function init_globals()
})
ui.set_default("maintab")
check_new_version()
tv_main:show()
ui.update()
check_reinstall_mtg()
check_new_version()
end
init_globals()

@ -2250,6 +2250,10 @@ update_last_checked (Last update check) string
# Ex: 5.5.0 is 005005000
update_last_known (Last known version update) int 0
# If this is set to true, the user will never (again) be shown the
# "reinstall Minetest Game" notification.
no_mtg_notification (Don't show "reinstall Minetest Game" notification) bool false
# Key for moving the player forward.
keymap_forward (Forward key) key KEY_KEY_W