]> git.lizzy.rs Git - worldedit.git/blobdiff - worldedit_gui/init.lua
Call minetest.deserialize with safe=true
[worldedit.git] / worldedit_gui / init.lua
index 27190ab2ae6d6bac0191b237d5abb43f691c8dbe..424d61f064f887d3955cf7c5d66743b2de52e5b7 100644 (file)
@@ -14,7 +14,7 @@ Use `nil` for the `options` parameter to unregister the function associated with
 
 Use `nil` for the `get_formspec` field to denote that the function does not have its own screen.
 
 
 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.
+The `privs` field may not be `nil`.
 
 If the identifier is already registered to another function, it will be replaced by the new one.
 
 
 If the identifier is already registered to another function, it will be replaced by the new one.
 
@@ -24,6 +24,9 @@ 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 = {} --mapping of identifiers to options
 local identifiers = {} --ordered list of identifiers
 worldedit.register_gui_function = function(identifier, options)
+       if options.privs == nil or next(options.privs) == nil then
+               error("privs unset")
+       end
        worldedit.pages[identifier] = options
        table.insert(identifiers, identifier)
 end
        worldedit.pages[identifier] = options
        table.insert(identifiers, identifier)
 end
@@ -37,17 +40,16 @@ Example:
 ]]
 
 worldedit.register_gui_handler = function(identifier, handler)
 ]]
 
 worldedit.register_gui_handler = function(identifier, handler)
+       local enabled = true
        minetest.register_on_player_receive_fields(function(player, formname, fields)
        minetest.register_on_player_receive_fields(function(player, formname, fields)
-               --ensure the form is not being exited since this is a duplicate message
-               if fields.quit then
-                       return false
-               end
-               
+               if not enabled then return false end
+               enabled = false
+               minetest.after(0.2, function() enabled = true end)
                local name = player:get_player_name()
                local name = player:get_player_name()
-               
+
                --ensure the player has permission to perform the action
                local entry = worldedit.pages[identifier]
                --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
+               if entry and minetest.check_player_privs(name, entry.privs) then
                        return handler(name, fields)
                end
                return false
                        return handler(name, fields)
                end
                return false
@@ -68,7 +70,7 @@ local get_formspec = function(name, identifier)
 end
 
 --implement worldedit.show_page(name, page) in different ways depending on the available APIs
 end
 
 --implement worldedit.show_page(name, page) in different ways depending on the available APIs
-if unified_inventory then --unified inventory installed
+if minetest.global_exists("unified_inventory") then -- unified inventory installed
        local old_func = worldedit.register_gui_function
        worldedit.register_gui_function = function(identifier, options)
                old_func(identifier, options)
        local old_func = worldedit.register_gui_function
        worldedit.register_gui_function = function(identifier, options)
                old_func(identifier, options)
@@ -86,18 +88,27 @@ if unified_inventory then --unified inventory installed
                        worldedit.show_page(name, "worldedit_gui")
                        return true
                elseif fields.worldedit_gui_exit then --return to original page
                        worldedit.show_page(name, "worldedit_gui")
                        return true
                elseif fields.worldedit_gui_exit then --return to original page
-                       unified_inventory.set_inventory_formspec(minetest.get_player_by_name(name), "craft")
+                       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)
                        return true
                end
                return false
        end)
 
        worldedit.show_page = function(name, page)
-               minetest.get_player_by_name(name):set_inventory_formspec(get_formspec(name, page))
+               local player = minetest.get_player_by_name(name)
+               if player then
+                       player:set_inventory_formspec(get_formspec(name, page))
+               end
        end
        end
-elseif inventory_plus then --inventory++ installed
+elseif minetest.global_exists("inventory_plus") then -- inventory++ installed
        minetest.register_on_joinplayer(function(player)
        minetest.register_on_joinplayer(function(player)
-               inventory_plus.register_button(player, "worldedit_gui", "WorldEdit")
+               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
        end)
 
        --show the form when the button is pressed and hide it when done
@@ -110,7 +121,7 @@ elseif inventory_plus then --inventory++ installed
                        return true
                elseif fields.worldedit_gui_exit then --return to original page
                        if gui_player_formspecs[name] then
                        return true
                elseif fields.worldedit_gui_exit then --return to original page
                        if gui_player_formspecs[name] then
-                               inventory_plus.set_inventory_formspec(player, gui_player_formspecs[name])
+                               inventory_plus.set_inventory_formspec(player, inventory_plus.get_formspec(player, "main"))
                        end
                        return true
                end
                        end
                        return true
                end
@@ -118,67 +129,102 @@ elseif inventory_plus then --inventory++ installed
        end)
 
        worldedit.show_page = function(name, page)
        end)
 
        worldedit.show_page = function(name, page)
-               inventory_plus.set_inventory_formspec(minetest.get_player_by_name(name), get_formspec(name, page))
-       end
-else --fallback button
-       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)
                local player = minetest.get_player_by_name(name)
-               if (minetest.check_player_privs(name, {creative=true}) or minetest.setting_getbool("creative_mode")) and creative_inventory then --creative_inventory is active, add button to modified formspec
-                       formspec = player:get_inventory_formspec() .. "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
-               else
-                       formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
+               if player then
+                       inventory_plus.set_inventory_formspec(player, get_formspec(name, page))
+               end
+       end
+elseif minetest.global_exists("smart_inventory") then -- smart_inventory installed
+       -- redefinition: Update the code element on inventory page to show the we-page
+       function worldedit.show_page(name, page)
+               local state = smart_inventory.get_page_state("worldedit_gui", name)
+               if state then
+                       state:get("code"):set_we_formspec(page)
+                       state.location.rootState:show() -- update inventory page
                end
                end
-               player:set_inventory_formspec(formspec)
        end
 
        end
 
-       minetest.register_on_joinplayer(function(player)
-               local name = player:get_player_name()
-               minetest.after(1, function()
-                       player_formspecs[name] = player:get_inventory_formspec()
-                       minetest.after(0.01, function()
-                               update_main_formspec(name)
-                       end)
+       -- smart_inventory page callback. Contains just a "custom code" element
+       local function smart_worldedit_gui_callback(state)
+               local codebox = state:element("code", { name = "code", code = "" })
+               function codebox:set_we_formspec(we_page)
+                       local new_formspec = get_formspec(state.location.rootState.location.player, we_page)
+                       new_formspec = new_formspec:gsub('button_exit','button') --no inventory closing
+                       self.data.code = "container[1,1]".. new_formspec .. "container_end[]"
+               end
+               codebox:set_we_formspec("worldedit_gui")
+
+               -- process input (the back button)
+               state:onInput(function(state, fields, player)
+                       if fields.worldedit_gui then --main page
+                               state:get("code"):set_we_formspec("worldedit_gui")
+                       elseif fields.worldedit_gui_exit then --return to original page
+                               state:get("code"):set_we_formspec("worldedit_gui")
+                               state.location.parentState:get("crafting_button"):submit() -- switch to the crafting tab
+                       end
                end)
                end)
-       end)
+       end
 
 
-       minetest.register_on_leaveplayer(function(player)
-               player_formspecs[player:get_player_name()] = nil
-       end)
+       -- all handler should return false to force inventory UI update
+       local orig_register_gui_handler = worldedit.register_gui_handler
+       worldedit.register_gui_handler = function(identifier, handler)
+               local wrapper = function(...)
+                       handler(...)
+                       return false
+               end
+               orig_register_gui_handler(identifier, wrapper)
+       end
 
 
-       local gui_player_formspecs = {}
+       -- register the inventory button
+       smart_inventory.register_page({
+               name = "worldedit_gui",
+               tooltip = "Edit your World!",
+               icon = "inventory_plus_worldedit_gui.png",
+               smartfs_callback = smart_worldedit_gui_callback,
+               sequence = 99
+       })
+elseif minetest.global_exists("sfinv") then -- sfinv installed
+       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)
        minetest.register_on_player_receive_fields(function(player, formname, fields)
-               local name = player:get_player_name()
                if fields.worldedit_gui then --main page
                if fields.worldedit_gui then --main page
-                       gui_player_formspecs[name] = player:get_inventory_formspec()
-                       worldedit.show_page(name, "worldedit_gui")
+                       worldedit.show_page(player:get_player_name(), "worldedit_gui")
                        return true
                elseif fields.worldedit_gui_exit then --return to original page
                        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
+                       sfinv.set_page(player, "sfinv:crafting")
                        return true
                        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
+               return false
        end)
 
        worldedit.show_page = function(name, page)
                local player = minetest.get_player_by_name(name)
        end)
 
        worldedit.show_page = function(name, page)
                local player = minetest.get_player_by_name(name)
-               player:set_inventory_formspec(get_formspec(name, page))
+               if player then
+                       player:set_inventory_formspec(get_formspec(name, page))
+               end
        end
        end
+else
+       error(
+               "worldedit_gui requires a supported gui management mod to be installed.\n"..
+               "To use the it you need to either:\n"..
+               "* use minetest_game or another sfinv-compatible subgame\n"..
+               "* install Unified Inventory, Inventory++ or Smart Inventory\n"..
+               "If you don't want to use worldedit_gui, disable it by editing world.mt or from the main menu."
+       )
 end
 
 worldedit.register_gui_function("worldedit_gui", {
        name = "WorldEdit GUI",
 end
 
 worldedit.register_gui_function("worldedit_gui", {
        name = "WorldEdit GUI",
+       privs = {interact=true},
        get_formspec = function(name)
                --create a form with all the buttons arranged in a grid
                local buttons, x, y, index = {}, 0, 1, 0
        get_formspec = function(name)
                --create a form with all the buttons arranged in a grid
                local buttons, x, y, index = {}, 0, 1, 0
@@ -211,7 +257,7 @@ 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
        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 {})
+                       local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs)
                        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
                        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