diff --git a/README.md b/README.md index c2d1549..03f8713 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # FS51 -A compatibility layer that makes formspec_version 3 (and later) formspecs -render more correctly in Minetest 5.1.0 and earlier. +A compatibility layer that makes formspec_version 4 (and later) formspecs +render more correctly in Minetest 5.3.0 and earlier. This will work with most mods without any additional configuration. If you want to disable automatic formspec translation, add diff --git a/monkey_patching.lua b/monkey_patching.lua index 66da337..c148081 100644 --- a/monkey_patching.lua +++ b/monkey_patching.lua @@ -33,10 +33,31 @@ local function remove_hypertext(text) return res end +-- Backport index_event by modifying the dropdown items so that they all start +-- with \x1b(fs51@idx_). This is then parsed out here if the player has been +-- shown any formspec with a dropdown that has index_event. The extra check is +-- done to prevent trying to parse every single field for every single player. +local dropdown_hack_enabled = {} +minetest.after(0, table.insert, minetest.registered_on_player_receive_fields, + 1, function(player, formname, fields) + if dropdown_hack_enabled[player:get_player_name()] then + for k, v in pairs(fields) do + local i = v:match("^\27%(fs51@idx_([0-9]+)%)") + if i then + fields[k] = i + end + end + end +end) + +minetest.register_on_leaveplayer(function(player) + dropdown_hack_enabled[player:get_player_name()] = nil +end) + local function backport_for(name, formspec) local info = get_player_information(name) local formspec_version = info and info.formspec_version or 1 - if formspec_version >= 3 then return formspec end + if formspec_version >= 4 then return formspec end local tree, err = formspec_ast.parse(formspec) if not tree then @@ -49,7 +70,18 @@ local function backport_for(name, formspec) local modified for node in formspec_ast.walk(tree) do local node_type = node.type - if formspec_version == 1 and node_type == 'background9' then + if node_type == "dropdown" and node.index_event and node.item then + -- Enable the dropdown hack for this player + dropdown_hack_enabled[name] = true + + modified = true + for i, item in ipairs(node.item) do + node.item[i] = "\27(fs51@idx_" .. i .. ")" .. item + end + node.index_event = nil + elseif formspec_version == 3 then + -- Don't do anything else + elseif formspec_version == 1 and node_type == 'background9' then -- No need to set modified here node.type = 'background' node.middle_x, node.middle_y = nil, nil