worldedit = worldedit or {} --[[ Example: worldedit.register_gui_function("worldedit_gui_hollow_cylinder", { name = "Make Hollow Cylinder", privs = {worldedit=true}, get_formspec = function(name) return "some formspec here" end, on_select = function(name) print(name .. " clicked the button!") end, }) Use `nil` for the `options` parameter to unregister the function associated with the given identifier. Use `nil` for the `get_formspec` field to denote that the function does not have its own screen. Use `nil` for the `privs` field to denote that no special privileges are required to use the function. If the identifier is already registered to another function, it will be replaced by the new one. The `on_select` function must not call `worldedit.show_page` ]] worldedit.pages = {} --mapping of identifiers to options local identifiers = {} --ordered list of identifiers worldedit.register_gui_function = function(identifier, options) worldedit.pages[identifier] = options table.insert(identifiers, identifier) end --[[ Example: worldedit.register_gui_handler("worldedit_gui_hollow_cylinder", function(name, fields) print(minetest.serialize(fields)) end) ]] worldedit.register_gui_handler = function(identifier, handler) local enabled = true minetest.register_on_player_receive_fields(function(player, formname, fields) if not enabled then return false end enabled = false minetest.after(0.2, function() enabled = true end) local name = player:get_player_name() --ensure the player has permission to perform the action local entry = worldedit.pages[identifier] if entry and minetest.check_player_privs(name, entry.privs or {}) then return handler(name, fields) end return false end) end worldedit.get_formspec_header = function(identifier) local entry = worldedit.pages[identifier] or {} return "button[0,0;2,0.5;worldedit_gui;Back]" .. string.format("label[2,0;WorldEdit GUI > %s]", entry.name or "") end local get_formspec = function(name, identifier) if worldedit.pages[identifier] then return worldedit.pages[identifier].get_formspec(name) end return worldedit.pages["worldedit_gui"].get_formspec(name) --default to showing main page if an unknown page is given end --implement worldedit.show_page(name, page) in different ways depending on the available APIs if rawget(_G, "unified_inventory") then --unified inventory installed local old_func = worldedit.register_gui_function worldedit.register_gui_function = function(identifier, options) old_func(identifier, options) unified_inventory.register_page(identifier, {get_formspec=function(player) return {formspec=options.get_formspec(player:get_player_name())} end}) end unified_inventory.register_button("worldedit_gui", { type = "image", image = "inventory_plus_worldedit_gui.png", }) minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if fields.worldedit_gui then --main page worldedit.show_page(name, "worldedit_gui") return true elseif fields.worldedit_gui_exit then --return to original page local player = minetest.get_player_by_name(name) if player then unified_inventory.set_inventory_formspec(player, "craft") end return true end return false end) worldedit.show_page = function(name, page) local player = minetest.get_player_by_name(name) if player then player:set_inventory_formspec(get_formspec(name, page)) end end elseif rawget(_G, "inventory_plus") then --inventory++ installed minetest.register_on_joinplayer(function(player) local can_worldedit = minetest.check_player_privs(player:get_player_name(), {worldedit=true}) if can_worldedit then inventory_plus.register_button(player, "worldedit_gui", "WorldEdit") end end) --show the form when the button is pressed and hide it when done local gui_player_formspecs = {} minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if fields.worldedit_gui then --main page gui_player_formspecs[name] = player:get_inventory_formspec() worldedit.show_page(name, "worldedit_gui") return true elseif fields.worldedit_gui_exit then --return to original page if gui_player_formspecs[name] then inventory_plus.set_inventory_formspec(player, inventory_plus.get_formspec(player, "main")) end return true end return false end) worldedit.show_page = function(name, page) local player = minetest.get_player_by_name(name) if player then inventory_plus.set_inventory_formspec(player, get_formspec(name, page)) end end elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0.4.15) assert(sfinv.enabled) local orig_get = sfinv.pages["sfinv:crafting"].get sfinv.override_page("sfinv:crafting", { get = function(self, player, context) local can_worldedit = minetest.check_player_privs(player, {worldedit=true}) local fs = orig_get(self, player, context) return fs .. (can_worldedit and "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" or "") end }) --show the form when the button is pressed and hide it when done minetest.register_on_player_receive_fields(function(player, formname, fields) if fields.worldedit_gui then --main page worldedit.show_page(player:get_player_name(), "worldedit_gui") return true elseif fields.worldedit_gui_exit then --return to original page sfinv.set_page(player, "sfinv:crafting") return true end return false end) worldedit.show_page = function(name, page) local player = minetest.get_player_by_name(name) if player then player:set_inventory_formspec(get_formspec(name, page)) end end else --fallback button -- FIXME: this is a huge clusterfuck and the back button is broken local player_formspecs = {} local update_main_formspec = function(name) local formspec = player_formspecs[name] if not formspec then return end local player = minetest.get_player_by_name(name) if not player then --this is in case the player signs off while the media is loading return end if (minetest.check_player_privs(name, {creative=true}) or minetest.setting_getbool("creative_mode")) and creative then --creative is active, add button to modified formspec local creative_formspec = player:get_inventory_formspec() local tab_id = tonumber(creative_formspec:match("tabheader%[.-;(%d+)%;")) if tab_id == 1 then formspec = creative_formspec .. "image_button[0,1;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" elseif not tab_id then formspec = creative_formspec .. "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" else return end else formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" end player:set_inventory_formspec(formspec) end minetest.register_on_joinplayer(function(player) local name = player:get_player_name() minetest.after(1, function() if minetest.get_player_by_name(name) then --ensure the player is still signed in player_formspecs[name] = player:get_inventory_formspec() minetest.after(0.01, function() update_main_formspec(name) end) end end) end) minetest.register_on_leaveplayer(function(player) player_formspecs[player:get_player_name()] = nil end) local gui_player_formspecs = {} minetest.register_on_player_receive_fields(function(player, formname, fields) local name = player:get_player_name() if fields.worldedit_gui then --main page gui_player_formspecs[name] = player:get_inventory_formspec() worldedit.show_page(name, "worldedit_gui") return true elseif fields.worldedit_gui_exit then --return to original page if gui_player_formspecs[name] then player:set_inventory_formspec(gui_player_formspecs[name]) end return true else --deal with creative_inventory setting the formspec on every single message minetest.after(0.01,function() update_main_formspec(name) end) return false --continue processing in creative inventory end end) worldedit.show_page = function(name, page) local player = minetest.get_player_by_name(name) if player then player:set_inventory_formspec(get_formspec(name, page)) end end end worldedit.register_gui_function("worldedit_gui", { name = "WorldEdit GUI", get_formspec = function(name) --create a form with all the buttons arranged in a grid local buttons, x, y, index = {}, 0, 1, 0 local width, height = 3, 0.8 local columns = 5 for i, identifier in pairs(identifiers) do if identifier ~= "worldedit_gui" then local entry = worldedit.pages[identifier] table.insert(buttons, string.format((entry.get_formspec and "button" or "button_exit") .. "[%g,%g;%g,%g;%s;%s]", x, y, width, height, identifier, minetest.formspec_escape(entry.name))) index, x = index + 1, x + width if index == columns then --row is full x, y = 0, y + height index = 0 end end end if index == 0 then --empty row y = y - height end return string.format("size[%g,%g]", math.max(columns * width, 5), math.max(y + 0.5, 3)) .. "button[0,0;2,0.5;worldedit_gui_exit;Back]" .. "label[2,0;WorldEdit GUI]" .. table.concat(buttons) end, }) worldedit.register_gui_handler("worldedit_gui", function(name, fields) for identifier, entry in pairs(worldedit.pages) do --check for WorldEdit GUI main formspec button selection if fields[identifier] and identifier ~= "worldedit_gui" then --ensure player has permission to perform action local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs or {}) if not has_privs then worldedit.player_notify(name, "you are not allowed to use this function (missing privileges: " .. table.concat(missing_privs, ", ") .. ")") return false end if entry.on_select then entry.on_select(name) end if entry.get_formspec then worldedit.show_page(name, identifier) end return true end end return false end) dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/functionality.lua")