mirror of
https://github.com/luanti-org/luanti.git
synced 2025-10-12 08:05:18 +02:00
In-game settings menu using separate Lua environment (#15614)
This commit is contained in:
@@ -2,7 +2,10 @@ local scriptpath = core.get_builtin_path()
|
||||
local clientpath = scriptpath.."client"..DIR_DELIM
|
||||
local commonpath = scriptpath.."common"..DIR_DELIM
|
||||
|
||||
dofile(clientpath .. "register.lua")
|
||||
local builtin_shared = {}
|
||||
|
||||
assert(loadfile(commonpath .. "register.lua"))(builtin_shared)
|
||||
assert(loadfile(clientpath .. "register.lua"))(builtin_shared)
|
||||
dofile(commonpath .. "after.lua")
|
||||
dofile(commonpath .. "mod_storage.lua")
|
||||
dofile(commonpath .. "chatcommands.lua")
|
||||
|
@@ -1,68 +1,6 @@
|
||||
core.callback_origins = {}
|
||||
local builtin_shared = ...
|
||||
|
||||
local getinfo = debug.getinfo
|
||||
debug.getinfo = nil
|
||||
|
||||
--- Runs given callbacks.
|
||||
--
|
||||
-- Note: this function is also called from C++
|
||||
-- @tparam table callbacks a table with registered callbacks, like `core.registered_on_*`
|
||||
-- @tparam number mode a RunCallbacksMode, as defined in src/script/common/c_internal.h
|
||||
-- @param ... arguments for the callback
|
||||
-- @return depends on mode
|
||||
function core.run_callbacks(callbacks, mode, ...)
|
||||
assert(type(callbacks) == "table")
|
||||
local cb_len = #callbacks
|
||||
if cb_len == 0 then
|
||||
if mode == 2 or mode == 3 then
|
||||
return true
|
||||
elseif mode == 4 or mode == 5 then
|
||||
return false
|
||||
end
|
||||
end
|
||||
local ret
|
||||
for i = 1, cb_len do
|
||||
local cb_ret = callbacks[i](...)
|
||||
|
||||
if mode == 0 and i == 1 or mode == 1 and i == cb_len then
|
||||
ret = cb_ret
|
||||
elseif mode == 2 then
|
||||
if not cb_ret or i == 1 then
|
||||
ret = cb_ret
|
||||
end
|
||||
elseif mode == 3 then
|
||||
if cb_ret then
|
||||
return cb_ret
|
||||
end
|
||||
ret = cb_ret
|
||||
elseif mode == 4 then
|
||||
if (cb_ret and not ret) or i == 1 then
|
||||
ret = cb_ret
|
||||
end
|
||||
elseif mode == 5 and cb_ret then
|
||||
return cb_ret
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
--
|
||||
-- Callback registration
|
||||
--
|
||||
|
||||
local function make_registration()
|
||||
local t = {}
|
||||
local registerfunc = function(func)
|
||||
t[#t + 1] = func
|
||||
core.callback_origins[func] = {
|
||||
mod = core.get_current_modname() or "??",
|
||||
name = getinfo(1, "n").name or "??"
|
||||
}
|
||||
--local origin = core.callback_origins[func]
|
||||
--print(origin.name .. ": " .. origin.mod .. " registering cbk " .. tostring(func))
|
||||
end
|
||||
return t, registerfunc
|
||||
end
|
||||
local make_registration = builtin_shared.make_registration
|
||||
|
||||
core.registered_globalsteps, core.register_globalstep = make_registration()
|
||||
core.registered_on_mods_loaded, core.register_on_mods_loaded = make_registration()
|
||||
|
@@ -54,7 +54,8 @@ function builtin_shared.make_registration()
|
||||
local registerfunc = function(func)
|
||||
t[#t + 1] = func
|
||||
core.callback_origins[func] = {
|
||||
mod = core.get_current_modname() or "??",
|
||||
-- may be nil or return nil
|
||||
mod = core.get_current_modname and core.get_current_modname() or "??",
|
||||
name = debug.getinfo(1, "n").name or "??"
|
||||
}
|
||||
end
|
||||
@@ -66,7 +67,8 @@ function builtin_shared.make_registration_reverse()
|
||||
local registerfunc = function(func)
|
||||
table.insert(t, 1, func)
|
||||
core.callback_origins[func] = {
|
||||
mod = core.get_current_modname() or "??",
|
||||
-- may be nil or return nil
|
||||
mod = core.get_current_modname and core.get_current_modname() or "??",
|
||||
name = debug.getinfo(1, "n").name or "??"
|
||||
}
|
||||
end
|
||||
|
@@ -98,6 +98,7 @@ local function make_field(converter, validator, stringifier)
|
||||
local fs = ("field[0,0.3;%f,0.8;%s;%s;%s]"):format(
|
||||
avail_w - 1.5, setting.name, get_label(setting), core.formspec_escape(value))
|
||||
fs = fs .. ("field_enter_after_edit[%s;true]"):format(setting.name)
|
||||
fs = fs .. ("field_close_on_enter[%s;false]"):format(setting.name) -- for pause menu env
|
||||
fs = fs .. ("button[%f,0.3;1.5,0.8;%s;%s]"):format(avail_w - 1.5, "set_" .. setting.name, fgettext("Set"))
|
||||
|
||||
return fs, 1.1
|
||||
@@ -217,6 +218,8 @@ local function make_path(setting)
|
||||
|
||||
local fs = ("field[0,0.3;%f,0.8;%s;%s;%s]"):format(
|
||||
avail_w - 3, setting.name, get_label(setting), core.formspec_escape(value))
|
||||
fs = fs .. ("field_enter_after_edit[%s;true]"):format(setting.name)
|
||||
fs = fs .. ("field_close_on_enter[%s;false]"):format(setting.name) -- for pause menu env
|
||||
fs = fs .. ("button[%f,0.3;1.5,0.8;%s;%s]"):format(avail_w - 3, "pick_" .. setting.name, fgettext("Browse"))
|
||||
fs = fs .. ("button[%f,0.3;1.5,0.8;%s;%s]"):format(avail_w - 1.5, "set_" .. setting.name, fgettext("Set"))
|
||||
|
||||
@@ -249,8 +252,11 @@ local function make_path(setting)
|
||||
}
|
||||
end
|
||||
|
||||
if PLATFORM == "Android" then
|
||||
if PLATFORM == "Android" or INIT == "pause_menu" then
|
||||
-- The Irrlicht file picker doesn't work on Android.
|
||||
-- Access to the Irrlicht file picker isn't implemented in the pause menu.
|
||||
-- We want to delete the Irrlicht file picker anyway, so any time spent on
|
||||
-- that would be wasted.
|
||||
make.path = make.string
|
||||
make.filepath = make.string
|
||||
else
|
||||
@@ -282,6 +288,14 @@ function make.v3f(setting)
|
||||
fs = fs .. ("field[%f,0.6;%f,0.8;%s;%s;%s]"):format(
|
||||
2 * (field_width + 0.25), field_width, setting.name .. "_z", "Z", value.z)
|
||||
|
||||
fs = fs .. ("field_enter_after_edit[%s;true]"):format(setting.name .. "_x")
|
||||
fs = fs .. ("field_enter_after_edit[%s;true]"):format(setting.name .. "_y")
|
||||
fs = fs .. ("field_enter_after_edit[%s;true]"):format(setting.name .. "_z")
|
||||
-- for pause menu env
|
||||
fs = fs .. ("field_close_on_enter[%s;false]"):format(setting.name .. "_x")
|
||||
fs = fs .. ("field_close_on_enter[%s;false]"):format(setting.name .. "_y")
|
||||
fs = fs .. ("field_close_on_enter[%s;false]"):format(setting.name .. "_z")
|
||||
|
||||
fs = fs .. ("button[%f,0.6;1,0.8;%s;%s]"):format(avail_w, "set_" .. setting.name, fgettext("Set"))
|
||||
|
||||
return fs, 1.4
|
||||
@@ -428,8 +442,22 @@ local function make_noise_params(setting)
|
||||
}
|
||||
end
|
||||
|
||||
make.noise_params_2d = make_noise_params
|
||||
make.noise_params_3d = make_noise_params
|
||||
if INIT == "pause_menu" then
|
||||
-- Making the noise parameter dialog work in the pause menu settings would
|
||||
-- require porting "FSTK" (at least the dialog API) from the mainmenu formspec
|
||||
-- API to the in-game formspec API.
|
||||
-- There's no reason you'd want to adjust mapgen noise parameter settings
|
||||
-- in-game (they only apply to new worlds), so there's no reason to implement
|
||||
-- this.
|
||||
local empty = function()
|
||||
return { get_formspec = function() return "", 0 end }
|
||||
end
|
||||
make.noise_params_2d = empty
|
||||
make.noise_params_3d = empty
|
||||
else
|
||||
make.noise_params_2d = make_noise_params
|
||||
make.noise_params_3d = make_noise_params
|
||||
end
|
||||
|
||||
|
||||
return make
|
@@ -16,11 +16,10 @@
|
||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
|
||||
local component_funcs = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
|
||||
"settings" .. DIR_DELIM .. "components.lua")
|
||||
local path = core.get_builtin_path() .. "common" .. DIR_DELIM .. "settings" .. DIR_DELIM
|
||||
|
||||
local shadows_component = dofile(core.get_mainmenu_path() .. DIR_DELIM ..
|
||||
"settings" .. DIR_DELIM .. "shadows_component.lua")
|
||||
local component_funcs = dofile(path .. "components.lua")
|
||||
local shadows_component = dofile(path .. "shadows_component.lua")
|
||||
|
||||
local loaded = false
|
||||
local full_settings
|
||||
@@ -514,7 +513,8 @@ local function get_formspec(dialogdata)
|
||||
"box[0,0;", tostring(tabsize.width), ",", tostring(tabsize.height), ";#0000008C]",
|
||||
|
||||
("button[0,%f;%f,0.8;back;%s]"):format(
|
||||
tabsize.height + 0.2, back_w, fgettext("Back")),
|
||||
tabsize.height + 0.2, back_w,
|
||||
fgettext(INIT == "pause_menu" and "Exit" or "Back")),
|
||||
|
||||
("box[%f,%f;%f,0.8;#0000008C]"):format(
|
||||
back_w + 0.2, tabsize.height + 0.2, checkbox_w),
|
||||
@@ -531,6 +531,7 @@ local function get_formspec(dialogdata)
|
||||
"field[0.25,0.25;", tostring(search_width), ",0.75;search_query;;",
|
||||
core.formspec_escape(dialogdata.query or ""), "]",
|
||||
"field_enter_after_edit[search_query;true]",
|
||||
"field_close_on_enter[search_query;false]", -- for pause menu env
|
||||
"container[", tostring(search_width + 0.25), ", 0.25]",
|
||||
"image_button[0,0;0.75,0.75;", core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]",
|
||||
"image_button[0.75,0;0.75,0.75;", core.formspec_escape(defaulttexturedir .. "clear.png"), ";search_clear;]",
|
||||
@@ -671,7 +672,8 @@ local function buttonhandler(this, fields)
|
||||
dialogdata.rightscroll = core.explode_scrollbar_event(fields.rightscroll).value or dialogdata.rightscroll
|
||||
dialogdata.query = fields.search_query
|
||||
|
||||
if fields.back then
|
||||
-- "fields.quit" is for the pause menu env
|
||||
if fields.back or fields.quit then
|
||||
this:delete()
|
||||
return true
|
||||
end
|
||||
@@ -765,11 +767,44 @@ local function eventhandler(event)
|
||||
end
|
||||
|
||||
|
||||
function create_settings_dlg()
|
||||
load()
|
||||
local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler)
|
||||
if INIT == "mainmenu" then
|
||||
function create_settings_dlg()
|
||||
load()
|
||||
local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler)
|
||||
|
||||
dlg.data.page_id = update_filtered_pages("")
|
||||
dlg.data.page_id = update_filtered_pages("")
|
||||
|
||||
return dlg
|
||||
return dlg
|
||||
end
|
||||
|
||||
else
|
||||
assert(INIT == "pause_menu")
|
||||
|
||||
local dialog
|
||||
|
||||
core.register_on_formspec_input(function(formname, fields)
|
||||
if dialog and formname == "__builtin:settings" then
|
||||
-- buttonhandler returning true means we should update the formspec.
|
||||
-- dialog is re-checked since the buttonhandler may have closed it.
|
||||
if buttonhandler(dialog, fields) and dialog then
|
||||
core.show_formspec("__builtin:settings", get_formspec(dialog.data))
|
||||
end
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
core.open_settings = function()
|
||||
load()
|
||||
dialog = {}
|
||||
dialog.data = {}
|
||||
dialog.data.page_id = update_filtered_pages("")
|
||||
dialog.delete = function()
|
||||
dialog = nil
|
||||
-- only needed for the "fields.back" case, in the "fields.quit"
|
||||
-- case it's a no-op
|
||||
core.show_formspec("__builtin:settings", "")
|
||||
end
|
||||
|
||||
core.show_formspec("__builtin:settings", get_formspec(dialog.data))
|
||||
end
|
||||
end
|
@@ -15,11 +15,11 @@
|
||||
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
local path = core.get_mainmenu_path() .. DIR_DELIM .. "settings"
|
||||
local path = core.get_builtin_path() .. "common" .. DIR_DELIM .. "settings" .. DIR_DELIM
|
||||
|
||||
dofile(path .. DIR_DELIM .. "settingtypes.lua")
|
||||
dofile(path .. DIR_DELIM .. "dlg_change_mapgen_flags.lua")
|
||||
dofile(path .. DIR_DELIM .. "dlg_settings.lua")
|
||||
dofile(path .. "settingtypes.lua")
|
||||
dofile(path .. "dlg_change_mapgen_flags.lua")
|
||||
dofile(path .. "dlg_settings.lua")
|
||||
|
||||
-- Uncomment to generate 'minetest.conf.example' and 'settings_translation_file.cpp'.
|
||||
-- For RUN_IN_PLACE the generated files may appear in the 'bin' folder.
|
@@ -408,7 +408,16 @@ function settingtypes.parse_config_file(read_all, parse_mods)
|
||||
file:close()
|
||||
end
|
||||
|
||||
if parse_mods then
|
||||
-- TODO: Support game/mod settings in the pause menu too
|
||||
-- Note that this will need to work different from how it's done in the
|
||||
-- mainmenu:
|
||||
-- * Only if in singleplayer / on local server, not on remote servers
|
||||
-- * Only show settings for the active game and mods
|
||||
-- (add API function to get them, can return nil if on a remote server)
|
||||
-- (names are probably not enough, will need paths for uniqueness)
|
||||
-- This means just making "pkgmgr.lua" work won't get you very far.
|
||||
|
||||
if INIT == "mainmenu" and parse_mods then
|
||||
-- Parse games
|
||||
local games_category_initialized = false
|
||||
for _, game in ipairs(pkgmgr.games) do
|
@@ -78,6 +78,8 @@ elseif INIT == "client" then
|
||||
dofile(scriptdir .. "client" .. DIR_DELIM .. "init.lua")
|
||||
elseif INIT == "emerge" then
|
||||
dofile(scriptdir .. "emerge" .. DIR_DELIM .. "init.lua")
|
||||
elseif INIT == "pause_menu" then
|
||||
dofile(scriptdir .. "pause_menu" .. DIR_DELIM .. "init.lua")
|
||||
else
|
||||
error(("Unrecognized builtin initialization type %s!"):format(tostring(INIT)))
|
||||
end
|
||||
|
@@ -47,7 +47,7 @@ dofile(menupath .. DIR_DELIM .. "game_theme.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "content" .. DIR_DELIM .. "init.lua")
|
||||
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_config_world.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "settings" .. DIR_DELIM .. "init.lua")
|
||||
dofile(basepath .. "common" .. DIR_DELIM .. "settings" .. DIR_DELIM .. "init.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua")
|
||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
|
||||
|
12
builtin/pause_menu/init.lua
Normal file
12
builtin/pause_menu/init.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
local scriptpath = core.get_builtin_path()
|
||||
local pausepath = scriptpath.."pause_menu"..DIR_DELIM
|
||||
local commonpath = scriptpath.."common"..DIR_DELIM
|
||||
|
||||
-- we're in-game, so no absolute paths are needed
|
||||
defaulttexturedir = ""
|
||||
|
||||
local builtin_shared = {}
|
||||
|
||||
assert(loadfile(commonpath .. "register.lua"))(builtin_shared)
|
||||
assert(loadfile(pausepath .. "register.lua"))(builtin_shared)
|
||||
dofile(commonpath .. "settings" .. DIR_DELIM .. "init.lua")
|
5
builtin/pause_menu/register.lua
Normal file
5
builtin/pause_menu/register.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
local builtin_shared = ...
|
||||
|
||||
local make_registration = builtin_shared.make_registration
|
||||
|
||||
core.registered_on_formspec_input, core.register_on_formspec_input = make_registration()
|
Reference in New Issue
Block a user