]> git.lizzy.rs Git - minetest.git/commitdiff
Run Minetest update checker on startup (#7629)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Tue, 2 Aug 2022 19:34:17 +0000 (21:34 +0200)
committerGitHub <noreply@github.com>
Tue, 2 Aug 2022 19:34:17 +0000 (21:34 +0200)
This feature is enabled by default for non-Android release builds. Package
maintainers may use -DENABLE_UPDATE_CHECKER=0 to disable it.

Co-authored-by: rubenwardy <rw@rubenwardy.com>
Co-authored-by: sfan5 <sfan5@live.de>
15 files changed:
CMakeLists.txt
README.md
android/build.gradle
android/native/build.gradle
android/native/jni/Android.mk
builtin/mainmenu/dlg_version_info.lua [new file with mode: 0644]
builtin/mainmenu/init.lua
builtin/settingtypes.txt
doc/lua_api.txt
src/cmake_config.h.in
src/config.h
src/defaultsettings.cpp
src/gui/guiFormSpecMenu.cpp
src/script/lua_api/l_util.cpp
util/bump_version.sh

index 9bec15c1b039df251e75d0a6c79cb88c76aa74be..c96b76fe8a4f7e044f9ed763c2ca07f1e13aac2f 100644 (file)
@@ -61,6 +61,9 @@ if(NOT CMAKE_BUILD_TYPE)
        set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type: Debug or Release" FORCE)
 endif()
 
+set(ENABLE_UPDATE_CHECKER (NOT ${DEVELOPMENT_BUILD}) CACHE BOOL
+       "Whether to enable update checks by default")
+
 # Included stuff
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
 
index bbd02aa94b26254cb86ab47c75444a99d3ebf30d..0bc5d4b4269179ee27da2f51aa7699d5ef0bb45c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -261,6 +261,7 @@ General options and their default values:
     ENABLE_SYSTEM_GMP=ON       - Use GMP from system (much faster than bundled mini-gmp)
     ENABLE_SYSTEM_JSONCPP=ON   - Use JsonCPP from system
     RUN_IN_PLACE=FALSE         - Create a portable install (worlds, settings etc. in current directory)
+    ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
     USE_GPROF=FALSE            - Enable profiling using GProf
     VERSION_EXTRA=             - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
     ENABLE_TOUCH=FALSE         - Enable Touchscreen support (requires support by IrrlichtMt)
index 02722360134928c6fd5cf3819e7a419043cb7191..8ba61c4a06bbd7b580b2ce2bd909b07387e8bea7 100644 (file)
@@ -5,6 +5,7 @@ project.ext.set("versionMinor", 6)      // Version Minor
 project.ext.set("versionPatch", 0)      // Version Patch
 project.ext.set("versionExtra", "-dev") // Version Extra
 project.ext.set("versionCode", 38)      // Android Version Code
+project.ext.set("developmentBuild", 1) // Whether it is a development build, or a release
 // NOTE: +2 after each release!
 // +1 for ARM and +1 for ARM64 APK's, because
 // each APK must have a larger `versionCode` than the previous
index 2ddc77135f7c6b01c33560a0735078adc1db6d34..2254aab3aba942009b95eacef47be42d8a5e21c1 100644 (file)
@@ -14,7 +14,8 @@ android {
                                                "versionMajor=${versionMajor}",
                                                "versionMinor=${versionMinor}",
                                                "versionPatch=${versionPatch}",
-                                               "versionExtra=${versionExtra}"
+                                               "versionExtra=${versionExtra}",
+                                               "developmentBuild=${developmentBuild}"
                        }
                }
        }
index b522042dea42661ea51990be742f8736be89b038..50651d5ba4ade70f52ce9134fcc2a7886022ad09 100644 (file)
@@ -102,6 +102,7 @@ LOCAL_CFLAGS += \
        -DVERSION_MINOR=${versionMinor} \
        -DVERSION_PATCH=${versionPatch} \
        -DVERSION_EXTRA=${versionExtra} \
+       -DDEVELOPMENT_BUILD=${developmentBuild} \
        $(GPROF_DEF)
 
 ifdef USE_BUILTIN_LUA
diff --git a/builtin/mainmenu/dlg_version_info.lua b/builtin/mainmenu/dlg_version_info.lua
new file mode 100644 (file)
index 0000000..568fca3
--- /dev/null
@@ -0,0 +1,172 @@
+--[[
+Minetest
+Copyright (C) 2018-2020 SmallJoker, 2022 rubenwardy
+
+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.
+]]
+
+if not core.get_http_api then
+       function check_new_version()
+       end
+       return
+end
+
+local function version_info_formspec(data)
+       local cur_ver = core.get_version()
+       local title = fgettext("A new $1 version is available", cur_ver.project)
+       local message =
+               fgettext("Installed version: $1\nNew version: $2\n" ..
+                               "Visit $3 to find out how to get the newest version and stay up to date" ..
+                               " with features and bugfixes.",
+                       cur_ver.string, data.new_version or "", data.url or "")
+
+       local fs = {
+               "formspec_version[3]",
+               "size[12.8,7]",
+               "style_type[label;textcolor=#0E0]",
+               "label[0.5,0.8;", core.formspec_escape(title), "]",
+               "textarea[0.4,1.6;12,3.4;;;",
+                       core.formspec_escape(message), "]",
+               "container[0.4,5.8]",
+               "button[0.0,0;4.0,0.8;version_check_visit;", fgettext("Visit website"), "]",
+               "button[4.5,0;3.5,0.8;version_check_remind;", fgettext("Later"), "]",
+               "button[8.5.5,0;3.5,0.8;version_check_never;", fgettext("Never"), "]",
+               "container_end[]",
+       }
+
+       return table.concat(fs, "")
+end
+
+local function version_info_buttonhandler(this, fields)
+       if fields.version_check_remind then
+               -- Erase last known, user will be reminded again at next check
+               core.settings:set("update_last_known", "")
+               this:delete()
+               return true
+       end
+       if fields.version_check_never then
+               core.settings:set("update_last_checked", "disabled")
+               this:delete()
+               return true
+       end
+       if fields.version_check_visit then
+               if type(this.data.url) == "string" then
+                       core.open_url(this.data.url)
+               end
+               this:delete()
+               return true
+       end
+
+       return false
+end
+
+local function create_version_info_dlg(new_version, url)
+       assert(type(new_version) == "string")
+       assert(type(url) == "string")
+
+       local retval = dialog_create("version_info",
+               version_info_formspec,
+               version_info_buttonhandler,
+               nil)
+
+       retval.data.new_version = new_version
+       retval.data.url = url
+
+       return retval
+end
+
+local function get_current_version_code()
+       -- Format: Major.Minor.Patch
+       -- Convert to MMMNNNPPP
+       local cur_string = core.get_version().string
+       local cur_major, cur_minor, cur_patch = cur_string:match("^(%d+).(%d+).(%d+)")
+
+       if not cur_patch then
+               core.log("error", "Failed to parse version numbers (invalid tag format?)")
+               return
+       end
+
+       return (cur_major * 1000 + cur_minor) * 1000 + cur_patch
+end
+
+local function on_version_info_received(json)
+       local maintab = ui.find_by_name("maintab")
+       if maintab.hidden then
+               -- Another dialog is open, abort.
+               return
+       end
+
+       local known_update = tonumber(core.settings:get("update_last_known")) or 0
+
+       -- Format: MMNNPPP (Major, Minor, Patch)
+       local new_number = type(json.latest) == "table" and json.latest.version_code
+       if type(new_number) ~= "number" then
+               core.log("error", "Failed to read version number (invalid response?)")
+               return
+       end
+
+       local cur_number = get_current_version_code()
+       if new_number <= known_update or new_number < cur_number then
+               return
+       end
+
+       -- Also consider updating from 1.2.3-dev to 1.2.3
+       if new_number == cur_number and not core.get_version().is_dev then
+               return
+       end
+
+       core.settings:set("update_last_known", tostring(new_number))
+
+       -- Show version info dialog (once)
+       maintab:hide()
+
+       local version_info_dlg = create_version_info_dlg(json.latest.version, json.latest.url)
+       version_info_dlg:set_parent(maintab)
+       version_info_dlg:show()
+
+       ui.update()
+end
+
+function check_new_version()
+       local url = core.settings:get("update_information_url")
+       if core.settings:get("update_last_checked") == "disabled" or
+                       url == "" then
+               -- Never show any updates
+               return
+       end
+
+       local time_now = os.time()
+       local time_checked = tonumber(core.settings:get("update_last_checked")) or 0
+       if time_now - time_checked < 2 * 24 * 3600 then
+               -- Check interval of 2 entire days
+               return
+       end
+
+       core.settings:set("update_last_checked", tostring(time_now))
+
+       core.handle_async(function(params)
+               local http = core.get_http_api()
+               return http.fetch_sync(params)
+       end, { url = url }, function(result)
+               local json = result.succeeded and core.parse_json(result.data)
+               if type(json) ~= "table" or not json.latest then
+                       core.log("error", "Failed to read JSON output from " .. url ..
+                                       ", status code = " .. result.code)
+                       return
+               end
+
+               on_version_info_received(json)
+       end)
+end
index f890765fadf533bad815af7051024345d18fc8aa..386d4928cd6f44c6787cbfcb91bf3fcf2af4e9fb 100644 (file)
@@ -47,6 +47,7 @@ dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua")
 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")
 
 local tabs = {}
 
@@ -121,8 +122,8 @@ local function init_globals()
        end
 
        ui.set_default("maintab")
+       check_new_version()
        tv_main:show()
-
        ui.update()
 end
 
index caa6e4db3c1800d1c27ab287a0423e7d88c0f259..52b4b4d9d3685ad7da8196a8bcee8c51bd217480 100644 (file)
@@ -571,6 +571,19 @@ serverlist_url (Serverlist URL) string servers.minetest.net
 #    If disabled, new accounts will be registered automatically when logging in.
 enable_split_login_register (Enable split login/register) bool true
 
+#    URL to JSON file which provides information about the newest Minetest release
+update_information_url (Update information URL) string https://www.minetest.net/release_info.json
+
+#    Unix timestamp (integer) of when the client last checked for an update
+#    Set this value to "disabled" to never check for updates.
+update_last_checked (Last update check) string
+
+#    Version number which was last seen during an update check.
+#
+#    Representation: MMMIIIPPP, where M=Major, I=Minor, P=Patch
+#    Ex: 5.5.0 is 005005000
+update_last_known (Last known version update) int 0
+
 [*Server]
 
 #    Name of the player.
index c7c78e877a44b9500252f128f5bdeb405a578c82..9e1633a149c392bf59c7818185bfcd7acc39085a 100644 (file)
@@ -4926,6 +4926,7 @@ Utilities
     * `string`: Simple version, eg, "1.2.3-dev"
     * `hash`: Full git version (only set if available),
       eg, "1.2.3-dev-01234567-dirty".
+    * `is_dev`: Boolean value indicating whether it's a development build
   Use this for informational purposes only. The information in the returned
   table does not represent the capabilities of the engine, nor is it
   reliable or verifiable. Compatible forks will have a different name and
index b1298165e4c06e557a340eb185354b0f43fc0aa3..17b70e2680a9bbf2856c0be5f8af4b0e3a6f0b4f 100644 (file)
@@ -15,6 +15,8 @@
 #define BUILD_TYPE "@CMAKE_BUILD_TYPE@"
 #define ICON_DIR "@ICONDIR@"
 #cmakedefine01 RUN_IN_PLACE
+#cmakedefine01 DEVELOPMENT_BUILD
+#cmakedefine01 ENABLE_UPDATE_CHECKER
 #cmakedefine01 USE_GETTEXT
 #cmakedefine01 USE_CURL
 #cmakedefine01 USE_SOUND
index 50e1184283368e1f32c2e173cfa96ec06ee5a038..a4c6c9f10e4d510c0fc28b7a77ef283e95db1e33 100644 (file)
@@ -16,6 +16,7 @@
                #define PROJECT_NAME "minetest"
                #define PROJECT_NAME_C "Minetest"
                #define STATIC_SHAREDIR ""
+               #define ENABLE_UPDATE_CHECKER 0
                #define VERSION_STRING STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_PATCH) STR(VERSION_EXTRA)
        #endif
        #ifdef NDEBUG
index 22200071204e97043caee7a099dafa4efe6e8685..c5d92e680cc9056db3b399168ea6d3b379d6737c 100644 (file)
@@ -335,6 +335,12 @@ void set_default_settings()
        settings->setDefault("contentdb_flag_blacklist", "nonfree, desktop_default");
 #endif
 
+       settings->setDefault("update_information_url", "https://www.minetest.net/release_info.json");
+#if ENABLE_UPDATE_CHECKER
+       settings->setDefault("update_last_checked", "");
+#else
+       settings->setDefault("update_last_checked", "disabled");
+#endif
 
        // Server
        settings->setDefault("disable_escape_sequences", "false");
index 5d4ca6747374ebbcf407d2c9172d31eeadd72f7d..1f9914e7275759747bc3b67938adeea081b4b1f9 100644 (file)
@@ -1686,7 +1686,7 @@ void GUIFormSpecMenu::parseField(parserData* data, const std::string &element,
 
 void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &element)
 {
-       MY_CHECKCLIENT("list");
+       MY_CHECKCLIENT("hypertext");
 
        std::vector<std::string> parts;
        if (!precheckElement("hypertext", element, 4, 4, parts))
index 47a68ad75e560377b4605640c650843c8e699e2f..f602aed9998d53f77fcbc60116f6ec57f127c144 100644 (file)
@@ -480,6 +480,8 @@ int ModApiUtil::l_get_version(lua_State *L)
                lua_setfield(L, table, "hash");
        }
 
+       lua_pushboolean(L, DEVELOPMENT_BUILD);
+       lua_setfield(L, table, "is_dev");
        return 1;
 }
 
index 3e64bfd8633fe63fc2365109191007232eaf00cd..271886d681a5f8609cf224cfad896f0fbd48807b 100755 (executable)
@@ -26,6 +26,7 @@ perform_release() {
        sed -i -re "s/^set\(DEVELOPMENT_BUILD TRUE\)$/set(DEVELOPMENT_BUILD FALSE)/" CMakeLists.txt
 
        sed -i 's/project.ext.set("versionExtra", "-dev")/project.ext.set("versionExtra", "")/' android/build.gradle
+       sed -i 's/project.ext.set("developmentBuild", 1)/project.ext.set("developmentBuild", 0)/' android/build.gradle
        sed -i -re "s/\"versionCode\", [0-9]+/\"versionCode\", $NEW_ANDROID_VERSION_CODE/" android/build.gradle
 
        sed -i '/\<release/s/\(version\)="[^"]*"/\1="'"$RELEASE_VERSION"'"/' misc/net.minetest.minetest.appdata.xml
@@ -55,6 +56,7 @@ back_to_devel() {
 
        # Update Android versions
        sed -i 's/set("versionExtra", "")/set("versionExtra", "-dev")/' android/build.gradle
+       sed -i 's/project.ext.set("developmentBuild", 0)/project.ext.set("developmentBuild", 1)/' android/build.gradle
        sed -i -re "s/set\(\"versionMajor\", [0-9]+\)/set(\"versionMajor\", $NEXT_VERSION_MAJOR)/" android/build.gradle
        sed -i -re "s/set\(\"versionMinor\", [0-9]+\)/set(\"versionMinor\", $NEXT_VERSION_MINOR)/" android/build.gradle
        sed -i -re "s/set\(\"versionPatch\", [0-9]+\)/set(\"versionPatch\", $NEXT_VERSION_PATCH)/" android/build.gradle