Move values the mainmenu caches to dedicated files (#14433)

This commit is contained in:
sfan5 2024-03-30 11:06:28 +01:00 committed by GitHub
parent bb6782ca58
commit 6c6e48f006
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 142 additions and 132 deletions

@ -18,6 +18,26 @@
-- Global menu data -- Global menu data
menudata = {} menudata = {}
-- located in user cache path, for remembering this like e.g. last update check
cache_settings = Settings(core.get_cache_path() .. DIR_DELIM .. "common.conf")
--- Checks if the given key contains a timestamp less than a certain age.
--- Pair this with a call to `cache_settings:set(key, tostring(os.time()))`
--- after successfully refreshing the cache.
--- @param key Name of entry in cache_settings
--- @param max_age Age to check against, in seconds
--- @return true if the max age is not reached
function check_cache_age(key, max_age)
local time_now = os.time()
local time_checked = tonumber(cache_settings:get(key)) or 0
return time_now - time_checked < max_age
end
function core.on_before_close()
-- called before the menu is closed, either exit or to join a game
cache_settings:write()
end
-- Local cached values -- Local cached values
local min_supp_proto, max_supp_proto local min_supp_proto, max_supp_proto
@ -27,6 +47,16 @@ function common_update_cached_supp_proto()
end end
common_update_cached_supp_proto() common_update_cached_supp_proto()
-- Other global functions
function core.sound_stop(handle, ...)
return handle:stop(...)
end
function os.tmpname()
error('do not use') -- instead: core.get_temp_path()
end
-- Menu helper functions -- Menu helper functions
local function render_client_count(n) local function render_client_count(n)
@ -140,11 +170,6 @@ function render_serverlist_row(spec)
return table.concat(details, ",") return table.concat(details, ",")
end end
---------------------------------------------------------------------------------
os.tmpname = function()
error('do not use') -- instead use core.get_temp_path()
end
--------------------------------------------------------------------------------
function menu_render_worldlist() function menu_render_worldlist()
local retval = {} local retval = {}

@ -26,13 +26,23 @@ if not core.get_http_api then
end end
assert(core.create_dir(core.get_cache_path() .. DIR_DELIM .. "cdb"))
local cache_file_path = core.get_cache_path() .. DIR_DELIM .. "cdb" .. DIR_DELIM .. "updates.json"
local has_fetched = false local has_fetched = false
local latest_releases local latest_releases
do do
local tmp = core.get_once("cdb_latest_releases") if check_cache_age("cdb_updates_last_checked", 3 * 3600) then
if tmp then local f = io.open(cache_file_path, "r")
latest_releases = core.deserialize(tmp, true) local data = ""
has_fetched = latest_releases ~= nil if f then
data = f:read("*a")
f:close()
end
data = data ~= "" and core.parse_json(data) or nil
if type(data) == "table" then
latest_releases = data
has_fetched = true
end
end end
end end
@ -97,7 +107,8 @@ local function fetch()
return return
end end
latest_releases = lowercase_keys(releases) latest_releases = lowercase_keys(releases)
core.set_once("cdb_latest_releases", core.serialize(latest_releases)) core.safe_file_write(cache_file_path, core.write_json(latest_releases))
cache_settings:set("cdb_updates_last_checked", tostring(os.time()))
if update_detector.get_count() > 0 then if update_detector.get_count() > 0 then
local maintab = ui.find_by_name("maintab") local maintab = ui.find_by_name("maintab")

@ -15,15 +15,30 @@
--with this program; if not, write to the Free Software Foundation, Inc., --with this program; if not, write to the Free Software Foundation, Inc.,
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
---- IMPORTANT ----
-- This whole file can be removed after a while.
-- It was only directly useful for upgrades from 5.7.0 to 5.8.0, but
-- maybe some odd fellow directly upgrades from 5.6.1 to 5.9.0 in the future...
-- see <https://github.com/minetest/minetest/pull/13850> in case it's not obvious
---- ----
local SETTING_NAME = "no_mtg_notification"
function check_reinstall_mtg() function check_reinstall_mtg()
if core.settings:get_bool("no_mtg_notification") then -- used to be in minetest.conf
if core.settings:get_bool(SETTING_NAME) then
cache_settings:set_bool(SETTING_NAME, true)
core.settings:remove(SETTING_NAME)
end
if cache_settings:get_bool(SETTING_NAME) then
return return
end end
local games = core.get_games() local games = core.get_games()
for _, game in ipairs(games) do for _, game in ipairs(games) do
if game.id == "minetest" then if game.id == "minetest" then
core.settings:set_bool("no_mtg_notification", true) cache_settings:set_bool(SETTING_NAME, true)
return return
end end
end end
@ -37,7 +52,7 @@ function check_reinstall_mtg()
end end
end end
if not mtg_world_found then if not mtg_world_found then
core.settings:set_bool("no_mtg_notification", true) cache_settings:set_bool(SETTING_NAME, true)
return return
end end
@ -87,7 +102,7 @@ local function buttonhandler(this, fields)
end end
if fields.dismiss then if fields.dismiss then
core.settings:set_bool("no_mtg_notification", true) cache_settings:set_bool("no_mtg_notification", true)
this:delete() this:delete()
return true return true
end end

@ -51,12 +51,13 @@ end
local function version_info_buttonhandler(this, fields) local function version_info_buttonhandler(this, fields)
if fields.version_check_remind then if fields.version_check_remind then
-- Erase last known, user will be reminded again at next check -- Erase last known, user will be reminded again at next check
core.settings:set("update_last_known", "") cache_settings:set("update_last_known", "")
this:delete() this:delete()
return true return true
end end
if fields.version_check_never then if fields.version_check_never then
core.settings:set("update_last_checked", "disabled") -- clear checked URL
core.settings:set("update_information_url", "")
this:delete() this:delete()
return true return true
end end
@ -116,7 +117,7 @@ local function on_version_info_received(json)
return return
end end
local known_update = tonumber(core.settings:get("update_last_known")) or 0 local known_update = tonumber(cache_settings:get("update_last_known")) or 0
-- Format: MMNNPPP (Major, Minor, Patch) -- Format: MMNNPPP (Major, Minor, Patch)
local new_number = type(json.latest) == "table" and json.latest.version_code local new_number = type(json.latest) == "table" and json.latest.version_code
@ -135,7 +136,7 @@ local function on_version_info_received(json)
return return
end end
core.settings:set("update_last_known", tostring(new_number)) cache_settings:set("update_last_known", tostring(new_number))
-- Show version info dialog (once) -- Show version info dialog (once)
maintab:hide() maintab:hide()
@ -149,20 +150,20 @@ end
function check_new_version() function check_new_version()
local url = core.settings:get("update_information_url") local url = core.settings:get("update_information_url")
if core.settings:get("update_last_checked") == "disabled" or if url == "" then
url == "" then
-- Never show any updates -- Never show any updates
return return
end end
local time_now = os.time() -- every 2 days
local time_checked = tonumber(core.settings:get("update_last_checked")) or 0 if check_cache_age("update_last_checked", 2 * 24 * 3600) then
if time_now - time_checked < 2 * 24 * 3600 then
-- Check interval of 2 entire days
return return
end end
cache_settings:set("update_last_checked", tostring(os.time()))
core.settings:set("update_last_checked", tostring(time_now)) -- Clean old leftovers (this can be removed after 5.9.0 or so)
core.settings:remove("update_last_checked")
core.settings:remove("update_last_known")
core.handle_async(function(params) core.handle_async(function(params)
local http = core.get_http_api() local http = core.get_http_api()

@ -28,8 +28,6 @@ local basepath = core.get_builtin_path()
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" .. defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
DIR_DELIM .. "pack" .. DIR_DELIM DIR_DELIM .. "pack" .. DIR_DELIM
dofile(menupath .. DIR_DELIM .. "misc.lua")
dofile(basepath .. "common" .. DIR_DELIM .. "filterlist.lua") dofile(basepath .. "common" .. DIR_DELIM .. "filterlist.lua")
dofile(basepath .. "fstk" .. DIR_DELIM .. "buttonbar.lua") dofile(basepath .. "fstk" .. DIR_DELIM .. "buttonbar.lua")
dofile(basepath .. "fstk" .. DIR_DELIM .. "dialog.lua") dofile(basepath .. "fstk" .. DIR_DELIM .. "dialog.lua")

@ -1,6 +0,0 @@
-- old non-method sound function
function core.sound_stop(handle, ...)
return handle:stop(...)
end

@ -17,7 +17,7 @@
serverlistmgr = { serverlistmgr = {
-- continent code we detected for ourselves -- continent code we detected for ourselves
my_continent = core.get_once("continent"), my_continent = nil,
-- list of locally favorites servers -- list of locally favorites servers
favorites = nil, favorites = nil,
@ -26,6 +26,15 @@ serverlistmgr = {
servers = nil, servers = nil,
} }
do
if check_cache_age("geoip_last_checked", 3600) then
local tmp = cache_settings:get("geoip") or ""
if tmp:match("^[A-Z][A-Z]$") then
serverlistmgr.my_continent = tmp
end
end
end
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Efficient data structure for normalizing arbitrary scores attached to objects -- Efficient data structure for normalizing arbitrary scores attached to objects
-- e.g. {{"a", 3.14}, {"b", 3.14}, {"c", 20}, {"d", 0}} -- e.g. {{"a", 3.14}, {"b", 3.14}, {"c", 20}, {"d", 0}}
@ -112,6 +121,22 @@ local public_downloading = false
local geoip_downloading = false local geoip_downloading = false
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
local function fetch_geoip()
local http = core.get_http_api()
local url = core.settings:get("serverlist_url") .. "/geoip"
local response = http.fetch_sync({ url = url })
if not response.succeeded then
return
end
local retval = core.parse_json(response.data)
if type(retval) ~= "table" then
return
end
return type(retval.continent) == "string" and retval.continent
end
function serverlistmgr.sync() function serverlistmgr.sync()
if not serverlistmgr.servers then if not serverlistmgr.servers then
serverlistmgr.servers = {{ serverlistmgr.servers = {{
@ -129,37 +154,23 @@ function serverlistmgr.sync()
return return
end end
-- only fetched once per MT instance
if not serverlistmgr.my_continent and not geoip_downloading then if not serverlistmgr.my_continent and not geoip_downloading then
geoip_downloading = true geoip_downloading = true
core.handle_async( core.handle_async(fetch_geoip, nil, function(result)
function(param)
local http = core.get_http_api()
local url = core.settings:get("serverlist_url") .. "/geoip"
local response = http.fetch_sync({ url = url })
if not response.succeeded then
return
end
local retval = core.parse_json(response.data)
return retval and type(retval.continent) == "string" and retval.continent
end,
nil,
function(result)
geoip_downloading = false geoip_downloading = false
if not result then if not result then
return return
end end
serverlistmgr.my_continent = result serverlistmgr.my_continent = result
core.set_once("continent", result) cache_settings:set("geoip", result)
-- reorder list if we already have it cache_settings:set("geoip_last_checked", tostring(os.time()))
-- re-sort list if applicable
if serverlistmgr.servers then if serverlistmgr.servers then
serverlistmgr.servers = order_server_list(serverlistmgr.servers) serverlistmgr.servers = order_server_list(serverlistmgr.servers)
core.event_handler("Refresh") core.event_handler("Refresh")
end end
end end)
)
end end
if public_downloading then if public_downloading then
@ -167,6 +178,7 @@ function serverlistmgr.sync()
end end
public_downloading = true public_downloading = true
-- note: this isn't cached because it's way too dynamic
core.handle_async( core.handle_async(
function(param) function(param)
local http = core.get_http_api() local http = core.get_http_api()

@ -1,5 +1,6 @@
_G.core = {get_once = function(_) end} _G.core = {}
_G.unpack = table.unpack _G.unpack = table.unpack
_G.check_cache_age = function() return false end
_G.serverlistmgr = {} _G.serverlistmgr = {}
dofile("builtin/common/vector.lua") dofile("builtin/common/vector.lua")

@ -776,6 +776,7 @@ serverlist_url (Serverlist URL) string servers.minetest.net
enable_split_login_register (Enable split login/register) bool true enable_split_login_register (Enable split login/register) bool true
# URL to JSON file which provides information about the newest Minetest release # URL to JSON file which provides information about the newest Minetest release
# If this is empty the engine will never check for updates.
update_information_url (Update information URL) string https://www.minetest.net/release_info.json update_information_url (Update information URL) string https://www.minetest.net/release_info.json
[*Server] [*Server]
@ -2291,20 +2292,6 @@ show_advanced (Show advanced settings) bool false
# Changing this setting requires a restart. # Changing this setting requires a restart.
enable_sound (Sound) bool true enable_sound (Sound) bool true
# 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
# 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. # Key for moving the player forward.
keymap_forward (Forward key) key KEY_KEY_W keymap_forward (Forward key) key KEY_KEY_W

@ -55,10 +55,6 @@ Functions
* Android only. Shares file using the share popup * Android only. Shares file using the share popup
* `core.get_version()` (possible in async calls) * `core.get_version()` (possible in async calls)
* returns current core version * returns current core version
* `core.set_once(key, value)`:
* save a string value that persists even if menu is closed
* `core.get_once(key)`:
* get a string value saved by above function, or `nil`

@ -356,11 +356,10 @@ void set_default_settings()
settings->setDefault("contentdb_flag_blacklist", "nonfree, desktop_default"); settings->setDefault("contentdb_flag_blacklist", "nonfree, desktop_default");
#endif #endif
settings->setDefault("update_information_url", "https://www.minetest.net/release_info.json");
#if ENABLE_UPDATE_CHECKER #if ENABLE_UPDATE_CHECKER
settings->setDefault("update_last_checked", ""); settings->setDefault("update_information_url", "https://www.minetest.net/release_info.json");
#else #else
settings->setDefault("update_last_checked", "disabled"); settings->setDefault("update_information_url", "");
#endif #endif
// Server // Server

@ -369,6 +369,8 @@ void GUIEngine::run()
#endif #endif
} }
m_script->beforeClose();
RenderingEngine::autosaveScreensizeAndCo(initial_screen_size, initial_window_maximized); RenderingEngine::autosaveScreensizeAndCo(initial_screen_size, initial_window_maximized);
} }

@ -1080,44 +1080,6 @@ int ModApiMainMenu::l_do_async_callback(lua_State *L)
return 1; return 1;
} }
/******************************************************************************/
// this is intentionally a global and not part of MainMenuScripting or such
namespace {
std::unordered_map<std::string, std::string> once_values;
std::mutex once_mutex;
}
int ModApiMainMenu::l_set_once(lua_State *L)
{
std::string key = readParam<std::string>(L, 1);
if (lua_isnil(L, 2))
return 0;
std::string value = readParam<std::string>(L, 2);
{
MutexAutoLock lock(once_mutex);
once_values[key] = value;
}
return 0;
}
int ModApiMainMenu::l_get_once(lua_State *L)
{
std::string key = readParam<std::string>(L, 1);
{
MutexAutoLock lock(once_mutex);
auto it = once_values.find(key);
if (it == once_values.end())
lua_pushnil(L);
else
lua_pushstring(L, it->second.c_str());
}
return 1;
}
/******************************************************************************/ /******************************************************************************/
void ModApiMainMenu::Initialize(lua_State *L, int top) void ModApiMainMenu::Initialize(lua_State *L, int top)
{ {
@ -1170,8 +1132,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(open_dir); API_FCT(open_dir);
API_FCT(share_file); API_FCT(share_file);
API_FCT(do_async_callback); API_FCT(do_async_callback);
API_FCT(set_once);
API_FCT(get_once);
} }
/******************************************************************************/ /******************************************************************************/

@ -166,10 +166,6 @@ private:
static int l_share_file(lua_State *L); static int l_share_file(lua_State *L);
static int l_set_once(lua_State *L);
static int l_get_once(lua_State *L);
// async // async
static int l_do_async_callback(lua_State *L); static int l_do_async_callback(lua_State *L);

@ -58,7 +58,6 @@ MainMenuScripting::MainMenuScripting(GUIEngine* guiengine):
infostream << "SCRIPTAPI: Initialized main menu modules" << std::endl; infostream << "SCRIPTAPI: Initialized main menu modules" << std::endl;
} }
/******************************************************************************/
void MainMenuScripting::initializeModApi(lua_State *L, int top) void MainMenuScripting::initializeModApi(lua_State *L, int top)
{ {
registerLuaClasses(L, top); registerLuaClasses(L, top);
@ -79,20 +78,31 @@ void MainMenuScripting::initializeModApi(lua_State *L, int top)
asyncEngine.initialize(MAINMENU_NUM_ASYNC_THREADS); asyncEngine.initialize(MAINMENU_NUM_ASYNC_THREADS);
} }
/******************************************************************************/
void MainMenuScripting::registerLuaClasses(lua_State *L, int top) void MainMenuScripting::registerLuaClasses(lua_State *L, int top)
{ {
LuaSettings::Register(L); LuaSettings::Register(L);
MainMenuSoundHandle::Register(L); MainMenuSoundHandle::Register(L);
} }
/******************************************************************************/ void MainMenuScripting::beforeClose()
{
SCRIPTAPI_PRECHECKHEADER
int error_handler = PUSH_ERROR_HANDLER(L);
lua_getglobal(L, "core");
lua_getfield(L, -1, "on_before_close");
PCALL_RES(lua_pcall(L, 0, 0, error_handler));
lua_pop(L, 2); // Pop core, error handler
}
void MainMenuScripting::step() void MainMenuScripting::step()
{ {
asyncEngine.step(getStack()); asyncEngine.step(getStack());
} }
/******************************************************************************/
u32 MainMenuScripting::queueAsync(std::string &&serialized_func, u32 MainMenuScripting::queueAsync(std::string &&serialized_func,
std::string &&serialized_param) std::string &&serialized_param)
{ {

@ -37,6 +37,9 @@ public:
// Global step handler to pass back async events // Global step handler to pass back async events
void step(); void step();
// Calls core.on_before_close()
void beforeClose();
// Pass async events from engine to async threads // Pass async events from engine to async threads
u32 queueAsync(std::string &&serialized_func, u32 queueAsync(std::string &&serialized_func,
std::string &&serialized_param); std::string &&serialized_param);