Allow closing a context from within its builder function.

This commit is contained in:
Signal 2026-01-28 14:08:23 -05:00
parent 48f7581a8f
commit 6e0f653928
2 changed files with 31 additions and 8 deletions

View file

@ -4,6 +4,7 @@ local hte = minetest.hypertext_escape
local ctx
local player_contexts = {}
local contexts = {}
local inventories = {}
@ -1005,7 +1006,9 @@ local Context = {
local tracker = e._linked_states
table.insert(observers, tracker)
local fs = type(e.formspec) == "function" and e.formspec(e.args) or e.formspec
local fs = type(e.formspec) == "function" and e.formspec(e.state, function() e:close() end) or e.formspec
e._window = fs
table.remove(observers)
@ -1036,12 +1039,24 @@ local Context = {
end
end,
deinit = function(e)
if contexts[e.id] then
contexts[e.id] = nil
end
if e._window._onclose then
e._window:_onclose()
end
e:clear_state_bindings()
end,
close = function(e)
-- Inventories cannot be 'closed', only replaced.
if e._is_inventory then return end
minetest.close_formspec(e.target, e.id)
e:deinit()
end
}
Context.__index = Context
local function fs_show(target, fs, args)
local function fs_show(target, fs, state)
local id = "form"..new_id()
local ctx = setmetatable({
formspec = fs,
@ -1049,17 +1064,22 @@ local function fs_show(target, fs, args)
target = type(target) == "string" and target or target:get_player_name(),
id = id,
_linked_states = {},
args = args or {}
state = state or {}
}, Context)
if player_contexts[ctx.target] then
player_contexts[ctx.target]:deinit()
end
contexts[id] = ctx
player_contexts[ctx.target] = ctx
ctx:rebuild()
return ctx
end
local function fs_set_inventory(p, fs, args)
local function fs_set_inventory(p, fs, state)
local id = "form"..new_id()
local name = type(p) == "string" and p or p:get_player_name()
local ctx = setmetatable({
@ -1070,7 +1090,7 @@ local function fs_set_inventory(p, fs, args)
target = name,
id = id,
_linked_states = {},
args = args or {}
state = state or {}
}, Context)
inventories[name] = ctx
@ -1125,7 +1145,6 @@ minetest.register_on_player_receive_fields(function(p, form, fields)
if fields.quit then
ctx:deinit()
contexts[form] = nil
else
if ctx._dirty then
ctx:rebuild()