3 -- Cache for result of item filters
4 local player_filters
= {}
5 local player_filter_results
= {}
6 local player_maxpage
= {}
8 local reset_player_info
= function(playername
)
9 player_filters
[playername
] = nil
10 player_filter_results
[playername
] = nil
11 player_maxpage
[playername
] = nil
15 select_item
.filters
= {}
17 -- Filters out all items not for the Creative Inventory.
18 -- This elimininates all items reserved for internal use.
19 select_item
.filters
.creative
= function(itemstring
)
20 local itemdef
= minetest
.registered_items
[itemstring
]
21 if itemstring
== "air" then
24 if itemdef
.description
== nil or itemdef
.description
== "" then
27 if minetest
.get_item_group(itemstring
, "not_in_creative_inventory") == 1 then
34 select_item
.filters
.all
= function()
38 local check_item
= function(itemstring
, filter
)
39 local itemdef
= minetest
.registered_items
[itemstring
]
40 if itemstring
== "" or itemstring
== "unknown" or itemstring
== "ignore" or itemdef
== nil then
43 if type(filter
) == "function" then
44 if filter(itemstring
) ~= true then
52 local get_items
= function(filter
)
54 for itemstring
, itemdef
in pairs(minetest
.registered_items
) do
55 if check_item(itemstring
, filter
) then
56 table.insert(it
, {itemstring
=itemstring
, itemdef
=itemdef
})
59 -- Sort alphabetically by itemstring
60 local compare
= function(t1
, t2
)
61 return t1
.itemstring
< t2
.itemstring
63 table.sort(it
, compare
)
70 -- Opens the item selection dialog for player with the given filter function at page.
71 -- The dialog has unique identifier dialogname.
72 -- Returns: Number of items it displays.
73 local show_dialog_page
= function(playername
, dialogname
, filter
, page
)
75 if player_filters
[playername
] == nil then
76 player_filters
[playername
] = filter
77 items
= get_items(filter
)
78 player_filter_results
[playername
] = items
80 items
= player_filter_results
[playername
]
81 local xsize
, ysize
, total_pages
82 if #items
< xsize_norm
* ysize_norm
then
84 ysize
= math
.ceil(#items
/ xsize
)
89 total_pages
= math
.ceil(#items
/ (xsize
* ysize
))
92 if minetest
.get_modpath("default") then
93 bg
= default
.gui_bg
.. default
.gui_bg_img
.. default
.gui_slots
96 local form
= "size[6,2]"..
98 "label[0,0;There are no items to choose from.]"..
99 "button_exit[0,1;2,1;cancel;OK]"
100 minetest
.show_formspec(playername
, "select_item:page1", form
)
103 local form
= "size["..xsize
..","..(ysize
+1).."]" .. bg
106 if page
== nil then page
= 1 end
107 local start
= 1 + (page
-1) * xsize
* ysize
108 player_maxpage
[playername
] = total_pages
109 form
= form
.. "label[0,0;Select an item:]"
110 for i
=start
, #items
do
111 local itemstring
= items
[i
].itemstring
112 local itemdef
= items
[i
].itemdef
113 local name
= "item_"..itemstring
114 form
= form
.. "item_image_button["..x
..","..y
..";1,1;"..itemstring
..";"..name
..";]"
115 if itemdef
.description
== nil or itemdef
.description
== "" then
116 form
= form
.. "tooltip["..name
..";"..itemstring
.."]"
128 local ynav
= (ysize
+ 0.5)
129 if total_pages
> 1 then
130 form
= form
.. "button[0,"..ynav
..";1,1;previous;<]"
131 form
= form
.. "button[1,"..ynav
..";1,1;next;>]"
132 form
= form
.. "label[2,"..ynav
..";"..minetest
.formspec_escape(string.format("Page %d/%d", page
, total_pages
)).."]"
134 form
= form
.. "button_exit["..(xsize
-2)..","..ynav
..";2,1;cancel;Cancel]"
135 minetest
.show_formspec(playername
, "select_item:page"..page
.."%%"..dialogname
, form
)
139 select_item
.show_dialog
= function(playername
, dialogname
, filter
)
140 show_dialog_page(playername
, dialogname
, filter
, 1)
144 select_item
.register_on_select_item
= function(callback
)
145 table.insert(callbacks
, callback
)
148 minetest
.register_on_player_receive_fields(function(player
, formname
, fields
)
149 local playername
= player
:get_player_name()
150 if string.sub(formname
, 1, 16) == "select_item:page" then
152 local rest
= string.sub(formname
, 17, string.len(formname
))
153 local split
= string.split(rest
, "%%", true, 2)
154 local page
= tonumber(split
[1])
155 local dialogname
= split
[2]
158 for field
,_
in pairs(fields
) do
159 if string.sub(field
, 1, 5) == "item_" then
160 item
= string.sub(field
, 6, string.len(field
))
164 if item
or fields
.quit
then
166 for i
=1,#callbacks
do
167 local ret
= callbacks
[i
](playername
, dialogname
, item
)
173 minetest
.close_formspec(playername
, formname
)
175 reset_player_info(playername
)
177 if fields
.quit
or fields
.cancel
then
178 reset_player_info(playername
)
181 if fields
.previous
and page
> 1 then
182 show_dialog_page(player
:get_player_name(), dialogname
, player_filters
[playername
], page
- 1)
183 elseif fields
.next then
184 local maxpage
= player_maxpage
[playername
]
185 if maxpage
and (page
+ 1 <= maxpage
) then
186 show_dialog_page(playername
, dialogname
, player_filters
[playername
], page
+ 1)
189 minetest
.log("warning", "[select_item] Player "..playername
.." managed to navigate select_item menu without maxpage set!")
196 minetest
.register_on_leaveplayer(function(player
)
197 reset_player_info(player
:get_player_name())