]> git.lizzy.rs Git - worldedit.git/blob - worldedit_gui/init.lua
Fix for player signing off before WorldEdit GUI has finished loading.
[worldedit.git] / worldedit_gui / init.lua
1 worldedit = worldedit or {}
2
3 --[[
4 Example:
5
6     worldedit.register_gui_function("worldedit_gui_hollow_cylinder", {
7         name = "Make Hollow Cylinder",
8         privs = {worldedit=true},
9         get_formspec = function(name) return "some formspec here" end,
10         on_select = function(name) print(name .. " clicked the button!") end,
11     })
12
13 Use `nil` for the `options` parameter to unregister the function associated with the given identifier.
14
15 Use `nil` for the `get_formspec` field to denote that the function does not have its own screen.
16
17 Use `nil` for the `privs` field to denote that no special privileges are required to use the function.
18
19 If the identifier is already registered to another function, it will be replaced by the new one.
20
21 The `on_select` function must not call `worldedit.show_page`
22 ]]
23
24 worldedit.pages = {} --mapping of identifiers to options
25 local identifiers = {} --ordered list of identifiers
26 worldedit.register_gui_function = function(identifier, options)
27         worldedit.pages[identifier] = options
28         table.insert(identifiers, identifier)
29 end
30
31 --[[
32 Example:
33
34     worldedit.register_gui_handler("worldedit_gui_hollow_cylinder", function(name, fields)
35         print(minetest.serialize(fields))
36     end)
37 ]]
38
39 worldedit.register_gui_handler = function(identifier, handler)
40         minetest.register_on_player_receive_fields(function(player, formname, fields)
41                 --ensure the form is not being exited since this is a duplicate message
42                 if fields.quit then
43                         return false
44                 end
45                 
46                 local name = player:get_player_name()
47                 
48                 --ensure the player has permission to perform the action
49                 local entry = worldedit.pages[identifier]
50                 if entry and minetest.check_player_privs(name, entry.privs or {}) then
51                         return handler(name, fields)
52                 end
53                 return false
54         end)
55 end
56
57 worldedit.get_formspec_header = function(identifier)
58         local entry = worldedit.pages[identifier] or {}
59         return "button[0,0;2,0.5;worldedit_gui;Back]" ..
60                 string.format("label[2,0;WorldEdit GUI > %s]", entry.name or "")
61 end
62
63 local get_formspec = function(name, identifier)
64         if worldedit.pages[identifier] then
65                 return worldedit.pages[identifier].get_formspec(name)
66         end
67         return worldedit.pages["worldedit_gui"].get_formspec(name) --default to showing main page if an unknown page is given
68 end
69
70 --implement worldedit.show_page(name, page) in different ways depending on the available APIs
71 if unified_inventory then --unified inventory installed
72         local old_func = worldedit.register_gui_function
73         worldedit.register_gui_function = function(identifier, options)
74                 old_func(identifier, options)
75                 unified_inventory.register_page(identifier, {get_formspec=function(player) return {formspec=options.get_formspec(player:get_player_name())} end})
76         end
77
78         unified_inventory.register_button("worldedit_gui", {
79                 type = "image",
80                 image = "inventory_plus_worldedit_gui.png",
81         })
82
83         minetest.register_on_player_receive_fields(function(player, formname, fields)
84                 local name = player:get_player_name()
85                 if fields.worldedit_gui then --main page
86                         worldedit.show_page(name, "worldedit_gui")
87                         return true
88                 elseif fields.worldedit_gui_exit then --return to original page
89                         local player = minetest.get_player_by_name(name)
90                         if player then
91                                 unified_inventory.set_inventory_formspec(player, "craft")
92                         end
93                         return true
94                 end
95                 return false
96         end)
97
98         worldedit.show_page = function(name, page)
99                 local player = minetest.get_player_by_name(name)
100                 if player then
101                         player:set_inventory_formspec(get_formspec(name, page))
102                 end
103         end
104 elseif inventory_plus then --inventory++ installed
105         minetest.register_on_joinplayer(function(player)
106                 inventory_plus.register_button(player, "worldedit_gui", "WorldEdit")
107         end)
108
109         --show the form when the button is pressed and hide it when done
110         local gui_player_formspecs = {}
111         minetest.register_on_player_receive_fields(function(player, formname, fields)
112                 local name = player:get_player_name()
113                 if fields.worldedit_gui then --main page
114                         gui_player_formspecs[name] = player:get_inventory_formspec()
115                         worldedit.show_page(name, "worldedit_gui")
116                         return true
117                 elseif fields.worldedit_gui_exit then --return to original page
118                         if gui_player_formspecs[name] then
119                                 inventory_plus.set_inventory_formspec(player, gui_player_formspecs[name])
120                         end
121                         return true
122                 end
123                 return false
124         end)
125
126         worldedit.show_page = function(name, page)
127                 local player = minetest.get_player_by_name(name)
128                 if player then
129                         inventory_plus.set_inventory_formspec(player, get_formspec(name, page))
130                 end
131         end
132 else --fallback button
133         local player_formspecs = {}
134
135         local update_main_formspec = function(name)
136                 local formspec = player_formspecs[name]
137                 if not formspec then
138                         return
139                 end
140                 local player = minetest.get_player_by_name(name)
141                 if not player then --this is in case the player signs off while the media is loading
142                         return
143                 end
144                 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
145                         formspec = player:get_inventory_formspec() .. "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
146                 else
147                         formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]"
148                 end
149                 player:set_inventory_formspec(formspec)
150         end
151
152         minetest.register_on_joinplayer(function(player)
153                 local name = player:get_player_name()
154                 minetest.after(1, function()
155                         if minetest.get_player_by_name(name) then --ensure the player is still signed in
156                                 player_formspecs[name] = player:get_inventory_formspec()
157                                 minetest.after(0.01, function()
158                                         update_main_formspec(name)
159                                 end)
160                         end
161                 end)
162         end)
163
164         minetest.register_on_leaveplayer(function(player)
165                 player_formspecs[player:get_player_name()] = nil
166         end)
167
168         local gui_player_formspecs = {}
169         minetest.register_on_player_receive_fields(function(player, formname, fields)
170                 local name = player:get_player_name()
171                 if fields.worldedit_gui then --main page
172                         gui_player_formspecs[name] = player:get_inventory_formspec()
173                         worldedit.show_page(name, "worldedit_gui")
174                         return true
175                 elseif fields.worldedit_gui_exit then --return to original page
176                         if gui_player_formspecs[name] then
177                                 player:set_inventory_formspec(gui_player_formspecs[name])
178                         end
179                         return true
180                 else --deal with creative_inventory setting the formspec on every single message
181                         minetest.after(0.01,function()
182                                 update_main_formspec(name)
183                         end)
184                         return false --continue processing in creative inventory
185                 end
186         end)
187
188         worldedit.show_page = function(name, page)
189                 local player = minetest.get_player_by_name(name)
190                 if player then
191                         player:set_inventory_formspec(get_formspec(name, page))
192                 end
193         end
194 end
195
196 worldedit.register_gui_function("worldedit_gui", {
197         name = "WorldEdit GUI",
198         get_formspec = function(name)
199                 --create a form with all the buttons arranged in a grid
200                 local buttons, x, y, index = {}, 0, 1, 0
201                 local width, height = 3, 0.8
202                 local columns = 5
203                 for i, identifier in pairs(identifiers) do
204                         if identifier ~= "worldedit_gui" then
205                                 local entry = worldedit.pages[identifier]
206                                 table.insert(buttons, string.format((entry.get_formspec and "button" or "button_exit") ..
207                                         "[%g,%g;%g,%g;%s;%s]", x, y, width, height, identifier, minetest.formspec_escape(entry.name)))
208
209                                 index, x = index + 1, x + width
210                                 if index == columns then --row is full
211                                         x, y = 0, y + height
212                                         index = 0
213                                 end
214                         end
215                 end
216                 if index == 0 then --empty row
217                         y = y - height
218                 end
219                 return string.format("size[%g,%g]", math.max(columns * width, 5), math.max(y + 0.5, 3)) ..
220                         "button[0,0;2,0.5;worldedit_gui_exit;Back]" ..
221                         "label[2,0;WorldEdit GUI]" ..
222                         table.concat(buttons)
223         end,
224 })
225
226 worldedit.register_gui_handler("worldedit_gui", function(name, fields)
227         for identifier, entry in pairs(worldedit.pages) do --check for WorldEdit GUI main formspec button selection
228                 if fields[identifier] and identifier ~= "worldedit_gui" then
229                         --ensure player has permission to perform action
230                         local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs or {})
231                         if not has_privs then
232                                 worldedit.player_notify(name, "you are not allowed to use this function (missing privileges: " .. table.concat(missing_privs, ", ") .. ")")
233                                 return false
234                         end
235                         if entry.on_select then
236                                 entry.on_select(name)
237                         end
238                         if entry.get_formspec then
239                                 worldedit.show_page(name, identifier)
240                         end
241                         return true
242                 end
243         end
244         return false
245 end)
246
247 dofile(minetest.get_modpath(minetest.get_current_modname()) .. "/functionality.lua")